diff --git a/request-blocklist/README.md b/request-blocklist/README.md new file mode 100644 index 0000000..a3081a1 --- /dev/null +++ b/request-blocklist/README.md @@ -0,0 +1,41 @@ +# Request Blocklist tests + +## Intro + +These are test cases for the Request Blocklist feature, that lets us block +requests where necessary, e.g. to fix website breakage. There are also test +cases included for how the Request Blocking feature interacts with other +features such as the Tracker Allowlist and the Tracker Blocklist. + + +## Files + +``` +. +├── config-reference.json # Reference configuration. +├── surrogates-reference.txt # Reference surrogates.txt +├── tds-reference.json # Reference Tracker Blocklist. +├── tests.json # The test cases. +└── user-allowlist-reference.json # Reference list of user-allowlisted domains. +``` + + +## Test structure + +```js +{ + // Test name + "name": "matching rule, domains", + + // Details of the test request + "requestUrl": "https://request-blocklist.example/block", + "requestType": "image", + "websiteUrl": "https://website.example", + + // Expected action (either "block" or "allow") + "expectAction": "block" + + // Platform exceptions for the test + "exceptPlatforms": [] +} +``` diff --git a/request-blocklist/config-reference.json b/request-blocklist/config-reference.json new file mode 100644 index 0000000..65d8264 --- /dev/null +++ b/request-blocklist/config-reference.json @@ -0,0 +1,151 @@ +{ + "version": 1, + "features": { + "contentBlocking": { + "state": "enabled", + "exceptions": [ + { + "domain": "content-blocking-exception.example", + "reason": "Example content blocking exception" + } + ] + }, + "requestBlocklist": { + "state": "enabled", + "settings": { + "blockedRequests": { + "request-blocklist.example": { + "rules": [ + { + "rule": "request-blocklist.example/block", + "domains": [""], + "reason": "Example all-domain blocking rule" + }, + { + "rule": "request-blocklist.example/*/block", + "domains": [""], + "reason": "Example all-domain wildcard blocking rule" + }, + { + "rule": "request-blocklist.example/sometimes-block", + "domains": ["sometimes.example", "subdomain.different.example"], + "reason": "Example domain-limited blocking rule" + }, + { + "rule": "request-blocklist.example/.*/regex", + "domains": [""], + "reason": "Example rule incorrectly using regex syntax" + }, + { + "rule": "request-blocklist.example/CASE", + "domains": [""], + "reason": "Example rule for case sensitive matching" + }, + { + "rule": "||request-blocklist.example^adblock-filter", + "domains": [""], + "reason": "Example rule incorrectly using adblock filter syntax" + }, + { + "rule": "request-blocklist.example/missing-prop", + "reason": "Example rule incorrectly missing domains property" + }, + { + "rule": "request-blocklist.example/extra-prop", + "domains": [""], + "unknown": "value", + "reason": "Example rule incorrectly including unknown property" + }, + { + "rule": "request-blocklist.example:3000/port-block", + "domains": [""], + "reason": "Example blocking rule with port part" + }, + { + "rule": "request-blocklist.example:443/incorrect-port-block", + "domains": [""], + "reason": "Example blocking rule that incorrectly includes redundant port" + }, + { + "rule": "request-blocklist.example/incorrect*query-part", + "domains": [""], + "reason": "Example blocking rule that incorrectly matches query string" + } + ] + }, + "subdomain.request-blocklist.example": { + "rules": [ + { + "rule": "subdomain.request-blocklist.example/subdomain", + "domains": [""], + "reason": "Example tracker entry and blocking rule for subdomain" + } + ] + }, + "request-blocklist-ordering.example": { + "rules": [ + { + "rule": "request-blocklist-ordering.example/block", + "domains": ["sometimes.example"], + "reason": "Example domain-specific blocking rule" + }, + { + "rule": "request-blocklist-ordering.example/block/path", + "domains": [""], + "reason": "Example blocking rule with extra path part" + }, + { + "rule": "request-blocklist-ordering.example/block", + "domains": [""], + "reason": "Example blocking rule that should still apply to all domains" + } + ] + }, + "tracker.example": { + "rules": [ + { + "rule": "tracker.example/*.js", + "domains": [""], + "reason": "Example blocking rule that applies to tracking requests" + }, + { + "rule": "tracker.example/block-first-party", + "domains": ["tracker.example"], + "reason": "Example blocking rule that applies to first-party requests" + } + ] + } + } + }, + "exceptions": [ + { + "domain": "request-blocking-exception.example", + "reason": "Example request-blocking exception" + } + ] + }, + "trackerAllowlist": { + "state": "enabled", + "settings": { + "allowlistedTrackers": { + "request-blocklist.example": { + "rules": [ + { + "rule": "request-blocklist.example/block", + "domains": ["allowlisted-website.example"], + "reason": "Example tracker allowlist entry" + } + ] + } + }, + "exceptions": [] + } + } + }, + "unprotectedTemporary": [ + { + "domain": "unprotected-temporary.example", + "reason": "Unprotected temporary example" + } + ] +} diff --git a/request-blocklist/surrogates-reference.txt b/request-blocklist/surrogates-reference.txt new file mode 100644 index 0000000..d28e493 --- /dev/null +++ b/request-blocklist/surrogates-reference.txt @@ -0,0 +1,4 @@ +tracker.example/noop.js application/javascript +(() => { + 'use strict'; +})(); diff --git a/request-blocklist/tds-reference.json b/request-blocklist/tds-reference.json new file mode 100644 index 0000000..4e60ad5 --- /dev/null +++ b/request-blocklist/tds-reference.json @@ -0,0 +1,42 @@ +{ + "trackers": { + "tracker.example": { + "domain": "tracker.example", + "owner": { + "name": "Example Entity", + "displayName": "Example Entity" + }, + "prevalence": 0, + "fingerprinting": 0, + "cookies": 0, + "categories": [], + "default": "ignore", + "rules": [ + { + "rule": "tracker.example/analytics.js", + "surrogate": "noop.js", + "fingerprinting": 0, + "cookies": 0 + }, + { + "rule": "tracker.example/block.js", + "fingerprinting": 0, + "cookies": 0 + } + ] + } + }, + "entities": { + "Example Entity": { + "domains": ["tracker.example"], + "prevalence": 0, + "displayName": "Example Entity" + } + }, + "domains": { + "tracker.example": "Example Entity" + }, + "cnames": { + "tracker.example": "tracker-example.cname.example" + } +} diff --git a/request-blocklist/tests.json b/request-blocklist/tests.json new file mode 100644 index 0000000..93f1f0e --- /dev/null +++ b/request-blocklist/tests.json @@ -0,0 +1,352 @@ +{ + "basic": { + "name": "Basic", + "desc": "Basic Request Blocklist functionality", + "tests": [ + { + "name": "matching rule, domains", + "requestUrl": "https://request-blocklist.example/block", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule (subdomain), domains", + "requestUrl": "https://subdomain.request-blocklist.example/block", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule (implicit wildcard), domains", + "requestUrl": "https://request-blocklist.example/block/ignored", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, matching domain", + "requestUrl": "https://request-blocklist.example/sometimes-block", + "requestType": "image", + "websiteUrl": "https://sometimes.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, matching subdomain", + "requestUrl": "https://request-blocklist.example/sometimes-block", + "requestType": "image", + "websiteUrl": "https://subdomain.sometimes.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, matching (non-eTLD+1) domain", + "requestUrl": "https://request-blocklist.example/sometimes-block", + "requestType": "image", + "websiteUrl": "https://subdomain.different.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, matching (non-eTLD+1) subdomain", + "requestUrl": "https://request-blocklist.example/sometimes-block", + "requestType": "image", + "websiteUrl": "https://another.subdomain.different.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, non-matching domain", + "requestUrl": "https://request-blocklist.example/sometimes-block", + "requestType": "image", + "websiteUrl": "https://other-website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "matching rule, non-matching domain", + "requestUrl": "https://request-blocklist.example/sometimes-block", + "requestType": "image", + "websiteUrl": "https://different.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "non-matching rule", + "requestUrl": "https://other-website.example/no-match", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "matching rule with wildcard, domains", + "requestUrl": "https://request-blocklist.example/path/block", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, port in URL", + "requestUrl": "https://request-blocklist.example:3000/port-block", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "non-matching rule due to port", + "requestUrl": "https://request-blocklist.example/port-block", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "matching rule, first-party request", + "requestUrl": "https://request-blocklist.example/block", + "requestType": "image", + "websiteUrl": "https://request-blocklist.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, query part of URL considered", + "requestUrl": "https://request-blocklist.example/incorrect?query-part", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, '.' literal considered", + "requestUrl": "https://request-blocklist.example/.path/regex", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, case considered", + "requestUrl": "https://request-blocklist.example/CASE", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "non-matching rule due to case", + "requestUrl": "https://request-blocklist.example/case", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "matching rule, URL case normalised", + "requestUrl": "HtTpS://ReQuEsT-BlOcKlIsT.ExAmPlE/CASE", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + } + ] + }, + "allowlisting": { + "name": "Allowlisting", + "desc": "Interactions between allowlisting and the Request Blocklist", + "tests": [ + { + "name": "matching rule, in tracker allowlist", + "requestUrl": "https://request-blocklist.example/block", + "requestType": "image", + "websiteUrl": "https://allowlisted-website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "matching rule, subdomain in tracker allowlist", + "requestUrl": "https://request-blocklist.example/block", + "requestType": "image", + "websiteUrl": "https://subdomain.allowlisted-website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "matching rule, content blocking disabled", + "requestUrl": "https://request-blocklist.example/block", + "requestType": "image", + "websiteUrl": "https://content-blocking-exception.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "matching rule, subdomain content blocking disabled", + "requestUrl": "https://request-blocklist.example/block", + "requestType": "image", + "websiteUrl": "https://subdomain.content-blocking-exception.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "matching rule, user allowlisted", + "requestUrl": "https://request-blocklist.example/block", + "requestType": "image", + "websiteUrl": "https://user-allowlisted.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "matching rule, subdomain exception", + "requestUrl": "https://request-blocklist.example/block", + "requestType": "image", + "websiteUrl": "https://subdomain.request-blocking-exception.example", + "expectAction": "allow", + "exceptPlatforms": [] + } + ] + }, + "trackers": { + "name": "Trackers", + "desc": "Interactions between Tracker Blocklist and the Request Blocklist", + "tests": [ + { + "name": "matching rule, tracker blocklist allow", + "requestUrl": "https://tracker.example/unknown.js", + "requestType": "script", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, tracker blocklist blocked", + "requestUrl": "https://tracker.example/block.js", + "requestType": "script", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, tracker blocklist surrogate", + "requestUrl": "https://tracker.example/analytics.js", + "requestType": "script", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, first-party request", + "requestUrl": "https://tracker.example/block-first-party", + "requestType": "image", + "websiteUrl": "https://tracker.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "matching rule, non-matching (cname alias) domain", + "requestUrl": "https://tracker.example/block-first-party", + "requestType": "image", + "websiteUrl": "https://tracker-example.cname.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "non-matching rule (cname alias), ", + "requestUrl": "https://tracker-example.cname.example/unknown.js", + "requestType": "script", + "websiteUrl": "https://website.example", + "expectAction": "allow", + "exceptPlatforms": [] + } + ] + }, + "incorrect": { + "name": "Incorrect", + "desc": "Incorrect rules that are not expected to match", + "tests": [ + { + "name": "incorrect rule using regexp syntax", + "requestUrl": "https://request-blocklist.example/path/regex", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "incorrect rule using adblock filter syntax", + "requestUrl": "https://request-blocklist.example/adblock-filter", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "incorrect rule that misses required property", + "requestUrl": "https://request-blocklist.example/missing-prop", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "incorrect rule that has extra property", + "requestUrl": "https://request-blocklist.example/extra-prop", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "rules don't match main_frame requests (aka navigations)", + "requestUrl": "https://request-blocklist.example/block", + "requestType": "main_frame", + "websiteUrl": "https://request-blocklist.example/block", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "incorrect rule that includes redundant port in URL", + "requestUrl": "https://request-blocklist.example/incorrect-port-block", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "allow", + "exceptPlatforms": [] + }, + { + "name": "incorrect entry under subdomain (instead of etld+1)", + "requestUrl": "https://subdomain.request-blocklist.example/subdomain", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "allow", + "exceptPlatforms": [] + } + ] + }, + "ordering": { + "name": "Ordering", + "desc": "Rules that should apply despite other rules that don't", + "tests": [ + { + "name": "two matching rules, first one applies to domain", + "requestUrl": "https://request-blocklist-ordering.example/block", + "requestType": "image", + "websiteUrl": "https://sometimes.example", + "expectAction": "block", + "exceptPlatforms": [] + }, + { + "name": "two matching rules, second one applies to domain", + "requestUrl": "https://request-blocklist-ordering.example/block", + "requestType": "image", + "websiteUrl": "https://website.example", + "expectAction": "block", + "exceptPlatforms": [] + } + ] + } +} diff --git a/request-blocklist/user-allowlist-reference.json b/request-blocklist/user-allowlist-reference.json new file mode 100644 index 0000000..d41d88f --- /dev/null +++ b/request-blocklist/user-allowlist-reference.json @@ -0,0 +1 @@ +["user-allowlisted.example"]