@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.
Files changed (154) 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 -1387
  6. package/dist/autoconsent.esm.js +1 -1379
  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 +58 -55
  14. package/lib/cmps/evidon.ts +29 -18
  15. package/lib/cmps/onetrust.ts +32 -20
  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/baden-wuerttemberg-de.json +7 -3
  38. package/rules/autoconsent/bundesregierung-de.json +5 -1
  39. package/rules/autoconsent/cc-banner.json +0 -1
  40. package/rules/autoconsent/cookie-notice.json +0 -1
  41. package/rules/autoconsent/cookieconsent.json +5 -6
  42. package/rules/autoconsent/destatis-de.json +0 -1
  43. package/rules/autoconsent/etsy.json +3 -2
  44. package/rules/autoconsent/eu-cookie-compliance.json +0 -1
  45. package/rules/autoconsent/hl-co-uk.json +8 -9
  46. package/rules/autoconsent/johnlewis.json +5 -2
  47. package/rules/autoconsent/notice-cookie.json +0 -1
  48. package/rules/autoconsent/osano.json +0 -1
  49. package/rules/autoconsent/tealium.json +4 -5
  50. package/rules/rules.json +44 -37
  51. package/tests/192.spec.ts +1 -1
  52. package/tests/arzt-auskunft.spec.ts +1 -1
  53. package/tests/asus.spec.ts +1 -1
  54. package/tests/ausopen.spec.ts +1 -1
  55. package/tests/aws.amazon.spec.ts +1 -1
  56. package/tests/baden-wuerttemberg.spec.ts +1 -1
  57. package/tests/borlabs.spec.ts +1 -1
  58. package/tests/bundesregierung.spec.ts +5 -2
  59. package/tests/ccbanner.spec.ts +1 -1
  60. package/tests/consentmanager.spec.ts +3 -3
  61. package/tests/cookiebot.spec.ts +8 -2
  62. package/tests/cookieconsent.spec.ts +1 -1
  63. package/tests/cookielawinfo.spec.ts +1 -1
  64. package/tests/cookienotice.spec.ts +1 -1
  65. package/tests/corona-in-zahlen.spec.ts +1 -1
  66. package/tests/deepl.spec.ts +1 -1
  67. package/tests/destatis.spec.ts +1 -1
  68. package/tests/didomi.spec.ts +6 -2
  69. package/tests/drupal.spec.ts +8 -0
  70. package/tests/dunelm.spec.ts +1 -1
  71. package/tests/etsy.spec.ts +1 -1
  72. package/tests/eu-cookie-compliance-banner.spec.ts +1 -1
  73. package/tests/evidon.spec.ts +1 -1
  74. package/tests/fundingchoices.spec.ts +2 -1
  75. package/tests/gov-uk.spec.ts +1 -1
  76. package/tests/hl-co-uk.spec.ts +1 -1
  77. package/tests/hubspot.spec.ts +1 -1
  78. package/tests/ionos.spec.ts +1 -1
  79. package/tests/johnlewis.spec.ts +2 -2
  80. package/tests/klaro.spec.ts +1 -1
  81. package/tests/marksandspencer.spec.ts +1 -1
  82. package/tests/mediamarkt.spec.ts +1 -1
  83. package/tests/metoffice-gov-uk.spec.ts +1 -1
  84. package/tests/microsoft.spec.ts +1 -1
  85. package/tests/moneysavingexpert.spec.ts +1 -1
  86. package/tests/motor-talk.spec.ts +1 -1
  87. package/tests/national-lottery.spec.ts +1 -1
  88. package/tests/netflix.spec.ts +1 -1
  89. package/tests/nhs.spec.ts +1 -1
  90. package/tests/notice-cookie.spec.ts +1 -1
  91. package/tests/obi.spec.ts +1 -1
  92. package/tests/oil.spec.ts +1 -1
  93. package/tests/onetrust.spec.ts +10 -1
  94. package/tests/osano.spec.ts +1 -1
  95. package/tests/otto.spec.ts +1 -1
  96. package/tests/paypal.spec.ts +1 -1
  97. package/tests/quantcast.spec.ts +4 -1
  98. package/tests/snigel.spec.ts +1 -1
  99. package/tests/sourcepoint.spec.ts +8 -8
  100. package/tests/springer.spec.ts +1 -1
  101. package/tests/steampowered.spec.ts +1 -1
  102. package/tests/tealium.spec.ts +1 -1
  103. package/tests/testcmp.spec.ts +1 -1
  104. package/tests/thalia.spec.ts +1 -1
  105. package/tests/thefreedictionary.spec.ts +1 -1
  106. package/tests/trustarc.spec.ts +25 -4
  107. package/tests/usercentrics-1.spec.ts +1 -1
  108. package/tests/uswitch.spec.ts +1 -1
  109. package/tests/vodafone.spec.ts +1 -1
  110. package/tests/waitrose.spec.ts +1 -1
  111. package/tests/wetransfer.spec.ts +1 -1
  112. package/tests/wordpressgdpr.spec.ts +1 -1
  113. package/tests/xing.spec.ts +1 -1
  114. package/tsconfig.json +2 -2
  115. package/.eslintrc +0 -12
  116. package/cosmetics/rules.json +0 -110
  117. package/dist/autoconsent.puppet.js +0 -1078
  118. package/lib/cmps/all.js +0 -19
  119. package/lib/cmps/base.js +0 -174
  120. package/lib/cmps/consentmanager.js +0 -31
  121. package/lib/cmps/cookiebot.js +0 -77
  122. package/lib/cmps/evidon.js +0 -26
  123. package/lib/cmps/onetrust.js +0 -34
  124. package/lib/cmps/sourcepoint.js +0 -82
  125. package/lib/cmps/sourcepoint.ts +0 -95
  126. package/lib/cmps/trustarc.js +0 -106
  127. package/lib/cmps/trustarc.ts +0 -147
  128. package/lib/config.js +0 -1
  129. package/lib/consentomatic/index.js +0 -52
  130. package/lib/detector.js +0 -33
  131. package/lib/detector.ts +0 -34
  132. package/lib/hider.js +0 -13
  133. package/lib/hider.ts +0 -16
  134. package/lib/index.js +0 -4
  135. package/lib/messages.d.ts +0 -61
  136. package/lib/node.js +0 -35
  137. package/lib/node.ts +0 -43
  138. package/lib/puppet/tab.js +0 -121
  139. package/lib/puppet/tab.ts +0 -146
  140. package/lib/rules.d.ts +0 -80
  141. package/lib/tabwrapper.js +0 -67
  142. package/lib/tabwrapper.ts +0 -74
  143. package/lib/types.d.ts +0 -61
  144. package/lib/web/consentomatic/index.js +0 -188
  145. package/lib/web/consentomatic/index.ts +0 -249
  146. package/lib/web/consentomatic/tools.js +0 -177
  147. package/lib/web/content-utils.js +0 -29
  148. package/lib/web/content-utils.ts +0 -31
  149. package/lib/web/content.js +0 -89
  150. package/lib/web/content.ts +0 -80
  151. package/lib/web/tab.js +0 -112
  152. package/lib/web/tab.ts +0 -178
  153. package/lib/web.js +0 -95
  154. package/tests/runner.ts +0 -61
