import { describe, it, expect } from "bun:test"; describe("HTMLRewriter", () => { it("exists globally", async () => { expect(typeof HTMLRewriter).toBe("function"); expect(typeof HTMLRewriter.constructor).toBe("function"); }); it("supports element handlers", async () => { var rewriter = new HTMLRewriter(); rewriter.on("div", { element(element) { element.setInnerContent("", { html: true }); }, }); var input = new Response("
test
")); expect(await res.text()).toBe( [ "", "prepend html", "<span>prepend</span>", "test", "<span>append</span>", "append html", "
", ].join("") ); // setInnerContent res = new HTMLRewriter() .on("p", { element(element) { element.setInnerContent("replace"); }, }) .transform(new Response("test
")); expect(await res.text()).toBe("<span>replace</span>
"); res = new HTMLRewriter() .on("p", { element(element) { element.setInnerContent("replace", { html: true }); }, }) .transform(new Response("test
")); expect(await res.text()).toBe("replace
"); // removeAndKeepContent res = new HTMLRewriter() .on("p", { element(element) { element.removeAndKeepContent(); }, }) .transform(new Response("test
")); expect(await res.text()).toBe("test"); }); it("handles element class properties", async () => { class Handler { constructor(content) { this.content = content; } // noinspection JSUnusedGlobalSymbols element(element) { element.setInnerContent(this.content); } } const res = new HTMLRewriter() .on("p", new Handler("new")) .transform(new Response("test
")); expect(await res.text()).toBe("new
"); }); const commentsMutationsInput = ""; const commentsMutationsExpected = { beforeAfter: [ "", "<span>before</span>", "before html", "", "after html", "<span>after</span>", "
", ].join(""), replace: "<span>replace</span>
", replaceHtml: "replace
", remove: "", }; const commentPropertiesMacro = async (t, func) => { const res = func(new HTMLRewriter(), (comment) => { expect(comment.removed).toBe(false); expect(comment.text).toBe("test"); comment.text = "new"; }).transform(new Response("")); t.is(await res.text(), ""); }; test( "HTMLRewriter: handles comment properties", commentPropertiesMacro, (rw, comments) => rw.on("p", { comments }) ); test( "HTMLRewriter: handles comment mutations", mutationsMacro, (rw, comments) => rw.on("p", { comments }), commentsMutationsInput, commentsMutationsExpected ); it("selector tests", async () => { const checkSelector = async (selector, input, expected) => { const res = new HTMLRewriter() .on(selector, { element(element) { element.setInnerContent("new"); }, }) .transform(new Response(input)); expect(await res.text()).toBe(expected); }; await checkSelector("*", "2
", "new
"); await checkSelector("p", "2
", "new
"); await checkSelector( "p:nth-child(2)", "1
2
3
1
new
3
1
2
3
new
2
3
1
3
5
1
new
5
2
3
new
3
1
2
3
1
new
new
1
2
', 'new
2
' ); await checkSelector( "h1#header", '1
2
", "new
2
" ); await checkSelector( 'p[data-test="one"]', '1
2
', 'new
2
' ); await checkSelector( 'p[data-test="one" i]', '1
2
3
', 'new
new
3
' ); await checkSelector( 'p[data-test="one" s]', '1
2
3
', 'new
2
3
' ); await checkSelector( 'p[data-test~="two"]', '1
2
3
', 'new
new
3
' ); await checkSelector( 'p[data-test^="a"]', '1
2
3
', 'new
new
3
' ); await checkSelector( 'p[data-test$="1"]', '1
2
3
', 'new
2
new
' ); await checkSelector( 'p[data-test*="b"]', '1
2
3
', 'new
new
3
' ); await checkSelector( 'p[data-test|="a"]', '1
2
3
', 'new
new
3
' ); await checkSelector( "div span", "