@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.
Files changed (165) hide show
  1. package/.eslintrc.cjs +14 -0
  2. package/.vscode/settings.json +7 -0
  3. package/Jenkinsfile +68 -39
  4. package/api.md +104 -0
  5. package/dist/autoconsent.cjs.js +1 -1371
  6. package/dist/autoconsent.esm.js +1 -1363
  7. package/dist/autoconsent.playwright.js +1 -0
  8. package/dist/autoconsent.standalone.js +1 -0
  9. package/lib/cmps/all.ts +15 -10
  10. package/lib/cmps/base.ts +91 -91
  11. package/lib/cmps/consentmanager.ts +31 -19
  12. package/lib/cmps/consentomatic.ts +89 -0
  13. package/lib/cmps/cookiebot.ts +62 -53
  14. package/lib/cmps/evidon.ts +29 -18
  15. package/lib/cmps/onetrust.ts +37 -19
  16. package/lib/cmps/sourcepoint-frame.ts +102 -0
  17. package/lib/cmps/sourcepoint-top.ts +47 -0
  18. package/lib/cmps/trustarc-frame.ts +115 -0
  19. package/lib/cmps/trustarc-top.ts +91 -0
  20. package/lib/consentomatic/index.ts +233 -70
  21. package/lib/{web/consentomatic → consentomatic}/tools.ts +0 -0
  22. package/lib/eval-handler.ts +58 -0
  23. package/lib/index.ts +0 -2
  24. package/lib/messages.ts +100 -0
  25. package/lib/rule-executors.ts +108 -0
  26. package/lib/rules.ts +82 -0
  27. package/lib/types.ts +35 -0
  28. package/lib/utils.ts +64 -0
  29. package/lib/web.ts +283 -74
  30. package/package.json +17 -14
  31. package/playwright/content.ts +27 -0
  32. package/playwright/runner.ts +131 -0
  33. package/playwright/standalone.ts +36 -0
  34. package/playwright.config.ts +7 -0
  35. package/readme.md +57 -47
  36. package/rollup.config.js +23 -15
  37. package/rules/autoconsent/192.json +17 -0
  38. package/rules/autoconsent/ausopen.json +7 -0
  39. package/rules/autoconsent/aws-amazon.json +1 -1
  40. package/rules/autoconsent/baden-wuerttemberg-de.json +7 -3
  41. package/rules/autoconsent/bing.json +14 -0
  42. package/rules/autoconsent/bundesregierung-de.json +6 -2
  43. package/rules/autoconsent/cc-banner.json +0 -1
  44. package/rules/autoconsent/cookie-notice.json +0 -1
  45. package/rules/autoconsent/cookieconsent.json +5 -6
  46. package/rules/autoconsent/destatis-de.json +0 -1
  47. package/rules/autoconsent/dunelm.json +18 -0
  48. package/rules/autoconsent/etsy.json +3 -2
  49. package/rules/autoconsent/eu-cookie-compliance.json +0 -1
  50. package/rules/autoconsent/gov-uk.json +10 -0
  51. package/rules/autoconsent/hl-co-uk.json +8 -9
  52. package/rules/autoconsent/johnlewis.json +5 -2
  53. package/rules/autoconsent/marksandspencer.json +7 -0
  54. package/rules/autoconsent/notice-cookie.json +0 -1
  55. package/rules/autoconsent/osano.json +0 -1
  56. package/rules/autoconsent/{paypal-de.json → paypal.json} +6 -2
  57. package/rules/autoconsent/tealium.json +4 -5
  58. package/rules/autoconsent/uswitch.json +8 -0
  59. package/rules/autoconsent/waitrose.json +28 -0
  60. package/rules/autoconsent/wetransfer.json +7 -0
  61. package/rules/rules.json +314 -39
  62. package/tests/192.spec.ts +7 -0
  63. package/tests/arzt-auskunft.spec.ts +1 -1
  64. package/tests/asus.spec.ts +1 -1
  65. package/tests/ausopen.spec.ts +7 -0
  66. package/tests/aws.amazon.spec.ts +1 -1
  67. package/tests/baden-wuerttemberg.spec.ts +1 -1
  68. package/tests/borlabs.spec.ts +1 -1
  69. package/tests/bundesregierung.spec.ts +5 -2
  70. package/tests/ccbanner.spec.ts +1 -1
  71. package/tests/consentmanager.spec.ts +3 -3
  72. package/tests/cookiebot.spec.ts +8 -1
  73. package/tests/cookieconsent.spec.ts +1 -1
  74. package/tests/cookielawinfo.spec.ts +1 -1
  75. package/tests/cookienotice.spec.ts +1 -1
  76. package/tests/corona-in-zahlen.spec.ts +1 -1
  77. package/tests/deepl.spec.ts +1 -1
  78. package/tests/destatis.spec.ts +1 -1
  79. package/tests/didomi.spec.ts +6 -2
  80. package/tests/drupal.spec.ts +8 -0
  81. package/tests/dunelm.spec.ts +7 -0
  82. package/tests/etsy.spec.ts +1 -1
  83. package/tests/eu-cookie-compliance-banner.spec.ts +1 -1
  84. package/tests/evidon.spec.ts +1 -1
  85. package/tests/fundingchoices.spec.ts +2 -1
  86. package/tests/gov-uk.spec.ts +9 -0
  87. package/tests/hl-co-uk.spec.ts +1 -1
  88. package/tests/hubspot.spec.ts +1 -1
  89. package/tests/ionos.spec.ts +1 -1
  90. package/tests/johnlewis.spec.ts +2 -2
  91. package/tests/klaro.spec.ts +1 -1
  92. package/tests/marksandspencer.spec.ts +7 -0
  93. package/tests/mediamarkt.spec.ts +1 -1
  94. package/tests/metoffice-gov-uk.spec.ts +1 -1
  95. package/tests/microsoft.spec.ts +1 -1
  96. package/tests/moneysavingexpert.spec.ts +1 -1
  97. package/tests/motor-talk.spec.ts +1 -1
  98. package/tests/national-lottery.spec.ts +1 -1
  99. package/tests/netflix.spec.ts +1 -1
  100. package/tests/nhs.spec.ts +1 -1
  101. package/tests/notice-cookie.spec.ts +1 -1
  102. package/tests/obi.spec.ts +1 -1
  103. package/tests/oil.spec.ts +1 -1
  104. package/tests/onetrust.spec.ts +10 -1
  105. package/tests/osano.spec.ts +1 -1
  106. package/tests/otto.spec.ts +1 -1
  107. package/tests/paypal.spec.ts +8 -6
  108. package/tests/quantcast.spec.ts +4 -1
  109. package/tests/snigel.spec.ts +1 -1
  110. package/tests/sourcepoint.spec.ts +8 -8
  111. package/tests/springer.spec.ts +1 -1
  112. package/tests/steampowered.spec.ts +1 -1
  113. package/tests/tealium.spec.ts +1 -1
  114. package/tests/testcmp.spec.ts +1 -1
  115. package/tests/thalia.spec.ts +1 -1
  116. package/tests/thefreedictionary.spec.ts +1 -1
  117. package/tests/trustarc.spec.ts +25 -3
  118. package/tests/usercentrics-1.spec.ts +1 -1
  119. package/tests/uswitch.spec.ts +7 -0
  120. package/tests/vodafone.spec.ts +1 -1
  121. package/tests/waitrose.spec.ts +7 -0
  122. package/tests/wetransfer.spec.ts +7 -0
  123. package/tests/wordpressgdpr.spec.ts +1 -1
  124. package/tests/xing.spec.ts +1 -1
  125. package/tsconfig.json +2 -2
  126. package/.eslintrc +0 -12
  127. package/cosmetics/rules.json +0 -110
  128. package/dist/autoconsent.puppet.js +0 -1072
  129. package/lib/cmps/all.js +0 -19
  130. package/lib/cmps/base.js +0 -174
  131. package/lib/cmps/consentmanager.js +0 -31
  132. package/lib/cmps/cookiebot.js +0 -73
  133. package/lib/cmps/evidon.js +0 -26
  134. package/lib/cmps/onetrust.js +0 -32
  135. package/lib/cmps/sourcepoint.js +0 -82
  136. package/lib/cmps/sourcepoint.ts +0 -95
  137. package/lib/cmps/trustarc.js +0 -106
  138. package/lib/cmps/trustarc.ts +0 -147
  139. package/lib/config.js +0 -1
  140. package/lib/consentomatic/index.js +0 -52
  141. package/lib/detector.js +0 -33
  142. package/lib/detector.ts +0 -34
  143. package/lib/hider.js +0 -13
  144. package/lib/hider.ts +0 -16
  145. package/lib/index.js +0 -4
  146. package/lib/messages.d.ts +0 -61
  147. package/lib/node.js +0 -35
  148. package/lib/node.ts +0 -43
  149. package/lib/puppet/tab.js +0 -121
  150. package/lib/puppet/tab.ts +0 -146
  151. package/lib/rules.d.ts +0 -80
  152. package/lib/tabwrapper.js +0 -67
  153. package/lib/tabwrapper.ts +0 -74
  154. package/lib/types.d.ts +0 -61
  155. package/lib/web/consentomatic/index.js +0 -188
  156. package/lib/web/consentomatic/index.ts +0 -249
  157. package/lib/web/consentomatic/tools.js +0 -177
  158. package/lib/web/content-utils.js +0 -29
  159. package/lib/web/content-utils.ts +0 -31
  160. package/lib/web/content.js +0 -79
  161. package/lib/web/content.ts +0 -71
  162. package/lib/web/tab.js +0 -112
  163. package/lib/web/tab.ts +0 -178
  164. package/lib/web.js +0 -95
  165. 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, TabActor } from "../types";
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 AutoConsentBase implements AutoCMP {
22
+ export default class AutoConsentCMPBase implements AutoCMP {
30
23
 
31
24
  name: string
32
- hasSelfTest = true
25
+ runContext: RunContext = defaultRunContext;
33
26
 
34
27
  constructor(name: string) {
35
28
  this.name = name;
36
29
  }
37
30
 
38
- detectCmp(tab: TabActor): Promise<boolean> {
31
+ get hasSelfTest(): boolean {
39
32
  throw new Error('Not Implemented');
40
33
  }
41
34
 
42
- async detectPopup(tab: TabActor) {
43
- return false;
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
- detectFrame(tab: TabActor, frame: { url: string }) {
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(tab: TabActor): Promise<boolean> {
69
+ optOut(): Promise<boolean> {
51
70
  throw new Error('Not Implemented');
52
71
  }
53
72
 
54
- optIn(tab: TabActor): Promise<boolean> {
73
+ optIn(): Promise<boolean> {
55
74
  throw new Error('Not Implemented');
56
75
  }
57
76
 
58
- openCmp(tab: TabActor): Promise<boolean> {
77
+ openCmp(): Promise<boolean> {
59
78
  throw new Error('Not Implemented');
60
79
  }
61
80
 
62
- async test(tab: TabActor): Promise<boolean> {
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 evaluateRule(rule: AutoConsentRuleStep, tab: TabActor) {
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(tab.elementExists(rule.exists, frameId));
90
+ results.push(elementExists(rule.exists));
76
91
  }
77
92
  if (rule.visible) {
78
- results.push(tab.elementsAreVisible(rule.visible, rule.check, frameId));
93
+ results.push(elementVisible(rule.visible, rule.check));
79
94
  }
80
95
  if (rule.eval) {
81
- results.push(new Promise(async (resolve) => {
82
- // catch eval error silently
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(tab.waitForElement(rule.waitFor, rule.timeout || 10000, frameId));
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
- if (rule.all === true) {
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(tab.waitForElement(rule.waitForThenClick, rule.timeout || 10000, frameId)
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(tab.wait(rule.wait));
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(tab.hideElements(rule.hide, frameId));
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
- return (await Promise.all(results)).reduce((a, b) => a && b, true);
119
+ const all = await Promise.all(results);
120
+ return all.reduce((a, b) => a && b, true);
121
121
  }
122
122
 
123
- export class AutoConsent extends AutoConsentBase {
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 prehideSelectors(): string[] {
130
- return this.config.prehideSelectors;
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 isHidingRule(): boolean {
134
- return this.config.isHidingRule;
138
+ get prehideSelectors(): string[] {
139
+ return this.config.prehideSelectors;
135
140
  }
136
141
 
137
- async _runRulesParallel(tab: TabActor, rules: AutoConsentRuleStep[]): Promise<boolean> {
138
- const detections = await Promise.all(rules.map(rule => evaluateRule(rule, tab)));
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(tab: TabActor, rules: AutoConsentRuleStep[]): Promise<boolean> {
148
+ async _runRulesSequentially(rules: AutoConsentRuleStep[]): Promise<boolean> {
143
149
  for (const rule of rules) {
144
- enableLogs && console.log('Running rule...', rule, tab.id);
145
- const result = await evaluateRule(rule, tab);
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(tab: TabActor) {
160
+ async detectCmp() {
155
161
  if (this.config.detectCmp) {
156
- return this._runRulesParallel(tab, this.config.detectCmp);
162
+ return this._runRulesParallel(this.config.detectCmp);
157
163
  }
158
164
  return false;
159
165
  }
160
166
 
161
- async detectPopup(tab: TabActor) {
167
+ async detectPopup() {
162
168
  if (this.config.detectPopup) {
163
- return this._runRulesParallel(tab, this.config.detectPopup);
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(tab: TabActor) {
174
+ async optOut() {
176
175
  if (this.config.optOut) {
177
176
  enableLogs && console.log('Initiated optOut()', this.config.optOut);
178
- return this._runRulesSequentially(tab, this.config.optOut);
177
+ return this._runRulesSequentially(this.config.optOut);
179
178
  }
180
179
  return false;
181
180
  }
182
181
 
183
- async optIn(tab: TabActor) {
182
+ async optIn() {
184
183
  if (this.config.optIn) {
185
- return this._runRulesSequentially(tab, this.config.optIn);
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(tab: TabActor) {
190
+ async openCmp() {
191
191
  if (this.config.openCmp) {
192
- return this._runRulesSequentially(tab, this.config.openCmp);
192
+ return this._runRulesSequentially(this.config.openCmp);
193
193
  }
194
194
  return false;
195
195
  }
196
196
 
197
- async test(tab: TabActor) {
198
- if (this.config.test) {
199
- return this._runRulesSequentially(tab, this.config.test);
197
+ async test() {
198
+ if (this.hasSelfTest) {
199
+ return this._runRulesSequentially(this.config.test);
200
200
  }
201
- return super.test(tab);
201
+ return super.test();
202
202
  }
203
203
  }
@@ -1,39 +1,51 @@
1
- import AutoConsentBase from "./base";
2
- import { TabActor } from "../types";
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 AutoConsentBase {
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(tab: TabActor) {
15
- return tab.elementExists("#cmpbox");
22
+ async detectCmp() {
23
+ return elementExists("#cmpbox");
16
24
  }
17
25
 
18
- detectPopup(tab: TabActor) {
19
- return tab.elementsAreVisible("#cmpbox .cmpmore", "any");
26
+ async detectPopup() {
27
+ return elementVisible("#cmpbox .cmpmore", 'any');
20
28
  }
21
29
 
22
- async optOut(tab: TabActor) {
23
- if (await tab.elementExists(".cmpboxbtnno")) {
24
- return tab.clickElement(".cmpboxbtnno");
30
+ async optOut() {
31
+ if (click(".cmpboxbtnno")) {
32
+ return true;
25
33
  }
26
- if (await tab.elementExists(".cmpwelcomeprpsbtn")) {
27
- await tab.clickElements(".cmpwelcomeprpsbtn > a[aria-checked=true]");
28
- return await tab.clickElement(".cmpboxbtnsave");
34
+
35
+ if (elementExists(".cmpwelcomeprpsbtn")) {
36
+ click(".cmpwelcomeprpsbtn > a[aria-checked=true]", true);
37
+ click(".cmpboxbtnsave");
38
+ return true;
29
39
  }
30
- await tab.clickElement(".cmpboxbtncustom");
31
- await tab.waitForElement(".cmptblbox", 2000);
32
- await tab.clickElements(".cmptdchoice > a[aria-checked=true]");
33
- return tab.clickElement(".cmpboxbtnyescustomchoices");
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(tab: TabActor) {
37
- return tab.clickElement(".cmpboxbtnyes");
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
+ }
@@ -1,81 +1,90 @@
1
- import AutoConsentBase from './base';
2
- import { TabActor } from '../types';
1
+ import { click, doEval, elementExists, wait, waitForElement } from '../rule-executors';
2
+ import AutoConsentCMPBase from './base';
3
3
 
4
- export default class Cookiebot extends AutoConsentBase {
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
- async detectCmp(tab: TabActor) {
13
- try {
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
- detectPopup(tab: TabActor) {
21
- return tab.elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner');
16
+ get isIntermediate(): boolean {
17
+ return false;
22
18
  }
23
19
 
24
- async optOut(tab: TabActor) {
25
- if (await tab.elementExists('.cookie-alert-extended-detail-link')) {
26
- await tab.clickElement('.cookie-alert-extended-detail-link');
27
- await tab.waitForElement('.cookie-alert-configuration', 1000);
28
- await tab.clickElements('.cookie-alert-configuration-input:checked');
29
- return tab.clickElement('.cookie-alert-extended-button-secondary');
30
- }
31
- if (await tab.elementExists('#dtcookie-container')) {
32
- return tab.clickElement('.h-dtcookie-decline');
33
- }
34
- if (await tab.elementExists('.cookiebot__button--settings')) {
35
- await tab.clickElement('.cookiebot__button--settings');
36
- }
37
- if (await tab.elementsAreVisible('#CybotCookiebotDialogBodyButtonDecline', 'all')) {
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
- if (await tab.elementExists('.cookiebanner__link--details')) {
41
- await tab.clickElement('.cookiebanner__link--details')
35
+
36
+ if (elementExists('#dtcookie-container')) {
37
+ return click('.h-dtcookie-decline');
42
38
  }
43
- await tab.clickElements('.CybotCookiebotDialogBodyLevelButton:checked:enabled,input[id*="CybotCookiebotDialogBodyLevelButton"]:checked:enabled');
44
- if (await tab.elementExists('#CybotCookiebotDialogBodyButtonDecline')) {
45
- await tab.clickElement('#CybotCookiebotDialogBodyButtonDecline');
39
+
40
+ if (click('.cookiebot__button--settings')) {
41
+ return true;
46
42
  }
47
- if (await tab.elementExists('input[id^=CybotCookiebotDialogBodyLevelButton]:checked')) {
48
- await tab.clickElements('input[id^=CybotCookiebotDialogBodyLevelButton]:checked')
43
+
44
+ if (click('#CybotCookiebotDialogBodyButtonDecline')) {
45
+ return true;
49
46
  }
50
- if (await tab.elementExists('#CybotCookiebotDialogBodyButtonAcceptSelected')) {
51
- await tab.clickElement('#CybotCookiebotDialogBodyButtonAcceptSelected');
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
- await tab.clickElements('#CybotCookiebotDialogBodyLevelButtonAccept,#CybotCookiebotDialogBodyButtonAccept,#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowallSelection');
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 tab.eval('CookieConsent.hasResponse !== true')) {
57
- await tab.eval('Cookiebot.dialog.submitConsent() || true');
58
- await tab.wait(500);
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
- async optIn(tab: TabActor) {
64
- if (await tab.elementExists('#dtcookie-container')) {
65
- return tab.clickElement('.h-dtcookie-accept');
68
+ // site with 3rd confirm settings modal
69
+ if (elementExists('#cb-confirmedSettings')) {
70
+ await doEval('endCookieProcess()');
66
71
  }
67
- await tab.clickElements('.CybotCookiebotDialogBodyLevelButton:not(:checked):enabled');
68
- await tab.clickElement('#CybotCookiebotDialogBodyLevelButtonAccept');
69
- await tab.clickElement('#CybotCookiebotDialogBodyButtonAccept');
72
+
70
73
  return true;
71
74
  }
72
75
 
73
- async openCmp(tab: TabActor) {
74
- await tab.eval('CookieConsent.renew() || true');
75
- return tab.waitForElement('#CybotCookiebotDialog', 10000);
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(tab: TabActor) {
79
- return tab.eval('CookieConsent.declined === true');
87
+ async test() {
88
+ return doEval('window.CookieConsent.declined === true');
80
89
  }
81
90
  }
@@ -1,32 +1,43 @@
1
- import AutoConsentBase from "./base";
2
- import { TabActor } from "../types";
1
+ import { click, elementExists, elementVisible, waitForElement } from "../rule-executors";
2
+ import { getStyleElement, hideElements } from "../utils";
3
+ import AutoConsentCMPBase from "./base";
3
4
 
4
- // Note: JS API is also available:
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
- detectCmp(tab: TabActor) {
12
- return tab.elementExists("#_evidon_banner");
10
+ get hasSelfTest(): boolean {
11
+ return false;
13
12
  }
14
13
 
15
- detectPopup(tab: TabActor) {
16
- return tab.elementsAreVisible("#_evidon_banner");
14
+ get isIntermediate(): boolean {
15
+ return false;
17
16
  }
18
17
 
19
- async optOut(tab: TabActor) {
20
- if (await tab.elementExists("#_evidon-decline-button")) {
21
- return tab.clickElement("#_evidon-decline-button");
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
- tab.hideElements(["#evidon-prefdiag-overlay", "#evidon-prefdiag-background"])
24
- await tab.clickElement("#_evidon-option-button");
25
- await tab.waitForElement("#evidon-prefdiag-overlay", 5000);
26
- return tab.clickElement("#evidon-prefdiag-decline");
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(tab: TabActor) {
30
- return tab.clickElement("#_evidon-accept-button");
40
+ async optIn() {
41
+ return click("#_evidon-accept-button");
31
42
  }
32
43
  }