Fix Trusted Types navigation and fragment history loops
This commit is contained in:
1 parent
1179fc2810
commit
5eae6f3b3c
4 files changed
+62
-6
No files matched your search
@@ -7,7 +7,7 @@ let win: any;
|
||||
let fetchCalls: { url: string; opts: any }[];
|
||||
let nextHtml: string;
|
||||
|
||||
function install(bodyHtml: string): void {
|
||||
function install(bodyHtml: string, configure?: (window: any) => void): void {
|
||||
win = new Window({ url: "https://example.test/" });
|
||||
win.document.body.innerHTML = bodyHtml;
|
||||
fetchCalls = [];
|
||||
@@ -32,6 +32,7 @@ function install(bodyHtml: string): void {
|
||||
text: () => Promise.resolve(nextHtml),
|
||||
});
|
||||
};
|
||||
configure?.(win);
|
||||
(0, eval)(NAV_RUNTIME);
|
||||
}
|
||||
|
||||
@@ -71,6 +72,38 @@ test("intercepts an internal link click and swaps #app in place", async () => {
|
||||
expect(win.document.title).toBe("About");
|
||||
});
|
||||
|
||||
test("fragment history navigation preserves the page without fetching", async () => {
|
||||
install('<div id="app"><input value="Unsaved draft"></div>');
|
||||
win.history.pushState({}, "", "/#setup-commands");
|
||||
win.dispatchEvent(new win.PopStateEvent("popstate"));
|
||||
await flush();
|
||||
expect(fetchCalls).toHaveLength(0);
|
||||
expect(win.document.querySelector("input").value).toBe("Unsaved draft");
|
||||
});
|
||||
|
||||
test("navigation supplies TrustedHTML to the document parser", async () => {
|
||||
let parses = 0;
|
||||
install('<div id="app"><a href="/next" id="lnk">Next</a></div>', (window) => {
|
||||
window.trustedTypes = { createPolicy: (_name: string, rules: any) => ({
|
||||
createHTML: (value: string) => ({ trusted: true, value: rules.createHTML(value) }),
|
||||
createScriptURL: rules.createScriptURL,
|
||||
}) };
|
||||
const Parser = window.DOMParser;
|
||||
(globalThis as any).DOMParser = class {
|
||||
parseFromString(value: any, type: string) {
|
||||
if (!value?.trusted) throw new TypeError("TrustedHTML required");
|
||||
parses++;
|
||||
return new Parser().parseFromString(value.value, type);
|
||||
}
|
||||
};
|
||||
});
|
||||
nextHtml = '<html><body><div id="app">Next page</div></body></html>';
|
||||
win.document.getElementById("lnk").click();
|
||||
await flush();
|
||||
expect(parses).toBe(1);
|
||||
expect(win.document.getElementById("app").textContent).toBe("Next page");
|
||||
});
|
||||
|
||||
test("navigation replaces document control registries before hydration", async () => {
|
||||
install('<div id="app"><a href="/next" id="lnk">Next</a></div><script type="application/json" data-wrn-controls id="old">[]</script>');
|
||||
nextHtml = '<html><body><div id="app">Next</div><script type="application/json" data-wrn-controls id="new">[[{"cond":null,"body":"Ready"}]]</script></body></html>';
|
||||
|
||||
Reference in new issue
Block a user