├── .editorconfig ├── .env.development ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── README.md ├── babel.config.js ├── bamboo-specs ├── bamboo.yaml ├── build.yaml └── increment.yaml ├── buildStaticData.js ├── functions ├── csp │ ├── [[path]].ts │ └── templates.ts ├── httpbin │ └── [[path]].ts └── userscripts-csp │ ├── [[path]].ts │ └── templates.ts ├── package.json ├── public ├── CNAME ├── Filters │ ├── badfilter-rules │ │ ├── README.md │ │ ├── test-badfilter-rules.html │ │ ├── test-badfilter-rules.js │ │ ├── test-badfilter-rules.txt │ │ └── test-files │ │ │ ├── adg1.png │ │ │ ├── adg2.png │ │ │ └── adg3.png │ ├── blocking-request-rules │ │ ├── README.md │ │ ├── test-blocking-request-rules.html │ │ ├── test-blocking-request-rules.js │ │ └── test-blocking-request-rules.txt │ ├── content-rules │ │ ├── README.md │ │ ├── content-modifier-test │ │ │ ├── content-modifier-test.html │ │ │ ├── content-modifier-test.js │ │ │ └── content-modifier-test.txt │ │ ├── test-content-rules.html │ │ ├── test-content-rules.js │ │ └── test-content-rules.txt │ ├── content-security-policy │ │ └── test-content-security-policy.txt │ ├── cookie-rules │ │ ├── README.md │ │ ├── test-cookie-rules.html │ │ ├── test-cookie-rules.js │ │ └── test-cookie-rules.txt │ ├── csp-rules │ │ ├── README.md │ │ ├── csp-global-exception │ │ │ ├── README.md │ │ │ ├── csp-global-exception.html │ │ │ ├── csp-global-exception.js │ │ │ └── csp-global-exception.txt │ │ ├── test-csp-rules.html │ │ ├── test-csp-rules.js │ │ └── test-csp-rules.txt │ ├── css-rules │ │ ├── README.md │ │ ├── css-rules.html │ │ ├── css-rules.js │ │ └── css-rules.txt │ ├── denyallow-rules │ │ ├── README.md │ │ ├── assets │ │ │ ├── adguard_circle.png │ │ │ └── adguard_dns_map.png │ │ ├── test-denyallow-rules.html │ │ ├── test-denyallow-rules.js │ │ └── test-denyallow-rules.txt │ ├── element-hiding-rules │ │ ├── README.md │ │ ├── subdocument-test-files │ │ │ ├── iframe-test-1.html │ │ │ ├── iframe-test-2.html │ │ │ └── iframe-test-3.html │ │ ├── test-element-hiding-rules.html │ │ ├── test-element-hiding-rules.js │ │ ├── test-element-hiding-rules.txt │ │ └── tld-test-files │ │ │ ├── adguard.png │ │ │ └── test-script.js │ ├── extended-css-rules │ │ ├── README.md │ │ ├── extended-css-iframejs-injection │ │ │ ├── README.md │ │ │ ├── extended-css-iframejs-injection.html │ │ │ ├── extended-css-iframejs-injection.js │ │ │ └── extended-css-iframejs-injection.txt │ │ ├── test-extended-css-rules.html │ │ ├── test-extended-css-rules.js │ │ ├── test-extended-css-rules.txt │ │ └── test-files │ │ │ └── frame1.html │ ├── generichide-rules │ │ ├── README.md │ │ ├── generichide-rules.html │ │ ├── generichide-rules.js │ │ └── generichide-rules.txt │ ├── header-rules │ │ ├── README.md │ │ ├── expect-global-error.js │ │ ├── test-header-rules.html │ │ ├── test-header-rules.js │ │ └── test-header-rules.txt │ ├── helpers.js │ ├── hls-rules │ │ ├── README.md │ │ ├── test-files │ │ │ ├── hls-test-1.m3u │ │ │ └── hls-test-2.m3u │ │ ├── test-hls-rules.html │ │ ├── test-hls-rules.js │ │ └── test-hls-rules.txt │ ├── important-rules │ │ ├── README.md │ │ ├── important-vs-urlblock │ │ │ ├── README.md │ │ │ ├── test-important-vs-urlblock.html │ │ │ ├── test-important-vs-urlblock.js │ │ │ └── test-important-vs-urlblock.txt │ │ ├── test-files │ │ │ ├── adg1.png │ │ │ ├── adg2.png │ │ │ └── adg3.png │ │ ├── test-important-rules.html │ │ ├── test-important-rules.js │ │ └── test-important-rules.txt │ ├── injection-speed │ │ ├── index.html │ │ ├── service-worker │ │ │ ├── index.html │ │ │ ├── no-bypass-network.jpg │ │ │ └── service-worker.js │ │ ├── simple-csp │ │ │ ├── index.html │ │ │ ├── simple-with-csp--firefox-error.png │ │ │ └── simple-with-csp--ok.png │ │ ├── simple-extended │ │ │ ├── index.html │ │ │ └── screenshot.png │ │ ├── simple │ │ │ ├── index.html │ │ │ └── screenshot.png │ │ ├── styles.css │ │ └── test-injection-speed.txt │ ├── jsonprune-rules │ │ ├── README.md │ │ ├── test-files │ │ │ ├── test-case-1.json │ │ │ ├── test-case-2.json │ │ │ ├── test-case-3.json │ │ │ ├── test-case-4.json │ │ │ └── test-case-5.json │ │ ├── test-jsonprune-rules.html │ │ ├── test-jsonprune-rules.js │ │ └── test-jsonprune-rules.txt │ ├── match-case-rules │ │ ├── README.md │ │ ├── test-match-case-rules.html │ │ ├── test-match-case-rules.js │ │ └── test-match-case-rules.txt │ ├── method-rules │ │ ├── README.md │ │ ├── test-method-rules.html │ │ ├── test-method-rules.js │ │ └── test-method-rules.txt │ ├── network-rules │ │ ├── README.md │ │ ├── test-network-rules.html │ │ ├── test-network-rules.js │ │ └── test-network-rules.txt │ ├── nonbasic-path-modifier │ │ ├── README.md │ │ ├── test-files │ │ │ └── subpage1.html │ │ ├── test-nonbasic-path-modifier.html │ │ ├── test-nonbasic-path-modifier.js │ │ └── test-nonbasic-path-modifier.txt │ ├── permissions-rules-mv3 │ │ ├── README.md │ │ ├── subpage.html │ │ ├── test-permissions-rules-mv3.css │ │ ├── test-permissions-rules-mv3.html │ │ ├── test-permissions-rules-mv3.js │ │ └── test-permissions-rules-mv3.txt │ ├── permissions-rules │ │ ├── README.md │ │ ├── subpage.html │ │ ├── test-permissions-rules.css │ │ ├── test-permissions-rules.html │ │ ├── test-permissions-rules.js │ │ └── test-permissions-rules.txt │ ├── qunit │ │ ├── custom.css │ │ ├── qunit.css │ │ ├── qunit.js │ │ └── readme_for_update.md │ ├── redirect-rules │ │ ├── README.md │ │ ├── test-files │ │ │ ├── csp-redirect-iframe.html │ │ │ ├── csp-redirect.js │ │ │ ├── redirect-exception-test.js │ │ │ ├── redirect-priority-test.js │ │ │ ├── redirect-test.css │ │ │ ├── redirect-test.html │ │ │ ├── redirect-test.js │ │ │ ├── redirect-test.png │ │ │ └── redirect-test.txt │ │ ├── test-redirect-rules.html │ │ ├── test-redirect-rules.js │ │ └── test-redirect-rules.txt │ ├── redirect-security │ │ ├── README.md │ │ ├── test-redirect-security.html │ │ ├── test-redirect-security.js │ │ └── test-redirect-security.txt │ ├── removeheader-rules │ │ ├── README.md │ │ ├── test-removeheader-rules.html │ │ ├── test-removeheader-rules.js │ │ └── test-removeheader-rules.txt │ ├── removeparam-rules │ │ ├── README.md │ │ ├── test-files │ │ │ └── adg1.png │ │ ├── test-removeparam-rules.html │ │ ├── test-removeparam-rules.js │ │ └── test-removeparam-rules.txt │ ├── replace-rules │ │ ├── README.md │ │ ├── replace-vs-content-rule │ │ │ ├── README.md │ │ │ ├── replace-vs-content-rule.html │ │ │ ├── replace-vs-content-rule.js │ │ │ └── replace-vs-content-rule.txt │ │ ├── replace-vs-elemhide-rule │ │ │ ├── README.md │ │ │ ├── replace-vs-elemhide-rule.html │ │ │ ├── replace-vs-elemhide-rule.js │ │ │ └── replace-vs-elemhide-rule.txt │ │ ├── replace-vs-generichide-rule │ │ │ ├── README.md │ │ │ ├── replace-vs-generichide-rule.html │ │ │ ├── replace-vs-generichide-rule.js │ │ │ └── replace-vs-generichide-rule.txt │ │ ├── test-files │ │ │ ├── case1-text-response.txt │ │ │ ├── case2-response-over-3mb.txt │ │ │ ├── case3-using-with-other-rules.txt │ │ │ ├── case4-multiple-replace-rules.txt │ │ │ ├── case5-disabling-replace-rule.txt │ │ │ ├── case6-disabling-multiple-replace-rules.txt │ │ │ └── case7-content-type-modifier.js │ │ ├── test-replace-rules.html │ │ ├── test-replace-rules.js │ │ └── test-replace-rules.txt │ ├── script-rules │ │ ├── README.md │ │ ├── jsinject-rules │ │ │ ├── README.md │ │ │ ├── test-jsinject-rules.html │ │ │ ├── test-jsinject-rules.js │ │ │ └── test-jsinject-rules.txt │ │ ├── test-script-firefox │ │ │ ├── test-script-firefox.html │ │ │ ├── test-script-firefox.js │ │ │ └── test-script-firefox.txt │ │ ├── test-script-rules.html │ │ ├── test-script-rules.js │ │ └── test-script-rules.txt │ ├── scriptlet-rules │ │ ├── README.md │ │ ├── allowlist-general │ │ │ ├── test-scriptlet-allowlist-general-rules.html │ │ │ ├── test-scriptlet-allowlist-general-rules.js │ │ │ └── test-scriptlet-allowlist-general-rules.txt │ │ ├── allowlist-specific │ │ │ ├── test-scriptlet-allowlist-specific-rules.html │ │ │ ├── test-scriptlet-allowlist-specific-rules.js │ │ │ └── test-scriptlet-allowlist-specific-rules.txt │ │ ├── test-scriptlet-rules.html │ │ ├── test-scriptlet-rules.js │ │ └── test-scriptlet-rules.txt │ ├── specifichide-rules │ │ ├── README.md │ │ ├── test-specifichide-rules.html │ │ ├── test-specifichide-rules.js │ │ └── test-specifichide-rules.txt │ ├── strict-party-rules │ │ ├── README.md │ │ ├── test-strict-party-rules.html │ │ ├── test-strict-party-rules.js │ │ └── test-strict-party-rules.txt │ ├── subdocument-rules │ │ ├── README.md │ │ ├── test-files │ │ │ ├── subdocument-test-1.png │ │ │ ├── subdocument-test-2.png │ │ │ ├── subdocument-test-3.png │ │ │ └── subdocument-test.html │ │ ├── test-subdocument-rules.html │ │ ├── test-subdocument-rules.js │ │ └── test-subdocument-rules.txt │ ├── to-rules │ │ ├── README.md │ │ ├── assets │ │ │ ├── adguard_circle.png │ │ │ └── adguard_dns_map.png │ │ ├── test-to-rules.html │ │ ├── test-to-rules.js │ │ └── test-to-rules.txt │ ├── urltransform-rules │ │ ├── README.md │ │ ├── test-urltransform-rules.html │ │ ├── test-urltransform-rules.js │ │ └── test-urltransform-rules.txt │ └── websockets │ │ ├── test-websockets.html │ │ ├── test-websockets.js │ │ └── test-websockets.txt ├── PopupBlocker │ ├── README.md │ ├── false-positive-installers.js │ ├── popup-installers.js │ ├── popup-opener-iframe.html │ ├── test-event-recovery-child.html │ ├── test-event-recovery.html │ ├── test-popup-blocker-rules.txt │ ├── test-popup-blocker.html │ ├── third-party │ │ └── jquery-3.3.1.min.js │ └── utils.js ├── Userscripts │ ├── GMapiV4Tester │ │ ├── 1x1.png │ │ ├── GMapi_v4-tester.user.js │ │ ├── jquery-2.1.1.min.js │ │ └── resource.js │ ├── TestGrantNone │ │ └── testscript.user.js │ ├── apiTester │ │ ├── 1x1.png │ │ ├── api-tester.user.js │ │ ├── jquery-2.1.1.min.js │ │ └── resource.js │ ├── cspTester │ │ └── csp-tester.user.js │ ├── gmapi-v4-tests.html │ ├── gmapi-v4-tests.js │ ├── qunit │ │ ├── custom.css │ │ ├── qunit.css │ │ └── qunit.js │ ├── test-userscripts.html │ └── test-userscripts.js ├── Web │ ├── etag.html │ └── load.html ├── favicon.png ├── index.html └── robots.txt ├── src ├── App.js ├── App.test.js ├── components │ ├── Compatibility.js │ ├── CopyLinkBtn.js │ ├── CopyRulesBtn.js │ ├── Footer.js │ ├── Header.js │ ├── Mission.js │ ├── ReadmeBtn.js │ ├── ShowReadme.js │ ├── StartTestBtn.js │ ├── SubscribeFilterBtn.js │ ├── TestItem.js │ └── TestList.js ├── constants.js ├── fonts │ ├── bold.woff │ └── regular.woff ├── helpers │ ├── copy-to-clipboard.js │ ├── get-file.js │ ├── index.js │ ├── object-utils.js │ └── parse-compatibility.js ├── img │ ├── arrow-down.png │ ├── close.png │ ├── comp-full.png │ ├── comp-partial.png │ ├── copy.png │ ├── incomp.png │ ├── link.png │ ├── list.png │ ├── logo.png │ ├── readme.png │ ├── search.png │ └── start.png ├── index.js ├── serviceWorker.js ├── setupProxy.js ├── styles │ ├── index.css │ └── styles.scss └── testsData.js ├── tsconfig.eslint.json ├── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | HOST=local.testcases.agrd.dev 2 | PORT=4000 3 | HTTPS=true 4 | SSL_KEY_FILE=cert/key.pem 5 | SSL_CRT_FILE=cert/cert.pem 6 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | public/Userscripts/ 4 | public/Filters/replace-rules/test-files/ 5 | qunit.js 6 | jquery*.js 7 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | 4 | parserOptions: { 5 | project: './tsconfig.eslint.json', 6 | tsconfigRootDir: __dirname, 7 | }, 8 | 9 | extends: [ 10 | 'airbnb', 11 | 'airbnb-typescript', 12 | ], 13 | 14 | env: { 15 | browser: true, 16 | node: true, 17 | jest: true, 18 | }, 19 | 20 | rules: { 21 | '@typescript-eslint/indent': ['error', 4], 22 | 'max-len': ['error', { 23 | code: 120, 24 | comments: 120, 25 | tabWidth: 4, 26 | ignoreUrls: false, 27 | ignoreTrailingComments: false, 28 | ignoreComments: false, 29 | }], 30 | 'no-shadow': 'off', 31 | 'import/prefer-default-export': 'off', 32 | 'import/extensions': 'off', 33 | 'arrow-body-style': 'off', 34 | 'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }], 35 | 'import/no-extraneous-dependencies': 0, 36 | indent: 0, 37 | 'react/jsx-indent': ['error', 4], 38 | 'react/jsx-indent-props': ['error', 4], 39 | 'no-underscore-dangle': 'off', 40 | 'react/destructuring-assignment': [ 41 | 'error', 42 | 'always', 43 | { 44 | ignoreClassFields: true, 45 | }, 46 | ], 47 | 'class-methods-use-this': 'off', 48 | }, 49 | }; 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # development 12 | cert 13 | 14 | # production 15 | /build 16 | 17 | /public/data.json 18 | 19 | # misc 20 | .DS_Store 21 | .env.local 22 | .env.development.local 23 | .env.test.local 24 | .env.production.local 25 | 26 | npm-debug.log* 27 | yarn-debug.log* 28 | yarn-error.log* 29 | 30 | .idea 31 | .vscode 32 | 33 | .eslintcache 34 | .wrangler 35 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = (api) => { 2 | api.cache(false); 3 | return { 4 | presets: [ 5 | [ 6 | 'react-app', 7 | { 8 | absoluteRuntime: false, 9 | }, 10 | ], 11 | ], 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /bamboo-specs/bamboo.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | !include 'build.yaml' 3 | 4 | --- 5 | !include 'increment.yaml' 6 | -------------------------------------------------------------------------------- /bamboo-specs/increment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | plan: 4 | project-key: QA 5 | key: FILTERSTESTINCR 6 | name: filters test - increment 7 | variables: 8 | dockerContainer: adguard/node-ssh:21.7--1 9 | 10 | stages: 11 | - Increment: 12 | manual: false 13 | final: false 14 | jobs: 15 | - Increment 16 | 17 | Increment: 18 | key: INCR 19 | docker: 20 | image: "${bamboo.dockerContainer}" 21 | volumes: 22 | ${system.YARN_DIR}: "${bamboo.cacheYarn}" 23 | other: 24 | clean-working-dir: true 25 | tasks: 26 | - checkout: 27 | force-clean-build: true 28 | - script: 29 | interpreter: SHELL 30 | scripts: 31 | - |- 32 | set -e 33 | set -x 34 | 35 | # Fix mixed logs 36 | exec 2>&1 37 | 38 | yarn increment 39 | - any-task: 40 | plugin-key: com.atlassian.bamboo.plugins.vcs:task.vcs.commit 41 | configuration: 42 | commitMessage: 'skipci: Automatic increment build number' 43 | selectedRepository: defaultRepository 44 | requirements: 45 | - adg-docker: true 46 | 47 | branches: 48 | create: manually 49 | delete: never 50 | link-to-jira: true 51 | 52 | labels: [] 53 | other: 54 | concurrent-build-plugin: system-default 55 | -------------------------------------------------------------------------------- /buildStaticData.js: -------------------------------------------------------------------------------- 1 | import { writeFileSync } from 'fs'; 2 | import { parseCompatibility } from './src/helpers'; 3 | import testsData from './src/testsData'; 4 | 5 | const publicData = testsData 6 | .map((testData) => { 7 | const publicTestData = { 8 | ...testData, 9 | }; 10 | 11 | const { compatibility, exceptions } = parseCompatibility(testData.compatibility).publicData; 12 | 13 | publicTestData.compatibility = compatibility; 14 | 15 | if (exceptions.length > 0) { 16 | publicTestData.exceptions = exceptions; 17 | } 18 | 19 | return publicTestData; 20 | }); 21 | 22 | writeFileSync('./public/data.json', JSON.stringify(publicData, null, 2)); 23 | -------------------------------------------------------------------------------- /functions/httpbin/[[path]].ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Proxies requests from `/httpbin` relative path to httpbin worker, including nested paths. 3 | * @see https://httpbin.agrd.dev 4 | * 5 | * @param context Request event context 6 | * @returns External source response. 7 | */ 8 | export async function onRequest({ request }: EventContext): Promise { 9 | const { pathname, search } = new URL(request.url); 10 | 11 | const url = `https://httpbin.agrd.dev${pathname.replace('/httpbin', '')}${search}`; 12 | 13 | return fetch(url, { 14 | method: request.method, 15 | headers: request.headers, 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /public/CNAME: -------------------------------------------------------------------------------- 1 | testcases.agrd.dev 2 | -------------------------------------------------------------------------------- /public/Filters/badfilter-rules/README.md: -------------------------------------------------------------------------------- 1 | # $badfilter rules test 2 | 3 | ## Case 1 4 | * First rule blocks request for `dg1.png`. 5 | * Applied second rule with `$badfilter` modifier. 6 | #### Expecting result: $badfilter rule should disable the rule to which it refers (`adg1.png` is displayed) 7 | 8 | ## Case 2 9 | * First rule blocks request for `dg2.png`. 10 | * Second rule is exception to disable the first rule. 11 | * Applied exception rule with `$badfilter` modifier. 12 | #### Expecting result: $badfilter exception rule should disable the exception rule to which it refers (`adg2.png` is hidden) 13 | 14 | ## Case 3 15 | * First rule with `$domain` modifier blocks request for `dg3.png`. 16 | * Applied rule with `$badfilter` and `$domain` modifier matching the same pattern. 17 | #### Expecting result: $badfilter rule should disable the rule with $domain modifier to which it refers. (`adg3.png` is displayed) 18 | -------------------------------------------------------------------------------- /public/Filters/badfilter-rules/test-badfilter-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $badfilter rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 |
22 | 23 |
24 | 25 |
26 | 27 |
28 | 29 |
30 | 31 |
32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/Filters/badfilter-rules/test-badfilter-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-badfilter-rules.txt to AdGuard 7 | */ 8 | window.addEventListener('DOMContentLoaded', () => { 9 | const adgCheck = isSubscribed('subscribe-to-test-badfilter-rules-filter'); 10 | 11 | agTest(1, '$badfilter rule test', (assert) => { 12 | const imageDisplayed = getComputedStyle(document.querySelector('#case1 > img')).display !== 'none'; 13 | assert.ok( 14 | adgCheck && imageDisplayed, 15 | '$badfilter rule should disable the rule to which it refers.', 16 | ); 17 | }); 18 | 19 | agTest(2, '$badfilter exception rule test', (assert) => { 20 | const testImg = document.querySelector('#case2 > img'); 21 | const isBlocked = !testImg 22 | || (getComputedStyle(testImg).display === 'none') 23 | || (getComputedStyle(testImg).height === '0px'); 24 | assert.ok( 25 | adgCheck && isBlocked, 26 | '$badfilter exception rule should disable the exception rule to which it refers.', 27 | ); 28 | }); 29 | 30 | agTest(3, '$badfilter rule test with $domain modifier', (assert) => { 31 | const imageDisplayed = getComputedStyle(document.querySelector('#case3 > img')).display !== 'none'; 32 | assert.ok( 33 | adgCheck && imageDisplayed, 34 | '$badfilter rule should disable the rule with $domain modifier to which it refers.', 35 | ); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /public/Filters/badfilter-rules/test-badfilter-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $badfilter rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-badfilter-rules-filter 9 | ! 10 | ! Case 1 11 | ||*/test-files/adg1.png 12 | ||*/test-files/adg1.png$badfilter 13 | ! Case 2 14 | ||*/test-files/adg2.png 15 | @@||*/test-files/adg2.png 16 | @@||*/test-files/adg2.png$badfilter 17 | ! Case 3 18 | ||*/test-files/adg3.png$domain=testcases.agrd.dev|pages.dev 19 | ||*/test-files/adg3.png$domain=testcases.agrd.dev|pages.dev,badfilter 20 | -------------------------------------------------------------------------------- /public/Filters/badfilter-rules/test-files/adg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/badfilter-rules/test-files/adg1.png -------------------------------------------------------------------------------- /public/Filters/badfilter-rules/test-files/adg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/badfilter-rules/test-files/adg2.png -------------------------------------------------------------------------------- /public/Filters/badfilter-rules/test-files/adg3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/badfilter-rules/test-files/adg3.png -------------------------------------------------------------------------------- /public/Filters/blocking-request-rules/README.md: -------------------------------------------------------------------------------- 1 | # $ping, $xmlhttprequest, $websocket rules test 2 | 3 | ### Case 1: Test $ping modifier 4 | Rule with `$ping` modifier should block `navigator.sendBeacon()` request. 5 | #### WARNING! 6 | Test is not fully automatic. To be 100% sure you have to check in DevTools console the request to `https://adguard.com` is blocked by the client. 7 | 8 | ### Case 2: Test $xmlhttprequest modifier 9 | Rule with `$xmlhttprequest` modifier should block xmlhttprequest request. 10 | #### Please note 11 | Corelibs often can't accurately detect this type of request and sometimes detects it as `other` or `script`. 12 | Will be fixed soon [GitHub #1469](https://github.com/AdguardTeam/CoreLibs/issues/1469) 13 | 14 | ### Case 3: Test $websocket modifier 15 | Rule with `$websocket` modifier should block websocket request. 16 | -------------------------------------------------------------------------------- /public/Filters/blocking-request-rules/test-blocking-request-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Ping, websocket, xmlhttprequest rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/Filters/blocking-request-rules/test-blocking-request-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-blocking-request-rules.txt to AdGuard 7 | */ 8 | 9 | window.addEventListener('load', () => { 10 | const adgCheck = isSubscribed('subscribe-to-test-blocking-request-rules-filter'); 11 | 12 | agTest(1, '$ping modifier', (assert) => { 13 | assert.ok( 14 | adgCheck && navigator.sendBeacon('https://adguard.com', 'Testdata'), 15 | 'Rule with $ping modifier blocks navigator.sendBeacon request, check the devtools console', 16 | ); 17 | }); 18 | 19 | agTest(2, '$xmlhttprequest modifier', async (assert) => { 20 | await assert.rejects( 21 | fetch('https://adguard-vpn.com', { mode: 'no-cors' }), 22 | 'Rule with $xmlhttprequest modifier should block xmlhttprequest request', 23 | ); 24 | }); 25 | 26 | agTest(3, '$websocket modifier', (assert) => { 27 | const done = assert.async(); 28 | 29 | const websocket = new WebSocket('wss://echo.websocket.org'); 30 | websocket.onopen = () => websocket.send('Test message'); 31 | websocket.onerror = () => { 32 | assert.ok(true, 'Rule with $websocket modifier blocks websocket request'); 33 | done(); 34 | }; 35 | assert.timeout(3000); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /public/Filters/blocking-request-rules/test-blocking-request-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for blocking-request (ping, websocket, xmlhttprequest) tests 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-blocking-request-rules-filter 9 | ! Test case 1: $ping modifier 10 | ||adguard.com/*^$ping 11 | ! Test case 2: $xmlhttprequest modifier 12 | ||adguard-vpn.com^$xmlhttprequest,domain=testcases.agrd.dev|pages.dev 13 | ! Test case 3: $websocket modifier 14 | $websocket,domain=testcases.agrd.dev|pages.dev 15 | -------------------------------------------------------------------------------- /public/Filters/content-rules/README.md: -------------------------------------------------------------------------------- 1 | Case 6 is supported by **CoreLibs v1.18** 2 | -------------------------------------------------------------------------------- /public/Filters/content-rules/content-modifier-test/content-modifier-test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $content modifier test 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 |
21 |
22 | case2 link 23 |
Lorem ipsum dolor sit amet
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /public/Filters/content-rules/content-modifier-test/content-modifier-test.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import content-modifier-test.txt to AdGuard 7 | */ 8 | window.addEventListener('load', () => { 9 | const adgCheck = isSubscribed('subscribe-to-test-content-modifier-filter'); 10 | 11 | agTest(1, "$content modifier with 'div' element", (assert) => { 12 | assert.ok( 13 | adgCheck && document.querySelector('#case1'), 14 | 'exception rule with $content modifier should disable all content rules', 15 | ); 16 | }); 17 | 18 | agTest(2, "$content modifier with 'a' element and 'tag-content' attribute", (assert) => { 19 | assert.ok( 20 | adgCheck && document.querySelector('#case2'), 21 | 'exception rule with $content modifier should disable all content rules', 22 | ); 23 | }); 24 | 25 | agTest(3, "$content modifier with 'div' element and 'wildcard' attribute", (assert) => { 26 | assert.ok( 27 | adgCheck && document.querySelector('#case3'), 28 | 'exception rule with $content modifier should disable all content rules', 29 | ); 30 | }); 31 | 32 | agTest(4, "$content modifier with 'class' element", (assert) => { 33 | assert.ok( 34 | adgCheck && document.querySelector('#case4'), 35 | 'exception rule with $content modifier should disable all content rules', 36 | ); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /public/Filters/content-rules/content-modifier-test/content-modifier-test.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $content modifier test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev###subscribe-to-test-content-modifier-filter 9 | ! 10 | ! Case 1 11 | testcases.agrd.dev$$div[id="case1"] 12 | ! 13 | ! Case 2 14 | testcases.agrd.dev$$a[tag-content="case2 link"] 15 | ! 16 | ! Case 3 17 | testcases.agrd.dev$$div[id="case3"][wildcard="*ipsum*sit*"] 18 | ! 19 | ! Case 4 20 | testcases.agrd.dev$$div[class="class4"] 21 | ! 22 | ! Exception rule with $content modifier for all cases 23 | @@||testcases.agrd.dev^$content 24 | -------------------------------------------------------------------------------- /public/Filters/content-rules/test-content-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Content rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 |
23 | 29 | 30 | 34 | 35 | 40 | 41 | 45 | 46 | 51 | 52 | 56 | 57 | 61 |
62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /public/Filters/content-rules/test-content-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-content-rules.txt to AdGuard 7 | */ 8 | window.addEventListener('load', () => { 9 | const adgCheck = isSubscribed('subscribe-to-test-content-rules-filter'); 10 | 11 | agTest(1, 'just id', (assert) => { 12 | assert.notOk(document.querySelector('#case1')); 13 | }); 14 | 15 | agTest(2, 'id and tag-content', (assert) => { 16 | assert.notOk(document.querySelector('#case2')); 17 | }); 18 | 19 | agTest(3, 'class', (assert) => { 20 | assert.notOk(document.querySelector('#case3')); 21 | }); 22 | 23 | agTest(4, 'wildcard', (assert) => { 24 | assert.notOk(document.querySelector('#case4')); 25 | }); 26 | 27 | agTest(5, 'exceptions', (assert) => { 28 | assert.ok(adgCheck && document.querySelector('#case5')); 29 | }); 30 | 31 | agTest(6, 'attribute without value', (assert) => { 32 | assert.notOk(document.querySelector('#case6')); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /public/Filters/content-rules/test-content-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for content rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-content-rules-filter 9 | ! 10 | testcases.agrd.dev,pages.dev$$div[id="case1"] 11 | testcases.agrd.dev,pages.dev$$div[id="case2"][tag-content="test-case-2-content"] 12 | testcases.agrd.dev,pages.dev$$div[class="test-case-3-class"] 13 | testcases.agrd.dev,pages.dev$$div[id="case4"][wildcard="*teasernet*tararar*"] 14 | testcases.agrd.dev,pages.dev$$div[id="case5"] 15 | testcases.agrd.dev,pages.dev$@$div[id="case5"] 16 | testcases.agrd.dev,pages.dev$$div[custom_attr] 17 | -------------------------------------------------------------------------------- /public/Filters/content-security-policy/test-content-security-policy.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for content security policy test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-content-rules-filter 9 | ! 10 | testcases.agrd.dev,pages.dev#%#//scriptlet('log', 'scriptlet rule is executed') 11 | ! TODO add scriptlets which use eval inside themselves 12 | testcases.agrd.dev,pages.dev#%#//console.log('script rules is executed') 13 | -------------------------------------------------------------------------------- /public/Filters/cookie-rules/README.md: -------------------------------------------------------------------------------- 1 | # $ping, $xmlhttprequest, $websocket rules test 2 | 3 | ### Case 1: $cookie rule blocks request cookie 4 | 5 | Cookie `case1` should be set on `api/cookie/case1` request. 6 | Cookie `case1` should be blocked by rule on `api/whoami` request. 7 | 8 | ### Case 2: $cookie rule blocks response cookie 9 | 10 | Cookie `case2` should be blocked by rule on request to `api/cookie/case2`. 11 | 12 | ### Case 3: $cookie allowlist rule bypass request cookie 13 | 14 | Cookie `case3` should be set on `api/cookie/case3` request. 15 | Cookie `case3` should be sent to `api/whoami` endpoint. 16 | 17 | ### Case 4: $cookie allowlist rule bypass response cookie 18 | 19 | Cookie `case4` should be set on `api/cookie/case4` request. 20 | Cookie `case4` should be sent to `api/whoami` endpoint. 21 | 22 | -------------------------------------------------------------------------------- /public/Filters/cookie-rules/test-cookie-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Cookie rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/Filters/cookie-rules/test-cookie-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-cookie-rules.txt to AdGuard 7 | */ 8 | 9 | const baseUrl = window.location.origin; 10 | 11 | const setCookie = async (name, value = '1') => { 12 | return fetch(`${baseUrl}/httpbin/cookies/set?${name}=${value}`); 13 | }; 14 | 15 | const deleteCookie = async (name) => { 16 | return fetch(`${baseUrl}/httpbin/cookies/delete?${name}`); 17 | }; 18 | 19 | const hasCookie = async (name) => { 20 | const result = await fetch(`${baseUrl}/httpbin/cookies`); 21 | const cookies = await result.json(); 22 | return !!cookies[name]; 23 | }; 24 | 25 | window.addEventListener('load', () => { 26 | agTest(1, '$cookie rule blocks request cookie', async (assert) => { 27 | await setCookie('case1'); 28 | assert.notOk(await hasCookie('case1'), '$cookie rule blocks request cookie'); 29 | await deleteCookie('case1'); 30 | }); 31 | 32 | agTest(2, '$cookie rule blocks response cookie', async (assert) => { 33 | await setCookie('case2'); 34 | assert.notOk(await hasCookie('case2'), '$cookie rule blocks response cookie'); 35 | await deleteCookie('case2'); 36 | }); 37 | 38 | agTest(3, '$cookie allowlist rule bypass request cookie', async (assert) => { 39 | await setCookie('case3'); 40 | assert.ok(await hasCookie('case3'), '$cookie allowlist rule bypass request cookie'); 41 | await deleteCookie('case3'); 42 | }); 43 | 44 | agTest(4, '$cookie allowlist rule bypass response cookie', async (assert) => { 45 | await setCookie('case4'); 46 | assert.ok(await hasCookie('case4'), '$cookie allowlist rule bypass response cookie'); 47 | await deleteCookie('case4'); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /public/Filters/cookie-rules/test-cookie-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $cookie tests 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-cookie-rules-filter 9 | ! 10 | ! Test case 1: $cookie rule blocks request cookie 11 | ||*/httpbin/cookies^$cookie=case1 12 | ! Test case 2: $cookie rule blocks response cookie 13 | ||*/httpbin/cookies/set?case2$cookie=case2 14 | ! Test case 3: $cookie allowlist rule bypass request cookie 15 | ||*/httpbin/cookies^$cookie=case3 16 | @@||*/httpbin/cookies^$cookie=case3 17 | ! Test case 4: $cookie allowlist rule bypass response cookie 18 | ||*/httpbin/cookies/set?case4$cookie=case4 19 | @@||*/httpbin/cookies/set?case4$cookie=case4 20 | -------------------------------------------------------------------------------- /public/Filters/csp-rules/README.md: -------------------------------------------------------------------------------- 1 | # $csp rules test 2 | 3 | ## Case 1 4 | * The inline script creates element `id="csp-test"` with the following text `Inline script works`. 5 | * $csp rule allows scripts only from original source (`$csp=script-src 'self'`). 6 | * basic rule hides element `id="some-element"`. 7 | #### Expecting result: inline script rejected, basic rule works (there is no element `id="csp-test"`; element `id="some-element"` is hidden) 8 | 9 | ## Case 2 10 | * Requesting to `/api/csp-rules/test-1` and `/api/csp-rules/test-2` via `fetch` and frame `src` attribute 11 | * first $csp rule allows requests via js api (fetch) only for `/api/csp-rules/test-1` 12 | * second $csp rule allows requests via frame src only for `/api/csp-rules/test-1` 13 | #### Expecting result: all $csp rules work together (only requests for /api/csp-rules/test-1 has sent) 14 | 15 | ## Case 3 16 | * inline style hides `id="case3"`. 17 | * $csp rule allows styles only from original source (`$csp=script-src 'self'`). 18 | * $csp exception rule disables previous $csp rule. 19 | #### Expecting result: $csp exception rule disables $csp rule with matching pattern (element `id="case3"` is hidden) 20 | -------------------------------------------------------------------------------- /public/Filters/csp-rules/csp-global-exception/README.md: -------------------------------------------------------------------------------- 1 | # Test case: $CSP global exception (no arguments). 2 | * The inline script creates element `id="csp-global-exception"` with the following text `Inline script works`. 3 | * $csp rule allows scripts only from original source (`$csp=script-src 'self'`). 4 | * $csp global exception rule (no arguments) disables previous $csp rule. 5 | #### Expecting result: $csp global exception (no arguments) disables $csp rule (inline script works) -------------------------------------------------------------------------------- /public/Filters/csp-rules/csp-global-exception/csp-global-exception.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $csp global exception rules test 8 | 9 | 10 | 11 | 12 | 13 | 17 |
18 |
19 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/Filters/csp-rules/csp-global-exception/csp-global-exception.js: -------------------------------------------------------------------------------- 1 | /* global tmp */ 2 | 3 | import { getAgTestRunner, isSubscribed } from '../../helpers.js'; 4 | 5 | const agTest = getAgTestRunner(window.location); 6 | 7 | /** 8 | * Before doing the test, import csp-global-exception.txt to AdGuard 9 | */ 10 | window.addEventListener('DOMContentLoaded', () => { 11 | const adgCheck = isSubscribed('subscribe-to-test-csp-global-exception-rules-filter'); 12 | 13 | agTest(1, '$csp global exception (no arguments) test', (assert) => { 14 | assert.ok( 15 | adgCheck && document.getElementById('csp-global-exception').innerHTML === 'Inline script works', 16 | '$csp exception rule should disable other $csp rules.', 17 | ); 18 | document.body.removeChild(tmp); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /public/Filters/csp-rules/csp-global-exception/csp-global-exception.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $csp global exception rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-csp-global-exception-rules-filter 9 | ! 10 | ! Case 1 11 | testcases.agrd.dev,pages.dev$csp=script-src 'self' 12 | @@testcases.agrd.dev,pages.dev$csp 13 | -------------------------------------------------------------------------------- /public/Filters/csp-rules/test-csp-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $csp rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 |
21 |

Some content

22 |
23 | 24 | 25 | 31 | 32 | 33 |
34 | 35 | 36 |
37 | 38 | 39 |
40 |

Case 3

41 |
42 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /public/Filters/csp-rules/test-csp-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-csp-rules.txt to AdGuard 7 | */ 8 | window.addEventListener('DOMContentLoaded', () => { 9 | const adgCheck = isSubscribed('subscribe-to-test-csp-rules-filter'); 10 | 11 | agTest(1, 'using with basic rules', (assert) => { 12 | const testElement1 = document.getElementById('csp-test'); 13 | assert.ok(!testElement1, '$csp rule prevents executing inline script'); 14 | 15 | const testElement2 = document.getElementById('some-element'); 16 | const testElement2Hidden = getComputedStyle(testElement2).display === 'none'; 17 | assert.ok(testElement2Hidden, '$csp rule should work together with basic rules.'); 18 | }); 19 | 20 | agTest(2, 'multiple $csp rules', async (assert) => { 21 | const baseUrl = 'https://httpbin.agrd.dev/anything'; 22 | 23 | const response = await fetch(`${baseUrl}/test-1`); 24 | const test = await response.json(); 25 | await assert.ok(test.url.endsWith('test-1')); 26 | 27 | await assert.rejects(fetch(`${baseUrl}/test-2`)); 28 | 29 | await assert.ok(new Promise((resolve) => { 30 | const frame1 = document.getElementById('test-1'); 31 | frame1.onload = () => { 32 | resolve(true); 33 | }; 34 | })); 35 | 36 | await assert.ok(new Promise((resolve) => { 37 | const frame2 = document.getElementById('test-2'); 38 | frame2.onerror = () => { 39 | resolve(true); 40 | }; 41 | })); 42 | }); 43 | 44 | agTest(3, '$csp exception and multiple $csp rules', (assert) => { 45 | const testElement = document.querySelector('#case3'); 46 | const testElementHidden = getComputedStyle(testElement).display === 'none'; 47 | assert.ok(adgCheck && testElementHidden, '$scp exception should disable the $csp rule with matching pattern.'); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /public/Filters/csp-rules/test-csp-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $csp rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-csp-rules-filter 9 | ! 10 | ! Case 1 11 | ||*/Filters/csp-rules/test-csp-rules$csp=script-src 'self' 12 | [$path=|/Filters/csp-rules/test-csp-rules]###some-element 13 | ! Case 2 14 | ||*/Filters/csp-rules/test-csp-rules$csp=connect-src https://httpbin.agrd.dev/anything/test-1 15 | ||*/Filters/csp-rules/test-csp-rules$csp=frame-src https://httpbin.agrd.dev/anything/test-1 16 | ! Case 3 17 | ||*/Filters/csp-rules/test-csp-rules$csp=style-src 'self' 18 | @@||*/Filters/csp-rules/test-csp-rules$csp=style-src 'self' 19 | -------------------------------------------------------------------------------- /public/Filters/css-rules/README.md: -------------------------------------------------------------------------------- 1 | ## AdGuard for iOS supports CSS rules since iOS 15 and AdGuard for iOS v4.3 2 | -------------------------------------------------------------------------------- /public/Filters/css-rules/css-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | CSS rules test 8 | 9 | 10 | 31 | 32 | 33 | 34 | 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | 54 | 57 |
58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /public/Filters/css-rules/css-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for CSS tests 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-css-rules-filter 9 | ! Test case 1: 10 | testcases.agrd.dev,pages.dev#$##case-1-single { width: 0 !important; height: 0 !important; margin: 0 !important; padding: 0 !important; overflow: visible !important; display: none !important; } 11 | ! 12 | ! Test case 2: 13 | testcases.agrd.dev,pages.dev#$##case-2-multiple { width: 0 !important; } 14 | testcases.agrd.dev,pages.dev#$##case-2-multiple { height: 0 !important; } 15 | testcases.agrd.dev,pages.dev#$##case-2-multiple { margin: 0 !important; } 16 | testcases.agrd.dev,pages.dev#$##case-2-multiple { padding: 0 !important; } 17 | testcases.agrd.dev,pages.dev#$##case-2-multiple { overflow: visible !important; } 18 | testcases.agrd.dev,pages.dev#$##case-2-multiple { display: none !important; } 19 | ! 20 | ! Test case 3: 21 | testcases.agrd.dev,pages.dev#$##case-3-important { width: 0 !important; height: 0 !important; margin: 0 !important; padding: 0 !important; } 22 | testcases.agrd.dev,pages.dev#$##case-3-important { overflow: visible !important; display: none !important; } 23 | ! 24 | ! Test case 4: 25 | testcases.agrd.dev,pages.dev#$##case-4-margin-padding { margin-top: 0 !important; } 26 | testcases.agrd.dev,pages.dev#$##case-4-margin-padding { padding-right: 0 !important; } 27 | ! 28 | ! Test case 5: 29 | testcases.agrd.dev,pages.dev#$?#div[id][class]:has(> .inner-div) { width: 0 !important; } 30 | ! 31 | ! Test case 5: 32 | testcases.agrd.dev,pages.dev#$?#div[id][class]:has(> .inner-div) { width: 0 !important; } 33 | ! 34 | ! Test case 6: 35 | testcases.agrd.dev,pages.dev#$##case6.banner:has(a.banner-link) { visibility: hidden!important; } 36 | ! Test case 7: 37 | testcases.agrd.dev,pages.dev#$##case7.banner:has(a.banner-link) { visibility: hidden!important; } 38 | testcases.agrd.dev,pages.dev#@$##case7.banner:has(a.banner-link) { visibility: hidden!important; } 39 | -------------------------------------------------------------------------------- /public/Filters/denyallow-rules/README.md: -------------------------------------------------------------------------------- 1 | ## Compatible with: 2 | 3 | 1. **AdGuard Browser extension v4.0** which uses TSUrlFilter 4 | 2. AdGuard for Windows, macOS and Android with **CoreLibs v1.8** 5 | -------------------------------------------------------------------------------- /public/Filters/denyallow-rules/assets/adguard_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/denyallow-rules/assets/adguard_circle.png -------------------------------------------------------------------------------- /public/Filters/denyallow-rules/assets/adguard_dns_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/denyallow-rules/assets/adguard_dns_map.png -------------------------------------------------------------------------------- /public/Filters/denyallow-rules/test-denyallow-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Denyallow rules test 7 | 8 | 9 | 14 | 15 | 16 | 17 | 20 |
21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /public/Filters/denyallow-rules/test-denyallow-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $denyallow rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-denyallow-rules-filter 9 | ! 10 | ! Case 1 11 | /adguard_circle.png$image,denyallow=raw.githubusercontent.com,domain=testcases.agrd.dev|pages.dev 12 | ! 13 | ! Case 2 14 | /adguard_dns_map.png 15 | @@/adguard_dns_map.png$image,denyallow=raw.githubusercontent.com,domain=testcases.agrd.dev|pages.dev 16 | ! 17 | ! Case 3 18 | ! block request to https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/NCDN_-_CDN.png/800px-NCDN_-_CDN.png 19 | /800px-NCDN_-_CDN.png$script,denyallow=wikimedia.org,domain=testcases.agrd.dev|pages.dev 20 | ||wikimedia.org^ 21 | ! 22 | ! Case 4 23 | ! allow request to https://use.fontawesome.com/releases/v5.15.4/css/all.css 24 | @@/all.css$stylesheet,denyallow=fontawesome.com,domain=testcases.agrd.dev|pages.dev 25 | -------------------------------------------------------------------------------- /public/Filters/element-hiding-rules/README.md: -------------------------------------------------------------------------------- 1 | ## Internet Explorer should be supported by AdGuard for Windows 2 | -------------------------------------------------------------------------------- /public/Filters/element-hiding-rules/subdocument-test-files/iframe-test-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Test 8 | 9 | 10 | 11 | iframe 1 12 | 13 | 14 | -------------------------------------------------------------------------------- /public/Filters/element-hiding-rules/subdocument-test-files/iframe-test-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Test 8 | 9 | 10 | 11 | iframe 2 12 | 13 | 14 | -------------------------------------------------------------------------------- /public/Filters/element-hiding-rules/subdocument-test-files/iframe-test-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Test iframe 8 | 9 | 10 | 11 |
this element should be hidden
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /public/Filters/element-hiding-rules/test-element-hiding-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for element hiding rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-element-hiding-rules-filter 9 | ! Test case 1: domain-specific elemhide rule 10 | testcases.agrd.dev,pages.dev###case-1-elemhide > .test-banner 11 | ! Test case 2: generic elemhide rule 12 | ###case-2-generic-elemhide > .test-banner 13 | ! Test case 3: elemhide rule exception 14 | ###case-3-elemhide-exception > .test-banner 15 | testcases.agrd.dev,pages.dev#@##case-3-elemhide-exception > .test-banner 16 | ! Test case 3: wildcard exception 17 | testcases.agrd.dev,pages.dev###case-3-elemhide-exception > h1 18 | *#@##case-3-elemhide-exception > h1 19 | ! Test case 3: generic exception 20 | testcases.agrd.dev,pages.dev###case-3-elemhide-exception > h2 21 | #@##case-3-elemhide-exception > h2 22 | ! Test case 3: generic exception for generic elemhide 23 | ###case-3-elemhide-exception > h3 24 | #@##case-3-elemhide-exception > h3 25 | ! Test case 4: domain exclusion 26 | ~testcases.agrd.dev,~pages.dev###case-4-domain-exclusion > .test-banner 27 | ! Test case 5: wildcard for tld 28 | testcases.agrd.*,pages.*###case-5-wildcard-for-tld > .test-banner 29 | ! Test case 6: wildcard for tld support with $domain modifier 30 | ||*/tld-test-files/$image,domain=testcases.agrd.*|pages.* 31 | ||*/tld*$script,domain=testcases.agrd.*|pages.* 32 | ! Test case 7: $third-party modifier 33 | ||antibanner.net^$third-party 34 | ! Test case 8: $subdocument modifier 35 | ||*/iframe-test-1.html^$subdocument,domain=testcases.agrd.dev|pages.dev 36 | ||*/iframe-test-2.html^$domain=testcases.agrd.dev|pages.dev 37 | @@||*/iframe-test-2.html^$subdocument,domain=testcases.agrd.dev|pages.dev 38 | ! Test case 9: pseudo-class ':has()' 39 | testcases.agrd.dev,pages.dev###case9.banner:has(a.banner-link) 40 | ! Test case 10: element hiding rule for element in sub frame 41 | testcases.agrd.dev,pages.dev##.subCase10 42 | -------------------------------------------------------------------------------- /public/Filters/element-hiding-rules/tld-test-files/adguard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/element-hiding-rules/tld-test-files/adguard.png -------------------------------------------------------------------------------- /public/Filters/element-hiding-rules/tld-test-files/test-script.js: -------------------------------------------------------------------------------- 1 | const element = document.querySelector('#case-6-wildcard-for-tld-basic-rules > .tld-test'); 2 | element.innerText = 'this text was added by test-script.js'; 3 | -------------------------------------------------------------------------------- /public/Filters/extended-css-rules/README.md: -------------------------------------------------------------------------------- 1 | ## 1. ExtendedCss do not support Internet Explorer (due to content-script incompatibility) 2 | 3 | ## 2. AdGuard for iOS supports CSS rules since iOS 15 and AdGuard for iOS v4.3 4 | -------------------------------------------------------------------------------- /public/Filters/extended-css-rules/extended-css-iframejs-injection/README.md: -------------------------------------------------------------------------------- 1 | ## Supported by AdGuard for iOS since iOS 15 and AdGuard for iOS v4.3 2 | -------------------------------------------------------------------------------- /public/Filters/extended-css-rules/extended-css-iframejs-injection/extended-css-iframejs-injection.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner } from '../../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import extended-css-iframejs-injection.txt to AdGuard 7 | */ 8 | window.addEventListener('load', () => { 9 | agTest(1, 'rules injection into iframe created by JS', (assert) => { 10 | const frame = document.querySelector('#case1 > #frame1'); 11 | const innerDoc = frame.contentDocument || frame.contentWindow.document; 12 | assert.ok( 13 | innerDoc.querySelector('#inframe1').style.display === 'none', 14 | 'Extended CSS rules should work inside of iframes created by JS', 15 | ); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /public/Filters/extended-css-rules/extended-css-iframejs-injection/extended-css-iframejs-injection.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for extended css rules injection into iframe created with js test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-extended-css-iframejs-injection 9 | ! Case 1 10 | testcases.agrd.dev,pages.dev#?##inframe1:has(.content) 11 | -------------------------------------------------------------------------------- /public/Filters/extended-css-rules/test-files/frame1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | iframe 9 | 10 | 11 | 12 |
13 |

Frame 1

14 |
this frame was loaded from local source
15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /public/Filters/generichide-rules/README.md: -------------------------------------------------------------------------------- 1 | * ### Warning: for testing in Firefox AMO version the test rules should be added to the user rules filter. 2 | Javascript rules don't work in Firefox AMO version, so if the rules added as a custom filter, the test will fail. 3 | 4 | * ### Internet Explorer should be supported by AdGuard for Windows 5 | -------------------------------------------------------------------------------- /public/Filters/generichide-rules/generichide-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Generic hide rule test 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 |
23 | 24 |
25 |
26 |
27 |
28 |
29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /public/Filters/generichide-rules/generichide-rules.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-arrow-callback, func-names */ 2 | 3 | import { getAgTestRunner } from '../helpers.js'; 4 | 5 | const agTest = getAgTestRunner(window.location); 6 | 7 | /** 8 | * Before doing the test, import generichide-rules.txt to AdGuard 9 | */ 10 | window.addEventListener('load', function () { 11 | agTest(1, '$generichide rule', function (assert) { 12 | const condition1 = getComputedStyle( 13 | window.document.querySelector('#case-1-generichide > .test-banner'), 14 | null, 15 | ).display === 'none'; 16 | const condition2 = getComputedStyle( 17 | window.document.querySelector('#case-1-generichide > .test-banner1'), 18 | null, 19 | ).display === 'block'; 20 | assert.ok(condition1 && condition2, '$generichide exception rule disables all generic cosmetic rules'); 21 | }); 22 | 23 | agTest(2, '$generichide rule and JS rule', function (assert) { 24 | const banner1 = window.document.querySelector('#case-1-generichide > .test-banner1'); 25 | assert.ok( 26 | banner1.style.width === '200px', 27 | 'JS rule is not applied, $generichide exception rule SHOULD NOT disable specific JS rule', 28 | ); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /public/Filters/generichide-rules/generichide-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for generic hide tests 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-generichide-rules-filter 9 | ! Test case 1: generichide 10 | testcases.agrd.dev,pages.dev###case-1-generichide > .test-banner 11 | ###case-1-generichide > .test-banner1 12 | @@||testcases.agrd.dev$generichide 13 | @@||pages.dev$generichide 14 | ! 15 | ! Test case 2: generichide rule and js rules 16 | testcases.agrd.dev,pages.dev#%#!function(){let e=()=>{document.querySelector("#case-1-generichide > .test-banner1").style.width="200px"};"complete"===document.readyState?e():window.document.addEventListener("readystatechange",e)}(); 17 | -------------------------------------------------------------------------------- /public/Filters/header-rules/expect-global-error.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Expect parsing error to be thrown from a url that responds 3 | * with a Content-Type header of 'application/javascript; charset=UTF-8'. 4 | */ 5 | window.onerror = function onerror(msg, url) { 6 | return url.includes('Content-Type=application%2Fjavascript%3B+charset%3DUTF-8'); 7 | }; 8 | -------------------------------------------------------------------------------- /public/Filters/header-rules/test-header-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Header rules test 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /public/Filters/header-rules/test-header-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $header rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-header-rules-filter 9 | ! 10 | ! Case 1 11 | ||*/httpbin/response-headers^$header=case1,script 12 | ! 13 | ! Case 2 14 | ||httpbin.agrd.workers.dev^$header=case2,third-party 15 | ! 16 | ! Case 3 17 | ||httpbin.agrd.workers.dev^$header=case3,domain=testcases.agrd.dev|pages.dev 18 | ! 19 | ! Case 4 20 | ||*/httpbin/response-headers/TestHeader^$header=case4,match-case -------------------------------------------------------------------------------- /public/Filters/hls-rules/README.md: -------------------------------------------------------------------------------- 1 | # $hls rules test 2 | Compatible with AdGuard for Windows, macOS and Android with **CoreLibs v1.10** 3 | 4 | ### Case 1 5 | Remove segments by simple pattern and by regex. 6 | 7 | ### Case 2 8 | Remove segments by pattern, but apply exception rule to disable the previous one. 9 | -------------------------------------------------------------------------------- /public/Filters/hls-rules/test-files/hls-test-1.m3u: -------------------------------------------------------------------------------- 1 | #EXTM3U 2 | #EXT-X-TARGETDURATION:10 3 | #EXTINF,5 4 | preroll.ts 5 | #UPLYNK-SEGMENT:abc123,ad 6 | #UPLYNK-KEY:aabb1122 7 | #EXT-X-DISCONTINUITY 8 | #EXTINF,10 9 | 01.ts 10 | #EXTINF,10 11 | 02.ts 12 | #UPLYNK-SEGMENT:abc123,segment 13 | #UPLYNK-KEY:ccdd2233 14 | #EXT-X-DISCONTINUITY 15 | #EXTINF,10 16 | 01.ts 17 | #EXTINF,10 18 | 02.ts 19 | #EXT-X-ENDLIST 20 | -------------------------------------------------------------------------------- /public/Filters/hls-rules/test-files/hls-test-2.m3u: -------------------------------------------------------------------------------- 1 | #EXTINF,5 2 | preroll.ts 3 | -------------------------------------------------------------------------------- /public/Filters/hls-rules/test-hls-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $hls rules tests 8 | 9 | 10 | 11 | 12 | 13 | 17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /public/Filters/hls-rules/test-hls-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-hls-rules.txt to AdGuard 7 | */ 8 | 9 | const expectedData1 = `#EXTM3U 10 | #EXT-X-TARGETDURATION:10 11 | #UPLYNK-SEGMENT:abc123,segment 12 | #UPLYNK-KEY:ccdd2233 13 | #EXT-X-DISCONTINUITY 14 | #EXTINF,10 15 | 01.ts 16 | #EXTINF,10 17 | 02.ts 18 | #EXT-X-ENDLIST`; 19 | 20 | const expectedData2 = `#EXTINF,5 21 | preroll.ts`; 22 | 23 | const getHlsData = async (path) => { 24 | const response = await fetch(path); 25 | const hlsData = await response.text(); 26 | return hlsData.trim(); 27 | }; 28 | 29 | window.addEventListener('DOMContentLoaded', () => { 30 | const adgCheck = isSubscribed('subscribe-to-test-hls-rules-filter'); 31 | 32 | agTest(1, '$hls rule', async (assert) => { 33 | const hlsData = await getHlsData('test-files/hls-test-1.m3u'); 34 | assert.ok(hlsData === expectedData1, '$hls rule should remove segments by provided pattern'); 35 | }); 36 | 37 | agTest(2, '$hls exception rule', async (assert) => { 38 | const hlsData = await getHlsData('test-files/hls-test-2.m3u'); 39 | assert.ok(adgCheck && hlsData === expectedData2, '$hls exception rule should disable $hls rule'); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /public/Filters/hls-rules/test-hls-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $hls rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-hls-rules-filter 9 | ! 10 | ! Case 1 11 | ||*/hls-test-1.m3u^$hls=preroll 12 | ||*/hls-test-1.m3u^$hls=/#UPLYNK-SEGMENT:.*\,ad/t 13 | ! Case 2 14 | ||*/hls-test-2.m3u^$hls=preroll 15 | @@||*/hls-test-2.m3u^$hls 16 | -------------------------------------------------------------------------------- /public/Filters/important-rules/README.md: -------------------------------------------------------------------------------- 1 | # $important rules test 2 | 3 | ## Case 1 4 | * First rule with $important modifier blocks request for `adg1.png`. 5 | * Second exception rule allows request for `adg1.png`. 6 | #### Expecting result: $important rule should have priority over exception rule (`adg1.png` is hidden) 7 | 8 | ## Case 2 9 | * First rule with $important modifier blocks request for `adg2.png`. 10 | * Second exception rule with $important modifier allows request for `adg2.png`. 11 | #### Expecting result: $important exception rule should have priority over $important rule (`adg2.png` is displayed) 12 | -------------------------------------------------------------------------------- /public/Filters/important-rules/important-vs-urlblock/README.md: -------------------------------------------------------------------------------- 1 | # $important vs $urlblock test 2 | 3 | ## Case 1 4 | 5 | There are two rules: 6 | - blocking rule for `adg3.png` with `$important` modifier; 7 | - `$urlblock` exception rule. 8 | 9 | ### Expecting result 10 | 11 | `$urlblock` exception **should not** disable `$important`, `adg3.png` is blocked. 12 | 13 | It happens because `$important` rule has higher priority than `$urlblock` exception rule 14 | due to the new [rules priority policy][kb-rule-priorities]. 15 | 16 | ### Compatibility 17 | 18 | New rules priority policy is already implemented in AdGuard Browser Extensions running **tsurlfilter v2.1.0** 19 | and shall be implemented in AdGuard for Windows, Mac, Android in **CoreLibs v1.13**. 20 | 21 | 22 | [kb-rule-priorities]: https://adguard.com/kb/general/ad-filtering/create-own-filters/#rule-priorities 23 | -------------------------------------------------------------------------------- /public/Filters/important-rules/important-vs-urlblock/test-important-vs-urlblock.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $important vs $urlblock test 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /public/Filters/important-rules/important-vs-urlblock/test-important-vs-urlblock.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-important-vs-urlblock.txt to AdGuard 7 | */ 8 | window.addEventListener('DOMContentLoaded', () => { 9 | const adgCheck = isSubscribed('subscribe-to-test-important-vs-urlblock-filter'); 10 | 11 | agTest(1, '$important rule vs $urlblock exception', (assert) => { 12 | const image = document.querySelector('#case1 > img'); 13 | const imageBlocked = (image === null) || (getComputedStyle(image, null).display === 'none'); 14 | assert.ok(adgCheck && imageBlocked, '$urlblock exception should not disable $important rule.'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /public/Filters/important-rules/important-vs-urlblock/test-important-vs-urlblock.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $important-vs-urlblock test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-important-vs-urlblock-filter 9 | ! 10 | ! Case 1 11 | ||*/test-files/adg1.png$important 12 | @@testcases.agrd.dev$urlblock 13 | @@pages.dev$urlblock 14 | -------------------------------------------------------------------------------- /public/Filters/important-rules/test-files/adg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/important-rules/test-files/adg1.png -------------------------------------------------------------------------------- /public/Filters/important-rules/test-files/adg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/important-rules/test-files/adg2.png -------------------------------------------------------------------------------- /public/Filters/important-rules/test-files/adg3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/important-rules/test-files/adg3.png -------------------------------------------------------------------------------- /public/Filters/important-rules/test-important-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $important rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 |
27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /public/Filters/important-rules/test-important-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-important-rules.txt to AdGuard 7 | */ 8 | window.addEventListener('DOMContentLoaded', () => { 9 | const adgCheck = isSubscribed('subscribe-to-test-important-rules-filter'); 10 | 11 | agTest(1, '$important rule vs exception rule', (assert) => { 12 | const testImg = document.querySelector('#case1 > img'); 13 | const isBlocked = !testImg 14 | || (getComputedStyle(testImg).display === 'none') 15 | || (getComputedStyle(testImg).height === '0px'); 16 | assert.ok(isBlocked, '$important rule should have priority over exception rule.'); 17 | }); 18 | 19 | agTest(2, '$important rule vs exception $important rule', (assert) => { 20 | const imageDisplayed = getComputedStyle(document.querySelector('#case2 > img')).display !== 'none'; 21 | assert.ok(adgCheck && imageDisplayed, 'exception $important rule should have priority over $important rule.'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /public/Filters/important-rules/test-important-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $important rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-important-rules-filter 9 | ! 10 | ! Case 1 11 | ||*/test-files/adg1.png$important 12 | @@||*/test-files/adg1.png 13 | ! Case 2 14 | ||*/test-files/adg2.png$important 15 | @@||*/test-files/adg2.png$important 16 | -------------------------------------------------------------------------------- /public/Filters/injection-speed/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Injection Speed Test 9 | 10 | 11 | 12 |
13 | 14 |

Injection Speed Test

15 | 16 | 17 |
18 | 23 |
24 | 25 | 26 |
    27 | 28 |
  1. 29 | 30 | Service worker page 31 | 32 |
  2. 33 | 34 | 35 |
  3. 36 | 37 | Simple page 38 | 39 |
  4. 40 | 41 | 42 |
  5. 43 | 44 | Simple page extended 45 | 46 |
  6. 47 | 48 | 49 | 50 |
  7. 51 | 52 | Simple page with CSP 'script-src' 53 | 54 |
  8. 55 |
56 |
57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /public/Filters/injection-speed/service-worker/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | Page Loaded by a Service Worker 11 | 12 | 13 | 14 | 15 | 16 |
17 |

Injection Speed Test into Page Served by a Service Worker

18 | 19 |
20 |

How to Test

21 |
22 |
    23 |
  1. Open DevTools.
  2. 24 |
  3. Go to the Application tab in DevTools.
  4. 25 |
  5. Ensure there is no checkbox next to the "Bypass for network" option.
  6. 26 | 27 | DevTools screenshot showing no checkbox for bypassing network 28 |
  7. Go back to the Console tab.
  8. 29 |
  9. Reload the page.
  10. 30 |
  11. Make sure that script and scriptlet rules were injected before the inline script at the end.
  12. 31 | 32 | Example screenshot of the feature 33 |
34 |
35 |
36 | 37 |

Go Back

38 |
39 | 40 | 46 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /public/Filters/injection-speed/service-worker/no-bypass-network.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/injection-speed/service-worker/no-bypass-network.jpg -------------------------------------------------------------------------------- /public/Filters/injection-speed/service-worker/service-worker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-globals */ 2 | 3 | // Install event - Skip waiting and activate the new service worker immediately 4 | self.addEventListener('install', () => { 5 | self.skipWaiting(); 6 | }); 7 | 8 | // Fetch event - Forward all requests to the network without caching 9 | self.addEventListener('fetch', (event) => { 10 | event.respondWith( 11 | fetch(event.request), 12 | ); 13 | }); 14 | 15 | // Activate event - Clean up old caches and enable navigation preload 16 | self.addEventListener('activate', () => { 17 | // Immediately claim any clients without waiting 18 | self.clients.claim(); 19 | }); 20 | -------------------------------------------------------------------------------- /public/Filters/injection-speed/simple-csp/simple-with-csp--firefox-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/injection-speed/simple-csp/simple-with-csp--firefox-error.png -------------------------------------------------------------------------------- /public/Filters/injection-speed/simple-csp/simple-with-csp--ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/injection-speed/simple-csp/simple-with-csp--ok.png -------------------------------------------------------------------------------- /public/Filters/injection-speed/simple-extended/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | Injection Speed Test 11 | 12 | 13 | 14 | 15 | 16 |
17 |

Injection Speed Test

18 | 19 |
20 |

How to Test

21 |
22 |
    23 |
  1. Open devtools
  2. 24 |
  3. Reload page
  4. 25 |
  5. Make sure that script and scriptlet rules were injected at least before the inline script at the end
  6. 26 | 27 |
28 |
29 |
30 | 31 |

Go Back

32 |
33 | 34 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /public/Filters/injection-speed/simple-extended/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/injection-speed/simple-extended/screenshot.png -------------------------------------------------------------------------------- /public/Filters/injection-speed/simple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | 22 | Injection Speed Test 23 | 24 | 25 | 26 | 27 | 28 |
29 |

Injection Speed Test

30 | 31 |
32 |

How to Test

33 |
34 |
    35 |
  1. Open devtools
  2. 36 |
  3. Reload page
  4. 37 |
  5. Make sure that script and scriptlet rules were injected at least before the inline script at the end
  6. 38 | 39 |
40 |
41 |
42 | 43 |

Go Back

44 |
45 | 46 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /public/Filters/injection-speed/simple/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/injection-speed/simple/screenshot.png -------------------------------------------------------------------------------- /public/Filters/injection-speed/styles.css: -------------------------------------------------------------------------------- 1 | .mt-2 { 2 | margin-top: 15px; 3 | } 4 | 5 | .mb-2 { 6 | margin-bottom: 15px; 7 | } 8 | 9 | .mt-4 { 10 | margin-top: 30px; 11 | } 12 | 13 | .mb-3 { 14 | margin-bottom: 20px; 15 | } 16 | 17 | .mb-4 { 18 | margin-bottom: 30px; 19 | } 20 | 21 | .mt-5 { 22 | margin-top: 40px; 23 | } 24 | 25 | p { 26 | margin: 0; 27 | } 28 | 29 | .img-border { 30 | border: 1px solid #ccc; 31 | } 32 | 33 | .note { 34 | margin-top: 16px; 35 | margin-left: 40px; 36 | } 37 | -------------------------------------------------------------------------------- /public/Filters/injection-speed/test-injection-speed.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for Injection speed test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | testcases.agrd.dev,pages.dev#%#//scriptlet('log', 'scriptlet rule is executed') 8 | testcases.agrd.dev,pages.dev#%#console.log(Date.now(), 'script rule is executed'); 9 | 10 | -------------------------------------------------------------------------------- /public/Filters/jsonprune-rules/README.md: -------------------------------------------------------------------------------- 1 | # $jsonprune rules tests 2 | Compatible with AdGuard for Windows, macOS and Android with **CoreLibs v1.10** 3 | 4 | ### Case 1 5 | Remove key "test2" from the response json. 6 | 7 | ### Case 2 8 | Remove key "test1", but also apply exception rule to disable the previous one. 9 | 10 | ### Case 3 11 | Remove all occurrences of the keys "one" and "two three" anywhere in the JSON document. 12 | 13 | ### Case 4 14 | Remove all children of "test_data" that have an "ad_origin" key. 15 | 16 | ### Case 5 17 | Remove all items that are at nesting level 3 and have a property "Some key" equal to "Some value". 18 | -------------------------------------------------------------------------------- /public/Filters/jsonprune-rules/test-files/test-case-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "test1": "test data 1", 3 | "test2": "test data 2", 4 | "test3": "test data 3" 5 | } 6 | -------------------------------------------------------------------------------- /public/Filters/jsonprune-rules/test-files/test-case-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "test1": "test data 1", 3 | "test2": "test data 2", 4 | "test3": "test data 3" 5 | } 6 | -------------------------------------------------------------------------------- /public/Filters/jsonprune-rules/test-files/test-case-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "one": "test data 1", 3 | "two three": "test data 2", 4 | "three four five": "test data 3" 5 | } 6 | -------------------------------------------------------------------------------- /public/Filters/jsonprune-rules/test-files/test-case-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "test_data": { 3 | "child1": { 4 | "test1": "test data 1", 5 | "ad_origin": "test data 2", 6 | "test2": "test data 3" 7 | }, 8 | "child2": "test data 4" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /public/Filters/jsonprune-rules/test-files/test-case-5.json: -------------------------------------------------------------------------------- 1 | { 2 | "level1": { 3 | "level2": { 4 | "child1": { 5 | "Some key": "Some value", 6 | "test1": "test data" 7 | }, 8 | "child2": { 9 | "test2": "test data" 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /public/Filters/jsonprune-rules/test-jsonprune-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $jsonprune rules tests 8 | 9 | 10 | 11 | 12 | 13 | 17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /public/Filters/jsonprune-rules/test-jsonprune-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-jsonprune-rules.txt to AdGuard 7 | */ 8 | 9 | const getJsonData = async (path) => { 10 | const response = await fetch(path); 11 | return response.json(); 12 | }; 13 | 14 | window.addEventListener('DOMContentLoaded', () => { 15 | const adgCheck = isSubscribed('subscribe-to-test-jsonprune-rules-filter'); 16 | 17 | agTest(1, '$jsonprune rule', async (assert) => { 18 | const jsonData = await getJsonData('test-files/test-case-1.json'); 19 | assert.ok(jsonData.test1 && !jsonData.test2, '$jsonprune rule should remove data from response json'); 20 | }); 21 | 22 | agTest(2, '$jsonprune exception rule', async (assert) => { 23 | const jsonData = await getJsonData('test-files/test-case-2.json'); 24 | assert.ok( 25 | adgCheck && jsonData.test1 && jsonData.test2, 26 | '$jsonprune exception rule should disable $jsonprune rule', 27 | ); 28 | }); 29 | 30 | agTest(3, '$jsonprune rule for multiple keys', async (assert) => { 31 | const jsonData = await getJsonData('test-files/test-case-3.json'); 32 | assert.ok(!jsonData.one 33 | && !jsonData['two three'] 34 | && jsonData['three four five'], '$jsonprune rule should remove data from response json'); 35 | }); 36 | 37 | agTest(4, '$jsonprune rule with expressions', async (assert) => { 38 | const jsonData = await getJsonData('test-files/test-case-4.json'); 39 | assert.ok(!jsonData.test_data.child1 40 | && jsonData.test_data.child2, '$jsonprune rule should remove data from response json by expression'); 41 | }); 42 | 43 | agTest(5, '$jsonprune rule with expressions', async (assert) => { 44 | const jsonData = await getJsonData('test-files/test-case-5.json'); 45 | assert.ok(!jsonData.level1.level2.child1 46 | && jsonData.level1.level2.child2, '$jsonprune rule should remove data from response json by expression'); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /public/Filters/jsonprune-rules/test-jsonprune-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $jsonprune rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-jsonprune-rules-filter 9 | ! 10 | ! Case 1 11 | ||*/test-case-1.json^$jsonprune=\$.test2 12 | ! Case 2 13 | ||*/test-case-2.json^$jsonprune=\$.test1 14 | @@||*/test-case-2.json^$jsonprune 15 | ! Case 3 16 | ||*/test-case-3.json^$jsonprune=\$..[one\, "two three"] 17 | ! Case 4 18 | ||*/test-case-4.json^$jsonprune=\$.test_data[?(has ad_origin)] 19 | ! Case 5 20 | ||*/test-case-5.json^$jsonprune=\$.*.*[?(key-eq 'Some key' 'Some value')] 21 | -------------------------------------------------------------------------------- /public/Filters/match-case-rules/README.md: -------------------------------------------------------------------------------- 1 | # $match-case modifier test 2 | 3 | Rules with the `$match-case` are supported by AdGuard for iOS and Safari, 4 | running **SafariConverterLib v2.0.43** or later. 5 | -------------------------------------------------------------------------------- /public/Filters/match-case-rules/test-match-case-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $match-case modifier rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/Filters/match-case-rules/test-match-case-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isBlockedFetch, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-match-case-rules.txt to AdGuard 7 | */ 8 | 9 | const baseUrl = `${window.location.origin}/httpbin/anything`; 10 | 11 | window.addEventListener('load', () => { 12 | const adgCheck = isSubscribed('subscribe-to-test-match-case-rules-filter'); 13 | 14 | agTest(1, '$match-case set + uppercase rule', async (assert) => { 15 | assert.ok(adgCheck); 16 | 17 | let isBlocked; 18 | const blockedTestUrl = `${baseUrl}/MATCH-CASE-1`; 19 | isBlocked = await isBlockedFetch(blockedTestUrl); 20 | assert.ok(isBlocked, 'uppercase url request is blocked'); 21 | 22 | const notBlockedTestUrl = `${baseUrl}/match-case-1`; 23 | isBlocked = await isBlockedFetch(notBlockedTestUrl); 24 | assert.ok(!isBlocked, 'lowercase url request is NOT blocked'); 25 | }); 26 | 27 | agTest(2, '$match-case set + lowercase rule', async (assert) => { 28 | assert.ok(adgCheck); 29 | 30 | let isBlocked; 31 | 32 | const blockedTestUrl = `${baseUrl}/match-case-2`; 33 | isBlocked = await isBlockedFetch(blockedTestUrl); 34 | assert.ok(isBlocked, 'lowercase url request is blocked'); 35 | 36 | const notBlockedTestUrl = `${baseUrl}/MATCH-CASE-2`; 37 | isBlocked = await isBlockedFetch(notBlockedTestUrl); 38 | assert.ok(!isBlocked, 'uppercase url request is NOT blocked'); 39 | }); 40 | 41 | agTest(3, 'no $match-case', async (assert) => { 42 | assert.ok(adgCheck); 43 | 44 | let blockedTestUrl; 45 | let isBlocked; 46 | 47 | blockedTestUrl = `${baseUrl}/Match-Case-3`; 48 | isBlocked = await isBlockedFetch(blockedTestUrl); 49 | assert.ok(isBlocked, 'Match-Case-3 request is blocked'); 50 | 51 | blockedTestUrl = `${baseUrl}/MATCH-CASE-3`; 52 | isBlocked = await isBlockedFetch(blockedTestUrl); 53 | assert.ok(isBlocked, 'MATCH-CASE-3 request is blocked'); 54 | 55 | blockedTestUrl = `${baseUrl}/match-case-3`; 56 | isBlocked = await isBlockedFetch(blockedTestUrl); 57 | assert.ok(isBlocked, 'match-case-3 request is blocked'); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /public/Filters/match-case-rules/test-match-case-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $match-case modifier 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-match-case-rules-filter 9 | ! 10 | ! Test case 1 — uppercase match 11 | ||*/MATCH-CASE-1^$match-case 12 | ! 13 | ! Test case 2 — lowercase match 14 | ||*/match-case-2^$match-case 15 | ! 16 | ! Test case 3 - no $match-case modifier 17 | ||*/Match-Case-3^ 18 | ! 19 | ! TODO: add unblocking rules later if needed 20 | -------------------------------------------------------------------------------- /public/Filters/method-rules/README.md: -------------------------------------------------------------------------------- 1 | # $method rules tests 2 | Compatible with AdGuard products, **that run CoreLibs v1.12 or later**, and AdGuard Browser extensions, **that run tsurlfilter 2.1.1 or later** 3 | 4 | ### Case 1 5 | Rule with `$method` modifier blocks requests with `get` method. 6 | Rule does not block requests with other methods. 7 | ### Case 2 8 | Allowlist rule with `$method` modifier only unblocks requests with `options` method. 9 | Other requests are not affected. 10 | ### Case 3 11 | Rule with `$method` modifier and inverted `~options` value only blocks requests with methods other than `options`. 12 | Rule does not block requests with other methods. 13 | ### Case 4 14 | Allowlist rule with `$method` modifier and inverted `~get` value only unblocks requests whose method is not `get`. 15 | Requests with `get` method will still be blocked. 16 | -------------------------------------------------------------------------------- /public/Filters/method-rules/test-method-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $method rules tests 7 | 8 | 9 | 10 | 11 | 14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /public/Filters/method-rules/test-method-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $method rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-method-rules-filter 9 | ! 10 | ! Case 1 11 | ||*/httpbin/anything/test-case-1.json^$method=get 12 | ! Case 2 13 | ||*/httpbin/anything/test-case-2.json^ 14 | @@||*/test-case-2.json^$method=options 15 | ! Case 3 16 | ||*/httpbin/anything/test-case-3.json^$method=~options 17 | ! Case 4 18 | ||*/httpbin/anything/test-case-4.json^ 19 | @@||*/httpbin/anything/test-case-4.json^$method=~get 20 | -------------------------------------------------------------------------------- /public/Filters/network-rules/README.md: -------------------------------------------------------------------------------- 1 | # $network rules test 2 | 3 | ## Case 1 4 | * Fetching response from `https://94.140.14.14/` 5 | * Applying `$network` rule for `https://94.140.14.14/` 6 | #### Expecting result: `$network` rule blocks fetching url 7 | 8 | ## Case 2 9 | * Fetching response from `https://94.140.14.15/info.txt` 10 | * Applying `$network` rule for `94.140.14.15` 11 | * Applying `$network` exception rule to disable previous rule and reject all other rules. 12 | * Blocking rule `||94.140.14.15/info.txt` is rejected by previous rule. 13 | #### Expecting result: `$network` exception rule disables `$network` rule and reject all other rules. 14 | -------------------------------------------------------------------------------- /public/Filters/network-rules/test-network-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $network rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /public/Filters/network-rules/test-network-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-network-rules.txt to AdGuard 7 | */ 8 | 9 | const download = async (url) => { 10 | const response = await fetch(url); 11 | const responseText = await response.text(); 12 | return responseText; 13 | }; 14 | 15 | const request = async (url) => fetch(url, { mode: 'no-cors' }); 16 | 17 | window.addEventListener('DOMContentLoaded', () => { 18 | const adgCheck = isSubscribed('subscribe-to-test-network-rules-filter'); 19 | 20 | agTest(1, '$network rule', async (assert) => { 21 | try { 22 | await request('https://94.140.14.14/'); 23 | } catch (e) { 24 | assert.ok(true, '$network rule should block request'); 25 | } 26 | }); 27 | 28 | agTest(2, '$network exception and priority test', async (assert) => { 29 | const result = await download('https://1.0.0.1/cdn-cgi/trace'); 30 | assert.ok( 31 | adgCheck && result.indexOf('h=1.0.0.1') !== -1, 32 | '$network exception rule should disable $network rule and reject all other rules.', 33 | ); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /public/Filters/network-rules/test-network-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $network rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-network-rules-filter 9 | ! 10 | ! Case 1 11 | 94.140.14.14^$network 12 | ! Case 2 13 | 1.0.0.1^$network 14 | @@1.0.0.1^$network 15 | ||1.0.0.1/cdn-cgi/trace 16 | -------------------------------------------------------------------------------- /public/Filters/nonbasic-path-modifier/README.md: -------------------------------------------------------------------------------- 1 | ## Compatible with: 2 | 3 | 1. **AdGuard Browser extension v4.0** which uses TSUrlFilter 4 | 2. AdGuard for Windows, macOS and Android with **CoreLibs v1.9** 5 | -------------------------------------------------------------------------------- /public/Filters/nonbasic-path-modifier/test-files/subpage1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | irame 9 | 10 | 11 | 12 | 15 | 16 | 19 | 20 | 23 | 24 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /public/Filters/nonbasic-path-modifier/test-nonbasic-path-modifier.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Non-basic $path modifier tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 |
23 | 29 | 30 |
31 | 32 |
33 | 34 |
35 | 36 |
37 | 38 |
39 | 40 |
41 | 42 |
43 | 44 |
45 | 46 |
47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /public/Filters/nonbasic-path-modifier/test-nonbasic-path-modifier.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for non-basic rules $path modifier test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-nonbasic-path-modifier 9 | ! 10 | [$path=/subpage1]testcases.agrd.dev,pages.dev##div#case1 11 | [$path=/subpage2]testcases.agrd.dev,pages.dev##div#case2 12 | [$path=/sub.*/]testcases.agrd.dev,pages.dev##div#case3 13 | [$path=/subpage(?!1)/]testcases.agrd.dev,pages.dev##div#case4 14 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules-mv3/README.md: -------------------------------------------------------------------------------- 1 | # $permissions rules test for MV3 2 | 3 | This test suite added specifically for MV3 to check is it correctly 4 | works without `content-type` modifiers, see [AdguardBrowserExtension#2954]. 5 | 6 | [AdguardBrowserExtension#2954](https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2954) 7 | 8 | ## Limitations 9 | 10 | You can read about limitations in the readme file for `$permissions rules test`. 11 | 12 | ## Case 1 13 | 14 | Checks if `$permissions` rules are applied correctly in the main frame. 15 | It sets the `autoplay` feature policy to `self` and `https://example.com`. 16 | 17 | #### Expecting result: applies `autoplay` feature policy to `self` and `https://example.com` 18 | 19 | ## Case 2 20 | 21 | Checks if `$permissions` rules are applied correctly in the subframe. 22 | Technically, did the same as in the first case, but in the subframe. 23 | 24 | #### Expecting result: applies `geolocation` feature policy to `self` and `https://example.com` 25 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules-mv3/subpage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Foo 7 | 8 | 9 | Bar 10 | 11 | 12 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules-mv3/test-permissions-rules-mv3.css: -------------------------------------------------------------------------------- 1 | [id^="case"] { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules-mv3/test-permissions-rules-mv3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $permissions rules tests for MV3 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules-mv3/test-permissions-rules-mv3.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | const baseUrl = window.location.origin; 5 | 6 | /** 7 | * Before doing the test, import test-permissions-rules-mv3.txt to AdGuard 8 | */ 9 | window.addEventListener('DOMContentLoaded', () => { 10 | agTest(1, 'permissions are set correctly in the main frame', async (assert) => { 11 | const allowlist = await document.featurePolicy.getAllowlistForFeature('autoplay'); 12 | assert.deepEqual(allowlist.sort(), [baseUrl, 'https://example.com'].sort()); 13 | }); 14 | 15 | agTest(2, 'permissions are set correctly in sub frames', async (assert) => { 16 | const iframe = document.querySelector('#case2'); 17 | const iframeDocument = iframe.contentWindow.document; 18 | const allowlist = await iframeDocument.featurePolicy.getAllowlistForFeature('geolocation'); 19 | assert.deepEqual(allowlist.sort(), [baseUrl, 'https://example.com'].sort()); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules-mv3/test-permissions-rules-mv3.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $permissions rules test for MV3 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-permissions-rules-mv3-filter 9 | ! 10 | 11 | ! Case 1 12 | ! Excluded `,domain=testcases.agrd.dev` part, because there is a bug in 13 | ! Chrome, when browser cannot correctly detect initiator domain for requests 14 | ! from omnibox and our integration tests it this case will fail (AG-37801). 15 | ||*/Filters/permissions-rules-mv3$permissions=autoplay=(self "https://example.com") 16 | 17 | ! Case 2 18 | ||*/Filters/permissions-rules-mv3/subpage$permissions=geolocation=(self "https://example.com"),subdocument,domain=testcases.agrd.dev 19 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules/README.md: -------------------------------------------------------------------------------- 1 | # $permissions rules test 2 | 3 | ## Limitations 4 | 5 | There are some strict limitations in testing `$permissions` rules: 6 | 7 | - `$permissions` rules only affect the main and subframes, so there is no way to debug response headers directly, 8 | like making a request to the server and checking the response headers. 9 | The only way to test the rules is to check the behavior of the page, but its also complicated, 10 | because browsers have different implementations and there are some inconsistencies and issues. 11 | - The most logical way to perform the testing is to utilize certain features, such as obtaining the user's location. 12 | If the feature is blocked, an error will be thrown. 13 | The problem is that the error code and message cannot be distinguished between the different reasons for blocking, 14 | like the `Permissions-Policy` header or the browser settings also can block the feature. 15 | - Firefox simply ignores `Permissions-Policy` header: https://bugzilla.mozilla.org/show_bug.cgi?id=1694922 16 | (until the bug is fixed, there is no need to test `$permissions` modifier in Firefox). 17 | - As there is no better option, tests are done with the help of the `document.featurePolicy` interface, 18 | which is only available in Chromium-based browsers. 19 | 20 | ## Case 1 21 | 22 | Checks if `$permissions` rules are applied correctly in the main frame. 23 | It sets the `autoplay` feature policy to `self` and `https://example.com` and checks if the allowlist is correct. 24 | It also tries to set `autoplay` feature policy to `self` and `https://example.net`, but right after that, 25 | adds an allowlist for `https://example.net` and checks if the allowlist is still `self` and `https://example.com`; 26 | 27 | #### Expecting result: allowlist for `autoplay` is `self` and `https://example.com` 28 | 29 | ## Case 2 30 | 31 | Checks if `$permissions` rules are applied correctly in the subframe. 32 | Technically, did the same as in the first case, but in the subframe. 33 | 34 | #### Expecting result: allowlist for `geolocation` is `self` and `https://example.com` 35 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules/subpage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Foo 7 | 8 | 9 | Bar 10 | 11 | 12 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules/test-permissions-rules.css: -------------------------------------------------------------------------------- 1 | [id^="case"] { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules/test-permissions-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $permissions rules tests 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules/test-permissions-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | const baseUrl = window.location.origin; 5 | 6 | /** 7 | * Before doing the test, import test-permissions-rules.txt to AdGuard 8 | */ 9 | window.addEventListener('DOMContentLoaded', () => { 10 | agTest(1, 'permissions are set correctly in the main frame', async (assert) => { 11 | const allowlist = await document.featurePolicy.getAllowlistForFeature('autoplay'); 12 | assert.deepEqual(allowlist.sort(), [baseUrl, 'https://example.com'].sort()); 13 | }); 14 | 15 | agTest(2, 'permissions are set correctly in sub frames', async (assert) => { 16 | const iframe = document.querySelector('#case2'); 17 | const iframeDocument = iframe.contentWindow.document; 18 | const allowlist = await iframeDocument.featurePolicy.getAllowlistForFeature('geolocation'); 19 | assert.deepEqual(allowlist.sort(), [baseUrl, 'https://example.com'].sort()); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /public/Filters/permissions-rules/test-permissions-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $permissions rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-permissions-rules-filter 9 | ! 10 | 11 | ! Case 1 12 | /\/Filters\/permissions-rules(?!\/subpage)/$permissions=autoplay=(self "https://example.com"),domain=testcases.agrd.dev 13 | /\/Filters\/permissions-rules(?!\/subpage)/$permissions=autoplay=(self "https://example.net"),domain=testcases.agrd.dev 14 | @@/\/Filters\/permissions-rules(?!\/subpage)/$permissions=autoplay=(self "https://example.net"),domain=testcases.agrd.dev 15 | 16 | ! Case 2 17 | ||*/Filters/permissions-rules/subpage$permissions=geolocation=(self "https://example.com"),subdocument,domain=testcases.agrd.dev 18 | ||*/Filters/permissions-rules/subpage$permissions=geolocation=(self "https://example.net"),subdocument,domain=testcases.agrd.dev 19 | @@||*/Filters/permissions-rules/subpage$permissions=geolocation=(self "https://example.net"),subdocument,domain=testcases.agrd.dev 20 | -------------------------------------------------------------------------------- /public/Filters/qunit/custom.css: -------------------------------------------------------------------------------- 1 | /** SUBSCRIBE LINK */ 2 | 3 | .subscribe-link { 4 | font-size: 46px; 5 | padding: 50px; 6 | text-align: center; 7 | background: #EE5757; 8 | border-radius: 5px; 9 | margin-bottom: 8px; 10 | } 11 | 12 | .subscribe-link a { 13 | color: white; 14 | text-decoration: none; 15 | text-transform: uppercase; 16 | font-family: sans-serif; 17 | font-weight: bold; 18 | } 19 | 20 | .subscribe-link a:after { 21 | content: "and disable all other filters before doing these tests"; 22 | font-size: 20px; 23 | display: block; 24 | padding-top: 3px; 25 | } -------------------------------------------------------------------------------- /public/Filters/qunit/readme_for_update.md: -------------------------------------------------------------------------------- 1 | ## Please do the following steps updating QUnit library: 2 | 3 | * Delete the old version of `qunit.js` and `qunit.css` 4 | * Download the actual version from https://qunitjs.com/ 5 | * Rename both files to `qunit.js` and `qunit.css` (remove version number from name) 6 | * DON'T REMOVE `custom.css` 7 | -------------------------------------------------------------------------------- /public/Filters/redirect-rules/README.md: -------------------------------------------------------------------------------- 1 | # $redirect rules test -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-files/csp-redirect-iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | Document 10 | 11 | 12 | 13 |
14 | 15 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-files/csp-redirect.js: -------------------------------------------------------------------------------- 1 | document.getElementById('case8').textContent = 'case8 script executed'; 2 | -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-files/redirect-exception-test.js: -------------------------------------------------------------------------------- 1 | document.getElementById('case6').innerText = 'redirect test'; 2 | -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-files/redirect-priority-test.js: -------------------------------------------------------------------------------- 1 | document.getElementById('case7').innerText = 'redirect test'; 2 | -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-files/redirect-test.css: -------------------------------------------------------------------------------- 1 | #case1 { 2 | width: 200px !important; 3 | } 4 | -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-files/redirect-test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $redirect test html page 7 | 8 | 9 | 10 |
$redirect test
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-files/redirect-test.js: -------------------------------------------------------------------------------- 1 | document.getElementById('case2').innerText = 'redirect test'; 2 | -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-files/redirect-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/redirect-rules/test-files/redirect-test.png -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-files/redirect-test.txt: -------------------------------------------------------------------------------- 1 | redirect test 2 | -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-redirect-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $redirect rules tests 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 |
18 |
19 | 20 | 21 |
22 |
23 | 24 |
25 | 26 | 27 |
28 | test-image 29 |
30 | 31 |
32 | 33 |
34 | 35 |
36 | 37 |
38 | 39 |
40 | 41 | 42 |
43 | 44 | 45 |
46 | 47 |
48 |
49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /public/Filters/redirect-rules/test-redirect-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $redirect rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-redirect-rules-filter 9 | ! 10 | ! Case 1 11 | ||*/redirect-test.css$redirect=noopcss 12 | ! Case 2 13 | ||*/redirect-test.js$redirect=noopjs 14 | ! Case 3 15 | ||*/redirect-test.png$redirect=2x2-transparent.png 16 | ! Case 4 17 | ||*/redirect-test.html$redirect=noopframe 18 | ! Case 5 19 | ||*/redirect-test.txt$redirect=nooptext 20 | ! Case 6 21 | ||*/redirect-exception-test.js$redirect=noopjs 22 | @@||*/redirect-exception-test.js 23 | ! Case 7 24 | ||*/redirect-priority-test.js$redirect=noopjs 25 | ||*/redirect-priority-test.js$important,csp=script-src 'self' 26 | 27 | ! Case 8 28 | ||*/csp-redirect.js$redirect=noopjs 29 | -------------------------------------------------------------------------------- /public/Filters/redirect-security/README.md: -------------------------------------------------------------------------------- 1 | ## $redirect resources security test 2 | 3 | 1. Makes request to some resource. 4 | 2. It's redirected to web-accessible resource by $redirect-rule. 5 | 3. Gets security key from the first request and makes second request to web-accessible resource using the same key. 6 | #### Expected behaviour: web-accessible resource request with the same security key should fail. 7 | 4. Makes third request to the same web-accessible resource, but without any security key. 8 | #### Expected behaviour: web-accessible resource request without security key should fail. 9 | 10 | * * * 11 | ## Compatible with AdGuard Browser extension with TSUrlFilter (version >= 4.0) 12 | -------------------------------------------------------------------------------- /public/Filters/redirect-security/test-redirect-security.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $redirect security tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /public/Filters/redirect-security/test-redirect-security.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $redirect security test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-redirect-security-filter 9 | ! 10 | ! Case 1 11 | ||*/redirect-test.html$redirect=click2load.html 12 | -------------------------------------------------------------------------------- /public/Filters/removeheader-rules/README.md: -------------------------------------------------------------------------------- 1 | ## Compatible with: 2 | 3 | 1. **AdGuard Browser extension v4.0** which uses TSUrlFilter 4 | 2. AdGuard for Windows, macOS and Android with **CoreLibs v1.8** 5 | -------------------------------------------------------------------------------- /public/Filters/removeheader-rules/test-removeheader-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Removeheader rules test 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /public/Filters/removeheader-rules/test-removeheader-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $removeheader rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-removeheader-rules-filter 9 | ! 10 | ! Case 1 11 | ||*/httpbin/response-headers^$removeheader=case1 12 | ! Case 2 13 | ||*/httpbin/response-headers^$removeheader=case2 14 | @@||*/httpbin/response-headers^$removeheader=case2 15 | ! 16 | ! Case 3 17 | ||*/httpbin/headers^$removeheader=request:case3 18 | ! 19 | ! Case 4 20 | ||*/httpbin/headers^$removeheader=request:case4 21 | @@||*/httpbin/headers^$removeheader=request:case4 22 | ! 23 | ! Case 5 24 | ||*/httpbin/headers^$removeheader=cache-control 25 | -------------------------------------------------------------------------------- /public/Filters/removeparam-rules/README.md: -------------------------------------------------------------------------------- 1 | ## Compatible with: 2 | 3 | 1. **AdGuard Browser extension v4.0** which uses TSUrlFilter 4 | 2. AdGuard for Windows, macOS and Android with **CoreLibs v1.8** 5 | 6 | Case 14 is supported by **CoreLibs v1.17** and by **TSUrlFilter** after **v3.1.0-alpha.7** 7 | 8 | ## Important: 9 | 10 | 1. The filter list should be added 11 | [as trusted](https://adguard.com/kb/general/ad-filtering/create-own-filters/#removeparam-modifier) 12 | 2. $removeparam tests should be run over **https** connection 13 | -------------------------------------------------------------------------------- /public/Filters/removeparam-rules/test-files/adg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/removeparam-rules/test-files/adg1.png -------------------------------------------------------------------------------- /public/Filters/removeparam-rules/test-removeparam-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Removeparam rules test 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/README.md: -------------------------------------------------------------------------------- 1 | # $replace rules tests: 2 | 3 | * ### Case 1 4 | Requested for file `test-files/case1-text-response.txt` and applied $replace rule (`Adguard` replaced to `Test passed`) 5 | 6 | * ### Case 2 7 | Requested for file (more then 3Mb) `test-files/case2-response-over-3mb.txt` and applied $replace rule (try to replace `Adguard` to `Test passed`) but $replace rule doesn't applied for response more then 3Mb. 8 | 9 | * ### Case 3 10 | Requested for file `test-files/case3-using-with-other-rules.txt` and applied two rules: with and without $replace modifier. 11 | 12 | * ### Case 4 13 | Requested for file `test-files/case4-multiple-replace-rules.txt` and applied two $replace rules (they must apllied alphabetically) 14 | 15 | * ### Case 5 16 | Requested for file `test-files/case5-disabling-replace-rule.txt` and applied two $replace rules and exception $replace rule. 17 | 18 | * ### Case 6 19 | Requested for file `test-files/case6-disabling-multiple-replace-rules.txt` and applied two $replace rules and exception $replace rule with pattern matching the second $replace rule (case from KB: Multiple $replace rules example) 20 | 21 | * ### Case 7 22 | Requested for script `test-files/case7-content-type-modifier.js` and applied $replace rule and rule with $script content type modifier 23 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-content-rule/README.md: -------------------------------------------------------------------------------- 1 | # $replace rule vs $content exception test 2 | 3 | ##Case 1 4 | * content rule ($$) hides element `id="case1-block2"`. 5 | * $replace rule applyed to element `id="case1-block1"`. 6 | * $content exception rule disables all other rules applied before. 7 | #### Expecting result: $replace rule is disabled and element `id="case1-block2"` is visible. -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-content-rule/replace-vs-content-rule.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $replace rule vs $content exception test 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 |
content rule disable a replace rule.
21 |
Test-banner
22 | 23 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-content-rule/replace-vs-content-rule.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import replace-vs-content-rule.txt to AdGuard 7 | */ 8 | 9 | window.addEventListener('DOMContentLoaded', () => { 10 | const adgCheck = isSubscribed('subscribe-to-replace-vs-content-rule-filter'); 11 | 12 | agTest(1, 'using with exception rule including $content modifier for a same request', (assert) => { 13 | const block1 = document.getElementById('case1-block1').innerText; 14 | const block2 = getComputedStyle(window.document.getElementById('case1-block2'), null).display === 'block'; 15 | assert.ok( 16 | block1 !== 'replace rule works' && block2 && adgCheck, 17 | 'Exception rule with $content modifier should disable the $replace rule', 18 | ); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-content-rule/replace-vs-content-rule.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $replace vs $content exception test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! 8 | ! Hide warning 9 | testcases.agrd.dev,pages.dev###subscribe-to-replace-vs-content-rule-filter 10 | ! 11 | ! Case 1: using with exception rules including $content modifier for a same request 12 | testcases.agrd.dev,pages.dev$$div[id="case1-block2"] 13 | ||testcases.agrd.dev$replace=/content\s+rule\s+disable\s+a\s+replace\s+rule\./replace rule works/i 14 | ||pages.dev$replace=/content\s+rule\s+disable\s+a\s+replace\s+rule\./replace rule works/i 15 | @@||testcases.agrd.dev$content 16 | @@||pages.dev$content 17 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-elemhide-rule/README.md: -------------------------------------------------------------------------------- 1 | # $replace rule vs $elemhide exceptions test 2 | 3 | ##Case 1 4 | * basic rule hides element subscription link. 5 | * $elemhide exception rule (disables basic rules) 6 | * $replace rule to change subscription link text to nothing. 7 | #### Expecting result: subscription link text is empty. -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-elemhide-rule/replace-vs-elemhide-rule.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $replace rule vs $elemhide exception test 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 |
$elemhide rule works proper.
21 | 22 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-elemhide-rule/replace-vs-elemhide-rule.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner } from '../../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import replace-vs-elemhide-rule.txt to AdGuard 7 | */ 8 | 9 | window.addEventListener('DOMContentLoaded', () => { 10 | agTest(1, 'using with exception rule including $elemhide modifier for a same request', (assert) => { 11 | const element = document.querySelector('#subscribe-to-replace-vs-elemhide-rule-filter > a').innerText; 12 | assert.equal(element, '', 'Exception rule with $elemhide modifier should not disable the $replace rule'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-elemhide-rule/replace-vs-elemhide-rule.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $replace vs $elemhide exceptions test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! 8 | ! Hide warning 9 | ||testcases.agrd.dev^$replace=/subscribe\s+to\s+test\s+filter//i 10 | ||pages.dev^$replace=/subscribe\s+to\s+test\s+filter//i 11 | ||testcases.agrd.dev^$replace=/and\s+disable\s+all\s+other\s+filters\s+before\s+doing\s+these\s+tests//i 12 | ||pages.dev^$replace=/and\s+disable\s+all\s+other\s+filters\s+before\s+doing\s+these\s+tests//i 13 | ! 14 | ! 15 | ! Case 1: using with exception rules including $elemhide modifier for a same request 16 | testcases.agrd.dev,pages.dev###subscribe-to-replace-vs-elemhide-rule-filter 17 | @@||testcases.agrd.dev^$elemhide 18 | @@||pages.dev^$elemhide 19 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-generichide-rule/README.md: -------------------------------------------------------------------------------- 1 | # $replace rule vs $generichide exception test 2 | 3 | ##Case 1 4 | * Generic rule hides element `id="case1-block1"`. 5 | * $generichide exception disables all generic cosmetic rules. 6 | * $replace rule applyed for `id="case1-block1"`. 7 | #### Expecting result: $generichide exception doesn't block $replace rule (text in element `id="case1-block1"` is replaced) -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-generichide-rule/replace-vs-generichide-rule.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $replace rule vs $generichide exceptions test 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 |
$generichide rule works proper.
21 | 22 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-generichide-rule/replace-vs-generichide-rule.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner } from '../../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import replace-vs-generichide-rule.txt to AdGuard 7 | */ 8 | 9 | window.addEventListener('DOMContentLoaded', () => { 10 | agTest(1, 'using with exception rule including $generichide modifier for a same request', (assert) => { 11 | const element = document.getElementById('case1-block1').textContent; 12 | const expect = "$generichide rule doesn't block a replace rule."; 13 | assert.equal(element, expect, 'Exception rule with $generichide modifier should not disable the $replace rule'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/replace-vs-generichide-rule/replace-vs-generichide-rule.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $replace vs $generichide exceptions test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! 8 | ! Hide warning 9 | testcases.agrd.dev,pages.dev###subscribe-to-replace-vs-generichide-rule-filter 10 | ! 11 | ! 12 | ! Case 1: using with exception rules including $generichide and $elemhide modifiers for a same request 13 | ###case1-block1 14 | @@||testcases.agrd.dev^$generichide 15 | @@||pages.dev^$generichide 16 | ||testcases.agrd.dev^$replace=/works\s+proper/doesn't block a replace rule/i 17 | ||pages.dev^$replace=/works\s+proper/doesn't block a replace rule/i 18 | -------------------------------------------------------------------------------- /public/Filters/replace-rules/test-files/case1-text-response.txt: -------------------------------------------------------------------------------- 1 | Adguard -------------------------------------------------------------------------------- /public/Filters/replace-rules/test-files/case3-using-with-other-rules.txt: -------------------------------------------------------------------------------- 1 | Adguard -------------------------------------------------------------------------------- /public/Filters/replace-rules/test-files/case4-multiple-replace-rules.txt: -------------------------------------------------------------------------------- 1 | Adguard team -------------------------------------------------------------------------------- /public/Filters/replace-rules/test-files/case5-disabling-replace-rule.txt: -------------------------------------------------------------------------------- 1 | Adguard -------------------------------------------------------------------------------- /public/Filters/replace-rules/test-files/case6-disabling-multiple-replace-rules.txt: -------------------------------------------------------------------------------- 1 | Adguard works -------------------------------------------------------------------------------- /public/Filters/replace-rules/test-files/case7-content-type-modifier.js: -------------------------------------------------------------------------------- 1 | const tmp = 0 -------------------------------------------------------------------------------- /public/Filters/replace-rules/test-replace-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Replace rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /public/Filters/script-rules/README.md: -------------------------------------------------------------------------------- 1 | ## Supported by AdGuard for iOS since iOS 15 and AdGuard for iOS v4.3 2 | -------------------------------------------------------------------------------- /public/Filters/script-rules/jsinject-rules/README.md: -------------------------------------------------------------------------------- 1 | ## Supported by AdGuard for iOS since iOS 15 and AdGuard for iOS v4.3 2 | -------------------------------------------------------------------------------- /public/Filters/script-rules/jsinject-rules/test-jsinject-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Jsinject rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/Filters/script-rules/jsinject-rules/test-jsinject-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-jsinject-rules.txt to AdGuard 7 | */ 8 | window.addEventListener('load', () => { 9 | const adgCheck = isSubscribed('subscribe-to-test-jsinject-rules-filter'); 10 | 11 | agTest(1, 'script rule', (assert) => { 12 | assert.ok(adgCheck && !document.__jsinjectTest); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /public/Filters/script-rules/jsinject-rules/test-jsinject-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for jsinject rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-jsinject-rules-filter 9 | ! 10 | ! Case 1 11 | testcases.agrd.dev,pages.dev#%#document.__jsinjectTest = true; 12 | @@testcases.agrd.dev^$jsinject 13 | @@pages.dev^$jsinject 14 | -------------------------------------------------------------------------------- /public/Filters/script-rules/test-script-firefox/test-script-firefox.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Script rules tests for Firefox browser 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/Filters/script-rules/test-script-firefox/test-script-firefox.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-script-firefox.txt to AdGuard 7 | */ 8 | window.addEventListener('load', () => { 9 | const adgCheck = isSubscribed('subscribe-to-test-script-firefox-filter'); 10 | 11 | agTest(1, 'script rule', (assert) => { 12 | assert.ok(adgCheck && !window.__firefoxTest1, 'Script rule does not work in Firefox'); 13 | }); 14 | 15 | agTest(2, 'script rule for cookie', (assert) => { 16 | const cookies = document.cookie; 17 | assert.ok(adgCheck && !cookies.includes('adg_test'), 'Script rule for cookies does not work in Firefox'); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /public/Filters/script-rules/test-script-firefox/test-script-firefox.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for script rules test in Firefox browser 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev###subscribe-to-test-script-firefox-filter 9 | ! 10 | ! Case 1 11 | testcases.agrd.dev#%#window.__firefoxTest1 = true; 12 | ! Case 2 13 | testcases.agrd.dev#%#document.cookie = "adg_test"; 14 | -------------------------------------------------------------------------------- /public/Filters/script-rules/test-script-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Script rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/Filters/script-rules/test-script-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-script-rules.txt to AdGuard 7 | */ 8 | window.addEventListener('load', () => { 9 | const adgCheck = isSubscribed('subscribe-to-test-script-rules-filter'); 10 | 11 | agTest(1, 'script rule', (assert) => { 12 | assert.ok(window.__testCase1, 'Script rule works'); 13 | }); 14 | 15 | agTest(2, 'script rule exception', (assert) => { 16 | assert.ok(adgCheck && window.adg_test === true, 'Exception script rule should disable script rule'); 17 | }); 18 | 19 | agTest(3, 'script rules order', (assert) => { 20 | assert.ok(window.orderTest === '1234', 'Rules have been applied in proper order'); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /public/Filters/script-rules/test-script-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for script rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-script-rules-filter 9 | ! 10 | ! Case 1 11 | testcases.agrd.dev,pages.dev#%#window.__testCase1 = true; 12 | ! 13 | ! Case 2 14 | testcases.agrd.dev,pages.dev#%#window.adg_test=true; 15 | testcases.agrd.dev,pages.dev#%#window.adg_test=false; 16 | testcases.agrd.dev,pages.dev#@%#window.adg_test=false; 17 | ! 18 | ! Case 3 19 | testcases.agrd.dev,pages.dev#%#window.orderTest = "" 20 | testcases.agrd.dev,pages.dev#%#window.orderTest += "1" 21 | testcases.agrd.dev,pages.dev#%#window.orderTest += "2" 22 | testcases.agrd.dev,pages.dev#%#window.orderTest += "3" 23 | testcases.agrd.dev,pages.dev#%#window.orderTest += "4" 24 | -------------------------------------------------------------------------------- /public/Filters/scriptlet-rules/README.md: -------------------------------------------------------------------------------- 1 | ## Scriptlets rules tests 2 | Supported by AdGuard for iOS since iOS 15 and AdGuard for iOS v4.3 3 | 4 | ## Allowlist scriptlets rules tests 5 | Supported by CoreLibs since v1.16 6 | 7 | ## Scriptlets trusted-set-cookie rules tests 8 | Supported by Scriptlets v1.12.1 or later 9 | -------------------------------------------------------------------------------- /public/Filters/scriptlet-rules/allowlist-general/test-scriptlet-allowlist-general-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Scriptlet allowlist general rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/Filters/scriptlet-rules/allowlist-general/test-scriptlet-allowlist-general-rules.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-eval */ 2 | 3 | import { getAgTestRunner } from '../../helpers.js'; 4 | 5 | const agTest = getAgTestRunner(window.location); 6 | 7 | /** 8 | * Before doing the test, import test-scriptlet-allowlist-general-rules.txt to AdGuard 9 | */ 10 | 11 | const clearProperties = (...props) => { 12 | props.forEach((prop) => { 13 | try { 14 | delete window[prop]; 15 | } catch (e) { 16 | try { 17 | // sometimes property deleting is not allowed 18 | // e.g. in Safari 19 | window[prop] = null; 20 | // eslint-disable-next-line @typescript-eslint/no-shadow 21 | } catch (e) { 22 | // ignore 23 | } 24 | } 25 | }); 26 | }; 27 | 28 | window.addEventListener('load', () => { 29 | agTest(1, 'allowlist-all', (assert) => { 30 | // `set-constant` scriptlets allowlisted 31 | const testVal = 'testVal'; 32 | assert.strictEqual(window[testVal], undefined, testVal); 33 | clearProperties(testVal); 34 | // `prevent-eval-if` also allowlisted 35 | eval('(function(preventIfTest) { window.test = "value" }) ()'); 36 | assert.equal(window.test, 'value', 'Do not prevent eval by string "preventIfTest"'); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /public/Filters/scriptlet-rules/allowlist-general/test-scriptlet-allowlist-general-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for scriptlet allowlist general rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-scriptlet-allowlist-general-rules-filter 9 | ! 10 | ! allowlist-all 11 | ! 12 | testcases.agrd.dev,pages.dev#%#//scriptlet("set-constant", "testVal", "true") 13 | testcases.agrd.dev,pages.dev#%#//scriptlet("prevent-eval-if", "preventIfTest") 14 | testcases.agrd.dev,pages.dev#@%#//scriptlet() 15 | -------------------------------------------------------------------------------- /public/Filters/scriptlet-rules/allowlist-specific/test-scriptlet-allowlist-specific-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Scriptlet allowlist specific rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/Filters/scriptlet-rules/allowlist-specific/test-scriptlet-allowlist-specific-rules.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-eval */ 2 | 3 | import { getAgTestRunner } from '../../helpers.js'; 4 | 5 | const agTest = getAgTestRunner(window.location); 6 | 7 | /** 8 | * Before doing the test, import test-scriptlet-allowlist-specific-rules.txt to AdGuard 9 | */ 10 | 11 | const clearProperties = (...props) => { 12 | props.forEach((prop) => { 13 | try { 14 | delete window[prop]; 15 | } catch (e) { 16 | try { 17 | // sometimes property deleting is not allowed 18 | // e.g. in Safari 19 | window[prop] = null; 20 | // eslint-disable-next-line @typescript-eslint/no-shadow 21 | } catch (e) { 22 | // ignore 23 | } 24 | } 25 | }); 26 | }; 27 | 28 | window.addEventListener('load', () => { 29 | agTest(1, 'allowlist-specific', (assert) => { 30 | // Rule not allowlisted 31 | const firstVal = 'firstVal'; 32 | assert.strictEqual(window[firstVal], true, firstVal); 33 | clearProperties(firstVal); 34 | 35 | // Rule allowlisted 36 | const secondVal = 'secondVal'; 37 | assert.strictEqual(window[secondVal], undefined, secondVal); 38 | clearProperties(secondVal); 39 | }); 40 | 41 | agTest(2, 'allowlist-by-name', (assert) => { 42 | // `prevent-eval-if` allowlisted 43 | eval('(function(preventIfTest) { window.test = "value" }) ()'); 44 | assert.equal(window.test, 'value', 'Do not prevent eval by string "preventIfTest"'); 45 | 46 | // `set-constant` scriptlet still works 47 | const testVal = 'testVal'; 48 | assert.strictEqual(window[testVal], true, testVal); 49 | clearProperties(testVal); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /public/Filters/scriptlet-rules/allowlist-specific/test-scriptlet-allowlist-specific-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for scriptlet allowlist specific rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-scriptlet-allowlist-specific-rules-filter 9 | ! 10 | ! allowlist-specific 11 | ! 12 | testcases.agrd.dev,pages.dev#%#//scriptlet("set-constant", "firstVal", "true") 13 | testcases.agrd.dev,pages.dev#@%#//scriptlet("set-constant", "firstVal", "false") 14 | testcases.agrd.dev,pages.dev#%#//scriptlet("set-constant", "secondVal", "true") 15 | testcases.agrd.dev,pages.dev#@%#//scriptlet("set-constant", "secondVal", "true") 16 | ! 17 | ! allowlist-by-name 18 | ! 19 | testcases.agrd.dev,pages.dev#%#//scriptlet("set-constant", "testVal", "true") 20 | testcases.agrd.dev,pages.dev#%#//scriptlet("prevent-eval-if", "preventIfTest") 21 | testcases.agrd.dev,pages.dev#@%#//scriptlet("prevent-eval-if") 22 | -------------------------------------------------------------------------------- /public/Filters/scriptlet-rules/test-scriptlet-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Scriptlet rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/Filters/specifichide-rules/README.md: -------------------------------------------------------------------------------- 1 | ## Compatible with: 2 | 3 | 1. **AdGuard Browser extension v4.0** which uses TSUrlFilter 4 | 2. AdGuard for Windows, macOS and Android with **CoreLibs v1.8** 5 | -------------------------------------------------------------------------------- /public/Filters/specifichide-rules/test-specifichide-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Specifichide rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 24 | 25 |
26 |
27 |
28 |
29 | 30 |
31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /public/Filters/specifichide-rules/test-specifichide-rules.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-arrow-callback, func-names */ 2 | 3 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 4 | 5 | const agTest = getAgTestRunner(window.location); 6 | 7 | /** 8 | * Before doing the test, import test-specifichide-rules.txt to AdGuard 9 | */ 10 | 11 | window.addEventListener('load', function () { 12 | const adgCheck = isSubscribed('subscribe-to-test-specifichide-rules-filter'); 13 | 14 | agTest(1, '$specifichide modifier', function (assert) { 15 | const element = document.querySelector('#case-1 > .test-banner-1'); 16 | assert.ok( 17 | adgCheck 18 | && window.getComputedStyle(element).display === 'block', 19 | 'Rule with specifichide modifier should disable basic rule', 20 | ); 21 | }); 22 | 23 | agTest(2, '$specifichide modifier vs generic basic rule', function (assert) { 24 | const element = document.querySelector('#case-2 > .test-banner-2'); 25 | assert.ok( 26 | adgCheck 27 | && window.getComputedStyle(element).display === 'none', 28 | "Rule with specifichide modifier shouldn't disable generic basic rule", 29 | ); 30 | }); 31 | 32 | agTest(3, '$specifichide modifier vs generic css rule', function (assert) { 33 | const element = document.querySelector('#case-3 > .test-banner-3'); 34 | assert.ok( 35 | adgCheck 36 | && window.getComputedStyle(element).display === 'block' 37 | && window.getComputedStyle(element).width === '200px', 38 | "Rule with specifichide modifier shouldn't disable generic css rule", 39 | ); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /public/Filters/specifichide-rules/test-specifichide-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for specifichide rules tests 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | ###subscribe-to-test-specifichide-rules-filter 9 | ! Test case 1: Test rule with specifichide modifier 10 | testcases.agrd.dev,pages.dev###case-1 > .test-banner-1 11 | @@||testcases.agrd.dev^$specifichide 12 | @@||pages.dev^$specifichide 13 | ! Test case 2: Test rule with specifichide modifier vs generic basic rule 14 | ###case-2 > .test-banner-2 15 | ! Test case 3: Test rule with specifichide modifier vs generic css rule 16 | #$##case-3 > .test-banner-3 { width: 200px !important; } 17 | -------------------------------------------------------------------------------- /public/Filters/strict-party-rules/README.md: -------------------------------------------------------------------------------- 1 | ## Supported by CoreLibs since v1.16 2 | -------------------------------------------------------------------------------- /public/Filters/strict-party-rules/test-strict-party-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $jsonprune rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /public/Filters/strict-party-rules/test-strict-party-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isBlockedFetch, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-strict-party-rules.txt to AdGuard 7 | */ 8 | 9 | const baseUrl = `${window.location.origin}/httpbin`; 10 | const httpbinUrl = 'https://httpbin.agrd.dev'; 11 | 12 | window.addEventListener('load', () => { 13 | const adgCheck = isSubscribed('subscribe-to-test-strict-party-rules-filter'); 14 | 15 | agTest(1, 'strict-third-party test', async (assert) => { 16 | assert.ok(adgCheck); 17 | 18 | let isBlocked; 19 | const blockedTestUrl = `${httpbinUrl}/xml`; 20 | isBlocked = await isBlockedFetch(blockedTestUrl); 21 | assert.ok(isBlocked, 'Request to subdomain is treated as strictly third-party and blocked'); 22 | 23 | const notBlockedTestUrl = `${baseUrl}/xml`; 24 | isBlocked = await isBlockedFetch(notBlockedTestUrl); 25 | assert.ok(!isBlocked, 'Request to the same domain is not strictly third-party and not blocked'); 26 | }); 27 | 28 | agTest(2, 'strict-first-party test', async (assert) => { 29 | assert.ok(adgCheck); 30 | 31 | let isBlocked; 32 | const blockedTestUrl = `${baseUrl}/anything`; 33 | isBlocked = await isBlockedFetch(blockedTestUrl); 34 | assert.ok(isBlocked, 'Request to the same domain is strictly first-party and blocked'); 35 | 36 | const notBlockedTestUrl = `${httpbinUrl}/anything`; 37 | isBlocked = await isBlockedFetch(notBlockedTestUrl); 38 | assert.ok(!isBlocked, 'Request to the sub domain is non strictly first-party and not blocked'); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /public/Filters/strict-party-rules/test-strict-party-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for strict-party rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-strict-party-rules-filter 9 | ! 10 | ! Case 1 - strict-third-party 11 | ||httpbin.agrd.dev/xml^$strict-third-party 12 | ||*/httpbin/xml^$strict-third-party 13 | ! Case 2 - strict-first-party 14 | ||httpbin.agrd.dev/anything^$strict-first-party 15 | ||*/httpbin/anything^$strict-first-party 16 | -------------------------------------------------------------------------------- /public/Filters/subdocument-rules/README.md: -------------------------------------------------------------------------------- 1 | ## Compatible with: 2 | 3 | * AdGuard for Safari v1.11.0+ on macOS Monterey 4 | * AdGuard for iOS v4.3.0+ on iOS 15 5 | 6 | In case of macOS Big Sur and Safari 15 we convert rules for Safari 14 to avoid resources types errors. 7 | -------------------------------------------------------------------------------- /public/Filters/subdocument-rules/test-files/subdocument-test-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/subdocument-rules/test-files/subdocument-test-1.png -------------------------------------------------------------------------------- /public/Filters/subdocument-rules/test-files/subdocument-test-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/subdocument-rules/test-files/subdocument-test-2.png -------------------------------------------------------------------------------- /public/Filters/subdocument-rules/test-files/subdocument-test-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/subdocument-rules/test-files/subdocument-test-3.png -------------------------------------------------------------------------------- /public/Filters/subdocument-rules/test-files/subdocument-test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | iframe test html page 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /public/Filters/subdocument-rules/test-subdocument-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Subdocument rules tests for Safari 15+ 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 23 | 24 |
25 |
26 | 27 |
28 |
29 | 30 |
31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /public/Filters/subdocument-rules/test-subdocument-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for subdocument rules tests 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | ###subscribe-to-test-subdocument-rules-filter 9 | ! Test case 1: Test rule with subdocument modifier 10 | ||*/subdocument-test-1.png^$subdocument,domain=testcases.agrd.dev|pages.dev 11 | ! Test case 2: Test rule with negated subdocument modifier 12 | ||*/subdocument-test-2.png^$~subdocument,domain=testcases.agrd.dev|pages.dev 13 | ! Test case 3: Test exclusion rule with subdocument modifier 14 | ||*/subdocument-test-3.png^$subdocument,domain=testcases.agrd.dev|pages.dev 15 | @@||*/subdocument-test-3.png^$subdocument,domain=testcases.agrd.dev|pages.dev 16 | ||*/subdocument-test-3.png^$~subdocument,domain=testcases.agrd.dev|pages.dev 17 | @@||*/subdocument-test-3.png^$~subdocument,domain=testcases.agrd.dev|pages.dev 18 | -------------------------------------------------------------------------------- /public/Filters/to-rules/README.md: -------------------------------------------------------------------------------- 1 | # $to rules tests 2 | Compatible with AdGuard products, **that run CoreLibs v1.12 or later**, and AdGuard Browser extensions, **that run tsurlfilter v2.1.3 or later** 3 | 4 | ### Case 1 5 | Rule with `$to` modifier blocks request to a specified domain. 6 | Rule does not block requests to other domains. 7 | ### Case 2 8 | Allowlist rule with `$to` modifier allows requests to a specified domain. 9 | -------------------------------------------------------------------------------- /public/Filters/to-rules/assets/adguard_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/to-rules/assets/adguard_circle.png -------------------------------------------------------------------------------- /public/Filters/to-rules/assets/adguard_dns_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Filters/to-rules/assets/adguard_dns_map.png -------------------------------------------------------------------------------- /public/Filters/to-rules/test-to-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $to rules tests 7 | 8 | 9 | 14 | 15 | 16 | 19 |
20 |
21 |
22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /public/Filters/to-rules/test-to-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | /** 6 | * Before doing the test, import test-to-rules.txt to AdGuard 7 | */ 8 | 9 | function loadImage(src) { 10 | return new Promise(((resolve) => { 11 | const testImg = document.createElement('img'); 12 | testImg.setAttribute('src', src); 13 | testImg.addEventListener('load', () => { 14 | resolve(testImg); 15 | }); 16 | testImg.addEventListener('error', () => { 17 | resolve(testImg); 18 | }); 19 | document.getElementById('test-container').appendChild(testImg); 20 | })); 21 | } 22 | 23 | window.addEventListener('DOMContentLoaded', () => { 24 | agTest(1, '$to rule blocks request to a specified domain', async (assert) => { 25 | const PASS_URL = '/Filters/to-rules/assets/adguard_circle.png'; 26 | // eslint-disable-next-line max-len 27 | const BLOCK_URL = 'https://raw.githubusercontent.com/AdguardTeam/TestCases/master/public/Filters/denyallow-rules/assets/adguard_circle.png'; 28 | 29 | const testLoadImg = await loadImage(PASS_URL); 30 | assert.ok(testLoadImg.height > 5); 31 | 32 | const testBlockedImg = await loadImage(BLOCK_URL); 33 | assert.notOk(testBlockedImg.height > 5); 34 | }); 35 | agTest(2, '$to rule ublocks request to a specified domain', async (assert) => { 36 | const PASS_URL = '/Filters/to-rules/assets/adguard_dns_map.png'; 37 | // eslint-disable-next-line max-len 38 | const BLOCK_URL = 'https://raw.githubusercontent.com/AdguardTeam/TestCases/master/public/Filters/denyallow-rules/assets/adguard_dns_map.png'; 39 | 40 | const testLoadImg = await loadImage(PASS_URL); 41 | assert.ok(testLoadImg.height > 5); 42 | 43 | const testBlockedImg = await loadImage(BLOCK_URL); 44 | assert.notOk(testBlockedImg.height > 5); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /public/Filters/to-rules/test-to-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $to rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-to-rules-filter 9 | ! 10 | ! Case 1 11 | /adguard_circle.png$image,to=raw.githubusercontent.com 12 | ! Case 2 13 | /adguard_dns_map.png 14 | @@/adguard_dns_map.png^$to=testcases.agrd.dev|pages.dev|~raw.githubusercontent.com 15 | -------------------------------------------------------------------------------- /public/Filters/urltransform-rules/README.md: -------------------------------------------------------------------------------- 1 | # $urltransform rules test 2 | 3 | Note: Cases 3 and 4 are valid starting with CoreLibs 1.16.19. 4 | 5 | ## Case 1 6 | * Try fetching a resource from an invalid URL. 7 | * A `$urltransform` rule should transform an invalid URL into a valid one. 8 | * Expect fetch success. 9 | 10 | ## Case 2 11 | * Try POSTing to an invalid URL. 12 | * A `$urltransform` rule should transform an invalid URL into a valid one. 13 | * A `$urltransform` rules should NOT break the POST request by redirecting it. 14 | * Expect POST success. 15 | 16 | ## Case 3 17 | * Try fetching a resource from an invalid URL. 18 | * A `$urltransform` rule should transform an invalid URL into a valid one, changing the origin. 19 | * Expect fetch success. 20 | 21 | ## Case 4 22 | * Try POSTing to an invalid URL. 23 | * A `$urltransform` rule that changes the origin should not be applied to a POST request. 24 | * Expect fetch failure. 25 | -------------------------------------------------------------------------------- /public/Filters/urltransform-rules/test-urltransform-rules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $urltransform rules tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /public/Filters/urltransform-rules/test-urltransform-rules.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | window.addEventListener('DOMContentLoaded', () => { 6 | const adgCheck = isSubscribed('subscribe-to-test-urltransform-rules-filter'); 7 | 8 | agTest(1, '$urltransform rule', async (assert) => { 9 | const response = await fetch('https://httpbin.agrd.dev/status/500'); 10 | assert.ok(adgCheck && response.ok, '$urltransform rule should transform an invalid URL into a valid one'); 11 | }); 12 | 13 | agTest(2, "$urltransform rule doesn't break POST requests", async (assert) => { 14 | const response = await fetch('https://httpbin.agrd.dev/royalmail', { method: 'POST', body: 'testdata' }); 15 | assert.ok(adgCheck && response.ok, '$urltransform rule should not break POST requests'); 16 | }); 17 | 18 | agTest(3, '$urltransform rule can change the origin', async (assert) => { 19 | try { 20 | const response = await fetch('https://example.org/status/200'); 21 | assert.ok(adgCheck && response.ok, '$urltransform rule should change the origin'); 22 | } catch (TypeError) { 23 | assert.true(false, '$urltransform rule should change the origin'); 24 | } 25 | }); 26 | 27 | agTest(4, "$urltransform rule doesn't change the origin for a POST request", async (assert) => { 28 | try { 29 | const response = await fetch('https://example.org/post', { method: 'POST', body: 'testdata' }); 30 | assert.ok(adgCheck && !response.ok, '$urltransform rule should not change the origin for a POST request'); 31 | } catch (TypeError) { 32 | // Succeed: TypeError is thrown because example.org don't send Access-Control-Allow-Origin with our origin 33 | assert.true(true, ''); 34 | } 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /public/Filters/urltransform-rules/test-urltransform-rules.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for $urltransform rules test 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-urltransform-rules-filter 9 | ! 10 | ! Case 1 11 | ||httpbin.agrd.dev^$urltransform=/^\/status\/500\$/\/status\/200/ 12 | ! 13 | ! Case 2 14 | ||httpbin.agrd.dev^$urltransform=/royalmail/post/ 15 | ! Case 3 and 4 16 | ||example.org^$urltransform=/^https:\/\/example.org/https:\/\/httpbin.agrd.dev/ 17 | -------------------------------------------------------------------------------- /public/Filters/websockets/test-websockets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Websocket tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /public/Filters/websockets/test-websockets.js: -------------------------------------------------------------------------------- 1 | import { getAgTestRunner, isSubscribed } from '../helpers.js'; 2 | 3 | const agTest = getAgTestRunner(window.location); 4 | 5 | const baseUrl = 'wss://httpbin.agrd.dev'; 6 | 7 | /** 8 | * Before doing the test, import test-websockets.txt to AdGuard 9 | */ 10 | window.addEventListener('load', () => { 11 | const adgCheck = isSubscribed('subscribe-to-test-websockets-filter'); 12 | 13 | agTest(1, 'valid websocket connection', (assert) => { 14 | if (!window.WebSocket) { 15 | assert.ok(true, 'Browser does not support WebSocket'); 16 | return; 17 | } 18 | 19 | const done = assert.async(); 20 | const ws = new WebSocket(`${baseUrl}/ws?valid`); 21 | 22 | ws.onopen = () => { 23 | assert.ok(adgCheck && 'Connection is open'); 24 | done(); 25 | }; 26 | 27 | /* eslint-disable-next-line no-multi-assign */ 28 | ws.onerror = ws.onclose = () => { 29 | assert.notOk('Connection error'); 30 | done(); 31 | }; 32 | }); 33 | 34 | agTest(2, 'blocking simple websocket connection', (assert) => { 35 | if (!window.WebSocket) { 36 | assert.ok(true, 'Browser does not support WebSocket'); 37 | return; 38 | } 39 | 40 | const done = assert.async(); 41 | const ws = new WebSocket(`${baseUrl}/ws?blocked`); 42 | 43 | ws.onopen = () => { 44 | assert.notOk('Connection is open'); 45 | done(); 46 | }; 47 | 48 | /* eslint-disable-next-line no-multi-assign */ 49 | ws.onerror = ws.onclose = () => { 50 | assert.ok('Connection is blocked'); 51 | done(); 52 | ws.onerror = null; 53 | ws.onclose = null; 54 | }; 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /public/Filters/websockets/test-websockets.txt: -------------------------------------------------------------------------------- 1 | ! 2 | ! Title: Rules for websocket rules tests 3 | ! 4 | ! Filter to be used for testing purposes 5 | ! https://testcases.agrd.dev 6 | ! 7 | ! Hide warning 8 | testcases.agrd.dev,pages.dev###subscribe-to-test-websockets-filter 9 | ! Test case 1: unblocking connection 10 | ||httpbin.agrd.dev/ws?valid 11 | @@||httpbin.agrd.dev/ws?valid 12 | ! Test case 2: blocking connection 13 | ||httpbin.agrd.dev/ws?blocked 14 | -------------------------------------------------------------------------------- /public/PopupBlocker/README.md: -------------------------------------------------------------------------------- 1 | ### Popup Blocking Test Instructions 2 | 3 | 1. Click on a button from the first row in the provided test interface [screenshot](https://uploads.adguard.org/Image_2024-08-07_18-37-07.png). 4 | 5 | 2. This action sets a listener on the document with various methods to trigger a popup. The listener is activated when you click anywhere on the document. 6 | 7 | 3. Click on a button in the first row, then click on an empty space in the document. The popup should be blocked. 8 | 9 | 4. Repeat the process: click the next button, then click on an empty space. The popup should be blocked again. 10 | -------------------------------------------------------------------------------- /public/PopupBlocker/popup-opener-iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /public/PopupBlocker/test-event-recovery-child.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
123
456
789
22 | 23 | 40 | 41 |
Clicked position
42 | 43 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /public/PopupBlocker/test-event-recovery.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /public/PopupBlocker/test-popup-blocker-rules.txt: -------------------------------------------------------------------------------- 1 | ||evilsite.com^$popup 2 | -------------------------------------------------------------------------------- /public/PopupBlocker/test-popup-blocker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 18 |

Clicking on each of buttons below will install a popup in the current page.

19 | 20 | 21 | 22 | 27 |

Clicking on buttons below will install a popup which shouldn't be blocked.

28 |

This test may interfere with browser's built-in popup blockers, so be sure to disable it on the testpage in order to test only the popup blocker.

29 | 34 |

Clicking on another button will remove a previous popup and install a new one.

35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /public/PopupBlocker/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * CustomEvent polyfill 3 | * from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill 4 | */ 5 | /* eslint-disable-next-line func-names, consistent-return */ 6 | (function () { 7 | if (typeof window.CustomEvent === 'function') return false; 8 | 9 | function CustomEvent(event, params) { 10 | /* eslint-disable-next-line no-param-reassign */ 11 | params = params || { bubbles: false, cancelable: false, detail: undefined }; 12 | const evt = document.createEvent('CustomEvent'); 13 | evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 14 | return evt; 15 | } 16 | 17 | CustomEvent.prototype = window.Event.prototype; 18 | 19 | window.CustomEvent = CustomEvent; 20 | }()); 21 | -------------------------------------------------------------------------------- /public/Userscripts/GMapiV4Tester/1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Userscripts/GMapiV4Tester/1x1.png -------------------------------------------------------------------------------- /public/Userscripts/GMapiV4Tester/resource.js: -------------------------------------------------------------------------------- 1 | 'привет, я resource'; 2 | -------------------------------------------------------------------------------- /public/Userscripts/TestGrantNone/testscript.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Test Grant None 3 | // @version 0.1 4 | // @author You 5 | // @match http://*/* 6 | // @grant none 7 | // ==/UserScript== 8 | 9 | (function() { 10 | 'use strict'; 11 | 12 | console.log('test') 13 | })(); -------------------------------------------------------------------------------- /public/Userscripts/apiTester/1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/Userscripts/apiTester/1x1.png -------------------------------------------------------------------------------- /public/Userscripts/apiTester/resource.js: -------------------------------------------------------------------------------- 1 | "привет, я resource" -------------------------------------------------------------------------------- /public/Userscripts/gmapi-v4-tests.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Greasemonkey API v4 tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /public/Userscripts/gmapi-v4-tests.js: -------------------------------------------------------------------------------- 1 | /* global QUnit */ 2 | 3 | /** 4 | * Before doing the test, install Greasemonkey API v4 Tester userscrip 5 | */ 6 | window.addEventListener('load', () => { 7 | if (!window.GmTests) { 8 | alert('You need to have Greasemonkey API v4 Tester userscript installed!'); 9 | return; 10 | } 11 | 12 | const startTest = (testName, assert) => { 13 | const testFunction = window.GmTests[testName]; 14 | assert.ok(testFunction); 15 | testFunction(assert); 16 | }; 17 | 18 | QUnit.test('GM.info', async (assert) => { 19 | startTest('GM.info', assert); 20 | }); 21 | 22 | QUnit.test('GM.setValue and GM.getValue', async (assert) => { 23 | startTest('GM.setValue and GM.getValue', assert); 24 | }); 25 | 26 | QUnit.test('GM.deleteValue', async (assert) => { 27 | startTest('GM.deleteValue', assert); 28 | }); 29 | 30 | QUnit.test('GM.listValues', async (assert) => { 31 | startTest('GM.listValues', assert); 32 | }); 33 | 34 | QUnit.test('GM.getResourceUrl', async (assert) => { 35 | startTest('GM.getResourceUrl', assert); 36 | }); 37 | 38 | QUnit.test('GM.xmlHttpRequest', (assert) => { 39 | startTest('GM.xmlHttpRequest', assert); 40 | }); 41 | 42 | QUnit.test('GM.notification', (assert) => { 43 | startTest('GM.notification', assert); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /public/Userscripts/qunit/custom.css: -------------------------------------------------------------------------------- 1 | /** SUBSCRIBE LINK */ 2 | 3 | .subscribe-link { 4 | font-size: 46px; 5 | padding: 50px; 6 | text-align: center; 7 | background: #EE5757; 8 | border-radius: 5px; 9 | margin-bottom: 8px; 10 | } 11 | 12 | .subscribe-link a { 13 | color: white; 14 | text-decoration: none; 15 | text-transform: uppercase; 16 | font-family: sans-serif; 17 | font-weight: bold; 18 | } 19 | 20 | .subscribe-link a:after { 21 | content: "and disable all other filters before doing these tests"; 22 | font-size: 20px; 23 | display: block; 24 | padding-top: 3px; 25 | } -------------------------------------------------------------------------------- /public/Userscripts/test-userscripts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Userscripts tests 8 | 9 | 10 | 11 | 12 | 13 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /public/Userscripts/test-userscripts.js: -------------------------------------------------------------------------------- 1 | /* global QUnit */ 2 | 3 | /** 4 | * Before doing the test, install apiTester userscript 5 | */ 6 | window.addEventListener('load', function() { 7 | if (!window.tests) { 8 | alert('You need to have apiTester userscript installed!'); 9 | return; 10 | } 11 | 12 | const startTest = function (testName, assert) { 13 | const testFunction = window.tests[testName]; 14 | assert.ok(testFunction); 15 | testFunction(assert); 16 | }; 17 | 18 | QUnit.test('GM_info', function (assert) { 19 | startTest('GM_info', assert); 20 | }); 21 | 22 | QUnit.test('GM_setValue', function (assert) { 23 | startTest('GM_setValue', assert); 24 | }); 25 | 26 | QUnit.test('GM_deleteValue', function (assert) { 27 | startTest('GM_deleteValue', assert); 28 | }); 29 | 30 | QUnit.test('GM_listValues', function (assert) { 31 | startTest('GM_listValues', assert); 32 | }); 33 | 34 | QUnit.test('GM_getResourceText', function (assert) { 35 | startTest('GM_getResourceText', assert); 36 | }); 37 | 38 | QUnit.test('GM_getResourceURL', function (assert) { 39 | startTest('GM_getResourceURL', assert); 40 | }); 41 | 42 | QUnit.test('GM_addStyle', function (assert) { 43 | startTest('GM_addStyle', assert); 44 | }); 45 | 46 | QUnit.test('GM_xmlhttpRequest', function (assert) { 47 | startTest('GM_xmlhttpRequest', assert); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /public/Web/etag.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Etag test 7 | 8 | 9 | 10 | 11 | Read details here 12 | 13 | 14 | -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdguardTeam/TestCases/1886eb28096e71ad0c17b577f9283f4af2ef2af7/public/favicon.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | AdGuard Filters Tests 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / 3 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import './styles/styles.scss'; 4 | import Header from './components/Header'; 5 | import TestList from './components/TestList'; 6 | import Footer from './components/Footer'; 7 | 8 | function App() { 9 | return ( 10 |
11 |
12 | 13 |
14 |
15 | ); 16 | } 17 | 18 | export default App; 19 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | const root = ReactDOM.createRoot(div); 8 | root.render(); 9 | root.unmount(); 10 | }); 11 | -------------------------------------------------------------------------------- /src/components/Compatibility.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { parseCompatibility } from '../helpers'; 4 | 5 | function Compatibility({ compatibility }) { 6 | const productsData = parseCompatibility(compatibility).frontendData; 7 | 8 | return ( 9 |
10 |
11 | {productsData.full.join(', ')} 12 |
13 | { 14 | productsData.partial.length > 0 15 | && ( 16 |
17 | {productsData.partial.join(', ')} 18 |
19 | ) 20 | } 21 | { 22 | productsData.none.length > 0 23 | && ( 24 |
25 | {productsData.none.join(', ')} 26 |
27 | ) 28 | } 29 |
30 | ); 31 | } 32 | 33 | export default Compatibility; 34 | 35 | Compatibility.propTypes = { 36 | compatibility: PropTypes.shape({ 37 | full: PropTypes.bool, 38 | partial: PropTypes.arrayOf(PropTypes.shape({ 39 | products: PropTypes.string, 40 | cases: PropTypes.arrayOf(PropTypes.number), 41 | })), 42 | none: PropTypes.arrayOf(PropTypes.string), 43 | special: PropTypes.shape({ 44 | compatible: PropTypes.arrayOf(PropTypes.string), 45 | incompatible: PropTypes.arrayOf(PropTypes.string), 46 | }), 47 | }).isRequired, 48 | }; 49 | -------------------------------------------------------------------------------- /src/components/CopyLinkBtn.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import PropTypes from 'prop-types'; 4 | import { copyToClipboard } from '../helpers'; 5 | 6 | export default class CopyLinkBtn extends React.Component { 7 | copyLink = () => { 8 | if (this.props.rulesUrl) { 9 | const url = window.location.href + this.props.rulesUrl; 10 | copyToClipboard( 11 | url, 12 | `Link for the rules for test "${this.props.title}" have been copied to your clipboard.`, 13 | ); 14 | } 15 | }; 16 | 17 | render() { 18 | const { copyLinkBtn } = this.props; 19 | return ( 20 | 28 | ); 29 | } 30 | } 31 | 32 | CopyLinkBtn.propTypes = { 33 | rulesUrl: PropTypes.string, 34 | title: PropTypes.string.isRequired, 35 | copyLinkBtn: PropTypes.string.isRequired, 36 | }; 37 | 38 | CopyLinkBtn.defaultProps = { 39 | rulesUrl: '', 40 | }; 41 | -------------------------------------------------------------------------------- /src/components/CopyRulesBtn.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import PropTypes from 'prop-types'; 4 | import { getFile, copyToClipboard } from '../helpers'; 5 | 6 | export default class CopyRulesBtn extends React.Component { 7 | constructor(props) { 8 | super(props); 9 | this.state = { 10 | rulesText: '', 11 | }; 12 | } 13 | 14 | componentDidMount() { 15 | const { rulesUrl } = this.props; 16 | (async () => { 17 | const rulesText = await getFile(rulesUrl); 18 | this.setState({ rulesText }); 19 | })(); 20 | } 21 | 22 | copyRules = async () => { 23 | await copyToClipboard( 24 | this.state.rulesText, 25 | `The rules for the test "${this.props.title}" have been copied to your clipboard.`, 26 | ); 27 | }; 28 | 29 | render() { 30 | const { copyRulesBtn } = this.props; 31 | return ( 32 | 40 | ); 41 | } 42 | } 43 | 44 | CopyRulesBtn.propTypes = { 45 | rulesUrl: PropTypes.string, 46 | title: PropTypes.string.isRequired, 47 | copyRulesBtn: PropTypes.string.isRequired, 48 | }; 49 | 50 | CopyRulesBtn.defaultProps = { 51 | rulesUrl: '', 52 | }; 53 | -------------------------------------------------------------------------------- /src/components/Footer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Mission from './Mission'; 3 | 4 | function Footer() { 5 | const currentYear = new Date().getFullYear().toString(); 6 | 7 | return ( 8 |
9 | 10 |
11 |
12 | © AdGuard, 2009– 13 | {currentYear} 14 |
15 |
16 |
17 | ); 18 | } 19 | 20 | export default Footer; 21 | -------------------------------------------------------------------------------- /src/components/Header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Mission from './Mission'; 3 | import project from '../../package.json'; 4 | 5 | function Header() { 6 | const versionHover = `v${project.version}`; 7 | 8 | return ( 9 |
10 |
11 |
12 |
13 |
14 |
15 |

ADGUARD

16 |

Automatic tests

17 |
18 |
19 | 20 |
21 |
22 |

Testing instruction:

23 |

24 | It‘s important to disable all filter lists as 25 | they may mess with the tests results. 26 |

27 |
    28 |
  • Disable all filter lists.
  • 29 |
  • 30 | Add the filter list corresponding to the test 31 | you‘re going to check. 32 |
  • 33 |
  • Enter the test page and refresh it.
  • 34 |
  • If any tests doesn‘t pass, clear your browser cache.
  • 35 |
36 |

Expected result: all tests are marked as passed.

37 |

38 | If any specific product is selected, 39 | some tests may be skipped due to the compatibility exceptions. 40 |

41 |
42 |
43 |
44 | ); 45 | } 46 | 47 | export default Header; 48 | -------------------------------------------------------------------------------- /src/components/Mission.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Mission() { 4 | return ( 5 |
6 | This small website is supposed to assist AdGuard QA department in testing 7 | different versions of AdGuard. 8 | The task of testing content blocking was always the most complicated, 9 | and this website aims to fix the situation, and make it as easy as possible. 10 |
11 | ); 12 | } 13 | 14 | export default Mission; 15 | -------------------------------------------------------------------------------- /src/components/ReadmeBtn.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Modal from 'react-modal'; 3 | import PropTypes from 'prop-types'; 4 | import ShowReadme from './ShowReadme'; 5 | 6 | const customStyles = { 7 | content: { 8 | width: '100%', 9 | height: '100%', 10 | padding: '5vw', 11 | boxSizing: 'border-box', 12 | borderRadius: '0', 13 | top: '0', 14 | bottom: '0', 15 | left: '0', 16 | right: '0', 17 | border: 'unset', 18 | background: '#585965', 19 | color: 'white', 20 | }, 21 | }; 22 | 23 | Modal.setAppElement(document.getElementById('root')); 24 | 25 | export default class ReadmeBtn extends React.Component { 26 | constructor(props) { 27 | super(props); 28 | this.state = { 29 | modalIsOpen: false, 30 | }; 31 | } 32 | 33 | openModal = () => { 34 | this.setState({ modalIsOpen: true }); 35 | }; 36 | 37 | closeModal = () => { 38 | this.setState({ modalIsOpen: false }); 39 | }; 40 | 41 | render() { 42 | const { readmeBtn, readmeUrl } = this.props; 43 | const { modalIsOpen } = this.state; 44 | return ( 45 | <> 46 | 55 | 61 | {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} 62 |