@duckduckgo/autoconsent 16.45.0 → 16.47.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 (57) hide show
  1. package/.github/dependabot.yml +6 -0
  2. package/.github/labeler.yml +1 -1
  3. package/.github/workflows/release-labels.yml +19 -11
  4. package/CHANGELOG.md +51 -0
  5. package/dist/addon-firefox/compact-rules.json +1 -1
  6. package/dist/addon-firefox/content.bundle.js +5 -3
  7. package/dist/addon-firefox/manifest.json +1 -1
  8. package/dist/addon-firefox/rule-index.json +1 -1
  9. package/dist/addon-firefox/rules.json +1 -1
  10. package/dist/addon-mv3/compact-rules.json +1 -1
  11. package/dist/addon-mv3/content.bundle.js +5 -3
  12. package/dist/addon-mv3/manifest.json +1 -1
  13. package/dist/addon-mv3/rule-index.json +1 -1
  14. package/dist/addon-mv3/rules.json +1 -1
  15. package/dist/autoconsent.cjs.js +5 -3
  16. package/dist/autoconsent.esm.js +5 -3
  17. package/dist/autoconsent.playwright.js +5 -3
  18. package/dist/autoconsent.standalone.js +6 -4
  19. package/lib/encoding.ts +1 -8
  20. package/lib/heuristic-patterns.ts +1 -1
  21. package/lib/messages.ts +1 -6
  22. package/lib/web.ts +5 -4
  23. package/package.json +6 -6
  24. package/playwright/runner.ts +13 -0
  25. package/rules/autoconsent/controlgame.json +12 -0
  26. package/rules/autoconsent/cookieyes.json +3 -1
  27. package/rules/autoconsent/cookiez.json +9 -0
  28. package/rules/autoconsent/cuvva.com.json +55 -0
  29. package/rules/autoconsent/dalecarnegie.json +44 -0
  30. package/rules/autoconsent/fanatics.json +9 -0
  31. package/rules/autoconsent/jpmorgan-chase.json +10 -0
  32. package/rules/autoconsent/lego.json +26 -0
  33. package/rules/autoconsent/privacy-area.json +56 -0
  34. package/rules/autoconsent/securiti-gpc-flyout.json +22 -0
  35. package/rules/autoconsent/speciesplus.json +10 -0
  36. package/rules/autoconsent/squarespace-cookie-banner.json +24 -1
  37. package/rules/autoconsent/ziptozipmoving.json +44 -0
  38. package/rules/compact-rules.json +1 -1
  39. package/rules/rule-index.json +1 -1
  40. package/rules/rules.json +1 -1
  41. package/tests/controlgame.spec.ts +3 -0
  42. package/tests/cookieyes.spec.ts +2 -0
  43. package/tests/cookiez.spec.ts +12 -0
  44. package/tests/cuvva.com.spec.ts +4 -0
  45. package/tests/dalecarnegie.spec.ts +3 -0
  46. package/tests/fanatics.spec.ts +9 -0
  47. package/tests/jpmorgan-chase.spec.ts +8 -0
  48. package/tests/lego.spec.ts +8 -0
  49. package/tests/privacy-area.spec.ts +9 -0
  50. package/tests/securiti-gpc-flyout.spec.ts +21 -0
  51. package/tests/speciesplus.spec.ts +3 -0
  52. package/tests/squarespace-cookie-banner.spec.ts +8 -1
  53. package/tests/ziptozipmoving.spec.ts +5 -0
  54. package/tests-wtr/heuristics/heuristics-utils.test.ts +6 -0
  55. package/tests-wtr/lifecycle/find-cmp.ts +13 -0
  56. package/tsconfig.build.json +1 -0
  57. package/tsconfig.json +2 -1
