mattermost/server/public/model/content_flagging_test.go
Maria A Nunez f1b9aa052e
Some checks are pending
API / build (push) Waiting to run
Server CI / Compute Go Version (push) Waiting to run
Server CI / Check mocks (push) Blocked by required conditions
Server CI / Check go mod tidy (push) Blocked by required conditions
Server CI / check-style (push) Blocked by required conditions
Server CI / Check serialization methods for hot structs (push) Blocked by required conditions
Server CI / Vet API (push) Blocked by required conditions
Server CI / Check migration files (push) Blocked by required conditions
Server CI / Generate email templates (push) Blocked by required conditions
Server CI / Check store layers (push) Blocked by required conditions
Server CI / Check mmctl docs (push) Blocked by required conditions
Server CI / Postgres with binary parameters (push) Blocked by required conditions
Server CI / Postgres (push) Blocked by required conditions
Server CI / Postgres (FIPS) (push) Blocked by required conditions
Server CI / Generate Test Coverage (push) Blocked by required conditions
Server CI / Run mmctl tests (push) Blocked by required conditions
Server CI / Run mmctl tests (FIPS) (push) Blocked by required conditions
Server CI / Build mattermost server app (push) Blocked by required conditions
Web App CI / check-lint (push) Waiting to run
Web App CI / check-i18n (push) Blocked by required conditions
Web App CI / check-types (push) Blocked by required conditions
Web App CI / test (platform) (push) Blocked by required conditions
Web App CI / test (mattermost-redux) (push) Blocked by required conditions
Web App CI / test (channels shard 1/4) (push) Blocked by required conditions
Web App CI / test (channels shard 2/4) (push) Blocked by required conditions
Web App CI / test (channels shard 3/4) (push) Blocked by required conditions
Web App CI / test (channels shard 4/4) (push) Blocked by required conditions
Web App CI / upload-coverage (push) Blocked by required conditions
Web App CI / build (push) Blocked by required conditions
Rename Content Flagging to Data Spillage Handling (#35407)
* Rename Content Flagging to Data Spillage Handling

Update all user-facing text to use "Data Spillage Handling" and
"Quarantine for Review" terminology. Rename i18n keys that referenced
content flagging. Auto-patch bot display name on pre-existing servers.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fixed searchable stringgs

* Revert unintended package-lock.json changes

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix i18n extract check: correct typo and key ordering

Fix "posed" -> "posted" typo in keep/remove quarantine modal
defaultMessages. Move admin.contentFlagging.title to correct
alphabetical position in en.json.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix webapp tests for Data Spillage Handling rename

Update test assertions to match renamed i18n strings:
notification settings, content reviewers, and additional
settings tests now expect the new quarantine terminology.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Use translatable i18n strings for notification messages

Replace hardcoded "flagged for review" notification templates with
i18n.T() calls using "quarantined for review" terminology. Add six
new server i18n keys for author, reporter, and reviewer notifications.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix server i18n key mismatches and update test assertions

Rename remaining app.content_flagging.* keys to app.data_spillage.*
in server/i18n/en.json to match Go code references. Fix the
quarantine_post_confirmation key name. Update test assertions to
match new "quarantined for review" terminology.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix gofmt formatting in content_flagging.go

Co-authored-by: Cursor <cursoragent@cursor.com>

* Prevent nil bot on PatchBot failure in getContentReviewBot

Use a separate variable for PatchBot result so the original bot
is preserved if the display name update fails.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Reorder server i18n keys after extract

Run mmgotool i18n extract to sort entries into correct
alphabetical order.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Replace i18n.T() with fmt.Sprintf for notification messages and fix test assertions

Use direct string formatting for bot notification messages instead of
i18n translation keys, which were being removed by mmgotool i18n extract
due to indirect key references. Also update test expectations for renamed
error keys (content_flagging -> data_spillage).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Update default quarantine reasons to DISC-aligned terminology

Replace generic content moderation reasons with defense/intelligence
sector terminology: Classification mismatch, Need-to-know violation,
PII exposure, OPSEC concern, CUI violation, Unauthorized disclosure,
and Other. Updated across model, API tests, webapp tests, and e2e tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Adding a string missing from bad merge

* Update remaining flagged terminology and icon for data spillage rename

- Change post menu icon from flag-outline to alert-outline
- Update reviewer notification: "quarantined" -> "submitted" a message
- Update action notifications: "flagged message" -> "quarantined message"
- Update modal errors: "flagging" -> "quarantining" this message
- Update report title: "flagged" -> "submitted" a message for review
- Update e2e page object locator for renamed menu item

Made-with: Cursor

* Fix tests

* Fix quarantine icon alignment in post dot menu

Use AlertOutlineIcon React component with size={18} instead of raw
<i> tag to match the sizing of all other menu item icons.

Made-with: Cursor

* Fixed E2E tests

* Missing test fix

* Fix E2E tests

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
2026-03-06 21:15:01 -05:00

118 lines
3.2 KiB
Go

package model
import (
"net/http"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestFlagContentRequest_IsValid(t *testing.T) {
validReasons := []string{"spam", "harassment", "inappropriate"}
t.Run("valid request without comment", func(t *testing.T) {
req := &FlagContentRequest{
Reason: "spam",
Comment: "",
}
err := req.IsValid(false, validReasons)
assert.Nil(t, err)
})
t.Run("valid request with comment", func(t *testing.T) {
req := &FlagContentRequest{
Reason: "harassment",
Comment: "This is inappropriate content",
}
err := req.IsValid(false, validReasons)
assert.Nil(t, err)
})
t.Run("valid request with comment when required", func(t *testing.T) {
req := &FlagContentRequest{
Reason: "inappropriate",
Comment: "This violates community guidelines",
}
err := req.IsValid(true, validReasons)
assert.Nil(t, err)
})
t.Run("missing comment when required", func(t *testing.T) {
req := &FlagContentRequest{
Reason: "spam",
Comment: "",
}
err := req.IsValid(true, validReasons)
assert.NotNil(t, err)
assert.Equal(t, "api.data_spillage.error.comment_required", err.Id)
assert.Equal(t, http.StatusBadRequest, err.StatusCode)
})
t.Run("missing reason", func(t *testing.T) {
req := &FlagContentRequest{
Reason: "",
Comment: "Some comment",
}
err := req.IsValid(false, validReasons)
assert.NotNil(t, err)
assert.Equal(t, "api.data_spillage.error.reason_required", err.Id)
assert.Equal(t, http.StatusBadRequest, err.StatusCode)
})
t.Run("invalid reason", func(t *testing.T) {
req := &FlagContentRequest{
Reason: "invalid_reason",
Comment: "Some comment",
}
err := req.IsValid(false, validReasons)
assert.NotNil(t, err)
assert.Equal(t, "api.data_spillage.error.reason_invalid", err.Id)
assert.Equal(t, http.StatusBadRequest, err.StatusCode)
})
t.Run("comment too long", func(t *testing.T) {
longComment := strings.Repeat("a", commentMaxRunes+1)
req := &FlagContentRequest{
Reason: "spam",
Comment: longComment,
}
err := req.IsValid(false, validReasons)
assert.NotNil(t, err)
assert.Equal(t, "api.data_spillage.error.comment_too_long", err.Id)
assert.Equal(t, http.StatusBadRequest, err.StatusCode)
assert.Equal(t, commentMaxRunes, err.params["MaxLength"])
})
t.Run("comment at max length", func(t *testing.T) {
maxLengthComment := strings.Repeat("a", commentMaxRunes)
req := &FlagContentRequest{
Reason: "harassment",
Comment: maxLengthComment,
}
err := req.IsValid(false, validReasons)
assert.Nil(t, err)
})
t.Run("unicode comment length validation", func(t *testing.T) {
// Test with unicode characters that take multiple bytes
unicodeComment := strings.Repeat("🚀", commentMaxRunes+1)
req := &FlagContentRequest{
Reason: "spam",
Comment: unicodeComment,
}
err := req.IsValid(false, validReasons)
assert.NotNil(t, err)
assert.Equal(t, "api.data_spillage.error.comment_too_long", err.Id)
})
t.Run("empty valid reasons list", func(t *testing.T) {
req := &FlagContentRequest{
Reason: "spam",
Comment: "Some comment",
}
err := req.IsValid(false, []string{})
assert.NotNil(t, err)
assert.Equal(t, "api.data_spillage.error.reason_invalid", err.Id)
})
}