@empiricalrun/playwright-utils 0.62.1 → 0.63.1

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 (136) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/api-worker-client.d.ts +0 -13
  3. package/dist/api-worker-client.d.ts.map +1 -1
  4. package/dist/api-worker-client.js +0 -15
  5. package/dist/auth/google.d.ts.map +1 -1
  6. package/dist/auth/google.js +0 -1
  7. package/dist/auth/index.d.ts.map +1 -1
  8. package/dist/auth/index.js +0 -9
  9. package/dist/config/index.d.ts.map +1 -1
  10. package/dist/config/index.js +0 -8
  11. package/dist/generated/api-worker-openapi.d.ts +3031 -1420
  12. package/dist/generated/api-worker-openapi.d.ts.map +1 -1
  13. package/dist/overlay-tests/cache.spec.js +31 -17
  14. package/dist/overlay-tests/click.spec.js +2 -25
  15. package/dist/overlay-tests/dismiss-mechanics.spec.d.ts +2 -0
  16. package/dist/overlay-tests/dismiss-mechanics.spec.d.ts.map +1 -0
  17. package/dist/overlay-tests/dismiss-mechanics.spec.js +59 -0
  18. package/dist/overlay-tests/dropdown.spec.d.ts +2 -0
  19. package/dist/overlay-tests/dropdown.spec.d.ts.map +1 -0
  20. package/dist/overlay-tests/dropdown.spec.js +53 -0
  21. package/dist/overlay-tests/fixtures.d.ts +3 -1
  22. package/dist/overlay-tests/fixtures.d.ts.map +1 -1
  23. package/dist/overlay-tests/fixtures.js +15 -0
  24. package/dist/overlay-tests/typesafe-hit-check.spec.d.ts +2 -0
  25. package/dist/overlay-tests/typesafe-hit-check.spec.d.ts.map +1 -0
  26. package/dist/overlay-tests/typesafe-hit-check.spec.js +57 -0
  27. package/dist/overlay-tests/typesafe.spec.d.ts +2 -0
  28. package/dist/overlay-tests/typesafe.spec.d.ts.map +1 -0
  29. package/dist/overlay-tests/typesafe.spec.js +86 -0
  30. package/dist/playwright-extensions.d.ts.map +1 -1
  31. package/dist/playwright-extensions.js +0 -1
  32. package/dist/reporter/attachment-cleanup-test-reporter.d.ts +0 -6
  33. package/dist/reporter/attachment-cleanup-test-reporter.d.ts.map +1 -1
  34. package/dist/reporter/attachment-cleanup-test-reporter.js +0 -6
  35. package/dist/reporter/attachment-cleanup.d.ts +0 -33
  36. package/dist/reporter/attachment-cleanup.d.ts.map +1 -1
  37. package/dist/reporter/attachment-cleanup.js +2 -51
  38. package/dist/reporter/empirical-reporter.d.ts.map +1 -1
  39. package/dist/reporter/empirical-reporter.js +0 -9
  40. package/dist/reporter/harness.d.ts +0 -62
  41. package/dist/reporter/harness.d.ts.map +1 -1
  42. package/dist/reporter/harness.js +1 -53
  43. package/dist/reporter/ibr-utils.d.ts +0 -5
  44. package/dist/reporter/ibr-utils.d.ts.map +1 -1
  45. package/dist/reporter/ibr-utils.js +0 -5
  46. package/dist/reporter/incremental-blob-reporter.d.ts +0 -17
  47. package/dist/reporter/incremental-blob-reporter.d.ts.map +1 -1
  48. package/dist/reporter/incremental-blob-reporter.js +5 -35
  49. package/dist/reporter/lifecycle-events.d.ts.map +1 -1
  50. package/dist/reporter/lifecycle-events.js +0 -9
  51. package/dist/reporter/parity-utils.d.ts +0 -30
  52. package/dist/reporter/parity-utils.d.ts.map +1 -1
  53. package/dist/reporter/parity-utils.js +4 -28
  54. package/dist/reporter/reporter-state.d.ts +0 -12
  55. package/dist/reporter/reporter-state.d.ts.map +1 -1
  56. package/dist/reporter/reporter-state.js +0 -12
  57. package/dist/reporter/test-case-sync.d.ts.map +1 -1
  58. package/dist/reporter/test-case-sync.js +0 -12
  59. package/dist/reporter/uploader.d.ts.map +1 -1
  60. package/dist/reporter/uploader.js +0 -6
  61. package/dist/reporter/util.d.ts +0 -33
  62. package/dist/reporter/util.d.ts.map +1 -1
  63. package/dist/reporter/util.js +0 -37
  64. package/dist/telemetry.d.ts.map +1 -1
  65. package/dist/telemetry.js +1 -10
  66. package/dist/test/coverage.d.ts.map +1 -1
  67. package/dist/test/coverage.js +1 -3
  68. package/dist/test/expect/visual.d.ts.map +1 -1
  69. package/dist/test/expect/visual.js +1 -9
  70. package/dist/test/index.d.ts.map +1 -1
  71. package/dist/test/index.js +4 -21
  72. package/dist/test/scripts/agent-capabilities.js +2 -2
  73. package/dist/test/scripts/index.d.ts +2 -2
  74. package/dist/test/scripts/index.d.ts.map +1 -1
  75. package/dist/test/scripts/index.js +3 -16
  76. package/dist/test/scripts/pw-locator-patch/actions/click.d.ts.map +1 -0
  77. package/dist/test/scripts/pw-locator-patch/{highlight → actions}/click.js +8 -6
  78. package/dist/test/scripts/pw-locator-patch/actions/hover.d.ts.map +1 -0
  79. package/dist/test/scripts/pw-locator-patch/{highlight → actions}/hover.js +0 -3
  80. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/cache.d.ts +1 -1
  81. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/cache.d.ts.map +1 -1
  82. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/cache.js +9 -13
  83. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/index.d.ts +3 -0
  84. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/index.d.ts.map +1 -1
  85. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/index.js +14 -12
  86. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/prompt.d.ts.map +1 -1
  87. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/prompt.js +0 -1
  88. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/typesafe.d.ts +38 -0
  89. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/typesafe.d.ts.map +1 -0
  90. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/typesafe.js +159 -0
  91. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/utils.d.ts +3 -0
  92. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/utils.d.ts.map +1 -1
  93. package/dist/test/scripts/pw-locator-patch/dismiss-overlays/utils.js +13 -5
  94. package/dist/test/scripts/pw-locator-patch/utils/index.d.ts +0 -1
  95. package/dist/test/scripts/pw-locator-patch/utils/index.d.ts.map +1 -1
  96. package/dist/test/scripts/pw-locator-patch/utils/index.js +0 -18
  97. package/dist/test/types.d.ts +2 -5
  98. package/dist/test/types.d.ts.map +1 -1
  99. package/dist/test/video-labels.d.ts.map +1 -1
  100. package/dist/test/video-labels.js +0 -1
  101. package/dist/webhook.d.ts.map +1 -1
  102. package/dist/webhook.js +0 -3
  103. package/docs/fixtures.md +4 -5
  104. package/package.json +6 -6
  105. package/playwright.config.ts +0 -4
  106. package/tsconfig.tsbuildinfo +1 -1
  107. package/upstream-oracle/ibr-adapter.js +0 -23
  108. package/upstream-oracle/run.mjs +1 -69
  109. package/dist/test/scripts/locator-highlights.d.ts +0 -4
  110. package/dist/test/scripts/locator-highlights.d.ts.map +0 -1
  111. package/dist/test/scripts/locator-highlights.js +0 -28
  112. package/dist/test/scripts/pw-locator-patch/highlight/click.d.ts.map +0 -1
  113. package/dist/test/scripts/pw-locator-patch/highlight/expect.d.ts +0 -5
  114. package/dist/test/scripts/pw-locator-patch/highlight/expect.d.ts.map +0 -1
  115. package/dist/test/scripts/pw-locator-patch/highlight/expect.js +0 -23
  116. package/dist/test/scripts/pw-locator-patch/highlight/hover.d.ts.map +0 -1
  117. package/dist/test/scripts/pw-locator-patch/highlight/inner-text.d.ts +0 -6
  118. package/dist/test/scripts/pw-locator-patch/highlight/inner-text.d.ts.map +0 -1
  119. package/dist/test/scripts/pw-locator-patch/highlight/inner-text.js +0 -30
  120. package/dist/test/scripts/pw-locator-patch/highlight/input-value.d.ts +0 -6
  121. package/dist/test/scripts/pw-locator-patch/highlight/input-value.d.ts.map +0 -1
  122. package/dist/test/scripts/pw-locator-patch/highlight/input-value.js +0 -30
  123. package/dist/test/scripts/pw-locator-patch/highlight/is-checked.d.ts +0 -6
  124. package/dist/test/scripts/pw-locator-patch/highlight/is-checked.d.ts.map +0 -1
  125. package/dist/test/scripts/pw-locator-patch/highlight/is-checked.js +0 -30
  126. package/dist/test/scripts/pw-locator-patch/highlight/is-disabled.d.ts +0 -6
  127. package/dist/test/scripts/pw-locator-patch/highlight/is-disabled.d.ts.map +0 -1
  128. package/dist/test/scripts/pw-locator-patch/highlight/is-disabled.js +0 -30
  129. package/dist/test/scripts/pw-locator-patch/highlight/is-editable.d.ts +0 -6
  130. package/dist/test/scripts/pw-locator-patch/highlight/is-editable.d.ts.map +0 -1
  131. package/dist/test/scripts/pw-locator-patch/highlight/is-editable.js +0 -29
  132. package/dist/test/scripts/pw-locator-patch/highlight/text-content.d.ts +0 -6
  133. package/dist/test/scripts/pw-locator-patch/highlight/text-content.d.ts.map +0 -1
  134. package/dist/test/scripts/pw-locator-patch/highlight/text-content.js +0 -30
  135. /package/dist/test/scripts/pw-locator-patch/{highlight → actions}/click.d.ts +0 -0
  136. /package/dist/test/scripts/pw-locator-patch/{highlight → actions}/hover.d.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/test/scripts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAI3C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAQjC,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,eAAgC,QAmB1C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/test/scripts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG1C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,EAAE,aAAoB,EAAE,iBAAwB,EAAE,GAAE,cAAmB,QAYxE"}