package/lib/encoding.ts CHANGED
@@ -13,14 +13,7 @@ export type CompactRuleStep = {
13
13
 
14
14
  export type CompactCMPRuleStep = AutoConsentRuleStep & Partial<CompactRuleStep>;
15
15
  type CompactableRuleStepKey =
16
- | 'exists'
17
- | 'visible'
18
- | 'waitForThenClick'
19
- | 'click'
20
- | 'waitFor'
21
- | 'waitForVisible'
22
- | 'hide'
23
- | 'cookieContains';
16
+ 'exists' | 'visible' | 'waitForThenClick' | 'click' | 'waitFor' | 'waitForVisible' | 'hide' | 'cookieContains';
24
17
  type CompactNullableBoolean = 0 | 1 | 2;
25
18
 
26
19
  export type CompactCMPRule = [
@@ -7,7 +7,7 @@ export const DETECT_PATTERNS = [
7
7
  /only necessary cookies/gi, // "only necessary" is probably too broad
8
8
  /(?:by continuing.{0,100}cookie)|(?:cookie.{0,100}by continuing)/gi,
9
9
  /(?:by continuing.{0,100}privacy)|(?:privacy.{0,100}by continuing)/gi,
10
- /we (?:use|serve)(?: optional)? cookies/gi,
10
+ /we (?:use|serve)(?: optional| essential)? cookies/gi,
11
11
  /we are using cookies/gi,
12
12
  /use of cookies/gi,
13
13
  /website uses cookies to enhance your browsing experience/gi,
package/lib/messages.ts CHANGED
@@ -2,12 +2,7 @@ import { snippets } from './eval-snippets';
2
2
  import { Config, ConsentState, RuleBundle } from './types';
3
3
 
4
4
  export type BackgroundMessage =
5
- | InitResponseMessage
6
- | EvalResponseMessage
7
- | OptOutMessage
8
- | OptInMessage
9
- | SelfTestMessage
10
- | MeasurePerformanceMessage;
5
+ InitResponseMessage | EvalResponseMessage | OptOutMessage | OptInMessage | SelfTestMessage | MeasurePerformanceMessage;
11
6
 
12
7
  export type ContentScriptMessage =
13
8
  | InitMessage
package/lib/web.ts CHANGED
@@ -274,10 +274,9 @@ export default class AutoConsent {
274
274
  }
275
275
  });
276
276
  // heuristic CMP is only run in the top frame and only if heuristic action is enabled and retries is odd
277
+ const heuristicEnabled = isTop && this.config.heuristicMode !== 'off';
277
278
  const heuristicRules =
278
- isTop && this.config.heuristicMode !== 'off' && this.state.findCmpAttempts % 2 === 0
279
- ? [new AutoConsentHeuristicCMP(this, this.config.heuristicMode)]
280
- : [];
279
+ heuristicEnabled && this.state.findCmpAttempts % 2 === 0 ? [new AutoConsentHeuristicCMP(this, this.config.heuristicMode)] : [];
281
280
 
282
281
  const rulesPriorityStages: [string, AutoCMP[]][] = [
283
282
  ['site-specific', siteSpecificRules],
@@ -330,7 +329,9 @@ export default class AutoConsent {
330
329
  // We wait 500ms, and also for some kind of dom mutation to happen before
331
330
  // rerunning the findCmp check
332
331
  const waitFor: Promise<boolean>[] = [this.domActions.wait(500)];
333
- if (this.state.findCmpAttempts > 1) {
332
+ // a skipped heuristic has not seen the current DOM yet, so the next attempt must not wait for another mutation
333
+ const heuristicSkipped = heuristicEnabled && heuristicRules.length === 0;
334
+ if (this.state.findCmpAttempts > 1 && !heuristicSkipped) {
334
335
  waitFor.push(mutationObserver);
335
336
  }
336
337
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duckduckgo/autoconsent",
3
- "version": "16.45.0",
3
+ "version": "16.47.0",
4
4
  "description": "",
5
5
  "types": "./dist/types/web.d.ts",
6
6
  "exports": {
@@ -42,7 +42,7 @@
42
42
  "author": "Sam Macbeth",
43
43
  "license": "MPL-2.0",
44
44
  "devDependencies": {
45
- "@duckduckgo/eslint-config": "github:duckduckgo/eslint-config#v0.3.0",
45
+ "@duckduckgo/eslint-config": "github:duckduckgo/eslint-config#v0.3.1",
46
46
  "@esm-bundle/chai": "^4.3.4-fix.0",
47
47
  "@octokit/rest": "^22.0.1",
48
48
  "@playwright/test": "^1.63.0",
@@ -65,13 +65,13 @@
65
65
  "jsonc-parser": "^3.3.1",
66
66
  "markdown-it": "^15.0.2",
67
67
  "mocha": "^12.0.3",
68
- "prettier": "3.8.3",
68
+ "prettier": "3.9.9",
69
69
  "randexp": "^0.5.3",
70
70
  "sinon": "^22.0.0",
71
71
  "ts-json-schema-generator": "^2.3.0",
72
72
  "ts-node": "^10.9.2",
73
73
  "tslib": "^2.4.0",
74
- "typescript": "^5.1.6",
74
+ "typescript": "^6.0.3",
75
75
  "typescript-eslint": "^8.12.2",
76
76
  "web-ext": "^10.0.0"
77
77
  },
@@ -182,10 +182,10 @@
182
182
  "color": "#ededed"
183
183
  },
184
184
  {
185
- "name": "code-update-needed",
185
+ "name": "needs-code-update",
186
186
  "description": "Changes the autoconsent library code, so consuming browsers need a version update",
187
187
  "releaseType": "none",
188
- "color": "#fbca04"
188
+ "color": "#0b591c"
189
189
  }
190
190
  ],
191
191
  "plugins": [
@@ -28,6 +28,7 @@ type TestOptions = {
28
28
  mobile: boolean;
29
29
  expectPopupOpen: boolean;
30
30
  expectedRuns: number;
31
+ gpc: boolean;
31
32
  };
32
33
  const defaultOptions: TestOptions = {
33
34
  testOptOut: true,
@@ -38,6 +39,7 @@ const defaultOptions: TestOptions = {
38
39
  mobile: false,
39
40
  expectPopupOpen: true,
40
41
  expectedRuns: 1,
42
+ gpc: false,
41
43
  };
42
44
 
43
45
  const contentScript = fs.readFileSync(path.join(__dirname, '../dist/autoconsent.playwright.js'), 'utf8');
@@ -93,6 +95,9 @@ class TestRun {
93
95
  });
94
96
 
95
97
  await this.page.exposeBinding('autoconsentSendMessage', this.messageCallback.bind(this));
98
+ if (this.options.gpc) {
99
+ await this.enableGpc();
100
+ }
96
101
  await this.page.goto(this.url, { waitUntil: 'commit' });
97
102
 
98
103
  await this.injectContentScripts();
@@ -123,6 +128,14 @@ class TestRun {
123
128
  }
124
129
  }
125
130
 
131
+ // emulate a browser that sends the Global Privacy Control signal
132
+ async enableGpc() {
133
+ await this.page.setExtraHTTPHeaders({ 'Sec-GPC': '1' });
134
+ await this.page.addInitScript(() => {
135
+ Object.defineProperty(Navigator.prototype, 'globalPrivacyControl', { get: () => true, configurable: true });
136
+ });
137
+ }
138
+
126
139
  async injectContentScript(pageOrFrame: Page | Frame) {
127
140
  try {
128
141
  await pageOrFrame.evaluate(contentScript);
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "controlgame",
3
+ "vendorUrl": "https://controlgame.com/",
4
+ "runContext": {
5
+ "urlPattern": "^https?://(www\\.)?controlgame\\.com/"
6
+ },
7
+ "detectCmp": [{ "exists": "[data-consent-button][data-value=accept_partial]" }],
8
+ "detectPopup": [{ "visible": "[data-consent-button][data-value=accept_partial]" }],
9
+ "optIn": [{ "waitForThenClick": "[data-consent-button][data-value=accept_all]", "retry": 10, "retryInterval": 500 }],
10
+ "optOut": [{ "waitForThenClick": "[data-consent-button][data-value=accept_partial]", "retry": 10, "retryInterval": 500 }],
11
+ "test": [{ "cookieContains": "advertisement:no" }]
12
+ }
@@ -39,7 +39,9 @@
39
39
  "if": { "exists": ".cky-consent-container [data-cky-tag=settings-button]" },
40
40
  "then": [
41
41
  { "click": ".cky-consent-container [data-cky-tag=settings-button]" },
42
- { "waitFor": ".cky-modal-open input[type=checkbox],.cky-consent-bar-expand input[type=checkbox]" },
42
+ {
43
+ "waitFor": ".cky-modal-open input[type=checkbox],.cky-consent-bar-expand input[type=checkbox],.cky-modal-open [data-cky-tag=detail-save-button],.cky-consent-bar-expand [data-cky-tag=detail-save-button]"
44
+ },
43
45
  {
44
46
  "click": ".cky-modal-open input[type=checkbox]:checked,.cky-consent-bar-expand input[type=checkbox]:checked",
45
47
  "all": true,
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "cookiez",
3
+ "prehideSelectors": [".elementor-popup-modal:has(.cookiez-footer)"],
4
+ "detectCmp": [{ "exists": ".cookiez-footer [data-cookiez-action]" }],
5
+ "detectPopup": [{ "visible": ".cookiez-footer [data-cookiez-action=\"deny-all\"]" }],
6
+ "optIn": [{ "waitForThenClick": ".cookiez-footer [data-cookiez-action=\"accept-all\"]" }],
7
+ "optOut": [{ "waitForThenClick": ".cookiez-footer [data-cookiez-action=\"deny-all\"]" }],
8
+ "test": [{ "wait": 1000 }, { "cookieContains": "%22analytics%22%3Afalse" }]
9
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "cuvva.com",
3
+ "vendorUrl": "https://www.cuvva.com/",
4
+ "cosmetic": false,
5
+ "runContext": {
6
+ "urlPattern": "^https://(www\\.)?cuvva\\.com/"
7
+ },
8
+ "prehideSelectors": [],
9
+ "detectCmp": [
10
+ {
11
+ "exists": "#cuvva-app-injection-site button[data-testid=\"accept-cookies\"]"
12
+ }
13
+ ],
14
+ "detectPopup": [
15
+ {
16
+ "visible": "#cuvva-app-injection-site button[data-testid=\"accept-cookies\"]"
17
+ },
18
+ {
19
+ "cookieContains": "cuvva.app.website.cookie-policy.consent.v2=",
20
+ "negated": true
21
+ }
22
+ ],
23
+ "optIn": [
24
+ {
25
+ "waitForThenClick": "#cuvva-app-injection-site button[data-testid=\"accept-cookies\"]"
26
+ }
27
+ ],
28
+ "optOut": [
29
+ {
30
+ "waitForThenClick": "#cuvva-app-injection-site button[aria-label=\"Reject all\"]",
31
+ "retry": 10,
32
+ "retryInterval": 500
33
+ },
34
+ {
35
+ "wait": 500
36
+ },
37
+ {
38
+ "if": {
39
+ "visible": "#cuvva-app-injection-site button[aria-label=\"Reject all\"]"
40
+ },
41
+ "then": [
42
+ {
43
+ "waitForThenClick": "#cuvva-app-injection-site button[aria-label=\"Reject all\"]",
44
+ "retry": 10,
45
+ "retryInterval": 500
46
+ }
47
+ ]
48
+ }
49
+ ],
50
+ "test": [
51
+ {
52
+ "cookieContains": "cuvva.app.website.cookie-policy.consent.v2={%22preferences%22:{%22functional%22:true%2C%22analytics%22:false%2C%22marketing%22:false"
53
+ }
54
+ ]
55
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "dalecarnegie",
3
+ "vendorUrl": "https://www.dalecarnegie.com/",
4
+ "runContext": {
5
+ "urlPattern": "^https?://(\\w+\\.)?dalecarnegie\\.com/"
6
+ },
7
+ "prehideSelectors": [],
8
+ "detectCmp": [
9
+ {
10
+ "exists": "[class*=\"PrivacyBar_gdprAgreement\"] [class*=\"PrivacyBar_managePrefsBtn\"]"
11
+ }
12
+ ],
13
+ "detectPopup": [
14
+ {
15
+ "visible": "[class*=\"PrivacyBar_gdprAgreement\"]"
16
+ }
17
+ ],
18
+ "optIn": [
19
+ {
20
+ "waitForThenClick": "[class*=\"PrivacyBar_gdprAgreement\"] [class*=\"PrivacyBar_allowBtn\"]"
21
+ }
22
+ ],
23
+ "optOut": [
24
+ {
25
+ "waitForThenClick": "[class*=\"PrivacyBar_gdprAgreement\"] [class*=\"PrivacyBar_managePrefsBtn\"]"
26
+ },
27
+ {
28
+ "waitForVisible": "[class*=\"CookieManagementModal_confirmBtn\"]"
29
+ },
30
+ {
31
+ "click": "[class*=\"CookieManagementModal_dropdownHeader\"] [class*=\"SwitchButton_toggleSwitch\"] input:checked",
32
+ "all": true,
33
+ "optional": true
34
+ },
35
+ {
36
+ "click": "[class*=\"CookieManagementModal_confirmBtn\"]"
37
+ }
38
+ ],
39
+ "test": [
40
+ {
41
+ "cookieContains": "%22targeting%22:false"
42
+ }
43
+ ]
44
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "fanatics",
3
+ "prehideSelectors": [".aspire-banner.marketing-cookies-banner"],
4
+ "detectCmp": [{ "exists": ".aspire-banner.marketing-cookies-banner" }],
5
+ "detectPopup": [{ "visible": ".aspire-banner.marketing-cookies-banner" }],
6
+ "optOut": [{ "waitForThenClick": "[data-trk-id=\"reject-marketing-cookies\"]" }],
7
+ "optIn": [{ "waitForThenClick": "[data-trk-id=\"accept-marketing-cookies\"]" }],
8
+ "test": [{ "cookieContains": "mktck=false" }]
9
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "jpmorgan-chase",
3
+ "vendorUrl": "https://www.jpmorganchase.com/",
4
+ "prehideSelectors": [".consent-banner:has(.consent-close-icon-wrapper)"],
5
+ "detectCmp": [{ "exists": ".consent-banner a.consent-close-icon-wrapper[data-pt-name=\"consent-closed\"]" }],
6
+ "detectPopup": [{ "visible": ".consent-banner a.consent-close-icon-wrapper[data-pt-name=\"consent-closed\"]" }],
7
+ "optIn": [{ "waitForThenClick": ".consent-banner a.consent-close-icon-wrapper[data-pt-name=\"consent-closed\"]" }],
8
+ "optOut": [{ "waitForThenClick": ".consent-banner a.consent-close-icon-wrapper[data-pt-name=\"consent-closed\"]" }],
9
+ "test": [{ "cookieContains": "cbc=true" }]
10
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "lego",
3
+ "runContext": {
4
+ "urlPattern": "^https?://(www\\.)?lego\\.com/"
5
+ },
6
+ "prehideSelectors": ["[class*=\"ConsentModal_consent-modal__modal-overlay\"]"],
7
+ "detectCmp": [{ "exists": "[data-test=\"cookie-necessary-button\"]" }],
8
+ "detectPopup": [{ "visible": "[data-test=\"cookie-necessary-button\"]" }],
9
+ "optOut": [
10
+ { "waitForThenClick": "[data-test=\"cookie-necessary-button\"]" },
11
+ {
12
+ "any": [{ "cookieContains": "AGE_GATE=" }, { "waitForVisible": "[data-test=\"age-gate-overlay\"]", "timeout": 1000 }],
13
+ "optional": true
14
+ },
15
+ {
16
+ "if": { "visible": "[data-test=\"age-gate-overlay\"]" },
17
+ "then": [
18
+ { "waitForVisible": "[data-test=\"age-gate-overlay\"]", "check": "none", "timeout": 30000 },
19
+ { "waitForThenClick": "[data-test=\"cookie-necessary-button\"]", "timeout": 5000 }
20
+ ],
21
+ "optional": true
22
+ }
23
+ ],
24
+ "optIn": [{ "waitForThenClick": "[data-test=\"cookie-accept-all\"]" }],
25
+ "test": [{ "cookieContains": "%22key%22%3A%22analytics%22%2C%22value%22%3Afalse" }]
26
+ }
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "privacy-area",
3
+ "vendorUrl": "https://www.yccable.com/",
4
+ "cosmetic": false,
5
+ "prehideSelectors": [".privacyArea"],
6
+ "detectCmp": [
7
+ {
8
+ "exists": ".privacyArea .privacyTrigger.acceptAll"
9
+ },
10
+ {
11
+ "exists": "#modulePrivacy .privacyTrigger.acceptCustom"
12
+ }
13
+ ],
14
+ "detectPopup": [
15
+ {
16
+ "visible": ".privacyArea"
17
+ }
18
+ ],
19
+ "optIn": [
20
+ {
21
+ "waitForThenClick": ".privacyArea .privacyTrigger.acceptAll"
22
+ }
23
+ ],
24
+ "optOut": [
25
+ {
26
+ "if": {
27
+ "exists": ".privacyArea .privacyTrigger.rejectOptional"
28
+ },
29
+ "then": [
30
+ {
31
+ "click": ".privacyArea .privacyTrigger.rejectOptional"
32
+ }
33
+ ],
34
+ "else": [
35
+ {
36
+ "click": "#modulePrivacy input[type=checkbox]:checked",
37
+ "all": true,
38
+ "optional": true
39
+ },
40
+ {
41
+ "click": "#modulePrivacy .privacyTrigger.acceptCustom"
42
+ }
43
+ ]
44
+ },
45
+ {
46
+ "waitForVisible": ".privacyArea",
47
+ "check": "none",
48
+ "timeout": 3000
49
+ }
50
+ ],
51
+ "test": [
52
+ {
53
+ "cookieContains": "privacy={\"necessary\":\"ok\"}"
54
+ }
55
+ ]
56
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "securiti-gpc-flyout",
3
+ "prehideSelectors": [".f-cmp-flyout-wrapper .f-gpc-banner"],
4
+ "detectCmp": [{ "exists": ".f-cmp-flyout-wrapper .f-gpc-banner .f-banner-close-btn" }],
5
+ "detectPopup": [
6
+ { "visible": ".f-cmp-flyout-wrapper .f-gpc-banner" },
7
+ {
8
+ "comment": "some sites show the cookie banner next to the flyout; leave it to the cookieconsent rules",
9
+ "exists": ".cc-window",
10
+ "negated": true
11
+ }
12
+ ],
13
+ "optIn": [{ "waitForThenClick": ".f-gpc-banner .f-banner-close-btn", "retry": 2 }],
14
+ "optOut": [
15
+ {
16
+ "comment": "the close handler is attached shortly after the flyout is inserted",
17
+ "waitForThenClick": ".f-gpc-banner .f-banner-close-btn",
18
+ "retry": 2
19
+ }
20
+ ],
21
+ "test": [{ "visible": ".f-gpc-banner", "check": "none" }]
22
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "speciesplus.net",
3
+ "runContext": { "urlPattern": "^https?://(www\\.)?speciesplus\\.net/" },
4
+ "prehideSelectors": ["#cookie-consent-message"],
5
+ "detectCmp": [{ "exists": "#cookie-consent-message #cookie-consent-reject" }],
6
+ "detectPopup": [{ "visible": "#cookie-consent-message" }],
7
+ "optIn": [{ "waitForThenClick": "#cookie-consent-accept" }],
8
+ "optOut": [{ "waitForThenClick": "#cookie-consent-reject" }, { "waitForVisible": "#cookie-consent-message", "check": "none" }],
9
+ "test": [{ "cookieContains": "cookieconsent_status=0" }]
10
+ }
@@ -18,7 +18,30 @@
18
18
  ],
19
19
  "optOut": [
20
20
  {
21
- "waitForThenClick": ".cookie-banner-mount-point button.decline"
21
+ "if": {
22
+ "exists": ".cookie-banner-mount-point button.decline"
23
+ },
24
+ "then": [
25
+ {
26
+ "waitForThenClick": ".cookie-banner-mount-point button.decline"
27
+ }
28
+ ],
29
+ "else": [
30
+ {
31
+ "waitForThenClick": ".cookie-banner-mount-point button.manage"
32
+ },
33
+ {
34
+ "waitForVisible": ".cookie-banner-manager .manage-cookies-overlay"
35
+ },
36
+ {
37
+ "click": ".cookie-banner-manager .manage-cookies-overlay label.sqs-toggle--on input",
38
+ "all": true,
39
+ "optional": true
40
+ },
41
+ {
42
+ "waitForThenClick": ".cookie-banner-manager .manage-cookies-overlay button.save"
43
+ }
44
+ ]
22
45
  }
23
46
  ],
24
47
  "test": [
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "ziptozipmoving",
3
+ "vendorUrl": "https://ziptozipmoving.com/",
4
+ "runContext": {
5
+ "urlPattern": "^https://(www\\.)?ziptozipmoving\\.com/"
6
+ },
7
+ "prehideSelectors": [],
8
+ "detectCmp": [
9
+ {
10
+ "exists": ".cookies.main-class .customize-btn"
11
+ }
12
+ ],
13
+ "detectPopup": [
14
+ {
15
+ "visible": ".cookies.main-class .customize-btn"
16
+ }
17
+ ],
18
+ "optIn": [
19
+ {
20
+ "waitForThenClick": ".cookies.main-class .cookies-container .accept-btn"
21
+ }
22
+ ],
23
+ "optOut": [
24
+ {
25
+ "waitForThenClick": ".cookies.main-class .cookies-container .customize-btn"
26
+ },
27
+ {
28
+ "waitForVisible": ".cookies.main-class .cookies-hidden .el-switch"
29
+ },
30
+ {
31
+ "click": ".cookies-hidden .el-switch.is-checked:not(.is-disabled)",
32
+ "all": true,
33
+ "optional": true
34
+ },
35
+ {
36
+ "waitForThenClick": ".cookies.main-class .cookies-hidden .accept-btn"
37
+ }
38
+ ],
39
+ "test": [
40
+ {
41
+ "cookieContains": "validCookies=general--"
42
+ }
43
+ ]
44
+ }