package/lib/web/tab.js DELETED
@@ -1,112 +0,0 @@
1
- import { waitFor } from "../cmps/base";
2
- import { enableLogs } from "../config";
3
- export default class TabActions {
4
- constructor(tabId, frame, sendContentMessage, browser) {
5
- this.frame = frame;
6
- this.sendContentMessage = sendContentMessage;
7
- this.browser = browser;
8
- this.id = tabId;
9
- }
10
- async elementExists(selector, frameId = 0) {
11
- return this.sendContentMessage(this.id, {
12
- type: "elemExists",
13
- selector
14
- }, {
15
- frameId
16
- });
17
- }
18
- async clickElement(selector, frameId = 0) {
19
- enableLogs && console.log(`click element ${selector} in tab ${this.id}`);
20
- return this.sendContentMessage(this.id, {
21
- type: "click",
22
- selector
23
- }, {
24
- frameId
25
- });
26
- }
27
- async clickElements(selector, frameId = 0) {
28
- enableLogs && console.log(`click elements ${selector} in tab ${this.id}`);
29
- return this.sendContentMessage(this.id, {
30
- type: "click",
31
- all: true,
32
- selector
33
- }, {
34
- frameId
35
- });
36
- }
37
- async elementsAreVisible(selector, check, frameId = 0) {
38
- return this.sendContentMessage(this.id, {
39
- type: "elemVisible",
40
- selector,
41
- check
42
- }, {
43
- frameId
44
- });
45
- }
46
- async getAttribute(selector, attribute, frameId = 0) {
47
- return this.sendContentMessage(this.id, {
48
- type: "getAttribute",
49
- selector,
50
- attribute
51
- }, { frameId });
52
- }
53
- async eval(script, frameId = 0) {
54
- // console.log(`run ${script} in tab ${this.id}`);
55
- return await this.sendContentMessage(this.id, {
56
- type: "eval",
57
- script
58
- }, { frameId });
59
- }
60
- async waitForElement(selector, timeout, frameId = 0) {
61
- const interval = 200;
62
- const times = Math.ceil(timeout / interval);
63
- return waitFor(() => this.elementExists(selector, frameId), times, interval);
64
- }
65
- async waitForThenClick(selector, timeout, frameId = 0) {
66
- if (await this.waitForElement(selector, timeout, frameId)) {
67
- return await this.clickElement(selector, frameId);
68
- }
69
- return false;
70
- }
71
- async hideElements(selectors, frameId = 0, method = 'display') {
72
- enableLogs && console.log('Sending hide elements to', this.id, selectors);
73
- return this.sendContentMessage(this.id, {
74
- type: "hide",
75
- selectors,
76
- method,
77
- }, { frameId });
78
- }
79
- async undoHideElements(frameId = 0) {
80
- return this.sendContentMessage(this.id, {
81
- type: "undohide",
82
- }, { frameId });
83
- }
84
- async getBrowserTab() {
85
- return this.browser.tabs.get(this.id);
86
- }
87
- async goto(url) {
88
- return this.browser.tabs.update(this.id, { url });
89
- }
90
- wait(ms) {
91
- enableLogs && console.log(`waiting for ${ms}ms in tab ${this.id}`);
92
- return new Promise(resolve => {
93
- setTimeout(() => {
94
- enableLogs && console.log(`done waiting in tab ${this.id}`);
95
- resolve(true);
96
- }, ms);
97
- });
98
- }
99
- matches(matcherConfig) {
100
- return this.sendContentMessage(this.id, {
101
- type: "matches",
102
- config: matcherConfig
103
- }, { frameId: 0 });
104
- }
105
- executeAction(config, param) {
106
- return this.sendContentMessage(this.id, {
107
- type: "executeAction",
108
- config,
109
- param
110
- }, { frameId: 0 });
111
- }
112
- }
package/lib/web/tab.ts DELETED
@@ -1,178 +0,0 @@
1
- import { waitFor } from "../cmps/base";
2
- import { enableLogs } from "../config";
3
- import { HideMethod } from "../messages";
4
- import { TabActor, MessageSender, Browser } from "../types";
5
-
6
- export default class TabActions implements TabActor {
7
- id: number;
8
-
9
- constructor(
10
- tabId: number,
11
- public frame: any,
12
- private sendContentMessage: MessageSender,
13
- private browser: Browser
14
- ) {
15
- this.id = tabId;
16
- }
17
-
18
- async elementExists(selector: string, frameId = 0) {
19
- return this.sendContentMessage(
20
- this.id,
21
- {
22
- type: "elemExists",
23
- selector
24
- },
25
- {
26
- frameId
27
- }
28
- );
29
- }
30
-
31
- async clickElement(selector: string, frameId = 0) {
32
- enableLogs && console.log(`click element ${selector} in tab ${this.id}`);
33
- return this.sendContentMessage(
34
- this.id,
35
- {
36
- type: "click",
37
- selector
38
- },
39
- {
40
- frameId
41
- }
42
- );
43
- }
44
-
45
- async clickElements(selector: string, frameId = 0) {
46
- enableLogs && console.log(`click elements ${selector} in tab ${this.id}`);
47
- return this.sendContentMessage(
48
- this.id,
49
- {
50
- type: "click",
51
- all: true,
52
- selector
53
- },
54
- {
55
- frameId
56
- }
57
- );
58
- }
59
-
60
- async elementsAreVisible(selector: string, check?: 'all' | 'any' | 'none', frameId = 0) {
61
- return this.sendContentMessage(
62
- this.id,
63
- {
64
- type: "elemVisible",
65
- selector,
66
- check
67
- },
68
- {
69
- frameId
70
- }
71
- );
72
- }
73
-
74
- async getAttribute(selector: string, attribute: string, frameId = 0) {
75
- return this.sendContentMessage(
76
- this.id,
77
- {
78
- type: "getAttribute",
79
- selector,
80
- attribute
81
- },
82
- { frameId }
83
- );
84
- }
85
-
86
- async eval(script: string, frameId = 0) {
87
- // console.log(`run ${script} in tab ${this.id}`);
88
- return await this.sendContentMessage(
89
- this.id,
90
- {
91
- type: "eval",
92
- script
93
- },
94
- { frameId }
95
- );
96
- }
97
-
98
- async waitForElement(selector: string, timeout: number, frameId = 0) {
99
- const interval = 200;
100
- const times = Math.ceil(timeout / interval);
101
- return waitFor(
102
- () => this.elementExists(selector, frameId),
103
- times,
104
- interval
105
- );
106
- }
107
-
108
- async waitForThenClick(selector: string, timeout: number, frameId = 0) {
109
- if (await this.waitForElement(selector, timeout, frameId)) {
110
- return await this.clickElement(selector, frameId);
111
- }
112
- return false;
113
- }
114
-
115
- async hideElements(selectors: string[], frameId = 0, method: HideMethod = 'display') {
116
- enableLogs && console.log('Sending hide elements to', this.id, selectors);
117
- return this.sendContentMessage(
118
- this.id,
119
- {
120
- type: "hide",
121
- selectors,
122
- method,
123
- },
124
- { frameId }
125
- );
126
- }
127
-
128
- async undoHideElements(frameId = 0): Promise<boolean> {
129
- return this.sendContentMessage(
130
- this.id,
131
- {
132
- type: "undohide",
133
- },
134
- { frameId }
135
- );
136
- }
137
-
138
- async getBrowserTab() {
139
- return this.browser.tabs.get(this.id);
140
- }
141
-
142
- async goto(url: string) {
143
- return this.browser.tabs.update(this.id, { url });
144
- }
145
-
146
- wait(ms: number): Promise<true> {
147
- enableLogs && console.log(`waiting for ${ms}ms in tab ${this.id}`);
148
- return new Promise(resolve => {
149
- setTimeout(() => {
150
- enableLogs && console.log(`done waiting in tab ${this.id}`);
151
- resolve(true);
152
- }, ms);
153
- });
154
- }
155
-
156
- matches(matcherConfig: any) {
157
- return this.sendContentMessage(
158
- this.id,
159
- {
160
- type: "matches",
161
- config: matcherConfig
162
- },
163
- { frameId: 0 }
164
- );
165
- }
166
-
167
- executeAction(config: any, param?: any): Promise<boolean> {
168
- return this.sendContentMessage(
169
- this.id,
170
- {
171
- type: "executeAction",
172
- config,
173
- param
174
- },
175
- { frameId: 0 }
176
- );
177
- }
178
- }
package/lib/web.js DELETED
@@ -1,95 +0,0 @@
1
- import Tab from './web/tab';
2
- import handleContentMessage from './web/content';
3
- import TabConsent from './tabwrapper';
4
- import detectDialog from './detector';
5
- import { rules, createAutoCMP } from './index';
6
- import { ConsentOMaticCMP } from './consentomatic/index';
7
- import prehideElements from './hider';
8
- import { enableLogs } from './config';
9
- export * from './index';
10
- export { Tab, handleContentMessage, };
11
- export default class AutoConsent {
12
- constructor(browser, sendContentMessage) {
13
- this.browser = browser;
14
- this.sendContentMessage = sendContentMessage;
15
- this.consentFrames = new Map();
16
- this.tabCmps = new Map();
17
- this.sendContentMessage = sendContentMessage;
18
- this.rules = [...rules];
19
- }
20
- addCMP(config) {
21
- this.rules.push(createAutoCMP(config));
22
- }
23
- disableCMPs(cmpNames) {
24
- this.rules = this.rules.filter((cmp) => !cmpNames.includes(cmp.name));
25
- }
26
- addConsentomaticCMP(name, config) {
27
- this.rules.push(new ConsentOMaticCMP(`com_${name}`, config));
28
- }
29
- createTab(tabId) {
30
- return new Tab(tabId, this.consentFrames.get(tabId), this.sendContentMessage, this.browser);
31
- }
32
- async checkTab(tabId, prehide = true) {
33
- enableLogs && console.log('checking tab', tabId, this.consentFrames, this.tabCmps);
34
- const tab = this.createTab(tabId);
35
- if (prehide) {
36
- this.prehideElements(tab);
37
- }
38
- const consent = new TabConsent(tab, this.detectDialog(tab, 20));
39
- this.tabCmps.set(tabId, consent);
40
- // check tabs
41
- consent.checked.then((rule) => {
42
- if (this.consentFrames.has(tabId) && rule) {
43
- const frame = this.consentFrames.get(tabId);
44
- enableLogs && console.log(`Found ${rule.name} in a nested iframe ${frame.id} inside tab ${tabId}`);
45
- if (frame.type === rule.name) {
46
- consent.tab.frame = frame;
47
- }
48
- }
49
- enableLogs && console.log('finished checking tab', tabId, this.consentFrames, this.tabCmps);
50
- // no CMP detected, undo hiding
51
- if (!rule && prehide) {
52
- enableLogs && console.log('no CMP detected, undo hiding');
53
- tab.undoHideElements();
54
- }
55
- });
56
- return this.tabCmps.get(tabId);
57
- }
58
- removeTab(tabId) {
59
- this.tabCmps.delete(tabId);
60
- this.consentFrames.delete(tabId);
61
- }
62
- onFrame({ tabId, url, frameId }) {
63
- // ignore main frames
64
- if (frameId === 0) {
65
- return;
66
- }
67
- try {
68
- const frame = {
69
- id: frameId,
70
- url: url,
71
- };
72
- const tab = this.createTab(tabId);
73
- const frameMatch = this.rules.findIndex(r => r.detectFrame(tab, frame));
74
- if (frameMatch > -1) {
75
- this.consentFrames.set(tabId, {
76
- type: this.rules[frameMatch].name,
77
- url,
78
- id: frameId,
79
- });
80
- if (this.tabCmps.has(tabId)) {
81
- this.tabCmps.get(tabId).tab.frame = this.consentFrames.get(tabId);
82
- }
83
- }
84
- }
85
- catch (e) {
86
- console.error(e);
87
- }
88
- }
89
- async detectDialog(tab, retries) {
90
- return detectDialog(tab, retries, this.rules);
91
- }
92
- async prehideElements(tab) {
93
- return prehideElements(tab, this.rules);
94
- }
95
- }
package/tests/runner.ts DELETED
@@ -1,61 +0,0 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
- import { test, expect } from '@playwright/test';
4
- import * as autoconsent from '../dist/autoconsent.puppet';
5
- import * as extraRules from '../rules/rules.json';
6
-
7
- const consentomatic = extraRules.consentomatic;
8
- const rules = [
9
- ...autoconsent.rules,
10
- ...Object.keys(consentomatic).map(name => new autoconsent.ConsentOMaticCMP(`com_${name}`, consentomatic[name])),
11
- ...extraRules.autoconsent.map(spec => autoconsent.createAutoCMP(spec)),
12
- ];
13
- const screenshotDir = `./screenshots`;
14
- const testRegion = (process.env.REGION || 'NA').trim();
15
-
16
- async function ensureScreenshotDir() {
17
- try {
18
- await fs.stat(screenshotDir);
19
- } catch(e) {
20
- await fs.mkdir(screenshotDir);
21
- }
22
- }
23
-
24
- type TestOptions = {
25
- testOptOut: boolean;
26
- testSelfTest: boolean;
27
- skipRegions?: string[];
28
- }
29
- const defaultOptions: TestOptions = {
30
- testOptOut: true,
31
- testSelfTest: true,
32
- skipRegions: [],
33
- }
34
-
35
- export function generateTest(url: string, expectedCmp: string, options: TestOptions = { testOptOut: true, testSelfTest: true }) {
36
- test(`${url.split('://')[1]} .${testRegion}`, async ({ page }) => {
37
- if (options.skipRegions && options.skipRegions.indexOf(testRegion) !== -1) {
38
- test.skip();
39
- }
40
- await page.goto(url, { waitUntil: 'commit' });
41
-
42
- const tab = autoconsent.attachToPage(page, url, rules, 20, true);
43
- await tab.checked;
44
- expect(tab.getCMPName()).toBe(expectedCmp);
45
- expect(await tab.isPopupOpen(50, 100)).toBeTruthy();
46
- if (options.testOptOut) {
47
- expect(await tab.doOptOut()).toBeTruthy();
48
- }
49
- if (options.testSelfTest) {
50
- expect(await tab.testOptOutWorked()).toBeTruthy();
51
- }
52
- });
53
- }
54
-
55
- export default function generateCMPTests(cmp: string, sites: string[], options: Partial<TestOptions> = {}) {
56
- test.describe(cmp, () => {
57
- sites.forEach((url) => {
58
- generateTest(url, cmp, Object.assign({}, defaultOptions, options));
59
- });
60
- })
61
- }