@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
@@ -13,12 +13,11 @@ const useCache = (data) => {
13
13
  version: "2025-03-06",
14
14
  data,
15
15
  };
16
- // Ensure the directory exists
17
- const dir = path_1.default.dirname(cache_1.CACHE_FILE);
16
+ const dir = path_1.default.dirname((0, cache_1.cacheFile)());
18
17
  if (!fs_1.default.existsSync(dir)) {
19
18
  fs_1.default.mkdirSync(dir, { recursive: true });
20
19
  }
21
- fs_1.default.writeFileSync(cache_1.CACHE_FILE, JSON.stringify(cacheValue, null, 2), "utf8");
20
+ fs_1.default.writeFileSync((0, cache_1.cacheFile)(), JSON.stringify(cacheValue, null, 2), "utf8");
22
21
  };
23
22
  // Unsets env vars for the duration of a test and puts them back exactly as they
24
23
  // were — assigning `undefined` to process.env would store the string
@@ -42,14 +41,7 @@ function clearEnv(names) {
42
41
  fixtures_1.test.beforeEach(async ({ page }) => {
43
42
  (0, test_1.injectLocatorHighlightScripts)(page, fixtures_1.test);
44
43
  });
45
- fixtures_1.test.afterEach(() => {
46
- // Delete overlay cache
47
- if (fs_1.default.existsSync(cache_1.CACHE_FILE)) {
48
- fs_1.default.unlinkSync(cache_1.CACHE_FILE);
49
- }
50
- });
51
44
  (0, fixtures_1.test)("overlay dismiss should not trigger recursively when executing from cache", async ({ page, server, }) => {
52
- // Set up cache with a bad value: click on "Target" to dimiss the glass pane
53
45
  useCache([
54
46
  {
55
47
  element: { dom: '<div class="glass-pane">', textContent: "" },
@@ -58,15 +50,8 @@ fixtures_1.test.afterEach(() => {
58
50
  ]);
59
51
  await page.goto(`${server.baseURL}/glass-pane.html`);
60
52
  let error;
61
- // The only two routes the browser agent has to a model: the project API key
62
- // (api-worker's proxy) and a sandbox's OPENAI_BASE_URL. Clearing both makes
63
- // llmProxyOpenAIConfig throw before any request — which matters here more
64
- // than elsewhere, because this is the recursive case and every extra
65
- // dismissal would spawn another agent and another set of screenshots.
66
53
  const restoreEnv = clearEnv(["EMPIRICALRUN_API_KEY", "OPENAI_BASE_URL"]);
67
54
  try {
68
- // Target element click will trigger the cache - which will invoke another
69
- // click to the same element (recursive overlay dismissal)
70
55
  await page.getByRole("button", { name: "Target" }).click();
71
56
  }
72
57
  catch (e) {
@@ -78,3 +63,32 @@ fixtures_1.test.afterEach(() => {
78
63
  (0, fixtures_1.expect)(error).toBeDefined();
79
64
  (0, fixtures_1.expect)(error.message).toContain('<div class="glass-pane"></div> intercepts pointer events');
80
65
  });
66
+ for (const clickMode of ["mouse", "dispatch"]) {
67
+ (0, fixtures_1.test)(`cached dismissal in ${clickMode} mode keeps the test's listbox open`, async ({ page, server, }) => {
68
+ fixtures_1.test.fail(clickMode === "mouse", "A mouse click replayed on the toast is a pointerdown outside the listbox, which closes it");
69
+ await page.goto(`${server.baseURL}/dropdown-toast.html`);
70
+ await page.getByRole("combobox", { name: "Usage month" }).click();
71
+ const toast = page.getByRole("status", { name: "Notifications" });
72
+ await (0, fixtures_1.expect)(toast).toBeVisible();
73
+ const toastText = await toast.evaluate((el) => el.textContent?.trim().replace(/\s+/g, " ") ?? "");
74
+ useCache([
75
+ {
76
+ element: {
77
+ dom: '<section id="toast" role="status" aria-label="Notifications">',
78
+ textContent: toastText,
79
+ },
80
+ code: `await page.getByRole('button', { name: 'Later' }).click();\n`,
81
+ },
82
+ ]);
83
+ const restoreEnv = clearEnv(["EMPIRICALRUN_API_KEY", "OPENAI_BASE_URL"]);
84
+ process.env.EMPIRICALRUN_OVERLAY_CLICK_MODE = clickMode;
85
+ try {
86
+ await page.getByRole("option", { name: "September" }).click();
87
+ }
88
+ finally {
89
+ delete process.env.EMPIRICALRUN_OVERLAY_CLICK_MODE;
90
+ restoreEnv();
91
+ }
92
+ await (0, fixtures_1.expect)(page.locator("#status")).toHaveText("Showing usage for September (1280 credits)");
93
+ });
94
+ }
@@ -10,14 +10,8 @@ const fixtures_1 = require("./fixtures");
10
10
  fixtures_1.test.beforeEach(async ({ page }) => {
11
11
  (0, test_1.injectLocatorHighlightScripts)(page, fixtures_1.test);
12
12
  });
13
- fixtures_1.test.afterAll(async () => {
14
- // Delete overlay cache
15
- if (fs_1.default.existsSync(cache_1.CACHE_FILE)) {
16
- fs_1.default.unlinkSync(cache_1.CACHE_FILE);
17
- }
18
- });
19
13
  function getCacheDataWithDom({ dom }) {
20
- const cacheData = JSON.parse(fs_1.default.readFileSync(cache_1.CACHE_FILE, "utf8"));
14
+ const cacheData = JSON.parse(fs_1.default.readFileSync((0, cache_1.cacheFile)(), "utf8"));
21
15
  return cacheData.data.find(({ element }) => {
22
16
  if (dom) {
23
17
  return element.dom.includes(dom);
@@ -26,7 +20,7 @@ function getCacheDataWithDom({ dom }) {
26
20
  });
27
21
  }
28
22
  function getCacheDataWithTextContent({ textContent }) {
29
- const cacheData = JSON.parse(fs_1.default.readFileSync(cache_1.CACHE_FILE, "utf8"));
23
+ const cacheData = JSON.parse(fs_1.default.readFileSync((0, cache_1.cacheFile)(), "utf8"));
30
24
  return cacheData.data.find(({ element }) => {
31
25
  if (textContent) {
32
26
  return element.textContent.includes(textContent);
@@ -36,28 +30,20 @@ function getCacheDataWithTextContent({ textContent }) {
36
30
  }
37
31
  (0, fixtures_1.test)("should dismiss survicate for hover", async ({ page, server }) => {
38
32
  await page.goto(`${server.baseURL}/survey.html`);
39
- // Assert that Survicate and button loads
40
33
  await (0, fixtures_1.expect)(page.getByText("Start survey")).toBeVisible();
41
34
  const targetButton = page.getByRole("button", { name: "Target" });
42
35
  await (0, fixtures_1.expect)(targetButton).toBeVisible();
43
- // Get initial z-index
44
36
  const initialZIndex = await targetButton.evaluate((el) => window.getComputedStyle(el).getPropertyValue("z-index"));
45
- // Do the hover, which should pass after survey overlay is dismissed
46
37
  await targetButton.hover();
47
- // Assert z-index hasn't changed
48
38
  const finalZIndex = await targetButton.evaluate((el) => window.getComputedStyle(el).getPropertyValue("z-index"));
49
39
  (0, fixtures_1.expect)(finalZIndex).toBe(initialZIndex);
50
40
  });
51
- // Skipped since it's flaky
52
41
  fixtures_1.test.skip("should dismiss two-step overlay for click", async ({ page, server, }) => {
53
42
  await page.goto(`${server.baseURL}/tos.html`);
54
- // Assert that button and overlay load
55
43
  await (0, fixtures_1.expect)(page.getByRole("button", { name: "Target" })).toBeVisible();
56
44
  await (0, fixtures_1.expect)(page.getByRole("heading", { name: "Terms of Service" })).toBeVisible();
57
- // Do the click, which should pass
58
45
  await page.getByRole("button", { name: "Target" }).click();
59
46
  await (0, fixtures_1.expect)(page.getByRole("heading", { name: "Terms of Service" })).not.toBeVisible();
60
- // Assert cache is correct
61
47
  const withDom = getCacheDataWithDom({
62
48
  dom: '<div class="terms-text">',
63
49
  });
@@ -75,7 +61,6 @@ fixtures_1.test.skip("should dismiss two-step overlay for click", async ({ page,
75
61
  await page.goto(`${server.baseURL}/overlay-form.html`);
76
62
  await page.getByRole("button", { name: "Target" }).click();
77
63
  await (0, fixtures_1.expect)(page.getByText("Target was clicked")).toBeVisible();
78
- // Assert cache is correct
79
64
  const withDom = getCacheDataWithDom({
80
65
  dom: 'id="hearAboutUs"',
81
66
  });
@@ -92,16 +77,12 @@ fixtures_1.test.skip("should dismiss two-step overlay for click", async ({ page,
92
77
  });
93
78
  (0, fixtures_1.test)("should choose and dismiss the correct overlay", async ({ page, server, }) => {
94
79
  await page.goto(`${server.baseURL}/choose-an-overlay.html`);
95
- // Assert that button and overlays load
96
80
  await (0, fixtures_1.expect)(page.getByRole("button", { name: "Target" })).toBeVisible();
97
81
  await (0, fixtures_1.expect)(page.getByText("This is a toast message")).toBeVisible();
98
82
  await (0, fixtures_1.expect)(page.getByRole("button", { name: "Close" })).toBeVisible();
99
- // Do the click, which should pass
100
83
  await page.getByRole("button", { name: "Target" }).click();
101
- // Assert correct overlay was dismissed
102
84
  await (0, fixtures_1.expect)(page.getByText("This is a toast message")).not.toBeVisible();
103
85
  await (0, fixtures_1.expect)(page.getByRole("button", { name: "Close" })).toBeVisible();
104
- // Assert cache is correct
105
86
  const withDom = getCacheDataWithDom({
106
87
  dom: '<div id="toast" class="z-[100]">',
107
88
  });
@@ -115,19 +96,15 @@ fixtures_1.test.skip("should dismiss two-step overlay for click", async ({ page,
115
96
  (0, fixtures_1.expect)(code).toBeDefined();
116
97
  (0, fixtures_1.expect)(code).toContain("await page.getByRole('button', { name: '×' }).click()");
117
98
  });
118
- // Test is flaky - skipping it
119
99
  fixtures_1.test.skip("should fallback when the overlay cannot be dismissed", async ({ page, server, }) => {
120
100
  await page.goto(`${server.baseURL}/no-overlay.html`);
121
101
  let error;
122
102
  try {
123
- // Click on element that is hidden below another button, which is not
124
- // dismissible
125
103
  await page.getByRole("button", { name: "Bottom Button" }).click();
126
104
  }
127
105
  catch (e) {
128
106
  error = e;
129
107
  }
130
- // TODO: add better assertions with result from master agent
131
108
  console.log(fixtures_1.test.info().annotations);
132
109
  (0, fixtures_1.expect)(error).toBeDefined();
133
110
  (0, fixtures_1.expect)(error.message).toContain('<button type="button" class="top-button">Top Button</button> intercepts pointer events');
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dismiss-mechanics.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dismiss-mechanics.spec.d.ts","sourceRoot":"","sources":["../../src/overlay-tests/dismiss-mechanics.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fixtures_1 = require("./fixtures");
4
+ const dismissals = {
5
+ "native click": (page) => page.getByRole("button", { name: "Later" }).click(),
6
+ "dispatched click": (page) => page.getByRole("button", { name: "Later" }).dispatchEvent("click"),
7
+ "Escape key": (page) => page.keyboard.press("Escape"),
8
+ };
9
+ const keepsListboxOpen = {
10
+ pointerdown: {
11
+ "native click": false,
12
+ "dispatched click": true,
13
+ "Escape key": false,
14
+ },
15
+ focusout: {
16
+ "native click": false,
17
+ "dispatched click": true,
18
+ "Escape key": false,
19
+ },
20
+ };
21
+ for (const [closeOn, expectations] of Object.entries(keepsListboxOpen)) {
22
+ for (const [name, keepsOpen] of Object.entries(expectations)) {
23
+ (0, fixtures_1.test)(`${name} on a toast ${keepsOpen ? "keeps" : "closes"} a listbox that closes on ${closeOn}`, async ({ page, server, }) => {
24
+ await page.goto(`${server.baseURL}/dropdown-toast.html?close=${closeOn}`);
25
+ await page.getByRole("combobox", { name: "Usage month" }).click();
26
+ const listbox = page.getByRole("listbox", { name: "Months" });
27
+ await (0, fixtures_1.expect)(listbox).toBeVisible();
28
+ await (0, fixtures_1.expect)(page.getByText("Install our CLI for your coding agents")).toBeVisible();
29
+ await dismissals[name](page);
30
+ await (0, fixtures_1.expect)(page.getByText("Install our CLI for your coding agents")).toBeVisible({ visible: name === "Escape key" });
31
+ await (0, fixtures_1.expect)(listbox).toBeVisible({ visible: keepsOpen });
32
+ });
33
+ }
34
+ }
35
+ (0, fixtures_1.test)("dispatched click lets the test finish selecting a month", async ({ page, server, }) => {
36
+ await page.goto(`${server.baseURL}/dropdown-toast.html?close=pointerdown`);
37
+ await page.getByRole("combobox", { name: "Usage month" }).click();
38
+ await (0, fixtures_1.expect)(page.getByText("Install our CLI for your coding agents")).toBeVisible();
39
+ await page.getByRole("button", { name: "Later" }).dispatchEvent("click");
40
+ const response = page.waitForResponse(/usage\.json/);
41
+ await page.getByRole("option", { name: "September" }).click();
42
+ await response;
43
+ await (0, fixtures_1.expect)(page.locator("#status")).toHaveText("Showing usage for September (1280 credits)");
44
+ });
45
+ (0, fixtures_1.test)("Escape on an open date picker throws away the picked date", async ({ page, server, }) => {
46
+ await page.goto(`${server.baseURL}/datepicker.html`);
47
+ await page.getByPlaceholder("Pick a date").click();
48
+ await page.getByRole("grid").getByRole("button", { name: "15" }).click();
49
+ await page.keyboard.press("Escape");
50
+ await page.getByRole("button", { name: "Save" }).click();
51
+ await (0, fixtures_1.expect)(page.locator("#status")).toHaveText("Saved without a date");
52
+ });
53
+ (0, fixtures_1.test)("Escape on open search results clears the query", async ({ page, server, }) => {
54
+ await page.goto(`${server.baseURL}/search-results.html`);
55
+ await page.getByRole("searchbox", { name: "Search assets" }).fill("orders");
56
+ await (0, fixtures_1.expect)(page.getByText("Showing 74 results")).toBeVisible();
57
+ await page.keyboard.press("Escape");
58
+ await (0, fixtures_1.expect)(page.getByRole("searchbox", { name: "Search assets" })).toHaveValue("");
59
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dropdown.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropdown.spec.d.ts","sourceRoot":"","sources":["../../src/overlay-tests/dropdown.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const test_1 = require("../test");
4
+ const fixtures_1 = require("./fixtures");
5
+ fixtures_1.test.beforeEach(async ({ page }) => {
6
+ (0, test_1.injectLocatorHighlightScripts)(page, fixtures_1.test);
7
+ });
8
+ async function openMonthsUnderToast(page) {
9
+ await page.getByRole("combobox", { name: "Usage month" }).click();
10
+ await (0, fixtures_1.expect)(page.getByText("Install our CLI for your coding agents")).toBeVisible();
11
+ }
12
+ for (const clickMode of ["mouse", "dispatch"]) {
13
+ fixtures_1.test.describe(`overlay click mode: ${clickMode}`, () => {
14
+ fixtures_1.test.beforeEach(() => {
15
+ process.env.EMPIRICALRUN_OVERLAY_CLICK_MODE = clickMode;
16
+ });
17
+ fixtures_1.test.afterEach(() => {
18
+ delete process.env.EMPIRICALRUN_OVERLAY_CLICK_MODE;
19
+ });
20
+ (0, fixtures_1.test)("selects a month through a toast covering the open listbox", async ({ page, server, }) => {
21
+ fixtures_1.test.fail(clickMode === "mouse", "A mouse click on the toast is a pointerdown outside the listbox, which closes it before the retried click");
22
+ await page.goto(`${server.baseURL}/dropdown-toast.html`);
23
+ await openMonthsUnderToast(page);
24
+ await page.getByRole("option", { name: "September" }).click();
25
+ await (0, fixtures_1.expect)(page.locator("#status")).toHaveText("Showing usage for September (1280 credits)");
26
+ });
27
+ });
28
+ }
29
+ (0, fixtures_1.test)("usage response wait survives a toast covering the listbox", async ({ page, server, }) => {
30
+ fixtures_1.test.fail(true, "waitForResponse times out while the click waits out its actionability timeout, before any dismissal runs");
31
+ await page.goto(`${server.baseURL}/dropdown-toast.html`);
32
+ await openMonthsUnderToast(page);
33
+ await Promise.all([
34
+ page.waitForResponse(/usage\.json/),
35
+ page.getByRole("option", { name: "September" }).click(),
36
+ ]);
37
+ });
38
+ (0, fixtures_1.test)("saves with the picked date when the open date picker covers Save", async ({ page, server, }) => {
39
+ fixtures_1.test.skip(true, "Not deterministic: the agent keeps the picked date in some runs and loses it in others");
40
+ await page.goto(`${server.baseURL}/datepicker.html`);
41
+ await page.getByPlaceholder("Pick a date").click();
42
+ await page.getByRole("grid").getByRole("button", { name: "15" }).click();
43
+ await page.getByRole("button", { name: "Save" }).click();
44
+ await (0, fixtures_1.expect)(page.locator("#status")).toHaveText("Saved for 2026-09-15");
45
+ });
46
+ (0, fixtures_1.test)("keeps the search query when open results cover a filter", async ({ page, server, }) => {
47
+ fixtures_1.test.skip(true, "Not deterministic: the agent keeps the query in some runs and clears it in others");
48
+ await page.goto(`${server.baseURL}/search-results.html`);
49
+ await page.getByRole("searchbox", { name: "Search assets" }).fill("orders");
50
+ await (0, fixtures_1.expect)(page.getByText("Showing 74 results")).toBeVisible();
51
+ await page.getByRole("button", { name: "Verified" }).click();
52
+ await (0, fixtures_1.expect)(page.locator("#status")).toHaveText('Query "orders", verified only: true');
53
+ });
@@ -3,7 +3,9 @@ type ServerFixture = {
3
3
  baseURL: string;
4
4
  };
5
5
  export declare const expect: import("@playwright/test").Expect<{}>;
6
- export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions & {
6
+ export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
7
+ overlayCacheFile: string;
8
+ }, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions & {
7
9
  server: ServerFixture;
8
10
  }>;
9
11
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/overlay-tests/fixtures.ts"],"names":[],"mappings":"AAKA,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,MAAM,uCAAc,CAAC;AAClC,eAAO,MAAM,IAAI;YAA6B,aAAa;EAuBzD,CAAC"}
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/overlay-tests/fixtures.ts"],"names":[],"mappings":"AAKA,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,MAAM,uCAAc,CAAC;AAClC,eAAO,MAAM,IAAI;sBACK,MAAM;;YAChB,aAAa;EAsCvB,CAAC"}
@@ -10,6 +10,21 @@ const path_1 = __importDefault(require("path"));
10
10
  const serve_handler_1 = __importDefault(require("serve-handler"));
11
11
  exports.expect = test_1.test.expect;
12
12
  exports.test = test_1.test.extend({
13
+ overlayCacheFile: [
14
+ async ({}, use, testInfo) => {
15
+ const previous = process.env.EMPIRICALRUN_OVERLAY_CACHE_FILE;
16
+ const file = testInfo.outputPath("overlay-cache.json");
17
+ process.env.EMPIRICALRUN_OVERLAY_CACHE_FILE = file;
18
+ await use(file);
19
+ if (previous === undefined) {
20
+ delete process.env.EMPIRICALRUN_OVERLAY_CACHE_FILE;
21
+ }
22
+ else {
23
+ process.env.EMPIRICALRUN_OVERLAY_CACHE_FILE = previous;
24
+ }
25
+ },
26
+ { auto: true },
27
+ ],
13
28
  server: [
14
29
  async ({}, use, workerInfo) => {
15
30
  const port = 1234 + workerInfo.workerIndex;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=typesafe-hit-check.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typesafe-hit-check.spec.d.ts","sourceRoot":"","sources":["../../src/overlay-tests/typesafe-hit-check.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const typesafe_1 = require("../test/scripts/pw-locator-patch/dismiss-overlays/typesafe");
4
+ const fixtures_1 = require("./fixtures");
5
+ async function centerOf(locator) {
6
+ const box = await locator.boundingBox();
7
+ if (!box) {
8
+ throw new Error("Element has no bounding box");
9
+ }
10
+ return { x: box.x + box.width / 2, y: box.y + box.height / 2 };
11
+ }
12
+ (0, fixtures_1.test)("allows the toast close button", async ({ page, server }) => {
13
+ await page.goto(`${server.baseURL}/choose-an-overlay.html`);
14
+ const target = await page
15
+ .getByRole("button", { name: "Target" })
16
+ .elementHandle();
17
+ const point = await centerOf(page.locator("#toastCloseBtn"));
18
+ (0, fixtures_1.expect)(await (0, typesafe_1.checkHit)(target, point)).toBe("ok");
19
+ });
20
+ (0, fixtures_1.test)("refuses the dialog behind a toast that blocks the target", async ({ page, server, }) => {
21
+ await page.goto(`${server.baseURL}/choose-an-overlay.html`);
22
+ const target = await page
23
+ .getByRole("button", { name: "Target" })
24
+ .elementHandle();
25
+ const point = await centerOf(page.getByRole("button", { name: "Noted" }));
26
+ (0, fixtures_1.expect)(await (0, typesafe_1.checkHit)(target, point)).toBe("outside_overlay");
27
+ });
28
+ (0, fixtures_1.test)("refuses a page control outside the blocking toast", async ({ page, server, }) => {
29
+ await page.goto(`${server.baseURL}/toast-without-close.html`);
30
+ const target = await page
31
+ .getByRole("button", { name: "Target" })
32
+ .elementHandle();
33
+ const point = await centerOf(page.getByRole("button", { name: "Close project" }));
34
+ (0, fixtures_1.expect)(await (0, typesafe_1.checkHit)(target, point)).toBe("outside_overlay");
35
+ });
36
+ (0, fixtures_1.test)("refuses text inside the blocking toast", async ({ page, server }) => {
37
+ await page.goto(`${server.baseURL}/toast-without-close.html`);
38
+ const target = await page
39
+ .getByRole("button", { name: "Target" })
40
+ .elementHandle();
41
+ const point = await centerOf(page.locator("#toast"));
42
+ (0, fixtures_1.expect)(await (0, typesafe_1.checkHit)(target, point)).toBe("not_clickable");
43
+ });
44
+ (0, fixtures_1.test)("refuses the target under a glass pane", async ({ page, server }) => {
45
+ await page.goto(`${server.baseURL}/glass-pane.html`);
46
+ const target = await page
47
+ .getByRole("button", { name: "Target" })
48
+ .elementHandle();
49
+ (0, fixtures_1.expect)(await (0, typesafe_1.checkHit)(target, await centerOf(page.getByRole("button", { name: "Target" })))).toBe("not_clickable");
50
+ });
51
+ (0, fixtures_1.test)("reports no blocker when the target is uncovered", async ({ page, server, }) => {
52
+ await page.goto(`${server.baseURL}/toast-without-close.html`);
53
+ const target = await page
54
+ .getByRole("button", { name: "Close project" })
55
+ .elementHandle();
56
+ (0, fixtures_1.expect)(await (0, typesafe_1.checkHit)(target, await centerOf(page.getByRole("button", { name: "Close project" })))).toBe("no_blocker");
57
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=typesafe.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typesafe.spec.d.ts","sourceRoot":"","sources":["../../src/overlay-tests/typesafe.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_fs_1 = __importDefault(require("node:fs"));
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const dismiss_overlays_1 = require("../test/scripts/pw-locator-patch/dismiss-overlays");
9
+ const typesafe_1 = require("../test/scripts/pw-locator-patch/dismiss-overlays/typesafe");
10
+ const utils_1 = require("../test/scripts/pw-locator-patch/dismiss-overlays/utils");
11
+ const fixtures_1 = require("./fixtures");
12
+ fixtures_1.test.skip(!process.env.TYPESAFE_API_KEY, "TYPESAFE_API_KEY is not set");
13
+ const RESULTS_FILE = node_path_1.default.join(process.cwd(), "test-results", "typesafe-overlay-results.jsonl");
14
+ const DISMISS_ATTEMPTS = 3;
15
+ async function actWithTypeSafeDismissal(page, target, action) {
16
+ const results = [];
17
+ for (let attempt = 0;; attempt++) {
18
+ try {
19
+ await target[action]({ timeout: 3_000 });
20
+ return results;
21
+ }
22
+ catch (error) {
23
+ if (attempt === DISMISS_ATTEMPTS || !(0, dismiss_overlays_1.isErrorSupported)(error.message)) {
24
+ throw error;
25
+ }
26
+ const element = (0, dismiss_overlays_1.extractInterceptingElement)(error.message);
27
+ const text = await (0, utils_1.textContent)(page, element);
28
+ const result = await (0, typesafe_1.dismissWithTypeSafe)(page, {
29
+ text,
30
+ target: await target.elementHandle(),
31
+ });
32
+ results.push(result);
33
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(RESULTS_FILE), { recursive: true });
34
+ node_fs_1.default.appendFileSync(RESULTS_FILE, JSON.stringify({
35
+ test: fixtures_1.test.info().title,
36
+ attempt,
37
+ overlayText: text,
38
+ ...result,
39
+ }) + "\n");
40
+ if (!result.dismissed) {
41
+ throw error;
42
+ }
43
+ }
44
+ }
45
+ }
46
+ (0, fixtures_1.test)("dismisses the toast but not the dialog", async ({ page, server }) => {
47
+ await page.goto(`${server.baseURL}/choose-an-overlay.html`);
48
+ await actWithTypeSafeDismissal(page, page.getByRole("button", { name: "Target" }), "click");
49
+ await (0, fixtures_1.expect)(page.getByText("This is a toast message")).not.toBeVisible();
50
+ await (0, fixtures_1.expect)(page.getByRole("heading", { name: "Center Overlay" })).toBeVisible();
51
+ });
52
+ (0, fixtures_1.test)("ticks the checkbox and accepts terms", async ({ page, server }) => {
53
+ await page.goto(`${server.baseURL}/tos.html`);
54
+ page.on("dialog", (dialog) => dialog.dismiss());
55
+ await actWithTypeSafeDismissal(page, page.getByRole("button", { name: "Target" }), "click");
56
+ await (0, fixtures_1.expect)(page.getByRole("heading", { name: "Terms of Service" })).not.toBeVisible();
57
+ });
58
+ (0, fixtures_1.test)("dismisses a product tour and terms in sequence", async ({ page, server, }) => {
59
+ await page.goto(`${server.baseURL}/loop-to-dismiss.html`);
60
+ await actWithTypeSafeDismissal(page, page.getByRole("button", { name: "Target" }), "click");
61
+ await (0, fixtures_1.expect)(page.getByText("Clicked!")).toBeVisible();
62
+ });
63
+ (0, fixtures_1.test)("dismisses a Survicate survey for hover", async ({ page, server }) => {
64
+ await page.goto(`${server.baseURL}/survey.html`);
65
+ await (0, fixtures_1.expect)(page.getByText("Start survey")).toBeVisible({ timeout: 15_000 });
66
+ await actWithTypeSafeDismissal(page, page.getByRole("button", { name: "Click target" }), "hover");
67
+ });
68
+ (0, fixtures_1.test)("cannot fill a form overlay", async ({ page, server }) => {
69
+ await page.goto(`${server.baseURL}/overlay-form.html`);
70
+ await (0, fixtures_1.expect)(actWithTypeSafeDismissal(page, page.getByRole("button", { name: "Target" }), "click")).rejects.toThrow();
71
+ });
72
+ (0, fixtures_1.test)("does not click a page control when the toast has no close button", async ({ page, server, }) => {
73
+ await page.goto(`${server.baseURL}/toast-without-close.html`);
74
+ await (0, fixtures_1.expect)(actWithTypeSafeDismissal(page, page.getByRole("button", { name: "Target" }), "click")).rejects.toThrow();
75
+ await (0, fixtures_1.expect)(page.getByText("Project closed")).not.toBeVisible();
76
+ });
77
+ (0, fixtures_1.test)("does not click anything for an invisible glass pane", async ({ page, server, }) => {
78
+ await page.goto(`${server.baseURL}/glass-pane.html`);
79
+ let dialogOpened = false;
80
+ page.on("dialog", (dialog) => {
81
+ dialogOpened = true;
82
+ return dialog.dismiss();
83
+ });
84
+ await (0, fixtures_1.expect)(actWithTypeSafeDismissal(page, page.getByRole("button", { name: "Target" }), "click")).rejects.toThrow();
85
+ (0, fixtures_1.expect)(dialogOpened).toBe(false);
86
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"playwright-extensions.d.ts","sourceRoot":"","sources":["../src/playwright-extensions.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7C,CAAC;AAEF,OAAO,QAAQ,iBAAiB,CAAC;IAC/B,UAAU,OAAQ,SAAQ,eAAe;KAAG;CAC7C;AAED,OAAO,QAAQ,kBAAkB,CAAC;IAChC,UAAU,OAAQ,SAAQ,eAAe;KAAG;CAC7C"}
1
+ {"version":3,"file":"playwright-extensions.d.ts","sourceRoot":"","sources":["../src/playwright-extensions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7C,CAAC;AAEF,OAAO,QAAQ,iBAAiB,CAAC;IAC/B,UAAU,OAAQ,SAAQ,eAAe;KAAG;CAC7C;AAED,OAAO,QAAQ,kBAAkB,CAAC;IAChC,UAAU,OAAQ,SAAQ,eAAe;KAAG;CAC7C"}
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
- // Extend Playwright core interfaces transparently to the end user.
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,9 +1,3 @@
1
- /**
2
- * Test-only reporter used by attachment-cleanup integration tests.
3
- *
4
- * Records a timestamped event log of register/markUploaded/eviction events
5
- * so tests can make precise assertions about ordering and timing.
6
- */
7
1
  import type { FullResult, Reporter, TestCase, TestResult } from "@playwright/test/reporter";
8
2
  declare class AttachmentCleanupTestReporter implements Reporter {
9
3
  private _timeline;
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-cleanup-test-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/attachment-cleanup-test-reporter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,UAAU,EACX,MAAM,2BAA2B,CAAC;AA0CnC,cAAM,6BAA8B,YAAW,QAAQ;IACrD,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,mBAAmB,CAAgB;IAC3C,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,MAAM,CAAkC;IAEhD,cAQC;IAED,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,QAyB5C;IAEK,KAAK,CAAC,OAAO,EAAE,UAAU,iBAyB9B;CACF;eAEc,6BAA6B"}
1
+ {"version":3,"file":"attachment-cleanup-test-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/attachment-cleanup-test-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,UAAU,EACX,MAAM,2BAA2B,CAAC;AA0CnC,cAAM,6BAA8B,YAAW,QAAQ;IACrD,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,mBAAmB,CAAgB;IAC3C,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,MAAM,CAAkC;IAEhD,cAQC;IAED,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,QAyB5C;IAEK,KAAK,CAAC,OAAO,EAAE,UAAU,iBAyB9B;CACF;eAEc,6BAA6B"}
@@ -1,10 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Test-only reporter used by attachment-cleanup integration tests.
4
- *
5
- * Records a timestamped event log of register/markUploaded/eviction events
6
- * so tests can make precise assertions about ordering and timing.
7
- */
8
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
9
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
10
4
  };
@@ -1,28 +1,3 @@
1
- /**
2
- * Tracks test attachments and evicts the oldest uploaded ones from disk
3
- * when total size exceeds the configured limit.
4
- *
5
- * Two-phase tracking:
6
- * 1. register() — called immediately when an attachment is created.
7
- * Adds the file to the total size accounting so the LRU knows about
8
- * all disk usage, even while uploads are still queued.
9
- * 2. markUploaded() — called after the file is uploaded to R2.
10
- * Marks the file as safe to evict (delete from disk).
11
- *
12
- * Eviction only deletes files that have been uploaded. This ensures we
13
- * never delete a file before its upload completes.
14
- *
15
- * Why this exists:
16
- * Test attachments (videos, traces, screenshots) accumulate on disk during a
17
- * test run. On Fargate workers with 50 GB ephemeral storage, large test suites
18
- * can exhaust disk space. Since attachments are already uploaded to R2, we can
19
- * safely delete them from disk — but we can't delete them immediately because
20
- * Playwright's blob reporter reads them during onEnd to embed as resources/.
21
- *
22
- * The blob reporter's statSync guard (Playwright 1.57+) gracefully skips
23
- * missing files, and patchBlobZip replaces resources/ with
24
- * _empirical_urls.json pointing to R2 URLs anyway.
25
- */
26
1
  export declare class AttachmentCleanup {
27
2
  private _pending;
28
3
  private _uploaded;
@@ -36,17 +11,9 @@ export declare class AttachmentCleanup {
36
11
  private _diskLogTick;
37
12
  private _onEvict;
38
13
  constructor(limitBytes?: number);
39
- /**
40
- * Phase 1: Register an attachment immediately when it's created.
41
- * Adds to total size accounting and attempts eviction of already-uploaded files.
42
- */
43
14
  register(attachment: {
44
15
  path?: string | undefined;
45
16
  }): void;
46
- /**
47
- * Phase 2: Mark an attachment as uploaded (safe to evict).
48
- * Moves from pending to the uploaded queue and attempts eviction.
49
- */
50
17
  markUploaded(attachmentPath: string): void;
51
18
  private _evict;
52
19
  private _logDiskStatus;
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-cleanup.d.ts","sourceRoot":"","sources":["../../src/reporter/attachment-cleanup.ts"],"names":[],"mappings":"AAgEA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAA+C;IACpE,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAyC;IAEzD,YAAY,UAAU,GAAE,MAAmC,EAU1D;IAED;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,QAiBjD;IAED;;;OAGG;IACH,YAAY,CAAC,cAAc,EAAE,MAAM,QASlC;IAED,OAAO,CAAC,MAAM;IA4Bd,OAAO,CAAC,cAAc;IAStB,UAAU,SAaT;IAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAE3C;IAED,IAAI,KAAK;QAEL,eAAe;QACf,aAAa;QACb,YAAY;QACZ,YAAY;QACZ,YAAY;QACZ,WAAW;QACX,SAAS;QACT,UAAU;MAEb;CACF"}
1
+ {"version":3,"file":"attachment-cleanup.d.ts","sourceRoot":"","sources":["../../src/reporter/attachment-cleanup.ts"],"names":[],"mappings":"AA6DA,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAA+C;IACpE,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAyC;IAEzD,YAAY,UAAU,GAAE,MAAmC,EAM1D;IAED,QAAQ,CAAC,UAAU,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,QAejD;IAED,YAAY,CAAC,cAAc,EAAE,MAAM,QASlC;IAED,OAAO,CAAC,MAAM;IA4Bd,OAAO,CAAC,cAAc;IAItB,UAAU,SAWT;IAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAE3C;IAED,IAAI,KAAK;QAEL,eAAe;QACf,aAAa;QACb,YAAY;QACZ,YAAY;QACZ,YAAY;QACZ,WAAW;QACX,SAAS;QACT,UAAU;MAEb;CACF"}