@duckduckgo/autoconsent 1.0.8 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +14 -0
- package/.vscode/settings.json +7 -0
- package/Jenkinsfile +68 -39
- package/api.md +104 -0
- package/dist/autoconsent.cjs.js +1 -1387
- package/dist/autoconsent.esm.js +1 -1379
- package/dist/autoconsent.playwright.js +1 -0
- package/dist/autoconsent.standalone.js +1 -0
- package/lib/cmps/all.ts +15 -10
- package/lib/cmps/base.ts +91 -91
- package/lib/cmps/consentmanager.ts +31 -19
- package/lib/cmps/consentomatic.ts +89 -0
- package/lib/cmps/cookiebot.ts +58 -55
- package/lib/cmps/evidon.ts +29 -18
- package/lib/cmps/onetrust.ts +32 -20
- package/lib/cmps/sourcepoint-frame.ts +102 -0
- package/lib/cmps/sourcepoint-top.ts +47 -0
- package/lib/cmps/trustarc-frame.ts +115 -0
- package/lib/cmps/trustarc-top.ts +91 -0
- package/lib/consentomatic/index.ts +233 -70
- package/lib/{web/consentomatic → consentomatic}/tools.ts +0 -0
- package/lib/eval-handler.ts +58 -0
- package/lib/index.ts +0 -2
- package/lib/messages.ts +100 -0
- package/lib/rule-executors.ts +108 -0
- package/lib/rules.ts +82 -0
- package/lib/types.ts +35 -0
- package/lib/utils.ts +64 -0
- package/lib/web.ts +283 -74
- package/package.json +17 -14
- package/playwright/content.ts +27 -0
- package/playwright/runner.ts +131 -0
- package/playwright/standalone.ts +36 -0
- package/playwright.config.ts +7 -0
- package/readme.md +57 -47
- package/rollup.config.js +23 -15
- package/rules/autoconsent/baden-wuerttemberg-de.json +7 -3
- package/rules/autoconsent/bundesregierung-de.json +5 -1
- package/rules/autoconsent/cc-banner.json +0 -1
- package/rules/autoconsent/cookie-notice.json +0 -1
- package/rules/autoconsent/cookieconsent.json +5 -6
- package/rules/autoconsent/destatis-de.json +0 -1
- package/rules/autoconsent/etsy.json +3 -2
- package/rules/autoconsent/eu-cookie-compliance.json +0 -1
- package/rules/autoconsent/hl-co-uk.json +8 -9
- package/rules/autoconsent/johnlewis.json +5 -2
- package/rules/autoconsent/notice-cookie.json +0 -1
- package/rules/autoconsent/osano.json +0 -1
- package/rules/autoconsent/tealium.json +4 -5
- package/rules/rules.json +44 -37
- package/tests/192.spec.ts +1 -1
- package/tests/arzt-auskunft.spec.ts +1 -1
- package/tests/asus.spec.ts +1 -1
- package/tests/ausopen.spec.ts +1 -1
- package/tests/aws.amazon.spec.ts +1 -1
- package/tests/baden-wuerttemberg.spec.ts +1 -1
- package/tests/borlabs.spec.ts +1 -1
- package/tests/bundesregierung.spec.ts +5 -2
- package/tests/ccbanner.spec.ts +1 -1
- package/tests/consentmanager.spec.ts +3 -3
- package/tests/cookiebot.spec.ts +8 -2
- package/tests/cookieconsent.spec.ts +1 -1
- package/tests/cookielawinfo.spec.ts +1 -1
- package/tests/cookienotice.spec.ts +1 -1
- package/tests/corona-in-zahlen.spec.ts +1 -1
- package/tests/deepl.spec.ts +1 -1
- package/tests/destatis.spec.ts +1 -1
- package/tests/didomi.spec.ts +6 -2
- package/tests/drupal.spec.ts +8 -0
- package/tests/dunelm.spec.ts +1 -1
- package/tests/etsy.spec.ts +1 -1
- package/tests/eu-cookie-compliance-banner.spec.ts +1 -1
- package/tests/evidon.spec.ts +1 -1
- package/tests/fundingchoices.spec.ts +2 -1
- package/tests/gov-uk.spec.ts +1 -1
- package/tests/hl-co-uk.spec.ts +1 -1
- package/tests/hubspot.spec.ts +1 -1
- package/tests/ionos.spec.ts +1 -1
- package/tests/johnlewis.spec.ts +2 -2
- package/tests/klaro.spec.ts +1 -1
- package/tests/marksandspencer.spec.ts +1 -1
- package/tests/mediamarkt.spec.ts +1 -1
- package/tests/metoffice-gov-uk.spec.ts +1 -1
- package/tests/microsoft.spec.ts +1 -1
- package/tests/moneysavingexpert.spec.ts +1 -1
- package/tests/motor-talk.spec.ts +1 -1
- package/tests/national-lottery.spec.ts +1 -1
- package/tests/netflix.spec.ts +1 -1
- package/tests/nhs.spec.ts +1 -1
- package/tests/notice-cookie.spec.ts +1 -1
- package/tests/obi.spec.ts +1 -1
- package/tests/oil.spec.ts +1 -1
- package/tests/onetrust.spec.ts +10 -1
- package/tests/osano.spec.ts +1 -1
- package/tests/otto.spec.ts +1 -1
- package/tests/paypal.spec.ts +1 -1
- package/tests/quantcast.spec.ts +4 -1
- package/tests/snigel.spec.ts +1 -1
- package/tests/sourcepoint.spec.ts +8 -8
- package/tests/springer.spec.ts +1 -1
- package/tests/steampowered.spec.ts +1 -1
- package/tests/tealium.spec.ts +1 -1
- package/tests/testcmp.spec.ts +1 -1
- package/tests/thalia.spec.ts +1 -1
- package/tests/thefreedictionary.spec.ts +1 -1
- package/tests/trustarc.spec.ts +25 -4
- package/tests/usercentrics-1.spec.ts +1 -1
- package/tests/uswitch.spec.ts +1 -1
- package/tests/vodafone.spec.ts +1 -1
- package/tests/waitrose.spec.ts +1 -1
- package/tests/wetransfer.spec.ts +1 -1
- package/tests/wordpressgdpr.spec.ts +1 -1
- package/tests/xing.spec.ts +1 -1
- package/tsconfig.json +2 -2
- package/.eslintrc +0 -12
- package/cosmetics/rules.json +0 -110
- package/dist/autoconsent.puppet.js +0 -1078
- package/lib/cmps/all.js +0 -19
- package/lib/cmps/base.js +0 -174
- package/lib/cmps/consentmanager.js +0 -31
- package/lib/cmps/cookiebot.js +0 -77
- package/lib/cmps/evidon.js +0 -26
- package/lib/cmps/onetrust.js +0 -34
- package/lib/cmps/sourcepoint.js +0 -82
- package/lib/cmps/sourcepoint.ts +0 -95
- package/lib/cmps/trustarc.js +0 -106
- package/lib/cmps/trustarc.ts +0 -147
- package/lib/config.js +0 -1
- package/lib/consentomatic/index.js +0 -52
- package/lib/detector.js +0 -33
- package/lib/detector.ts +0 -34
- package/lib/hider.js +0 -13
- package/lib/hider.ts +0 -16
- package/lib/index.js +0 -4
- package/lib/messages.d.ts +0 -61
- package/lib/node.js +0 -35
- package/lib/node.ts +0 -43
- package/lib/puppet/tab.js +0 -121
- package/lib/puppet/tab.ts +0 -146
- package/lib/rules.d.ts +0 -80
- package/lib/tabwrapper.js +0 -67
- package/lib/tabwrapper.ts +0 -74
- package/lib/types.d.ts +0 -61
- package/lib/web/consentomatic/index.js +0 -188
- package/lib/web/consentomatic/index.ts +0 -249
- package/lib/web/consentomatic/tools.js +0 -177
- package/lib/web/content-utils.js +0 -29
- package/lib/web/content-utils.ts +0 -31
- package/lib/web/content.js +0 -89
- package/lib/web/content.ts +0 -80
- package/lib/web/tab.js +0 -112
- package/lib/web/tab.ts +0 -178
- package/lib/web.js +0 -95
- package/tests/runner.ts +0 -61
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { test, expect, Page, Frame } from "@playwright/test";
|
|
4
|
+
import { waitFor } from "../lib/utils";
|
|
5
|
+
import { ContentScriptMessage } from "../lib/messages";
|
|
6
|
+
import { enableLogs } from "../lib/config";
|
|
7
|
+
|
|
8
|
+
const testRegion = (process.env.REGION || "NA").trim();
|
|
9
|
+
|
|
10
|
+
type TestOptions = {
|
|
11
|
+
testOptOut: boolean;
|
|
12
|
+
testSelfTest: boolean;
|
|
13
|
+
skipRegions?: string[];
|
|
14
|
+
onlyRegions?: string[];
|
|
15
|
+
};
|
|
16
|
+
const defaultOptions: TestOptions = {
|
|
17
|
+
testOptOut: true,
|
|
18
|
+
testSelfTest: true,
|
|
19
|
+
skipRegions: [],
|
|
20
|
+
onlyRegions: [],
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const contentScript = fs.readFileSync(
|
|
24
|
+
path.join(__dirname, "../dist/autoconsent.playwright.js"),
|
|
25
|
+
"utf8"
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export async function injectContentScript(page: Page | Frame) {
|
|
29
|
+
try {
|
|
30
|
+
await page.evaluate(contentScript);
|
|
31
|
+
} catch (e) {
|
|
32
|
+
// frame was detached
|
|
33
|
+
// console.log(e);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function generateTest(
|
|
38
|
+
url: string,
|
|
39
|
+
expectedCmp: string,
|
|
40
|
+
options: TestOptions = { testOptOut: true, testSelfTest: true }
|
|
41
|
+
) {
|
|
42
|
+
test(`${url.split("://")[1]} .${testRegion}`, async ({ page }) => {
|
|
43
|
+
if (options.onlyRegions && options.onlyRegions.length > 0 && !options.onlyRegions.includes(testRegion)) {
|
|
44
|
+
test.skip();
|
|
45
|
+
}
|
|
46
|
+
if (options.skipRegions && options.skipRegions.includes(testRegion)) {
|
|
47
|
+
test.skip();
|
|
48
|
+
}
|
|
49
|
+
enableLogs && page.on('console', async msg => {
|
|
50
|
+
console.log(` page log:`, msg.text());
|
|
51
|
+
});
|
|
52
|
+
await page.exposeBinding("autoconsentSendMessage", messageCallback);
|
|
53
|
+
await page.goto(url, { waitUntil: "commit" });
|
|
54
|
+
|
|
55
|
+
// set up a messaging function
|
|
56
|
+
const received: ContentScriptMessage[] = [];
|
|
57
|
+
|
|
58
|
+
function isMessageReceived(msg: Partial<ContentScriptMessage>, partial = true) {
|
|
59
|
+
return received.some((m) => {
|
|
60
|
+
const keysMatch = partial || Object.keys(m).length === Object.keys(msg).length;
|
|
61
|
+
return keysMatch && Object.keys(msg).every(
|
|
62
|
+
(k) => (<any>m)[k] === (<any>msg)[k]
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let selfTestFrame: Frame = null;
|
|
68
|
+
async function messageCallback({ frame }: { frame: Frame }, msg: ContentScriptMessage) {
|
|
69
|
+
enableLogs && msg.type !== 'eval' && console.log(msg);
|
|
70
|
+
received.push(msg);
|
|
71
|
+
switch (msg.type) {
|
|
72
|
+
case 'optInResult':
|
|
73
|
+
case 'optOutResult': {
|
|
74
|
+
if (msg.scheduleSelfTest) {
|
|
75
|
+
selfTestFrame = frame;
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case 'autoconsentDone': {
|
|
80
|
+
if (selfTestFrame && options.testSelfTest) {
|
|
81
|
+
await selfTestFrame.evaluate(`autoconsentReceiveMessage({ type: "selfTest" })`);
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case 'eval': {
|
|
86
|
+
const result = await frame.evaluate(msg.code);
|
|
87
|
+
await frame.evaluate(`autoconsentReceiveMessage({ id: "${msg.id}", type: "evalResp", result: ${JSON.stringify(result)} })`);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case 'autoconsentError': {
|
|
91
|
+
console.error(url, msg.details);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// inject content scripts into every frame
|
|
98
|
+
await injectContentScript(page);
|
|
99
|
+
page.frames().forEach(injectContentScript);
|
|
100
|
+
page.on("framenavigated", injectContentScript);
|
|
101
|
+
|
|
102
|
+
// wait for all messages and assertions
|
|
103
|
+
await waitFor(() => isMessageReceived({ type: "popupFound", cmp: expectedCmp }), 50, 500);
|
|
104
|
+
expect(isMessageReceived({ type: "popupFound", cmp: expectedCmp })).toBe(true);
|
|
105
|
+
|
|
106
|
+
if (options.testOptOut) {
|
|
107
|
+
await waitFor(() => isMessageReceived({ type: "optOutResult", result: true }), 50, 300);
|
|
108
|
+
expect(isMessageReceived({ type: "optOutResult", result: true })).toBe(true);
|
|
109
|
+
}
|
|
110
|
+
if (options.testSelfTest && selfTestFrame) {
|
|
111
|
+
await waitFor(() => isMessageReceived({ type: "selfTestResult", result: true }), 50, 300);
|
|
112
|
+
expect(isMessageReceived({ type: "selfTestResult", result: true })).toBe(true);
|
|
113
|
+
}
|
|
114
|
+
await waitFor(() => isMessageReceived({ type: "autoconsentDone" }), 10, 500);
|
|
115
|
+
expect(isMessageReceived({ type: "autoconsentDone" })).toBe(true);
|
|
116
|
+
|
|
117
|
+
expect(isMessageReceived({ type: "autoconsentError" })).toBe(false);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export default function generateCMPTests(
|
|
122
|
+
cmp: string,
|
|
123
|
+
sites: string[],
|
|
124
|
+
options: Partial<TestOptions> = {}
|
|
125
|
+
) {
|
|
126
|
+
test.describe(cmp, () => {
|
|
127
|
+
sites.forEach((url) => {
|
|
128
|
+
generateTest(url, cmp, Object.assign({}, defaultOptions, options));
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import AutoConsent from "../lib/web";
|
|
2
|
+
import { BackgroundMessage } from "../lib/messages";
|
|
3
|
+
import { Config, RuleBundle } from "../lib/types";
|
|
4
|
+
import * as rules from '../rules/rules.json';
|
|
5
|
+
|
|
6
|
+
declare global {
|
|
7
|
+
interface Window {
|
|
8
|
+
initAutoconsentStandalone: () => void;
|
|
9
|
+
autoconsentStandaloneSendMessage: (msg: string) => void;
|
|
10
|
+
autoconsentStandaloneReceiveMessage: (message: BackgroundMessage) => void;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
window.initAutoconsentStandalone = (config: Config = {
|
|
16
|
+
enabled: true,
|
|
17
|
+
autoAction: 'optOut',
|
|
18
|
+
disabledCmps: [],
|
|
19
|
+
enablePrehide: true,
|
|
20
|
+
detectRetries: 20,
|
|
21
|
+
}) => {
|
|
22
|
+
if (!window.autoconsentStandaloneReceiveMessage) {
|
|
23
|
+
const autoconsent = new AutoConsent(
|
|
24
|
+
async message => {
|
|
25
|
+
window.autoconsentStandaloneSendMessage(JSON.stringify(message));
|
|
26
|
+
},
|
|
27
|
+
config,
|
|
28
|
+
<RuleBundle>rules
|
|
29
|
+
);
|
|
30
|
+
window.autoconsentStandaloneReceiveMessage = (msg) => {
|
|
31
|
+
autoconsent.receiveMessageCallback(msg);
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
console.warn('autoconsent already initialized', window.autoconsentStandaloneReceiveMessage);
|
|
35
|
+
}
|
|
36
|
+
}
|
package/playwright.config.ts
CHANGED
package/readme.md
CHANGED
|
@@ -1,28 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
# Autoconsent
|
|
2
2
|
|
|
3
3
|
This is a library of rules for navigating through common consent popups on the web. These rules
|
|
4
|
-
can be run in a
|
|
4
|
+
can be run in a Chrome extension, or in a Playwright-orchestrated headless browser. Using
|
|
5
5
|
these rules, opt-in and opt-out options can be selected automatically, without requiring
|
|
6
6
|
user-input.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## Browser extension
|
|
9
9
|
|
|
10
|
-
The
|
|
10
|
+
The web extension can be built with the following steps:
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
13
|
# Download dependencies
|
|
14
14
|
npm ci
|
|
15
|
-
# Build JS bundles
|
|
16
|
-
npm run bundle
|
|
17
15
|
# Build consent ruleset
|
|
18
16
|
npm run build-rules
|
|
17
|
+
# Build JS bundles (rules must be built first)
|
|
18
|
+
npm run bundle
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
The
|
|
22
|
-
Alternatively, you can use `web-ext build -s addon/` to generate a packaged addon that can
|
|
23
|
-
be installed in an existing Firefox profile.
|
|
21
|
+
The extension-specific code can be found in the `addon` directory and can be [loaded directly from there](https://developer.chrome.com/docs/extensions/mv3/getstarted/#unpacked) in developer mode.
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
## Rules
|
|
26
24
|
|
|
27
25
|
The library's functionality is implemented as a set of rules that define how to manage consent on
|
|
28
26
|
a subset of sites. These generally correspond to specific Consent Management Providers (CMPs)
|
|
@@ -41,33 +39,50 @@ There are currently three ways of implementing a CMP:
|
|
|
41
39
|
3. As a [Consent-O-Matic](https://github.com/cavi-au/Consent-O-Matic) rule. The `ConsentOMaticCMP` class implements
|
|
42
40
|
compability with rules written for the Consent-O-Matic extension.
|
|
43
41
|
|
|
44
|
-
|
|
42
|
+
## Intermediate rules
|
|
43
|
+
|
|
44
|
+
Sometimes the opt-out process requires actions that span across multiple pages or iframes. In this case it is necessary to define stages (each corresponding to a separate page context) as separate rulesets. Each one, except the very last stage, must be marked as intermediate using the `intermediate: true` flag. If the `intermediate` flag is not set correctly, autoconsent may report a successful opt-out even if it is not yet finished.
|
|
45
|
+
|
|
46
|
+
## Context filters
|
|
47
|
+
|
|
48
|
+
By default, rules will be executed in all top-level documents. Some rules are designed for specific contexts (e.g. only nested iframes, or only specific URLs). This can be configured in `runContext` field (see the syntax reference below).
|
|
49
|
+
|
|
50
|
+
## Rule Syntax Reference
|
|
45
51
|
|
|
46
52
|
An autoconsent CMP rule can be written as either:
|
|
47
|
-
* a class implementing the `AutoCMP` interface, or
|
|
48
53
|
* a JSON file adhering to the `AutoConsentCMPRule` type.
|
|
54
|
+
* a class implementing the `AutoCMP` interface, or
|
|
55
|
+
* common JSON rules are available as reusable functions in [rule-executors.ts](/lib/rule-executors.ts). You can also use existing class-based rules as reference.
|
|
49
56
|
|
|
50
|
-
In most cases the JSON syntax should be sufficient, unless non-linear logic is required, in which case a class is required.
|
|
57
|
+
In most cases the JSON syntax should be sufficient, unless some complex non-linear logic is required, in which case a class is required.
|
|
51
58
|
|
|
52
|
-
Both JSON and class implementations
|
|
59
|
+
Both JSON and class implementations have the following components:
|
|
53
60
|
* `name` - to identify this CMP.
|
|
54
61
|
* `detectCMP` - which determines if this CMP is included on the page.
|
|
55
62
|
* `detectPopup` - which determines if a popup is being shown by the CMP.
|
|
56
|
-
* `optOut` -
|
|
57
|
-
* `optIn` -
|
|
63
|
+
* `optOut` - a list of actions to do an 'opt-out' from the popup screen. i.e. denying all consents possible.
|
|
64
|
+
* `optIn` - a list of actions for an 'opt-in' from the popup screen.
|
|
65
|
+
* (optional) `prehideSelectors` - a list of CSS selectors to "pre-hide" early before detecting a CMP. This helps against flickering. Pre-hiding is done using CSS `opacity` and `z-index`, so be it should be used with care to prevent conflicts with the opt-out process.
|
|
66
|
+
* (optional) `intermediate` - a boolean flag indicating that the ruleset is part of a multi-stage process, see the [Intermediate rules](#intermediate-rules) section. This is `false` by default.
|
|
67
|
+
* (optional) `runContext` - an object describing when this rule should be tried:
|
|
68
|
+
* `main` - boolean, set to `true` if the rule should be executed in top-level documents (default: `true`)
|
|
69
|
+
* `frame` - boolean, set to `true` if the rule should be executed in nested frames (default: `false`)
|
|
70
|
+
* `url` - string, specifies a string prefix that should match the page URL (default: empty)
|
|
71
|
+
* (optional) `test` - a list of actions to verify a successful opt-out. This is currently only used in Playwright tests.
|
|
58
72
|
|
|
59
|
-
Except for `name` this are defined as a set of checks or actions on the page. In the JSON syntax this is a list of `AutoConsentRuleStep` objects. For `detect` checks, we return true for the check if all steps return true. For opt in and out, we execute actions in order, exiting if one fails. The following checks/actions are supported:
|
|
60
73
|
|
|
61
|
-
|
|
74
|
+
`detectCMP`, `detectPopup`, `optOut`, `optIn`, and `test` are defined as a set of checks or actions on the page. In the JSON syntax this is a list of `AutoConsentRuleStep` objects. For `detect` checks, we return true for the check if all steps return true. For opt in and out, we execute actions in order, exiting if one fails. The following checks/actions are supported:
|
|
75
|
+
|
|
76
|
+
### Element exists
|
|
62
77
|
|
|
63
78
|
```json
|
|
64
79
|
{
|
|
65
80
|
"exists": "selector"
|
|
66
81
|
}
|
|
67
82
|
```
|
|
68
|
-
Returns true if `document.
|
|
83
|
+
Returns true if `document.querySelector(selector)` returns elements.
|
|
69
84
|
|
|
70
|
-
|
|
85
|
+
### Element visible
|
|
71
86
|
|
|
72
87
|
```json
|
|
73
88
|
{
|
|
@@ -75,18 +90,9 @@ Returns true if `document.querySelect(selector)` returns elements.
|
|
|
75
90
|
"check": "any" | "all" | "none"
|
|
76
91
|
}
|
|
77
92
|
```
|
|
78
|
-
Returns true if
|
|
93
|
+
Returns true if elements returned from `document.querySelectorAll(selector)` are currently visible on the page. If `check` is `all`, every element must be visible. If `check` is `none`, no element should be visible. Visibility check is a CSS-based heuristic.
|
|
79
94
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
```json
|
|
83
|
-
{
|
|
84
|
-
"eval": "code"
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
Evaluates `code` in the context of the page. NB: the result of this action depends on the truthiness of the evaluated expression, make sure it returns `true` in case of success.
|
|
88
|
-
|
|
89
|
-
#### Wait for element
|
|
95
|
+
### Wait for element
|
|
90
96
|
|
|
91
97
|
```json
|
|
92
98
|
{
|
|
@@ -96,25 +102,26 @@ Evaluates `code` in the context of the page. NB: the result of this action depen
|
|
|
96
102
|
```
|
|
97
103
|
Waits until `selector` exists in the page. After `timeout` ms the step fails.
|
|
98
104
|
|
|
99
|
-
|
|
105
|
+
### Click an element
|
|
100
106
|
```json
|
|
101
107
|
{
|
|
102
108
|
"click": "selector",
|
|
103
109
|
"all": true | false,
|
|
104
110
|
}
|
|
105
111
|
```
|
|
106
|
-
Click on an element returned by `selector`. If `all` is `true`, all matching elements are clicked.
|
|
112
|
+
Click on an element returned by `selector`. If `all` is `true`, all matching elements are clicked. If `all` is `false`, only the first returned value is clicked.
|
|
107
113
|
|
|
108
|
-
|
|
114
|
+
### Wait for then click
|
|
109
115
|
```json
|
|
110
116
|
{
|
|
111
117
|
"waitForThenClick": "selector",
|
|
112
|
-
"timeout": 1000
|
|
118
|
+
"timeout": 1000,
|
|
119
|
+
"all": true | false
|
|
113
120
|
}
|
|
114
121
|
```
|
|
115
122
|
Combines `waitFor` and `click`.
|
|
116
123
|
|
|
117
|
-
|
|
124
|
+
### Unconditional wait
|
|
118
125
|
```json
|
|
119
126
|
{
|
|
120
127
|
"wait": 1000,
|
|
@@ -122,30 +129,33 @@ Combines `waitFor` and `click`.
|
|
|
122
129
|
```
|
|
123
130
|
Wait for the specified number of milliseconds.
|
|
124
131
|
|
|
125
|
-
|
|
132
|
+
### Hide
|
|
126
133
|
```json
|
|
127
134
|
{
|
|
128
|
-
"
|
|
135
|
+
"hide": ["selector", ...],
|
|
136
|
+
"method": "display" | "opacity"
|
|
129
137
|
}
|
|
130
138
|
```
|
|
131
|
-
|
|
139
|
+
Hide the elements matched by the selectors. `method` defines how elements are hidden: "display" sets `display: none`, "opacity" sets `opacity: 0`. Method is "display" by default.
|
|
140
|
+
|
|
141
|
+
### Eval
|
|
132
142
|
|
|
133
|
-
#### Hide rule
|
|
134
143
|
```json
|
|
135
144
|
{
|
|
136
|
-
"
|
|
145
|
+
"eval": "code"
|
|
137
146
|
}
|
|
138
147
|
```
|
|
139
|
-
|
|
148
|
+
Evaluates `code` in the context of the page. The rule is considered successful if it *evaluates to a truthy value*.
|
|
149
|
+
Eval rules are not 100% reliable because they can be blocked by a CSP policy on the page. Therefore, they should only be used as a last resort when none of the other rules are sufficient.
|
|
140
150
|
|
|
141
|
-
|
|
151
|
+
### Optional actions
|
|
142
152
|
|
|
143
|
-
|
|
153
|
+
Any rule can include the `"optional": true` to ignore failure.
|
|
144
154
|
|
|
145
|
-
|
|
155
|
+
## API
|
|
146
156
|
|
|
147
|
-
|
|
157
|
+
See [this document](/api.md) for more details on internal APIs.
|
|
148
158
|
|
|
149
|
-
|
|
159
|
+
## License
|
|
150
160
|
|
|
151
161
|
MPLv2.
|
package/rollup.config.js
CHANGED
|
@@ -1,14 +1,29 @@
|
|
|
1
|
+
import json from '@rollup/plugin-json';
|
|
1
2
|
import typescript from '@rollup/plugin-typescript';
|
|
3
|
+
import { terser } from "rollup-plugin-terser";
|
|
2
4
|
import pkg from './package.json';
|
|
3
5
|
|
|
4
6
|
export default [{
|
|
5
|
-
input: './
|
|
7
|
+
input: './playwright/content.ts',
|
|
6
8
|
output: [{
|
|
7
|
-
file: 'dist/autoconsent.
|
|
8
|
-
format: '
|
|
9
|
+
file: 'dist/autoconsent.playwright.js',
|
|
10
|
+
format: 'iife'
|
|
9
11
|
}],
|
|
10
12
|
plugins: [
|
|
13
|
+
json(),
|
|
11
14
|
typescript(),
|
|
15
|
+
terser(),
|
|
16
|
+
]
|
|
17
|
+
}, {
|
|
18
|
+
input: './playwright/standalone.ts',
|
|
19
|
+
output: [{
|
|
20
|
+
file: 'dist/autoconsent.standalone.js',
|
|
21
|
+
format: 'iife'
|
|
22
|
+
}],
|
|
23
|
+
plugins: [
|
|
24
|
+
json(),
|
|
25
|
+
typescript(),
|
|
26
|
+
terser(),
|
|
12
27
|
]
|
|
13
28
|
}, {
|
|
14
29
|
input: './lib/web.ts',
|
|
@@ -22,7 +37,8 @@ export default [{
|
|
|
22
37
|
}],
|
|
23
38
|
plugins: [
|
|
24
39
|
typescript(),
|
|
25
|
-
|
|
40
|
+
terser(),
|
|
41
|
+
],
|
|
26
42
|
}, {
|
|
27
43
|
input: './addon/background.ts',
|
|
28
44
|
output: [{
|
|
@@ -31,6 +47,7 @@ export default [{
|
|
|
31
47
|
}],
|
|
32
48
|
plugins: [
|
|
33
49
|
typescript(),
|
|
50
|
+
terser(),
|
|
34
51
|
]
|
|
35
52
|
}, {
|
|
36
53
|
input: './addon/content.ts',
|
|
@@ -40,15 +57,6 @@ export default [{
|
|
|
40
57
|
}],
|
|
41
58
|
plugins: [
|
|
42
59
|
typescript(),
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
input: './addon/test.ts',
|
|
46
|
-
output: [{
|
|
47
|
-
file: './addon/test.bundle.js',
|
|
48
|
-
format: 'iife',
|
|
49
|
-
external: ['chai', 'mocha']
|
|
50
|
-
}],
|
|
51
|
-
plugins: [
|
|
52
|
-
typescript(),
|
|
53
|
-
]
|
|
60
|
+
terser(),
|
|
61
|
+
],
|
|
54
62
|
}];
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "baden-wuerttemberg.de",
|
|
3
|
-
"isHidingRule": true,
|
|
4
3
|
"prehideSelectors": [".cookie-alert.t-dark"],
|
|
5
4
|
"detectCmp": [{ "exists": ".cookie-alert.t-dark" }],
|
|
6
5
|
"detectPopup": [{ "visible": ".cookie-alert.t-dark" }],
|
|
7
|
-
"optIn": [
|
|
8
|
-
|
|
6
|
+
"optIn": [
|
|
7
|
+
{ "click": ".cookie-alert__form input:not([disabled]):not([checked])" },
|
|
8
|
+
{ "click": ".cookie-alert__button button" }
|
|
9
|
+
],
|
|
10
|
+
"optOut": [
|
|
11
|
+
{ "hide": [".cookie-alert.t-dark"] }
|
|
12
|
+
]
|
|
9
13
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cookieconsent",
|
|
3
|
-
"prehideSelectors": ["[aria-label=\"cookieconsent\"]"],
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"detectPopup": [{ "visible": "[aria-label=\"cookieconsent\"]" }],
|
|
3
|
+
"prehideSelectors": ["[aria-label=\"cookieconsent\"][aria-describedby=\"cookieconsent:desc\"]"],
|
|
4
|
+
"detectCmp": [{ "exists": "[aria-label=\"cookieconsent\"][aria-describedby=\"cookieconsent:desc\"]" }],
|
|
5
|
+
"detectPopup": [{ "visible": "[aria-label=\"cookieconsent\"][aria-describedby=\"cookieconsent:desc\"]" }],
|
|
7
6
|
"optIn": [{ "click": ".cc-dismiss" }],
|
|
8
|
-
"optOut": [{ "hide": ["[aria-label=\"cookieconsent\"]"] }]
|
|
9
|
-
|
|
7
|
+
"optOut": [{ "hide": ["[aria-label=\"cookieconsent\"][aria-describedby=\"cookieconsent:desc\"]"] }]
|
|
8
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "etsy",
|
|
3
|
+
"prehideSelectors": ["#gdpr-single-choice-overlay", "#gdpr-privacy-settings"],
|
|
3
4
|
"detectCmp": [{ "exists": "#gdpr-single-choice-overlay" }],
|
|
4
5
|
"detectPopup": [{ "visible": "#gdpr-single-choice-overlay" }],
|
|
5
6
|
"optOut": [
|
|
6
|
-
{"hide": ["#gdpr-single-choice-overlay", "#gdpr-privacy-settings"]},
|
|
7
7
|
{"click": "button[data-gdpr-open-full-settings]"},
|
|
8
|
-
{"
|
|
8
|
+
{"waitForVisible": ".gdpr-overlay-body input", "timeout": 3000},
|
|
9
|
+
{"wait": 1000},
|
|
9
10
|
{"eval": "document.querySelectorAll('.gdpr-overlay-body input').forEach(toggle => { toggle.checked = false; }) || true"},
|
|
10
11
|
{"eval": "document.querySelector('.gdpr-overlay-view button[data-wt-overlay-close]').click() || true"}
|
|
11
12
|
],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
"name": "hl.co.uk",
|
|
3
|
+
"prehideSelectors": [".cookieModalContent", "#cookie-banner-overlay"],
|
|
4
4
|
"detectCmp": [{ "exists": "#cookie-banner-overlay" }],
|
|
5
5
|
"detectPopup": [{ "exists": "#cookie-banner-overlay" }],
|
|
6
6
|
"optIn": [{ "click": "#acceptCookieButton" }],
|
|
@@ -12,19 +12,18 @@
|
|
|
12
12
|
"hide": [".cookieSettingsModal"]
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
"
|
|
15
|
+
"waitFor": "#AOCookieToggle"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
|
-
"click": "#AOCookieToggle"
|
|
18
|
+
"click": "#AOCookieToggle[aria-pressed=true]",
|
|
19
|
+
"optional": true
|
|
19
20
|
},
|
|
20
21
|
{
|
|
21
|
-
"
|
|
22
|
+
"waitFor": "#TPCookieToggle"
|
|
22
23
|
},
|
|
23
24
|
{
|
|
24
|
-
"click": "#TPCookieToggle"
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
"eval": "document.querySelector('#TPCookieToggle').getAttribute('aria-pressed') === 'false'"
|
|
25
|
+
"click": "#TPCookieToggle[aria-pressed=true]",
|
|
26
|
+
"optional": true
|
|
28
27
|
},
|
|
29
28
|
{
|
|
30
29
|
"click": "#updateCookieButton"
|
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
"optOut": [
|
|
7
7
|
{"click": "button[data-test^=manage-cookies]"},
|
|
8
8
|
{"wait": "500"},
|
|
9
|
-
{
|
|
10
|
-
|
|
9
|
+
{
|
|
10
|
+
"click": "label[data-test^=toggle][class*=checked]:not([class*=disabled])",
|
|
11
|
+
"all": true,
|
|
12
|
+
"optional": true
|
|
13
|
+
},
|
|
11
14
|
{"click": "button[data-test=save-preferences]"}
|
|
12
15
|
],
|
|
13
16
|
"optIn": [{ "click": "button[data-test=allow-all]"}]
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Tealium",
|
|
3
3
|
"prehideSelectors": ["#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs,#consent-layer"],
|
|
4
|
-
"
|
|
5
|
-
"detectCmp": [{ "exists": "#__tealiumGDPRecModal" }, { "eval": "window.utag && typeof utag.gdpr === 'object'" }],
|
|
4
|
+
"detectCmp": [{ "visible": "#__tealiumGDPRecModal" }, { "eval": "typeof window.utag !== 'undefined' && typeof utag.gdpr === 'object'" }],
|
|
6
5
|
"detectPopup": [{ "visible": "#__tealiumGDPRecModal" }],
|
|
7
6
|
"optOut": [
|
|
8
7
|
{ "hide": ["#__tealiumGDPRecModal", "#__tealiumGDPRcpPrefs", "#consent-layer"] },
|
|
9
|
-
{ "
|
|
8
|
+
{ "waitForThenClick": "#cm-acceptNone,.js-accept-essential-cookies", "timeout": 1000 },
|
|
9
|
+
{ "eval": "utag.gdpr.setConsentValue(false) || true" }
|
|
10
10
|
],
|
|
11
11
|
"optIn": [
|
|
12
12
|
{ "hide": ["#__tealiumGDPRecModal"] },
|
|
13
|
-
{ "eval": "utag.gdpr.setConsentValue(true)" }
|
|
13
|
+
{ "eval": "utag.gdpr.setConsentValue(true) || true" }
|
|
14
14
|
],
|
|
15
15
|
"test": [
|
|
16
16
|
{ "eval": "utag.gdpr.getConsentState() !== 1" }
|
|
17
17
|
]
|
|
18
18
|
}
|
|
19
|
-
|