@@ -3,26 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.injectLocatorHighlightScripts = injectLocatorHighlightScripts;
4
4
  const logger_1 = require("../../logger");
5
5
  const agent_capabilities_1 = require("./agent-capabilities");
6
- const locator_highlights_1 = require("./locator-highlights");
7
6
  const locator_vision_1 = require("./locator-vision");
8
- const defaultOptions = {
9
- locatorHighlighter: true,
10
- visionMethods: true,
11
- agentCapabilities: true,
12
- };
13
- function injectLocatorHighlightScripts(page, testFn, options = defaultOptions) {
14
- const opts = {
15
- ...defaultOptions,
16
- ...options,
17
- };
7
+ function injectLocatorHighlightScripts(page, testFn, { visionMethods = true, agentCapabilities = true } = {}) {
18
8
  try {
19
- if (opts.locatorHighlighter) {
20
- (0, locator_highlights_1.addLocatorHighlights)(page, testFn);
21
- }
22
- if (opts.visionMethods) {
9
+ if (visionMethods) {
23
10
  (0, locator_vision_1.addLocatorVisionMethods)(page);
24
11
  }
25
- if (opts.agentCapabilities) {
12
+ if (agentCapabilities) {
26
13
  (0, agent_capabilities_1.addAgentCapabilities)(page, testFn);
27
14
  }
28
15
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"click.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/actions/click.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAWrC,wBAAgB,UAAU,CACxB,YAAY,EAAE,QAAQ,GAAG;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,EAC/C,MAAM,EAAE,MAAM,QA+Df"}
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.patchClick = patchClick;
4
+ const cua_1 = require("@empiricalrun/cua");
4
5
  const dismiss_overlays_1 = require("../dismiss-overlays");
5
6
  const utils_1 = require("../dismiss-overlays/utils");
6
7
  const utils_2 = require("../utils");
7
- // Static flag to track if click has been patched
8
8
  const isClickPatched = new WeakMap();
9
9
  function patchClick(LocatorClass, testFn) {
10
10
  if (isClickPatched.get(LocatorClass)) {
@@ -16,6 +16,13 @@ function patchClick(LocatorClass, testFn) {
16
16
  LocatorClass.prototype.click = async function (options) {
17
17
  const stepName = `locator.click(${(0, utils_2.description)(this)})`;
18
18
  return await testFn.step(stepName, async () => {
19
+ if (options?.isExecutingForOverlayDismiss &&
20
+ (0, dismiss_overlays_1.overlayClickMode)() === "dispatch" &&
21
+ !(await this.evaluate(cua_1.needsFocus, undefined, {
22
+ timeout: options.timeout,
23
+ }))) {
24
+ return await this.dispatchEvent("click");
25
+ }
19
26
  let overlayAttemptsRemaining = 2;
20
27
  let originalError;
21
28
  const overlayDismiss = new dismiss_overlays_1.OverlayDismissAgent(this._frame._page);
@@ -23,19 +30,15 @@ function patchClick(LocatorClass, testFn) {
23
30
  overlayAttemptsRemaining--;
24
31
  try {
25
32
  let result = await originalClick.apply(this, [options]);
26
- // If click is successful, we can save overlay dismissal code to cache and return
27
33
  await overlayDismiss.saveToCache();
28
34
  return result;
29
35
  }
30
36
  catch (error) {
31
37
  originalError = error;
32
38
  if (originalError instanceof Error) {
33
- // Overwrite the stack trace to show the original click (remove patch)
34
39
  Error.captureStackTrace(originalError, LocatorClass.prototype.click);
35
40
  }
36
41
  if (options?.isExecutingForOverlayDismiss) {
37
- // While executing dismiss code from cache, we attach this custom option
38
- // which ensures that the overlay dismissal will not trigger recursively
39
42
  throw originalError;
40
43
  }
41
44
  if (!(0, dismiss_overlays_1.isErrorSupported)(originalError.message)) {
@@ -45,7 +48,6 @@ function patchClick(LocatorClass, testFn) {
45
48
  throw originalError;
46
49
  }
47
50
  await overlayDismiss.run(originalError, reporter, testFn);
48
- // Dismissal attempt finished (implicitly successful if no error thrown)
49
51
  reporter(`Overlay dismissal attempted, retrying original action.`);
50
52
  }
51
53
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hover.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/actions/hover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAOrC,wBAAgB,UAAU,CACxB,YAAY,EAAE,QAAQ,GAAG;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,EAC/C,MAAM,EAAE,MAAM,QAgDf"}
@@ -21,7 +21,6 @@ function patchHover(LocatorClass, testFn) {
21
21
  overlayAttemptsRemaining--;
22
22
  try {
23
23
  let result = await originalHover.apply(this, [options]);
24
- // If hover is successful, we can save overlay dismissal code to cache and return
25
24
  await overlayDismiss.saveToCache();
26
25
  return result;
27
26
  }
@@ -31,8 +30,6 @@ function patchHover(LocatorClass, testFn) {
31
30
  Error.captureStackTrace(originalError, LocatorClass.prototype.hover);
32
31
  }
33
32
  if (options?.isExecutingForOverlayDismiss) {
34
- // While executing dismiss code from cache, we attach this custom option
35
- // which ensures that the overlay dismissal will not trigger recursively
36
33
  throw originalError;
37
34
  }
38
35
  if (!(0, dismiss_overlays_1.isErrorSupported)(originalError.message)) {
@@ -1,5 +1,5 @@
1
1
  import type { Page } from "@playwright/test";
2
- export declare const CACHE_FILE: string;
2
+ export declare function cacheFile(): string;
3
3
  export declare function setCodeToCache({ dom, text, code, }: {
4
4
  dom: string | undefined;
5
5
  text: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/dismiss-overlays/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAM7C,eAAO,MAAM,UAAU,QAItB,CAAC;AAOF,wBAAsB,cAAc,CAAC,EACnC,GAAG,EACH,IAAI,EACJ,IAAI,GACL,EAAE;IACD,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd,iBAkCA;AAED,wBAAsB,gBAAgB,CAAC,EACrC,IAAI,EACJ,GAAG,EACH,IAAI,GACL,EAAE;IACD,IAAI,EAAE,IAAI,CAAC;IACX,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAmChC;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,UAc5C"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/dismiss-overlays/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAM7C,wBAAgB,SAAS,WAKxB;AAMD,wBAAsB,cAAc,CAAC,EACnC,GAAG,EACH,IAAI,EACJ,IAAI,GACL,EAAE;IACD,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd,iBAgCA;AAED,wBAAsB,gBAAgB,CAAC,EACrC,IAAI,EACJ,GAAG,EACH,IAAI,GACL,EAAE;IACD,IAAI,EAAE,IAAI,CAAC;IACX,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAiChC;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,UAY5C"}
@@ -3,24 +3,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.CACHE_FILE = void 0;
6
+ exports.cacheFile = cacheFile;
7
7
  exports.setCodeToCache = setCodeToCache;
8
8
  exports.executeFromCache = executeFromCache;
9
9
  exports.addOverlayOption = addOverlayOption;
10
10
  const fs_1 = __importDefault(require("fs"));
11
11
  const path_1 = __importDefault(require("path"));
12
- exports.CACHE_FILE = path_1.default.join(process.cwd(), ".empiricalrun", `overlay-cache.json`);
12
+ function cacheFile() {
13
+ return (process.env.EMPIRICALRUN_OVERLAY_CACHE_FILE ??
14
+ path_1.default.join(process.cwd(), ".empiricalrun", "overlay-cache.json"));
15
+ }
13
16
  function normalizeString(str) {
14
- // Replace all whitespace sequences with a single space
15
17
  return str.replace(/\s+/g, " ").trim();
16
18
  }
17
19
  async function setCodeToCache({ dom, text, code, }) {
18
20
  if (!dom && !text) {
19
- // At least one of the two is required
20
21
  return;
21
22
  }
22
23
  if (process.env.TEST_GEN_TOKEN) {
23
- // No caching for test gen sessions (we don't want steps to get committed)
24
24
  return;
25
25
  }
26
26
  const obj = {
@@ -35,7 +35,7 @@ async function setCodeToCache({ dom, text, code, }) {
35
35
  data: [],
36
36
  };
37
37
  try {
38
- cache = JSON.parse(fs_1.default.readFileSync(exports.CACHE_FILE, "utf8"));
38
+ cache = JSON.parse(fs_1.default.readFileSync(cacheFile(), "utf8"));
39
39
  cache.data.push(obj);
40
40
  }
41
41
  catch {
@@ -44,19 +44,18 @@ async function setCodeToCache({ dom, text, code, }) {
44
44
  data: [obj],
45
45
  };
46
46
  }
47
- const dir = path_1.default.dirname(exports.CACHE_FILE);
47
+ const dir = path_1.default.dirname(cacheFile());
48
48
  if (!fs_1.default.existsSync(dir)) {
49
49
  fs_1.default.mkdirSync(dir, { recursive: true });
50
50
  }
51
- fs_1.default.writeFileSync(exports.CACHE_FILE, JSON.stringify(cache, null, 2));
51
+ fs_1.default.writeFileSync(cacheFile(), JSON.stringify(cache, null, 2));
52
52
  }
53
53
  async function executeFromCache({ page, dom, text, }) {
54
54
  if (!dom && !text) {
55
- // At least one of the two is required
56
55
  return { success: false };
57
56
  }
58
57
  try {
59
- const cache = JSON.parse(fs_1.default.readFileSync(exports.CACHE_FILE, "utf8"));
58
+ const cache = JSON.parse(fs_1.default.readFileSync(cacheFile(), "utf8"));
60
59
  const match = cache.data.find((c) => {
61
60
  return (c.element.dom === (dom || "") &&
62
61
  c.element.textContent === normalizeString(text || ""));
@@ -66,7 +65,6 @@ async function executeFromCache({ page, dom, text, }) {
66
65
  }
67
66
  try {
68
67
  console.log(`Executing from cache: "${match.code}" for element: ${dom}`);
69
- // Ref: https://davidwalsh.name/async-function-class
70
68
  const AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
71
69
  const codeToExecute = addOverlayOption(match.code);
72
70
  const exec = new AsyncFunction("page", codeToExecute);
@@ -85,12 +83,10 @@ async function executeFromCache({ page, dom, text, }) {
85
83
  function addOverlayOption(code) {
86
84
  return code.replace(/\.(click|hover)(\s*\(\s*)(\{[^}]*\})?(\s*\))(;)?/g, (match, action, openParen, options, closeParen, semicolon) => {
87
85
  if (options) {
88
- // If options exist, add isExecutingForOverlayDismiss to them
89
86
  const optionsObj = options.replace(/\s*}\s*$/, "");
90
87
  return `.${action}${openParen}${optionsObj}, isExecutingForOverlayDismiss: true }${closeParen}${semicolon || ""}`;
91
88
  }
92
89
  else {
93
- // If no options, add them with isExecutingForOverlayDismiss
94
90
  return `.${action}${openParen}{ isExecutingForOverlayDismiss: true }${closeParen}${semicolon || ""}`;
95
91
  }
96
92
  });
@@ -1,6 +1,8 @@
1
+ import { type ClickMode } from "@empiricalrun/cua";
1
2
  import { Page } from "@playwright/test";
2
3
  import type { TestFn } from "../../types";
3
4
  import type { OverlayElement } from "./types";
5
+ export declare function overlayClickMode(): ClickMode;
4
6
  export declare function isErrorSupported(errorMessage: string | undefined): boolean;
5
7
  export declare class OverlayDismissAgent {
6
8
  private readonly page;
@@ -8,6 +10,7 @@ export declare class OverlayDismissAgent {
8
10
  constructor(page: Page);
9
11
  saveToCache(): Promise<void>;
10
12
  run(originalError: any, reporter: (description: string) => void, testFn: TestFn): Promise<void>;
13
+ private dismiss;
11
14
  private runAgent;
12
15
  }
13
16
  export declare function extractInterceptingElement(errorMessage: string): OverlayElement | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/dismiss-overlays/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAIxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK9C,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,WAKhE;AAED,qBAAa,mBAAmB;IAOlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IANjC,OAAO,CAAC,iBAAiB,CAIhB;IAET,YAA6B,IAAI,EAAE,IAAI,EAAI;IAErC,WAAW,kBAIhB;IAEK,GAAG,CACP,aAAa,EAAE,GAAG,EAClB,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,EACvC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAuDf;YAEa,QAAQ;CAqCvB;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,GACnB,cAAc,GAAG,SAAS,CAiC5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/dismiss-overlays/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAEf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAIxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAW9C,wBAAgB,gBAAgB,IAAI,SAAS,CAI5C;AAED,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,WAKhE;AAED,qBAAa,mBAAmB;IAOlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IANjC,OAAO,CAAC,iBAAiB,CAIhB;IAET,YAA6B,IAAI,EAAE,IAAI,EAAI;IAErC,WAAW,kBAIhB;IAEK,GAAG,CACP,aAAa,EAAE,GAAG,EAClB,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,EACvC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAUf;YAEa,OAAO;YAwDP,QAAQ;CAkCvB;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,GACnB,cAAc,GAAG,SAAS,CAiC5B"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OverlayDismissAgent = void 0;
4
+ exports.overlayClickMode = overlayClickMode;
4
5
  exports.isErrorSupported = isErrorSupported;
5
6
  exports.extractInterceptingElement = extractInterceptingElement;
6
7
  const cua_1 = require("@empiricalrun/cua");
@@ -10,6 +11,11 @@ const cache_1 = require("./cache");
10
11
  const prompt_1 = require("./prompt");
11
12
  const utils_1 = require("./utils");
12
13
  const ERROR_SUBSTRING_INTERCEPTION = "intercepts pointer events";
14
+ function overlayClickMode() {
15
+ return process.env.EMPIRICALRUN_OVERLAY_CLICK_MODE === "dispatch"
16
+ ? "dispatch"
17
+ : "mouse";
18
+ }
13
19
  function isErrorSupported(errorMessage) {
14
20
  if (!errorMessage) {
15
21
  return false;
@@ -28,14 +34,15 @@ class OverlayDismissAgent {
28
34
  }
29
35
  }
30
36
  async run(originalError, reporter, testFn) {
31
- const startTime = Date.now();
32
37
  let element;
33
38
  try {
34
39
  element = extractInterceptingElement(originalError.message);
35
40
  }
36
- catch {
37
- // Ignoring this error
38
- }
41
+ catch { }
42
+ await testFn.step((0, utils_1.dismissOverlayStepTitle)(element), () => this.dismiss(element, originalError, reporter, testFn), { box: true });
43
+ }
44
+ async dismiss(element, originalError, reporter, testFn) {
45
+ const startTime = Date.now();
39
46
  const description = (0, utils_1.overlayDescription)(element) ?? "unknown";
40
47
  const testName = testFn.info().title;
41
48
  reporter(`Attempting to auto-dismiss overlay: ${description}`);
@@ -85,7 +92,7 @@ class OverlayDismissAgent {
85
92
  async runAgent(element, text, testFn) {
86
93
  const task = await (0, prompt_1.getTask)(this.page, element, text);
87
94
  const trace = (0, utils_1.traceThis)(task, testFn);
88
- const result = await (0, cua_1.createTestUsingComputerUseAgent)({
95
+ const result = await testFn.step(utils_1.DISMISSAL_AGENT_STEP, () => (0, cua_1.createTestUsingComputerUseAgent)({
89
96
  page: this.page,
90
97
  task,
91
98
  trace,
@@ -96,15 +103,10 @@ class OverlayDismissAgent {
96
103
  // only once in a particular test run.
97
104
  // Ran into this here: https://empirical.run/quizizz-tests/sessions/2825
98
105
  prefersElementFromPointCodegen: true,
99
- // Overlay dismissal doesn't need page navigation — the overlay is
100
- // already on the current page. Including page_goto causes the model
101
- // to waste turns trying to navigate instead of clicking dismiss.
102
106
  includePageGotoTool: false,
103
- // Route the model call through api-worker (Cloudflare AI Gateway) on the
104
- // project API key, so test-run containers carry no OpenAI key. Undefined
105
- // on a dev machine or in a pi sandbox — see the helper.
106
107
  openAIClientConfig: (0, api_worker_client_1.llmProxyOpenAIConfig)(),
107
- });
108
+ clickMode: overlayClickMode(),
109
+ }));
108
110
  this.cachingCandidates.push({
109
111
  dom: element?.interceptor,
110
112
  text,
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/dismiss-overlays/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,wBAAsB,OAAO,CAC3B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,cAAc,GAAG,SAAS,EACnC,IAAI,EAAE,MAAM,GAAG,SAAS,mBAsCzB"}
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/dismiss-overlays/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,wBAAsB,OAAO,CAC3B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,cAAc,GAAG,SAAS,EACnC,IAAI,EAAE,MAAM,GAAG,SAAS,mBAqCzB"}
@@ -13,7 +13,6 @@ ${text}
13
13
  `
14
14
  : "";
15
15
  if ((0, utils_1.isProductFruitsOverlay)(element)) {
16
- // TODO: Remove this special handling with app knowledge
17
16
  promptAddition = promptForPFScenario(text);
18
17
  }
19
18
  let task = `
@@ -0,0 +1,38 @@
1
+ import type { ElementHandle, Page } from "playwright-core";
2
+ type Box = {
3
+ top: number;
4
+ bottom: number;
5
+ left: number;
6
+ right: number;
7
+ };
8
+ export type TypeSafeDismissStep = {
9
+ popupProbability: number;
10
+ box: Box;
11
+ boxConfidence: number;
12
+ clicked: {
13
+ x: number;
14
+ y: number;
15
+ } | undefined;
16
+ hitCheck: HitCheck | undefined;
17
+ latencyMs: number;
18
+ inputTokens: number;
19
+ outputTokens: number;
20
+ };
21
+ type Point = {
22
+ x: number;
23
+ y: number;
24
+ };
25
+ type HitCheck = "ok" | "no_blocker" | "outside_overlay" | "not_clickable";
26
+ export type TypeSafeStopReason = "popup_gone" | "low_box_confidence" | Exclude<HitCheck, "ok"> | "no_visual_change" | "max_steps";
27
+ export type TypeSafeDismissResult = {
28
+ dismissed: boolean;
29
+ stopReason: TypeSafeStopReason;
30
+ steps: TypeSafeDismissStep[];
31
+ };
32
+ export declare function dismissWithTypeSafe(page: Page, overlay: {
33
+ text: string | undefined;
34
+ target: ElementHandle<Element>;
35
+ }): Promise<TypeSafeDismissResult>;
36
+ export declare function checkHit(target: ElementHandle<Element>, point: Point): Promise<"no_blocker" | "not_clickable" | "ok" | "outside_overlay">;
37
+ export {};
38
+ //# sourceMappingURL=typesafe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typesafe.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/dismiss-overlays/typesafe.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAQ3D,KAAK,GAAG,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAWxE,MAAM,MAAM,mBAAmB,GAAG;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,GAAG,EAAE,GAAG,CAAC;IACT,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC9C,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,KAAK,KAAK,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,KAAK,QAAQ,GAAG,IAAI,GAAG,YAAY,GAAG,iBAAiB,GAAG,eAAe,CAAC;AAE1E,MAAM,MAAM,kBAAkB,GAC1B,YAAY,GACZ,oBAAoB,GACpB,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,GACvB,kBAAkB,GAClB,WAAW,CAAC;AAEhB,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,KAAK,EAAE,mBAAmB,EAAE,CAAC;CAC9B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;CAAE,GACpE,OAAO,CAAC,qBAAqB,CAAC,CAoDhC;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,sEAyDpE"}
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dismissWithTypeSafe = dismissWithTypeSafe;
4
+ exports.checkHit = checkHit;
5
+ const node_crypto_1 = require("node:crypto");
6
+ const SYSTEM_ONE_URL = "https://api.typesafe.ai/v1/systemone";
7
+ const MODEL = "jev-preview";
8
+ const MAX_STEPS = 4;
9
+ const MIN_POPUP_PROBABILITY = 0.5;
10
+ const MIN_BOX_CONFIDENCE = 0.3;
11
+ async function dismissWithTypeSafe(page, overlay) {
12
+ const steps = [];
13
+ const stop = (stopReason) => ({
14
+ dismissed: stopReason === "popup_gone" && steps.length > 1,
15
+ stopReason,
16
+ steps,
17
+ });
18
+ let previousScreenshot;
19
+ for (let i = 0; i < MAX_STEPS; i++) {
20
+ const viewport = page.viewportSize();
21
+ if (!viewport) {
22
+ throw new Error("Viewport size is required for TypeSafe dismissal");
23
+ }
24
+ const screenshot = await page.screenshot({ type: "png" });
25
+ if (previousScreenshot?.equals(screenshot)) {
26
+ return stop("no_visual_change");
27
+ }
28
+ previousScreenshot = screenshot;
29
+ const startedAt = Date.now();
30
+ const response = await askSystemOne(screenshot, overlay.text);
31
+ const { popup_visible, dismiss_control } = response.answers;
32
+ const step = {
33
+ popupProbability: popup_visible.noul,
34
+ box: dismiss_control.box,
35
+ boxConfidence: dismiss_control.confidence,
36
+ clicked: undefined,
37
+ hitCheck: undefined,
38
+ latencyMs: Date.now() - startedAt,
39
+ inputTokens: response.usage.input_tokens,
40
+ outputTokens: response.usage.output_tokens,
41
+ };
42
+ steps.push(step);
43
+ if (popup_visible.noul < MIN_POPUP_PROBABILITY) {
44
+ return stop("popup_gone");
45
+ }
46
+ if (dismiss_control.confidence < MIN_BOX_CONFIDENCE) {
47
+ return stop("low_box_confidence");
48
+ }
49
+ const { box } = dismiss_control;
50
+ const point = {
51
+ x: Math.round(((box.left + box.right) / 2) * viewport.width),
52
+ y: Math.round(((box.top + box.bottom) / 2) * viewport.height),
53
+ };
54
+ step.hitCheck = await checkHit(overlay.target, point);
55
+ if (step.hitCheck !== "ok") {
56
+ return stop(step.hitCheck);
57
+ }
58
+ step.clicked = point;
59
+ await page.mouse.click(point.x, point.y);
60
+ await page.waitForTimeout(300);
61
+ }
62
+ return stop("max_steps");
63
+ }
64
+ function checkHit(target, point) {
65
+ return target.evaluate((targetEl, { x, y }) => {
66
+ const deepHit = (px, py) => {
67
+ let el = document.elementFromPoint(px, py);
68
+ while (el?.shadowRoot) {
69
+ const inner = el.shadowRoot.elementFromPoint(px, py);
70
+ if (!inner || inner === el) {
71
+ break;
72
+ }
73
+ el = inner;
74
+ }
75
+ return el;
76
+ };
77
+ const parentOf = (el) => el.parentNode instanceof ShadowRoot
78
+ ? el.parentNode.host
79
+ : el.parentElement;
80
+ const isAncestorOrSelf = (ancestor, el) => {
81
+ for (let n = el; n; n = parentOf(n)) {
82
+ if (n === ancestor) {
83
+ return true;
84
+ }
85
+ }
86
+ return false;
87
+ };
88
+ const rect = targetEl.getBoundingClientRect();
89
+ const blocker = deepHit(rect.left + rect.width / 2, rect.top + rect.height / 2);
90
+ if (!blocker || isAncestorOrSelf(targetEl, blocker)) {
91
+ return "no_blocker";
92
+ }
93
+ let overlayRoot = blocker;
94
+ for (let p = parentOf(overlayRoot); p && !isAncestorOrSelf(p, targetEl); p = parentOf(p)) {
95
+ overlayRoot = p;
96
+ }
97
+ const hit = deepHit(x, y);
98
+ if (!hit || !isAncestorOrSelf(overlayRoot, hit)) {
99
+ return "outside_overlay";
100
+ }
101
+ const interactive = 'button, a[href], input, select, label, summary, iframe, [role=button], [role=link], [role=checkbox], [role=menuitem], [role=tab], [onclick], [tabindex]:not([tabindex="-1"])';
102
+ for (let n = hit; n; n = parentOf(n)) {
103
+ if (n.matches(interactive) || getComputedStyle(n).cursor === "pointer") {
104
+ return "ok";
105
+ }
106
+ if (n === overlayRoot) {
107
+ break;
108
+ }
109
+ }
110
+ return "not_clickable";
111
+ }, point);
112
+ }
113
+ async function askSystemOne(screenshot, overlayText) {
114
+ const apiKey = process.env.TYPESAFE_API_KEY;
115
+ if (!apiKey) {
116
+ throw new Error("TYPESAFE_API_KEY is not set");
117
+ }
118
+ const reference = (0, node_crypto_1.randomUUID)();
119
+ const popup = overlayText
120
+ ? `the popup that contains the text "${overlayText.trim().slice(0, 300)}"`
121
+ : "the popup";
122
+ const body = {
123
+ model: MODEL,
124
+ state: {
125
+ screenshot: reference,
126
+ context: "A browser test was blocked because a popup (modal, toast, survey, banner or product tour) covers the element it wants to click.",
127
+ },
128
+ assets: {
129
+ [reference]: {
130
+ type: "image",
131
+ format: "png",
132
+ data_base64: screenshot.toString("base64"),
133
+ },
134
+ },
135
+ questions: {
136
+ popup_visible: {
137
+ type: "noul",
138
+ instructions: `Is ${popup} still visible in \`screenshot\`?`,
139
+ },
140
+ dismiss_control: {
141
+ type: "box",
142
+ instructions: `the single control in \`screenshot\` to click next to dismiss ${popup}: a close (×) button, or a Close, Skip, No thanks, Got it, Accept, Agree or Continue button. Prefer the option that accepts or continues over Decline or Cancel. If a required checkbox must be ticked first, the checkbox. Never the page's own controls behind the popup.`,
143
+ },
144
+ },
145
+ };
146
+ const response = await fetch(SYSTEM_ONE_URL, {
147
+ method: "POST",
148
+ headers: {
149
+ Authorization: `Bearer ${apiKey}`,
150
+ "Content-Type": "application/json",
151
+ "TypeSafe-Danger-Zone-Images": "true",
152
+ },
153
+ body: JSON.stringify(body),
154
+ });
155
+ if (!response.ok) {
156
+ throw new Error(`TypeSafe ${response.status}: ${await response.text()}`);
157
+ }
158
+ return (await response.json());
159
+ }
@@ -2,6 +2,9 @@ import type { Page } from "@playwright/test";
2
2
  import type { TestFn } from "../../types";
3
3
  import type { OverlayElement } from "./types";
4
4
  export declare function overlayDescription(element: OverlayElement | undefined): string | undefined;
5
+ export declare const DISMISS_OVERLAY_STEP = "Dismiss overlay";
6
+ export declare const DISMISSAL_AGENT_STEP = "Run overlay dismissal agent";
7
+ export declare function dismissOverlayStepTitle(element: OverlayElement | undefined): string;
5
8
  export declare function isProductFruitsOverlay(element: OverlayElement | undefined): boolean | undefined;
6
9
  export declare function textContent(pageRef: Page, element: OverlayElement | undefined): Promise<string | undefined>;
7
10
  export declare function annotateForReport(testFn: TestFn, description: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/dismiss-overlays/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,sBASrE;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,uBAKzE;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,IAAI,EACb,OAAO,EAAE,cAAc,GAAG,SAAS,+BAmDpC;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,QAMpE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,uDAiBrD"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/dismiss-overlays/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,sBASrE;AAED,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AACtD,eAAO,MAAM,oBAAoB,gCAAgC,CAAC;AAElE,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,UAO1E;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,uBAKzE;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,IAAI,EACb,OAAO,EAAE,cAAc,GAAG,SAAS,+BAgDpC;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,QAMpE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,uDAiBrD"}
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DISMISSAL_AGENT_STEP = exports.DISMISS_OVERLAY_STEP = void 0;
3
4
  exports.overlayDescription = overlayDescription;
5
+ exports.dismissOverlayStepTitle = dismissOverlayStepTitle;
4
6
  exports.isProductFruitsOverlay = isProductFruitsOverlay;
5
7
  exports.textContent = textContent;
6
8
  exports.annotateForReport = annotateForReport;
@@ -17,6 +19,15 @@ function overlayDescription(element) {
17
19
  }
18
20
  }
19
21
  }
22
+ exports.DISMISS_OVERLAY_STEP = "Dismiss overlay";
23
+ exports.DISMISSAL_AGENT_STEP = "Run overlay dismissal agent";
24
+ function dismissOverlayStepTitle(element) {
25
+ const root = element?.parent ?? element?.interceptor ?? "";
26
+ const name = /aria-label="([^"]+)"/.exec(root)?.[1] ??
27
+ /role="([^"]+)"/.exec(root)?.[1] ??
28
+ /<([a-z][a-z0-9-]*)/i.exec(root)?.[1];
29
+ return name ? `${exports.DISMISS_OVERLAY_STEP} "${name}"` : exports.DISMISS_OVERLAY_STEP;
30
+ }
20
31
  function isProductFruitsOverlay(element) {
21
32
  return (element?.parent?.includes("productfruits--container") ||
22
33
  element?.interceptor.includes("productfruits--container"));
@@ -29,7 +40,7 @@ async function textContent(pageRef, element) {
29
40
  let endTag;
30
41
  const match = startTag.match(/^<\s*([^\s>]+)/);
31
42
  if (match) {
32
- const tagName = match[1]; // "div"
43
+ const tagName = match[1];
33
44
  endTag = `</${tagName}>`;
34
45
  }
35
46
  if (!startTag || !endTag) {
@@ -41,18 +52,15 @@ async function textContent(pageRef, element) {
41
52
  const parser = new DOMParser();
42
53
  const doc = parser.parseFromString(htmlString, "text/html");
43
54
  const tempEl = doc.body.firstElementChild;
44
- let selector = tempEl.tagName.toLowerCase(); // start with the tag name, e.g., 'div'
45
- // If there's an id, add it (id is unique and very specific)
55
+ let selector = tempEl.tagName.toLowerCase();
46
56
  if (tempEl.id) {
47
57
  selector += `#${CSS.escape(tempEl.id)}`;
48
58
  }
49
- // Add classes individually, escaping each one
50
59
  if (tempEl.classList.length > 0) {
51
60
  Array.from(tempEl.classList).forEach((cls) => {
52
61
  selector += `.${CSS.escape(cls)}`;
53
62
  });
54
63
  }
55
- // Add other attributes, being careful with escaping
56
64
  Array.from(tempEl.attributes).forEach((attr) => {
57
65
  if (attr.name === "id" || attr.name === "class") {
58
66
  return;
@@ -1,4 +1,3 @@
1
1
  import { Locator } from "playwright-core";
2
2
  export declare function description(locator: Locator): string;
3
- export declare function scrollIntoView(locator: Locator): Promise<void>;
4
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAK1C,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,UA0B3C;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,iBAgBpD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,UA0B3C"}
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.description = description;
4
- exports.scrollIntoView = scrollIntoView;
5
- const logger_1 = require("../../../../logger");
6
- const constants_1 = require("../../../constants");
7
4
  function description(locator) {
8
5
  const fallbackDescription = locator.toString();
9
6
  try {
@@ -25,18 +22,3 @@ function description(locator) {
25
22
  return fallbackDescription;
26
23
  }
27
24
  }
28
- async function scrollIntoView(locator) {
29
- try {
30
- await locator.evaluate((node) => {
31
- if (node.scrollIntoViewIfNeeded) {
32
- node.scrollIntoViewIfNeeded();
33
- }
34
- else {
35
- node.scrollIntoView();
36
- }
37
- }, undefined, { timeout: constants_1.DEFAULT_SCRIPT_EXECUTION_TIMEOUT });
38
- }
39
- catch {
40
- logger_1.logger.debug("Failed to scroll into view for locator method");
41
- }
42
- }
@@ -1,11 +1,8 @@
1
- export type HighlighterOpts = {
2
- /** Show Playwright's action annotations (cursor, target box, title) in videos */
3
- mousePointerHighlighter?: boolean;
4
- locatorHighlighter?: boolean;
1
+ export type PageScriptOpts = {
5
2
  visionMethods?: boolean;
6
3
  agentCapabilities?: boolean;
7
4
  };
8
- export type BaseTestFixtureOpts = HighlighterOpts & {
5
+ export type BaseTestFixtureOpts = PageScriptOpts & {
9
6
  collectCoverage?: boolean;
10
7
  };
11
8
  //# sourceMappingURL=types.d.ts.map