test(16.2-06): full unit coverage of the Journal Blog Editor field types
- Decode: clean values byte for byte, nil, non-string refusal, the 35 unsafe payloads stripped with notices exactly when changed - notices order, ten-name cut, plural forms in lang/en and lang/pl - LooksLikeHTML, options, ListValue, Upload sniffing and safe names - StoreMedia layout, suffixes, no overwrite, size and folder rules - editor corpus and policy cross-check extended in place: more negatives, notices only when stripped, stable second pass - TestPostsEditorHooks: create and update, default and non-default writes, no writes, no writer - TestCategoriesAdminBlogEditor (Docker host): untouched saves keep imported markup and NULL, clean edit, strip and report, blank to NULL, editor upload
This commit is contained in:
@@ -66,6 +66,25 @@ func tagAttrs(doc, tag string) [][]string {
|
||||
// and with an empty removal report, and its four editor-output additions
|
||||
// (figure data-embed and data-id, img alt, ol start) admit nothing else.
|
||||
func TestEditorOutputPassesPolicy(t *testing.T) {
|
||||
t.Run("corpus is the editor's full output set", func(t *testing.T) {
|
||||
corpus := editorCorpus(t)
|
||||
if len(corpus) < 15 {
|
||||
t.Fatalf("corpus has %d entries, want at least 15", len(corpus))
|
||||
}
|
||||
names := map[string]bool{}
|
||||
for _, e := range corpus {
|
||||
if e.Name == "" || strings.TrimSpace(e.HTML) == "" || names[e.Name] {
|
||||
t.Fatalf("corpus entry %q is empty or repeated", e.Name)
|
||||
}
|
||||
names[e.Name] = true
|
||||
}
|
||||
for _, want := range []string{"embed-youtube", "image-with-caption", "image-without-caption", "ordered-list-start-3", "table-header-row", "links", "combined"} {
|
||||
if !names[want] {
|
||||
t.Fatalf("corpus has no %s entry", want)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
for _, e := range editorCorpus(t) {
|
||||
t.Run("corpus "+e.Name, func(t *testing.T) {
|
||||
if got := SanitizeHTML(e.HTML); got != e.HTML {
|
||||
@@ -77,6 +96,7 @@ func TestEditorOutputPassesPolicy(t *testing.T) {
|
||||
if err := CheckHTML(e.HTML); err != nil {
|
||||
t.Fatalf("CheckHTML = %v", err)
|
||||
}
|
||||
assertNoActiveContent(t, e.HTML)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -114,6 +134,15 @@ func TestEditorOutputPassesPolicy(t *testing.T) {
|
||||
{"negative start", `<ol start="-1"><li>a</li></ol>`, `<ol><li>a</li></ol>`},
|
||||
{"start on ul", `<ul start="3"><li>a</li></ul>`, `<ul><li>a</li></ul>`},
|
||||
{"alt on p", `<p alt="x">y</p>`, `<p>y</p>`},
|
||||
{"upper-case provider", `<figure data-embed="YouTube" data-id="dQw4w9WgXcQ"></figure>`, `<figure data-id="dQw4w9WgXcQ"></figure>`},
|
||||
{"provider with white space", `<figure data-embed=" youtube" data-id="dQw4w9WgXcQ"></figure>`, `<figure data-id="dQw4w9WgXcQ"></figure>`},
|
||||
{"empty id", `<figure data-embed="youtube" data-id=""></figure>`, `<figure data-embed="youtube"></figure>`},
|
||||
{"id with a URL", `<figure data-embed="youtube" data-id="javascript:1"></figure>`, `<figure data-embed="youtube"></figure>`},
|
||||
{"iframe alone", `<iframe src="https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ"></iframe>`, ``},
|
||||
{"script inside the placeholder", `<figure data-embed="youtube" data-id="dQw4w9WgXcQ"><script>alert(1)</script></figure>`, editorPlaceholder},
|
||||
{"embed attributes on section", `<section data-embed="youtube" data-id="dQw4w9WgXcQ">x</section>`, `<section>x</section>`},
|
||||
{"embed attributes on a", `<a href="/x" data-embed="youtube" data-id="dQw4w9WgXcQ">x</a>`, `<a href="/x">x</a>`},
|
||||
{"start with a fraction", `<ol start="1.5"><li>a</li></ol>`, `<ol><li>a</li></ol>`},
|
||||
}
|
||||
for _, tc := range stripped {
|
||||
t.Run("strips "+tc.name, func(t *testing.T) {
|
||||
@@ -248,6 +277,29 @@ func TestSanitizeHTMLReport(t *testing.T) {
|
||||
if got != SanitizeHTML(in) {
|
||||
t.Fatalf("SanitizeHTMLReport and SanitizeHTML disagree on %q", in)
|
||||
}
|
||||
// Notices only when something was stripped (D-10 amended).
|
||||
if notices := removalNotices(r); (len(notices) == 0) != (got == in) {
|
||||
t.Fatalf("SanitizeHTMLReport(%q): %d notices, output changed = %v", in, len(notices), got != in)
|
||||
}
|
||||
// The report is stable: sanitizing the output again changes nothing.
|
||||
if again, r2 := SanitizeHTMLReport(got); again != got || !r2.Empty() {
|
||||
t.Fatalf("second pass over %q = %q, %+v", got, again, r2)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("the imported post is stripped of exactly its style block", func(t *testing.T) {
|
||||
fixture, err := os.ReadFile("../tests/blogeditor/fixtures/imported-post.html")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, r := SanitizeHTMLReport(string(fixture))
|
||||
if got == string(fixture) || r.Empty() {
|
||||
t.Fatalf("the imported post passed the policy unchanged; the fixture should hold markup the policy strips")
|
||||
}
|
||||
if !slices.Contains(r.Elements, "style") {
|
||||
t.Fatalf("report = %+v, want the style element named", r)
|
||||
}
|
||||
assertNoActiveContent(t, got)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user