Files
sigilbox/test/archiver.test.mjs

181 lines
6.0 KiB
JavaScript
Raw Permalink Normal View History

2026-05-16 16:36:51 -07:00
import assert from "node:assert/strict";
import test from "node:test";
2026-05-16 22:07:39 -07:00
import {
getCosmeticCssForHostname,
parseFilterRules,
renderPage,
shouldBlockRequestWithRules
} from "../src/archiver.mjs";
test("parses EasyList-style network rules, exceptions, and badfilter entries", () => {
const rules = parseFilterRules(`
[Adblock Plus 2.0]
||ads.example.com^$script,third-party
@@||ads.example.com/allowed.js$script,domain=publisher.test
banner$~image
||disabled.example^$script
||disabled.example^$script,badfilter
`);
assert.equal(
shouldBlockRequestWithRules(
rules,
"https://ads.example.com/banner.js",
"script",
"www.publisher.test"
),
true
);
assert.equal(
shouldBlockRequestWithRules(
rules,
"https://ads.example.com/banner.png",
"image",
"www.publisher.test"
),
false
);
assert.equal(
shouldBlockRequestWithRules(
rules,
"https://ads.example.com/allowed.js",
"script",
"www.publisher.test"
),
false
);
assert.equal(
shouldBlockRequestWithRules(
rules,
"https://disabled.example/ad.js",
"script",
"www.publisher.test"
),
false
);
});
test("applies cosmetic filters with domain exceptions and skips unsupported procedural selectors", () => {
const rules = parseFilterRules(`
##.generic-ad
example.com##.site-ad
example.com#@#.generic-ad
~news.example.com,example.com##.except-news
example.*##.entity-ad
bad.example##div:has-text(ad)
foo.com#$#.adguard { display: none !important; }
`);
const exampleCss = getCosmeticCssForHostname(rules, "www.example.com").join("\n");
assert.doesNotMatch(exampleCss, /\.generic-ad/);
assert.match(exampleCss, /\.site-ad/);
assert.match(exampleCss, /\.except-news/);
assert.match(exampleCss, /\.entity-ad/);
const newsCss = getCosmeticCssForHostname(rules, "news.example.com").join("\n");
assert.doesNotMatch(newsCss, /\.except-news/);
assert.equal(getCosmeticCssForHostname(rules, "bad.example").length, 1);
assert.match(getCosmeticCssForHostname(rules, "foo.com").join("\n"), /\.adguard/);
});
2026-05-16 16:36:51 -07:00
2026-05-16 22:32:30 -07:00
test("renderPage removes common cookie consent overlays before snapshot", async () => {
const html = `<!doctype html>
<html class="js sp-message-open" style="overflow: hidden;">
<body class="didomi-popup-open" style="overflow: hidden;">
<main>Article text</main>
<div id="sp_message_container_123" role="dialog" aria-modal="true">
<iframe id="sp_message_iframe_123" title="SP Consent Message" srcdoc="<p>Cookies on FT Sites</p>"></iframe>
</div>
</body>
</html>`;
const rendered = await renderPage(`data:text/html,${encodeURIComponent(html)}`, {
userscriptDelay: 0
});
assert.match(rendered, /Article text/);
assert.doesNotMatch(rendered, /sp_message_container_123/);
assert.doesNotMatch(rendered, /sp_message_iframe_123/);
assert.doesNotMatch(rendered, /<html[^>]*class="[^"]*sp-message-open/i);
assert.doesNotMatch(rendered, /<body[^>]*class="[^"]*didomi-popup-open/i);
});
2026-05-22 13:37:58 -07:00
test("renderPage removes Ketch consent banners before snapshot", async () => {
const html = `<!doctype html>
<html>
<body>
<main>Article text</main>
<div id="lanyard_root">
<div id="ketch-banner" style="position: fixed; bottom: 0; left: 0; right: 0; z-index: 2147483647;">
<div id="ketch-consent-banner" role="dialog" aria-label="privacy banner">
<p>We and our vendors use tracking technologies to recognize visitors.</p>
<button id="ketch-banner-button-tertiary" aria-label="Reject Non-Essential Cookies">
Reject Non-Essential Cookies
</button>
</div>
</div>
</div>
</body>
</html>`;
const rendered = await renderPage(`data:text/html,${encodeURIComponent(html)}`, {
userscriptDelay: 0
});
assert.match(rendered, /Article text/);
assert.doesNotMatch(rendered, /id="ketch-/);
assert.doesNotMatch(rendered, /Reject Non-Essential Cookies/);
assert.doesNotMatch(rendered, /tracking technologies/);
});
2026-05-16 22:45:23 -07:00
test("renderPage removes Admiral adblock walls before snapshot", async () => {
const html = `<!doctype html>
<html style="overflow: hidden;">
<body style="overflow: hidden;">
<main>Article text</main>
<div style="position: fixed; inset: 0; z-index: 2147483647; overflow: auto;">
<section>
<h2>Support The Verge by allowing ads</h2>
<p>Or <a href="https://www.theverge.com/subscribe?itm_campaign=admiraladblock&itm_source=popup">subscribe</a> to continue using your ad blocker uninterrupted.</p>
<button>ALLOW ADS</button>
<a href="https://%67e%74%61%64mi%72%61l.com/pb/">Powered By</a>
</section>
</div>
</body>
</html>`;
const rendered = await renderPage(`data:text/html,${encodeURIComponent(html)}`, {
userscriptDelay: 0
});
assert.match(rendered, /Article text/);
assert.doesNotMatch(rendered, /Support The Verge by allowing ads/);
assert.doesNotMatch(rendered, /ALLOW ADS/);
assert.doesNotMatch(rendered, /getadmiral|%67e%74%61%64mi%72%61l/i);
assert.doesNotMatch(rendered, /<html[^>]*style="[^"]*overflow:\s*hidden/i);
assert.doesNotMatch(rendered, /<body[^>]*style="[^"]*overflow:\s*hidden/i);
});
2026-05-16 16:36:51 -07:00
test("renderPage serializes CSSOM-inserted style rules", async () => {
const html = `<!doctype html>
<html>
<head>
<style id="runtime-style"></style>
<script>
document
.getElementById("runtime-style")
.sheet
.insertRule(".runtime-rule { color: rgb(1, 2, 3); }", 0);
</script>
</head>
<body><div class="runtime-rule">Styled by CSSOM</div></body>
</html>`;
const rendered = await renderPage(`data:text/html,${encodeURIComponent(html)}`, {
userscriptDelay: 0
});
assert.match(rendered, /<style id="runtime-style">[\s\S]*\.runtime-rule/);
assert.match(rendered, /color:\s*rgb\(1,\s*2,\s*3\)/);
});