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 = (expectedResult: string | null, html: string | null): void => {
if (html === null) {
expect(KcSanitizer.sanitize(html)).toThrow("Cannot escape null value.");
} else {
const result = 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);
// });
// }
// });
// }
// });
describe("KcSanitizer - Client Side", () => {
const decodeHtmlEntities = (html: string): string => {
const entitiesMap: { [key: string]: string } = {
"&": "&",
"<": "<",
">": ">",
""": '"',
"'": "'"
};
return html.replace(
/&|<|>|"|'/g,
entity => entitiesMap[entity] || entity
);
};
beforeAll(() => {
vi.stubGlobal("window", {});
// 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}`, () => {
if (test.html == null)
expect(() =>
assertResult(test.expectedResult, test.html)
).toThrow("Cannot escape null value.");
else assertResult(test.expectedResult, test.html);
});
}
});
}
});