@duckduckgo/autoconsent 1.0.6 → 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 -1371
- package/dist/autoconsent.esm.js +1 -1363
- 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 +62 -53
- package/lib/cmps/evidon.ts +29 -18
- package/lib/cmps/onetrust.ts +37 -19
- 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/192.json +17 -0
- package/rules/autoconsent/ausopen.json +7 -0
- package/rules/autoconsent/aws-amazon.json +1 -1
- package/rules/autoconsent/baden-wuerttemberg-de.json +7 -3
- package/rules/autoconsent/bing.json +14 -0
- package/rules/autoconsent/bundesregierung-de.json +6 -2
- 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/dunelm.json +18 -0
- package/rules/autoconsent/etsy.json +3 -2
- package/rules/autoconsent/eu-cookie-compliance.json +0 -1
- package/rules/autoconsent/gov-uk.json +10 -0
- package/rules/autoconsent/hl-co-uk.json +8 -9
- package/rules/autoconsent/johnlewis.json +5 -2
- package/rules/autoconsent/marksandspencer.json +7 -0
- package/rules/autoconsent/notice-cookie.json +0 -1
- package/rules/autoconsent/osano.json +0 -1
- package/rules/autoconsent/{paypal-de.json → paypal.json} +6 -2
- package/rules/autoconsent/tealium.json +4 -5
- package/rules/autoconsent/uswitch.json +8 -0
- package/rules/autoconsent/waitrose.json +28 -0
- package/rules/autoconsent/wetransfer.json +7 -0
- package/rules/rules.json +314 -39
- package/tests/192.spec.ts +7 -0
- package/tests/arzt-auskunft.spec.ts +1 -1
- package/tests/asus.spec.ts +1 -1
- package/tests/ausopen.spec.ts +7 -0
- 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 -1
- 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 +7 -0
- 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 +9 -0
- 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 +7 -0
- 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 +8 -6
- 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 -3
- package/tests/usercentrics-1.spec.ts +1 -1
- package/tests/uswitch.spec.ts +7 -0
- package/tests/vodafone.spec.ts +1 -1
- package/tests/waitrose.spec.ts +7 -0
- package/tests/wetransfer.spec.ts +7 -0
- 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 -1072
- 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 -73
- package/lib/cmps/evidon.js +0 -26
- package/lib/cmps/onetrust.js +0 -32
- 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 -79
- package/lib/web/content.ts +0 -71
- 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
package/lib/cmps/base.ts
CHANGED
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
/* eslint-disable no-restricted-syntax,no-await-in-loop,no-underscore-dangle */
|
|
2
2
|
|
|
3
|
-
import { AutoCMP
|
|
4
|
-
import { AutoConsentCMPRule, AutoConsentRuleStep } from "../rules";
|
|
3
|
+
import { AutoCMP } from "../types";
|
|
4
|
+
import { AutoConsentCMPRule, AutoConsentRuleStep, RunContext } from "../rules";
|
|
5
5
|
import { enableLogs } from "../config";
|
|
6
|
-
|
|
7
|
-
export async function waitFor(predicate: () => Promise<boolean> | boolean, maxTimes: number, interval: number): Promise<boolean> {
|
|
8
|
-
let result = await predicate();
|
|
9
|
-
if (!result && maxTimes > 0) {
|
|
10
|
-
return new Promise((resolve) => {
|
|
11
|
-
setTimeout(async () => {
|
|
12
|
-
resolve(waitFor(predicate, maxTimes - 1, interval));
|
|
13
|
-
}, interval);
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return Promise.resolve(result);
|
|
17
|
-
}
|
|
18
|
-
|
|
6
|
+
import { click, doEval, elementExists, elementVisible, hide, wait, waitForElement, waitForThenClick, waitForVisible } from "../rule-executors";
|
|
19
7
|
|
|
20
8
|
export async function success(action: Promise<boolean>): Promise<boolean> {
|
|
21
9
|
const result = await action;
|
|
@@ -25,124 +13,142 @@ export async function success(action: Promise<boolean>): Promise<boolean> {
|
|
|
25
13
|
return result
|
|
26
14
|
}
|
|
27
15
|
|
|
16
|
+
export const defaultRunContext: RunContext = {
|
|
17
|
+
main: true,
|
|
18
|
+
frame: false,
|
|
19
|
+
url: "",
|
|
20
|
+
}
|
|
28
21
|
|
|
29
|
-
export default class
|
|
22
|
+
export default class AutoConsentCMPBase implements AutoCMP {
|
|
30
23
|
|
|
31
24
|
name: string
|
|
32
|
-
|
|
25
|
+
runContext: RunContext = defaultRunContext;
|
|
33
26
|
|
|
34
27
|
constructor(name: string) {
|
|
35
28
|
this.name = name;
|
|
36
29
|
}
|
|
37
30
|
|
|
38
|
-
|
|
31
|
+
get hasSelfTest(): boolean {
|
|
39
32
|
throw new Error('Not Implemented');
|
|
40
33
|
}
|
|
41
34
|
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
get isIntermediate(): boolean {
|
|
36
|
+
throw new Error('Not Implemented');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
checkRunContext(): boolean {
|
|
40
|
+
const runCtx: RunContext = {
|
|
41
|
+
...defaultRunContext,
|
|
42
|
+
...this.runContext,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const isTop = window.top === window;
|
|
46
|
+
|
|
47
|
+
if (isTop && !runCtx.main) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!isTop && !runCtx.frame) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (runCtx.url && !window.location.href.startsWith(runCtx.url)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
44
59
|
}
|
|
45
60
|
|
|
46
|
-
|
|
61
|
+
detectCmp(): Promise<boolean> {
|
|
62
|
+
throw new Error('Not Implemented');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async detectPopup() {
|
|
47
66
|
return false;
|
|
48
67
|
}
|
|
49
68
|
|
|
50
|
-
optOut(
|
|
69
|
+
optOut(): Promise<boolean> {
|
|
51
70
|
throw new Error('Not Implemented');
|
|
52
71
|
}
|
|
53
72
|
|
|
54
|
-
optIn(
|
|
73
|
+
optIn(): Promise<boolean> {
|
|
55
74
|
throw new Error('Not Implemented');
|
|
56
75
|
}
|
|
57
76
|
|
|
58
|
-
openCmp(
|
|
77
|
+
openCmp(): Promise<boolean> {
|
|
59
78
|
throw new Error('Not Implemented');
|
|
60
79
|
}
|
|
61
80
|
|
|
62
|
-
async test(
|
|
81
|
+
async test(): Promise<boolean> {
|
|
63
82
|
// try IAB by default
|
|
64
83
|
return Promise.resolve(true);
|
|
65
84
|
}
|
|
66
85
|
}
|
|
67
86
|
|
|
68
|
-
async function
|
|
69
|
-
if (rule.frame && !tab.frame) {
|
|
70
|
-
await waitFor(() => Promise.resolve(!!tab.frame), 10, 500);
|
|
71
|
-
}
|
|
72
|
-
const frameId = rule.frame && tab.frame ? tab.frame.id : undefined;
|
|
87
|
+
async function evaluateRuleStep(rule: AutoConsentRuleStep) {
|
|
73
88
|
const results = [];
|
|
74
89
|
if (rule.exists) {
|
|
75
|
-
results.push(
|
|
90
|
+
results.push(elementExists(rule.exists));
|
|
76
91
|
}
|
|
77
92
|
if (rule.visible) {
|
|
78
|
-
results.push(
|
|
93
|
+
results.push(elementVisible(rule.visible, rule.check));
|
|
79
94
|
}
|
|
80
95
|
if (rule.eval) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
resolve(await tab.eval(rule.eval!, frameId));
|
|
85
|
-
} catch (e) {
|
|
86
|
-
resolve(false);
|
|
87
|
-
}
|
|
88
|
-
}));
|
|
96
|
+
const res = doEval(rule.eval)
|
|
97
|
+
results.push(res);
|
|
89
98
|
}
|
|
90
99
|
if (rule.waitFor) {
|
|
91
|
-
results.push(
|
|
100
|
+
results.push(waitForElement(rule.waitFor, rule.timeout));
|
|
101
|
+
}
|
|
102
|
+
if (rule.waitForVisible) {
|
|
103
|
+
results.push(waitForVisible(rule.waitForVisible, rule.timeout, rule.check));
|
|
92
104
|
}
|
|
93
105
|
if (rule.click) {
|
|
94
|
-
|
|
95
|
-
results.push(tab.clickElements(rule.click, frameId));
|
|
96
|
-
} else {
|
|
97
|
-
results.push(tab.clickElement(rule.click, frameId));
|
|
98
|
-
}
|
|
106
|
+
results.push(click(rule.click, rule.all));
|
|
99
107
|
}
|
|
100
108
|
if (rule.waitForThenClick) {
|
|
101
|
-
results.push(
|
|
102
|
-
.then(() => tab.clickElement(rule.waitForThenClick!, frameId)));
|
|
109
|
+
results.push(waitForThenClick(rule.waitForThenClick, rule.timeout, rule.all));
|
|
103
110
|
}
|
|
104
111
|
if (rule.wait) {
|
|
105
|
-
results.push(
|
|
106
|
-
}
|
|
107
|
-
if (rule.goto) {
|
|
108
|
-
results.push(tab.goto(rule.goto));
|
|
112
|
+
results.push(wait(rule.wait));
|
|
109
113
|
}
|
|
110
114
|
if (rule.hide) {
|
|
111
|
-
results.push(
|
|
112
|
-
}
|
|
113
|
-
if (rule.undoHide) {
|
|
114
|
-
results.push(tab.undoHideElements(frameId));
|
|
115
|
-
}
|
|
116
|
-
if (rule.waitForFrame) {
|
|
117
|
-
results.push(waitFor(() => !!tab.frame, 40, 500))
|
|
115
|
+
results.push(hide(rule.hide, rule.method));
|
|
118
116
|
}
|
|
117
|
+
|
|
119
118
|
// boolean and of results
|
|
120
|
-
|
|
119
|
+
const all = await Promise.all(results);
|
|
120
|
+
return all.reduce((a, b) => a && b, true);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
export class
|
|
123
|
+
export class AutoConsentCMP extends AutoConsentCMPBase {
|
|
124
124
|
|
|
125
125
|
constructor(public config: AutoConsentCMPRule) {
|
|
126
126
|
super(config.name);
|
|
127
|
+
this.runContext = config.runContext || defaultRunContext;
|
|
127
128
|
}
|
|
128
129
|
|
|
129
|
-
get
|
|
130
|
-
return this.config.
|
|
130
|
+
get hasSelfTest(): boolean {
|
|
131
|
+
return !!this.config.test;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
get isIntermediate(): boolean {
|
|
135
|
+
return !!this.config.intermediate;
|
|
131
136
|
}
|
|
132
137
|
|
|
133
|
-
get
|
|
134
|
-
return this.config.
|
|
138
|
+
get prehideSelectors(): string[] {
|
|
139
|
+
return this.config.prehideSelectors;
|
|
135
140
|
}
|
|
136
141
|
|
|
137
|
-
async _runRulesParallel(
|
|
138
|
-
const
|
|
142
|
+
async _runRulesParallel(rules: AutoConsentRuleStep[]): Promise<boolean> {
|
|
143
|
+
const results = rules.map(rule => evaluateRuleStep(rule));
|
|
144
|
+
const detections = await Promise.all(results);
|
|
139
145
|
return detections.every(r => !!r);
|
|
140
146
|
}
|
|
141
147
|
|
|
142
|
-
async _runRulesSequentially(
|
|
148
|
+
async _runRulesSequentially(rules: AutoConsentRuleStep[]): Promise<boolean> {
|
|
143
149
|
for (const rule of rules) {
|
|
144
|
-
enableLogs && console.log('Running rule...', rule
|
|
145
|
-
const result = await
|
|
150
|
+
enableLogs && console.log('Running rule...', rule);
|
|
151
|
+
const result = await evaluateRuleStep(rule);
|
|
146
152
|
enableLogs && console.log('...rule result', result);
|
|
147
153
|
if (!result && !rule.optional) {
|
|
148
154
|
return false;
|
|
@@ -151,53 +157,47 @@ export class AutoConsent extends AutoConsentBase {
|
|
|
151
157
|
return true;
|
|
152
158
|
}
|
|
153
159
|
|
|
154
|
-
async detectCmp(
|
|
160
|
+
async detectCmp() {
|
|
155
161
|
if (this.config.detectCmp) {
|
|
156
|
-
return this._runRulesParallel(
|
|
162
|
+
return this._runRulesParallel(this.config.detectCmp);
|
|
157
163
|
}
|
|
158
164
|
return false;
|
|
159
165
|
}
|
|
160
166
|
|
|
161
|
-
async detectPopup(
|
|
167
|
+
async detectPopup() {
|
|
162
168
|
if (this.config.detectPopup) {
|
|
163
|
-
return this._runRulesParallel(
|
|
164
|
-
}
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
detectFrame(tab: TabActor, frame: { url: string }) {
|
|
169
|
-
if (this.config.frame) {
|
|
170
|
-
return frame.url.startsWith(this.config.frame);
|
|
169
|
+
return this._runRulesParallel(this.config.detectPopup);
|
|
171
170
|
}
|
|
172
171
|
return false;
|
|
173
172
|
}
|
|
174
173
|
|
|
175
|
-
async optOut(
|
|
174
|
+
async optOut() {
|
|
176
175
|
if (this.config.optOut) {
|
|
177
176
|
enableLogs && console.log('Initiated optOut()', this.config.optOut);
|
|
178
|
-
return this._runRulesSequentially(
|
|
177
|
+
return this._runRulesSequentially(this.config.optOut);
|
|
179
178
|
}
|
|
180
179
|
return false;
|
|
181
180
|
}
|
|
182
181
|
|
|
183
|
-
async optIn(
|
|
182
|
+
async optIn() {
|
|
184
183
|
if (this.config.optIn) {
|
|
185
|
-
|
|
184
|
+
enableLogs && console.log('Initiated optIn()', this.config.optIn);
|
|
185
|
+
return this._runRulesSequentially(this.config.optIn);
|
|
186
186
|
}
|
|
187
187
|
return false;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
async openCmp(
|
|
190
|
+
async openCmp() {
|
|
191
191
|
if (this.config.openCmp) {
|
|
192
|
-
return this._runRulesSequentially(
|
|
192
|
+
return this._runRulesSequentially(this.config.openCmp);
|
|
193
193
|
}
|
|
194
194
|
return false;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
async test(
|
|
198
|
-
if (this.
|
|
199
|
-
return this._runRulesSequentially(
|
|
197
|
+
async test() {
|
|
198
|
+
if (this.hasSelfTest) {
|
|
199
|
+
return this._runRulesSequentially(this.config.test);
|
|
200
200
|
}
|
|
201
|
-
return super.test(
|
|
201
|
+
return super.test();
|
|
202
202
|
}
|
|
203
203
|
}
|
|
@@ -1,39 +1,51 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { click, elementExists, elementVisible, waitForElement } from "../rule-executors";
|
|
2
|
+
import AutoConsentCMPBase from "./base";
|
|
3
3
|
|
|
4
4
|
// Note: JS API is also available:
|
|
5
5
|
// https://help.consentmanager.net/books/cmp/page/javascript-api
|
|
6
|
-
export default class ConsentManager extends
|
|
6
|
+
export default class ConsentManager extends AutoConsentCMPBase {
|
|
7
7
|
|
|
8
8
|
prehideSelectors = ["#cmpbox,#cmpbox2"]
|
|
9
9
|
|
|
10
|
+
get hasSelfTest(): boolean {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get isIntermediate(): boolean {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
10
18
|
constructor() {
|
|
11
19
|
super("consentmanager.net");
|
|
12
20
|
}
|
|
13
21
|
|
|
14
|
-
detectCmp(
|
|
15
|
-
return
|
|
22
|
+
async detectCmp() {
|
|
23
|
+
return elementExists("#cmpbox");
|
|
16
24
|
}
|
|
17
25
|
|
|
18
|
-
detectPopup(
|
|
19
|
-
return
|
|
26
|
+
async detectPopup() {
|
|
27
|
+
return elementVisible("#cmpbox .cmpmore", 'any');
|
|
20
28
|
}
|
|
21
29
|
|
|
22
|
-
async optOut(
|
|
23
|
-
if (
|
|
24
|
-
return
|
|
30
|
+
async optOut() {
|
|
31
|
+
if (click(".cmpboxbtnno")) {
|
|
32
|
+
return true;
|
|
25
33
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
|
|
35
|
+
if (elementExists(".cmpwelcomeprpsbtn")) {
|
|
36
|
+
click(".cmpwelcomeprpsbtn > a[aria-checked=true]", true);
|
|
37
|
+
click(".cmpboxbtnsave");
|
|
38
|
+
return true;
|
|
29
39
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
await
|
|
33
|
-
|
|
40
|
+
|
|
41
|
+
click(".cmpboxbtncustom");
|
|
42
|
+
await waitForElement(".cmptblbox", 2000);
|
|
43
|
+
click(".cmptdchoice > a[aria-checked=true]", true);
|
|
44
|
+
click(".cmpboxbtnyescustomchoices");
|
|
45
|
+
return true;
|
|
34
46
|
}
|
|
35
47
|
|
|
36
|
-
async optIn(
|
|
37
|
-
return
|
|
48
|
+
async optIn() {
|
|
49
|
+
return click(".cmpboxbtnyes");
|
|
38
50
|
}
|
|
39
51
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { AutoCMP } from "../types";
|
|
2
|
+
import { executeAction, matches } from "../consentomatic";
|
|
3
|
+
import { RunContext } from "../rules";
|
|
4
|
+
import { defaultRunContext } from "./base";
|
|
5
|
+
|
|
6
|
+
export type DetectorConfig = {
|
|
7
|
+
presentMatcher: any;
|
|
8
|
+
showingMatcher: any;
|
|
9
|
+
};
|
|
10
|
+
export type MethodConfig = {
|
|
11
|
+
action?: any;
|
|
12
|
+
name: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type ConsentOMaticConfig = {
|
|
16
|
+
detectors: DetectorConfig[];
|
|
17
|
+
methods: MethodConfig[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export class ConsentOMaticCMP implements AutoCMP {
|
|
21
|
+
methods = new Map<string, any>();
|
|
22
|
+
hasSelfTest: boolean;
|
|
23
|
+
runContext: RunContext = defaultRunContext;
|
|
24
|
+
|
|
25
|
+
constructor(public name: string, public config: ConsentOMaticConfig) {
|
|
26
|
+
config.methods.forEach(methodConfig => {
|
|
27
|
+
if (methodConfig.action) {
|
|
28
|
+
this.methods.set(methodConfig.name, methodConfig.action);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
this.hasSelfTest = false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get isIntermediate(): boolean {
|
|
35
|
+
return false; // TODO: support UTILITY rules
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
checkRunContext(): boolean {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async detectCmp(): Promise<boolean> {
|
|
43
|
+
const matchResults = this.config.detectors.map(detectorConfig =>
|
|
44
|
+
matches(detectorConfig.presentMatcher)
|
|
45
|
+
)
|
|
46
|
+
return matchResults.some(r => !!r);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async detectPopup(): Promise<boolean> {
|
|
50
|
+
const matchResults = this.config.detectors.map(detectorConfig =>
|
|
51
|
+
matches(detectorConfig.showingMatcher)
|
|
52
|
+
)
|
|
53
|
+
return matchResults.some(r => !!r);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async executeAction(method: string, param?: any) {
|
|
57
|
+
if (this.methods.has(method)) {
|
|
58
|
+
return executeAction(this.methods.get(method), param);
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async optOut(): Promise<boolean> {
|
|
64
|
+
await this.executeAction("HIDE_CMP");
|
|
65
|
+
await this.executeAction("OPEN_OPTIONS");
|
|
66
|
+
await this.executeAction("HIDE_CMP");
|
|
67
|
+
await this.executeAction("DO_CONSENT", []);
|
|
68
|
+
await this.executeAction("SAVE_CONSENT");
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async optIn(): Promise<boolean> {
|
|
73
|
+
await this.executeAction("HIDE_CMP");
|
|
74
|
+
await this.executeAction("OPEN_OPTIONS");
|
|
75
|
+
await this.executeAction("HIDE_CMP");
|
|
76
|
+
await this.executeAction("DO_CONSENT", ['D', 'A', 'B', 'E', 'F', 'X']);
|
|
77
|
+
await this.executeAction("SAVE_CONSENT");
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
async openCmp(): Promise<boolean> {
|
|
81
|
+
await this.executeAction("HIDE_CMP");
|
|
82
|
+
await this.executeAction("OPEN_OPTIONS");
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async test(): Promise<boolean> {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
}
|
package/lib/cmps/cookiebot.ts
CHANGED
|
@@ -1,81 +1,90 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { click, doEval, elementExists, wait, waitForElement } from '../rule-executors';
|
|
2
|
+
import AutoConsentCMPBase from './base';
|
|
3
3
|
|
|
4
|
-
export default class Cookiebot extends
|
|
4
|
+
export default class Cookiebot extends AutoConsentCMPBase {
|
|
5
5
|
|
|
6
|
-
prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner"]
|
|
6
|
+
prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookieoverlay"]
|
|
7
7
|
|
|
8
8
|
constructor() {
|
|
9
9
|
super('Cybotcookiebot');
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return await tab.eval('typeof window.CookieConsent === "object" && typeof window.CookieConsent.name === "string"');
|
|
15
|
-
} catch (e) {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
12
|
+
get hasSelfTest(): boolean {
|
|
13
|
+
return true;
|
|
18
14
|
}
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
return
|
|
16
|
+
get isIntermediate(): boolean {
|
|
17
|
+
return false;
|
|
22
18
|
}
|
|
23
19
|
|
|
24
|
-
async
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return await tab.clickElement('#CybotCookiebotDialogBodyButtonDecline');
|
|
20
|
+
async detectCmp() {
|
|
21
|
+
return elementExists('#CybotCookiebotDialogBodyLevelButtonPreferences');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async detectPopup() {
|
|
25
|
+
return elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookiebanner');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async optOut() {
|
|
29
|
+
if (click('.cookie-alert-extended-detail-link')) {
|
|
30
|
+
await waitForElement('.cookie-alert-configuration', 2000);
|
|
31
|
+
click('.cookie-alert-configuration-input:checked', true);
|
|
32
|
+
click('.cookie-alert-extended-button-secondary');
|
|
33
|
+
return true;
|
|
39
34
|
}
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
|
|
36
|
+
if (elementExists('#dtcookie-container')) {
|
|
37
|
+
return click('.h-dtcookie-decline');
|
|
42
38
|
}
|
|
43
|
-
|
|
44
|
-
if (
|
|
45
|
-
|
|
39
|
+
|
|
40
|
+
if (click('.cookiebot__button--settings')) {
|
|
41
|
+
return true;
|
|
46
42
|
}
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
|
|
44
|
+
if (click('#CybotCookiebotDialogBodyButtonDecline')) {
|
|
45
|
+
return true;
|
|
49
46
|
}
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
|
|
48
|
+
click('.cookiebanner__link--details');
|
|
49
|
+
|
|
50
|
+
click('.CybotCookiebotDialogBodyLevelButton:checked:enabled,input[id*="CybotCookiebotDialogBodyLevelButton"]:checked:enabled', true);
|
|
51
|
+
|
|
52
|
+
click('#CybotCookiebotDialogBodyButtonDecline');
|
|
53
|
+
|
|
54
|
+
click('input[id^=CybotCookiebotDialogBodyLevelButton]:checked', true);
|
|
55
|
+
|
|
56
|
+
if (elementExists('#CybotCookiebotDialogBodyButtonAcceptSelected')) {
|
|
57
|
+
click('#CybotCookiebotDialogBodyButtonAcceptSelected');
|
|
52
58
|
} else {
|
|
53
|
-
|
|
59
|
+
click('#CybotCookiebotDialogBodyLevelButtonAccept,#CybotCookiebotDialogBodyButtonAccept,#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowallSelection', true);
|
|
54
60
|
}
|
|
61
|
+
|
|
55
62
|
// some sites have custom submit buttons with no obvious selectors. In this case we just call the submitConsent API.
|
|
56
|
-
if (await
|
|
57
|
-
await
|
|
58
|
-
await
|
|
63
|
+
if (await doEval('window.CookieConsent.hasResponse !== true')) {
|
|
64
|
+
await doEval('window.Cookiebot.dialog.submitConsent()');
|
|
65
|
+
await wait(500);
|
|
59
66
|
}
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
67
|
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
|
|
68
|
+
// site with 3rd confirm settings modal
|
|
69
|
+
if (elementExists('#cb-confirmedSettings')) {
|
|
70
|
+
await doEval('endCookieProcess()');
|
|
66
71
|
}
|
|
67
|
-
|
|
68
|
-
await tab.clickElement('#CybotCookiebotDialogBodyLevelButtonAccept');
|
|
69
|
-
await tab.clickElement('#CybotCookiebotDialogBodyButtonAccept');
|
|
72
|
+
|
|
70
73
|
return true;
|
|
71
74
|
}
|
|
72
75
|
|
|
73
|
-
async
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
async optIn() {
|
|
77
|
+
if (elementExists('#dtcookie-container')) {
|
|
78
|
+
return click('.h-dtcookie-accept');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
click('.CybotCookiebotDialogBodyLevelButton:not(:checked):enabled', true);
|
|
82
|
+
click('#CybotCookiebotDialogBodyLevelButtonAccept');
|
|
83
|
+
click('#CybotCookiebotDialogBodyButtonAccept');
|
|
84
|
+
return true;
|
|
76
85
|
}
|
|
77
86
|
|
|
78
|
-
async test(
|
|
79
|
-
return
|
|
87
|
+
async test() {
|
|
88
|
+
return doEval('window.CookieConsent.declined === true');
|
|
80
89
|
}
|
|
81
90
|
}
|
package/lib/cmps/evidon.ts
CHANGED
|
@@ -1,32 +1,43 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { click, elementExists, elementVisible, waitForElement } from "../rule-executors";
|
|
2
|
+
import { getStyleElement, hideElements } from "../utils";
|
|
3
|
+
import AutoConsentCMPBase from "./base";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
// https://help.consentmanager.net/books/cmp/page/javascript-api
|
|
6
|
-
export default class Evidon extends AutoConsentBase {
|
|
5
|
+
export default class Evidon extends AutoConsentCMPBase {
|
|
7
6
|
constructor() {
|
|
8
7
|
super("Evidon");
|
|
9
8
|
}
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
return
|
|
10
|
+
get hasSelfTest(): boolean {
|
|
11
|
+
return false;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
return
|
|
14
|
+
get isIntermediate(): boolean {
|
|
15
|
+
return false;
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
async
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
async detectCmp() {
|
|
19
|
+
return elementExists("#_evidon_banner");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async detectPopup() {
|
|
23
|
+
return elementVisible("#_evidon_banner", 'any');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async optOut() {
|
|
27
|
+
if (click("#_evidon-decline-button")) {
|
|
28
|
+
return true;
|
|
22
29
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
|
|
31
|
+
hideElements(getStyleElement(), ["#evidon-prefdiag-overlay", "#evidon-prefdiag-background"]);
|
|
32
|
+
click("#_evidon-option-button");
|
|
33
|
+
|
|
34
|
+
await waitForElement("#evidon-prefdiag-overlay", 5000);
|
|
35
|
+
|
|
36
|
+
click("#evidon-prefdiag-decline");
|
|
37
|
+
return true;
|
|
27
38
|
}
|
|
28
39
|
|
|
29
|
-
async optIn(
|
|
30
|
-
return
|
|
40
|
+
async optIn() {
|
|
41
|
+
return click("#_evidon-accept-button");
|
|
31
42
|
}
|
|
32
43
|
}
|