import { describe, it, expect, vi, beforeAll } from "vitest"; import { KcSanitizer } from "keycloakify/tools/kcSanitize/KcSanitizer"; // Implementation of Keycloak Java method KeycloakSanitizerTest with bunch of more test for p tag styling // https://github.com/keycloak/keycloak/blob/8ce8a4ba089eef25a0e01f58e09890399477b9ef/services/src/test/java/org/keycloak/theme/KeycloakSanitizerTest.java#L32 const testCases = [ { description: "should handle escapes correctly", cases: [ { html: "
Keycloak
", expectedResult: '
Keycloak
' }, { html: "

Foo

", expectedResult: "

Foo

" }, { html: '
Keycloak
', expectedResult: '
Keycloak
' }, { html: null, expectedResult: null }, { html: "", expectedResult: "" } ] }, { description: "should handle URLs correctly", cases: [ { html: "

link

", expectedResult: '

link

' }, { html: '

link

', expectedResult: "

link

" }, { html: "

link

", expectedResult: "

link

" }, { html: '

link

', expectedResult: "

link

" }, { html: '

link

', expectedResult: "

link

" }, { html: '

link

', expectedResult: "

link

" }, { html: '

link

', expectedResult: "

link

" }, { html: '

link

', expectedResult: '

link

' }, { html: '

link2

', expectedResult: '

link2

' } ] }, { description: "should handle ordinary texts correctly", cases: [ { html: "Some text", expectedResult: "Some text" }, { html: `text with "double quotation"`, expectedResult: `text with "double quotation"` }, { html: `text with 'single quotation'`, expectedResult: `text with 'single quotation'` } ] }, { description: "should handle text styles correctly", cases: [ { html: "

text

", expectedResult: "

text

" }, { html: "

text

", expectedResult: "

text

" }, { html: '

red text

', expectedResult: '

red text

' }, { html: '

red text

', expectedResult: '

red text

' }, { html: '

Case-insensitive

', expectedResult: '

Case-insensitive

' }, { html: '

wrong value for align

', expectedResult: "

wrong value for align

" }, { html: '

wrong value for align

', expectedResult: "

wrong value for align

" }, { html: '

This is a paragraph with larger text.

', expectedResult: '

This is a paragraph with larger text.

' }, { html: "

או נושא שתבחר

", expectedResult: "

או נושא שתבחר

" } ] }, { description: "should handle styles correctly", cases: [ { html: '
', expectedResult: '
' }, { html: '
', expectedResult: "
" }, { html: ' Content ', expectedResult: ' Content ' } ] } ]; const assertResult = async ( expectedResult: string | null, html: string | null ): Promise => { if (html === null) { await expect(KcSanitizer.sanitize(html)).rejects.toThrow( "Cannot escape null value." ); } else { const result = await KcSanitizer.sanitize(html); expect(result).toBe(expectedResult); } }; // Server-side tests describe("KcSanitizer - Server Side", () => { for (const group of testCases) { describe(group.description, () => { for (const test of group.cases) { it(`should handle ${test.html}`, async () => { await assertResult(test.expectedResult, test.html); }); } }); } }); // Client-side tests describe("KcSanitizer - Client Side (jsdom)", () => { const decodeHtmlEntities = (html: string): string => { const entitiesMap: { [key: string]: string } = { "&": "&", "<": "<", ">": ">", """: '"', "'": "'" }; return html.replace( /&|<|>|"|'/g, entity => entitiesMap[entity] || entity ); }; beforeAll(() => { // Mocking the `document.createElement` to simulate textarea behavior vi.stubGlobal("document", { createElement: (tagName: string) => { if (tagName === "textarea") { let _innerHTML = ""; return { get innerHTML() { return _innerHTML; }, set innerHTML(html) { _innerHTML = html; this.value = decodeHtmlEntities(html); // Simulate decoding }, value: "" // Mimic the textarea behavior where innerHTML -> value }; } throw new Error("Unsupported element"); } }); }); for (const group of testCases) { describe(group.description, () => { for (const test of group.cases) { it(`should handle ${test.html}`, async () => { await assertResult(test.expectedResult, test.html); }); } }); } });