@empiricalrun/playwright-utils 0.62.0 → 0.63.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.
- package/CHANGELOG.md +25 -0
- package/dist/api-worker-client.d.ts +0 -13
- package/dist/api-worker-client.d.ts.map +1 -1
- package/dist/api-worker-client.js +0 -15
- package/dist/auth/google.d.ts.map +1 -1
- package/dist/auth/google.js +0 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +0 -9
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +0 -8
- package/dist/generated/api-worker-openapi.d.ts +2773 -1298
- package/dist/generated/api-worker-openapi.d.ts.map +1 -1
- package/dist/overlay-tests/cache.spec.js +0 -10
- package/dist/overlay-tests/click.spec.js +0 -18
- package/dist/playwright-extensions.d.ts.map +1 -1
- package/dist/playwright-extensions.js +0 -1
- package/dist/reporter/attachment-cleanup-test-reporter.d.ts +0 -6
- package/dist/reporter/attachment-cleanup-test-reporter.d.ts.map +1 -1
- package/dist/reporter/attachment-cleanup-test-reporter.js +0 -6
- package/dist/reporter/attachment-cleanup.d.ts +0 -33
- package/dist/reporter/attachment-cleanup.d.ts.map +1 -1
- package/dist/reporter/attachment-cleanup.js +2 -51
- package/dist/reporter/empirical-reporter.d.ts.map +1 -1
- package/dist/reporter/empirical-reporter.js +0 -9
- package/dist/reporter/harness.d.ts +0 -62
- package/dist/reporter/harness.d.ts.map +1 -1
- package/dist/reporter/harness.js +1 -53
- package/dist/reporter/ibr-utils.d.ts +0 -5
- package/dist/reporter/ibr-utils.d.ts.map +1 -1
- package/dist/reporter/ibr-utils.js +0 -5
- package/dist/reporter/incremental-blob-reporter.d.ts +0 -17
- package/dist/reporter/incremental-blob-reporter.d.ts.map +1 -1
- package/dist/reporter/incremental-blob-reporter.js +5 -35
- package/dist/reporter/lifecycle-events.d.ts.map +1 -1
- package/dist/reporter/lifecycle-events.js +0 -9
- package/dist/reporter/parity-utils.d.ts +0 -30
- package/dist/reporter/parity-utils.d.ts.map +1 -1
- package/dist/reporter/parity-utils.js +4 -28
- package/dist/reporter/reporter-state.d.ts +0 -12
- package/dist/reporter/reporter-state.d.ts.map +1 -1
- package/dist/reporter/reporter-state.js +0 -12
- package/dist/reporter/test-case-sync.d.ts.map +1 -1
- package/dist/reporter/test-case-sync.js +0 -12
- package/dist/reporter/uploader.d.ts.map +1 -1
- package/dist/reporter/uploader.js +0 -6
- package/dist/reporter/util.d.ts +0 -33
- package/dist/reporter/util.d.ts.map +1 -1
- package/dist/reporter/util.js +0 -37
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +1 -10
- package/dist/test/coverage.d.ts.map +1 -1
- package/dist/test/coverage.js +1 -3
- package/dist/test/expect/visual.d.ts.map +1 -1
- package/dist/test/expect/visual.js +1 -9
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +4 -21
- package/dist/test/scripts/agent-capabilities.js +2 -2
- package/dist/test/scripts/index.d.ts +2 -2
- package/dist/test/scripts/index.d.ts.map +1 -1
- package/dist/test/scripts/index.js +3 -16
- package/dist/test/scripts/pw-locator-patch/actions/click.d.ts.map +1 -0
- package/dist/test/scripts/pw-locator-patch/{highlight → actions}/click.js +0 -6
- package/dist/test/scripts/pw-locator-patch/actions/hover.d.ts.map +1 -0
- package/dist/test/scripts/pw-locator-patch/{highlight → actions}/hover.js +0 -3
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/cache.d.ts.map +1 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/cache.js +0 -7
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/index.d.ts.map +1 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/index.js +1 -9
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/prompt.d.ts.map +1 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/prompt.js +0 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/utils.d.ts.map +1 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/utils.js +2 -5
- package/dist/test/scripts/pw-locator-patch/utils/index.d.ts +0 -1
- package/dist/test/scripts/pw-locator-patch/utils/index.d.ts.map +1 -1
- package/dist/test/scripts/pw-locator-patch/utils/index.js +0 -18
- package/dist/test/types.d.ts +2 -5
- package/dist/test/types.d.ts.map +1 -1
- package/dist/test/video-labels.d.ts.map +1 -1
- package/dist/test/video-labels.js +0 -1
- package/dist/webhook.d.ts.map +1 -1
- package/dist/webhook.js +0 -3
- package/docs/fixtures.md +4 -5
- package/package.json +6 -6
- package/playwright.config.ts +0 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/upstream-oracle/ibr-adapter.js +0 -23
- package/upstream-oracle/run.mjs +1 -69
- package/dist/test/scripts/locator-highlights.d.ts +0 -4
- package/dist/test/scripts/locator-highlights.d.ts.map +0 -1
- package/dist/test/scripts/locator-highlights.js +0 -28
- package/dist/test/scripts/pw-locator-patch/highlight/click.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/expect.d.ts +0 -5
- package/dist/test/scripts/pw-locator-patch/highlight/expect.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/expect.js +0 -23
- package/dist/test/scripts/pw-locator-patch/highlight/hover.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/inner-text.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/inner-text.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/inner-text.js +0 -30
- package/dist/test/scripts/pw-locator-patch/highlight/input-value.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/input-value.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/input-value.js +0 -30
- package/dist/test/scripts/pw-locator-patch/highlight/is-checked.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/is-checked.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/is-checked.js +0 -30
- package/dist/test/scripts/pw-locator-patch/highlight/is-disabled.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/is-disabled.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/is-disabled.js +0 -30
- package/dist/test/scripts/pw-locator-patch/highlight/is-editable.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/is-editable.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/is-editable.js +0 -29
- package/dist/test/scripts/pw-locator-patch/highlight/text-content.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/text-content.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/text-content.js +0 -30
- /package/dist/test/scripts/pw-locator-patch/{highlight → actions}/click.d.ts +0 -0
- /package/dist/test/scripts/pw-locator-patch/{highlight → actions}/hover.d.ts +0 -0
|
@@ -107,9 +107,6 @@ class Uploader {
|
|
|
107
107
|
await (0, r2_uploader_1.waitForTaskQueueToFinish)();
|
|
108
108
|
return;
|
|
109
109
|
}
|
|
110
|
-
// This drain runs after the last test with no other output (observed at
|
|
111
|
-
// 4+ minutes on spot runs), so make it visible: count up front, progress
|
|
112
|
-
// every 30s, duration at the end.
|
|
113
110
|
const start = Date.now();
|
|
114
111
|
console.log(`[Uploader] Waiting for ${pending} pending uploads (${executing} executing, ${waiting} queued)...`);
|
|
115
112
|
const progress = setInterval(() => {
|
|
@@ -143,7 +140,6 @@ function createUploader() {
|
|
|
143
140
|
logger_1.logger.debug("[Uploader] PROJECT_NAME and TEST_RUN_GITHUB_ACTION_ID must be set");
|
|
144
141
|
return null;
|
|
145
142
|
}
|
|
146
|
-
// REPORT_STORAGE_BACKEND selects the upload target; anything else is a misconfig.
|
|
147
143
|
const backend = process.env.REPORT_STORAGE_BACKEND;
|
|
148
144
|
if (backend !== "s3" && backend !== "r2") {
|
|
149
145
|
logger_1.logger.debug(`[Uploader] REPORT_STORAGE_BACKEND must be "s3" or "r2" (got ${backend ?? "unset"})`);
|
|
@@ -165,8 +161,6 @@ function createUploader() {
|
|
|
165
161
|
logger_1.logger.debug("[Uploader] S3_REGION or S3_UPLOAD_BUCKET not configured");
|
|
166
162
|
return null;
|
|
167
163
|
}
|
|
168
|
-
// Upload through the task role to S3, but persist CDN URLs so the bucket
|
|
169
|
-
// can stay private. Direct S3 is the fallback for envs without a CDN.
|
|
170
164
|
baseUrl =
|
|
171
165
|
process.env.REPORTS_BASE_URL?.replace(/\/+$/, "") ||
|
|
172
166
|
`https://${bucket}.s3.${region}.amazonaws.com`;
|
package/dist/reporter/util.d.ts
CHANGED
|
@@ -20,40 +20,7 @@ export declare function suitesAndProjectForTest(test: TestCase): {
|
|
|
20
20
|
export declare function sendTestCaseUpdateToDashboard(params: TestCaseRunEndEventV2): Promise<void>;
|
|
21
21
|
export declare function safelySerialiseJSON(obj: any, keyFilter?: (key: string) => boolean): any;
|
|
22
22
|
export declare function updateHtmlZipFileAttachmentPaths(jsonFilePath: string, htmlFilePath: string, repoPath: string): Promise<void>;
|
|
23
|
-
/**
|
|
24
|
-
* Replaces media paths in test results with normalized paths from the test attachment map.
|
|
25
|
-
* This function updates the attachments array in each test result with the corresponding
|
|
26
|
-
* normalized attachments from the test attachment map.
|
|
27
|
-
*
|
|
28
|
-
* @param jsonData - The JSON data containing test results, which can be either in the format
|
|
29
|
-
* of { files: [{ tests: [...] }] } or { tests: [...] }
|
|
30
|
-
* @param testAttachmentMap - A Map where the key is the test ID and the value is an array of
|
|
31
|
-
* objects containing attachments with updated path for each test result
|
|
32
|
-
* @returns void
|
|
33
|
-
*/
|
|
34
|
-
/**
|
|
35
|
-
* Builds a map from test ID to an array of objects containing attachments for each result (retry).
|
|
36
|
-
* The attachments are normalized to use relative paths starting with 'data/'.
|
|
37
|
-
* @param summaryJsonFilePath Path to the summary JSON file
|
|
38
|
-
* @returns Map<string, { attachments: GenericPlaywrightAttachment[] }[]>
|
|
39
|
-
*/
|
|
40
23
|
export declare function buildTestAttachmentMapFromSummary(summaryJsonFilePath: string, repoPath: string, doNotNormalize?: boolean): TestAttachmentMap;
|
|
41
|
-
/**
|
|
42
|
-
* Checks asynchronously if a file exists at the given path.
|
|
43
|
-
* @param filePath - The path to the file to check
|
|
44
|
-
* @returns Promise<boolean> - true if the file exists, false otherwise
|
|
45
|
-
*/
|
|
46
24
|
export declare function checkFileExistsAsync(filePath: string): Promise<boolean>;
|
|
47
|
-
/**
|
|
48
|
-
* Updates the attachment paths in the summary JSON file to use remote URLs.
|
|
49
|
-
*
|
|
50
|
-
* This function rewrites all attachment `path` fields in the given Playwright summary JSON file
|
|
51
|
-
* so that they point to remote URLs based on the current `PROJECT_NAME` and `TEST_RUN_GITHUB_ACTION_ID`
|
|
52
|
-
* environment variables.
|
|
53
|
-
*
|
|
54
|
-
* @param filePath - The path to the summary JSON file
|
|
55
|
-
* @returns The updated summary JSON
|
|
56
|
-
*
|
|
57
|
-
*/
|
|
58
25
|
export declare function updateSummaryJsonAttachmentPaths(filePath: string, repoPath: string, urlPrefix: string): Promise<PlaywrightJSONReport | undefined>;
|
|
59
26
|
//# sourceMappingURL=util.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/reporter/util.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAQhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EACL,UAAU,IAAI,oBAAoB,EAElC,QAAQ,EACT,MAAM,2BAA2B,CAAC;AA0BnC,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAqB7D;AAED,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAAG,SAAS,UAQhC;AAED,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5E,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CA6CD;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ;
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/reporter/util.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAQhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EACL,UAAU,IAAI,oBAAoB,EAElC,QAAQ,EACT,MAAM,2BAA2B,CAAC;AA0BnC,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAqB7D;AAED,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAAG,SAAS,UAQhC;AAED,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5E,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CA6CD;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ;IAmBlD,MAAM;IACN,WAAW;EAEd;AAED,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,GAAG,EACR,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GACnC,GAAG,CAIL;AAED,wBAAsB,gCAAgC,CACpD,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,iBAkFjB;AAED,wBAAgB,iCAAiC,CAC/C,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EAChB,cAAc,GAAE,OAAe,GAC9B,iBAAiB,CAgBnB;AAED,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7E;AAED,wBAAsB,gCAAgC,CACpD,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,6CA+BlB"}
|
package/dist/reporter/util.js
CHANGED
|
@@ -108,8 +108,6 @@ function suitesAndProjectForTest(test) {
|
|
|
108
108
|
parent = parent.parent;
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
// rawSuites looks like [ 'describe 3', 'describe 1', 'home.spec.ts', 'chromium', '' ]
|
|
112
|
-
// For suites, we will extract suites and then reverse them, since we expect top-to-bottom ordering for suites
|
|
113
111
|
let suites = [];
|
|
114
112
|
let iteratorIdx = 0;
|
|
115
113
|
for (; iteratorIdx < rawSuites.length; iteratorIdx++) {
|
|
@@ -210,27 +208,8 @@ async function updateHtmlZipFileAttachmentPaths(jsonFilePath, htmlFilePath, repo
|
|
|
210
208
|
logger_1.logger.error("❌ Error processing report.json or updating files:", err);
|
|
211
209
|
}
|
|
212
210
|
finally {
|
|
213
|
-
// Optional cleanup:
|
|
214
|
-
// await fs.promises.rm(tempDir, { recursive: true, force: true });
|
|
215
211
|
}
|
|
216
212
|
}
|
|
217
|
-
/**
|
|
218
|
-
* Replaces media paths in test results with normalized paths from the test attachment map.
|
|
219
|
-
* This function updates the attachments array in each test result with the corresponding
|
|
220
|
-
* normalized attachments from the test attachment map.
|
|
221
|
-
*
|
|
222
|
-
* @param jsonData - The JSON data containing test results, which can be either in the format
|
|
223
|
-
* of { files: [{ tests: [...] }] } or { tests: [...] }
|
|
224
|
-
* @param testAttachmentMap - A Map where the key is the test ID and the value is an array of
|
|
225
|
-
* objects containing attachments with updated path for each test result
|
|
226
|
-
* @returns void
|
|
227
|
-
*/
|
|
228
|
-
/**
|
|
229
|
-
* Builds a map from test ID to an array of objects containing attachments for each result (retry).
|
|
230
|
-
* The attachments are normalized to use relative paths starting with 'data/'.
|
|
231
|
-
* @param summaryJsonFilePath Path to the summary JSON file
|
|
232
|
-
* @returns Map<string, { attachments: GenericPlaywrightAttachment[] }[]>
|
|
233
|
-
*/
|
|
234
213
|
function buildTestAttachmentMapFromSummary(summaryJsonFilePath, repoPath, doNotNormalize = false) {
|
|
235
214
|
const summaryJson = JSON.parse(fs_1.default.readFileSync(summaryJsonFilePath, "utf8"));
|
|
236
215
|
return (0, reporter_1.buildTestAttachmentMap)(summaryJson, {
|
|
@@ -245,11 +224,6 @@ function buildTestAttachmentMapFromSummary(summaryJsonFilePath, repoPath, doNotN
|
|
|
245
224
|
},
|
|
246
225
|
});
|
|
247
226
|
}
|
|
248
|
-
/**
|
|
249
|
-
* Checks asynchronously if a file exists at the given path.
|
|
250
|
-
* @param filePath - The path to the file to check
|
|
251
|
-
* @returns Promise<boolean> - true if the file exists, false otherwise
|
|
252
|
-
*/
|
|
253
227
|
async function checkFileExistsAsync(filePath) {
|
|
254
228
|
try {
|
|
255
229
|
await fs_1.default.promises.access(filePath);
|
|
@@ -259,17 +233,6 @@ async function checkFileExistsAsync(filePath) {
|
|
|
259
233
|
return false;
|
|
260
234
|
}
|
|
261
235
|
}
|
|
262
|
-
/**
|
|
263
|
-
* Updates the attachment paths in the summary JSON file to use remote URLs.
|
|
264
|
-
*
|
|
265
|
-
* This function rewrites all attachment `path` fields in the given Playwright summary JSON file
|
|
266
|
-
* so that they point to remote URLs based on the current `PROJECT_NAME` and `TEST_RUN_GITHUB_ACTION_ID`
|
|
267
|
-
* environment variables.
|
|
268
|
-
*
|
|
269
|
-
* @param filePath - The path to the summary JSON file
|
|
270
|
-
* @returns The updated summary JSON
|
|
271
|
-
*
|
|
272
|
-
*/
|
|
273
236
|
async function updateSummaryJsonAttachmentPaths(filePath, repoPath, urlPrefix) {
|
|
274
237
|
if (!process.env.PROJECT_NAME || !process.env.TEST_RUN_GITHUB_ACTION_ID) {
|
|
275
238
|
console.error("PROJECT_NAME and TEST_RUN_GITHUB_ACTION_ID must be set");
|
package/dist/telemetry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAOtE,wBAAsB,UAAU,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBrE;AAED,UAAU,uBAAuB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBhB;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhB"}
|
package/dist/telemetry.js
CHANGED
|
@@ -5,9 +5,6 @@ exports.trackReportUpload = trackReportUpload;
|
|
|
5
5
|
exports.trackOverlayDismissed = trackOverlayDismissed;
|
|
6
6
|
exports.trackLLMResponseGenerated = trackLLMResponseGenerated;
|
|
7
7
|
const api_worker_client_1 = require("./api-worker-client");
|
|
8
|
-
// Events go to api-worker on the project API key the run already carries, so
|
|
9
|
-
// a runner needs no telemetry secret. Best-effort: no key means no telemetry,
|
|
10
|
-
// and a failed send is never retried or surfaced to the test.
|
|
11
8
|
async function trackEvent(event) {
|
|
12
9
|
if (!process.env.EMPIRICALRUN_API_KEY) {
|
|
13
10
|
return;
|
|
@@ -16,14 +13,10 @@ async function trackEvent(event) {
|
|
|
16
13
|
const { client } = new api_worker_client_1.ApiWorkerClient();
|
|
17
14
|
const { response } = await client.POST("/api/v1/telemetry/track", {
|
|
18
15
|
body: {
|
|
19
|
-
// api-worker accepts only test-run events; the ones sent from here
|
|
20
|
-
// are all on its allowlist.
|
|
21
16
|
name: event.name,
|
|
22
17
|
properties: event.properties,
|
|
23
18
|
timestamp: event.timestamp?.toISOString(),
|
|
24
19
|
},
|
|
25
|
-
// Plain fetch, not the client's retrying one: a test should not wait
|
|
26
|
-
// out backoff for a metric.
|
|
27
20
|
fetch,
|
|
28
21
|
signal: AbortSignal.timeout(10_000),
|
|
29
22
|
});
|
|
@@ -31,9 +24,7 @@ async function trackEvent(event) {
|
|
|
31
24
|
throw new Error(`Telemetry request failed: ${response.status}`);
|
|
32
25
|
}
|
|
33
26
|
}
|
|
34
|
-
catch {
|
|
35
|
-
// Don't throw - telemetry failures shouldn't break the application
|
|
36
|
-
}
|
|
27
|
+
catch { }
|
|
37
28
|
}
|
|
38
29
|
async function trackReportUpload(params) {
|
|
39
30
|
const environment = process.env.ENVIRONMENT || "unknown";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/test/coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAYvD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,cAAc,qBAwBpE;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,MAAM,EAAE,EACvB,QAAQ,EAAE;IACR,MAAM,EAAE,CACN,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,KAC3C,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,
|
|
1
|
+
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/test/coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAYvD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,cAAc,qBAwBpE;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,MAAM,EAAE,EACvB,QAAQ,EAAE;IACR,MAAM,EAAE,CACN,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,KAC3C,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,iBAmBF"}
|
package/dist/test/coverage.js
CHANGED
|
@@ -31,9 +31,7 @@ async function collectAndAttachCoverage(context, coverageFiles, testInfo) {
|
|
|
31
31
|
try {
|
|
32
32
|
await page.evaluate(() => window.collectIstanbulCoverage(JSON.stringify(window.__coverage__)));
|
|
33
33
|
}
|
|
34
|
-
catch {
|
|
35
|
-
// Page might be closed or coverage not available
|
|
36
|
-
}
|
|
34
|
+
catch { }
|
|
37
35
|
}
|
|
38
36
|
for (const filepath of coverageFiles) {
|
|
39
37
|
if (fs_1.default.existsSync(filepath)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visual.d.ts","sourceRoot":"","sources":["../../../src/test/expect/visual.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAY,MAAM,kBAAkB,CAAC;AAOhE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"visual.d.ts","sourceRoot":"","sources":["../../../src/test/expect/visual.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAY,MAAM,kBAAkB,CAAC;AAOhE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAgE7C,wBAAsB,WAAW,CAC/B,MAAM,EAAE,IAAI,GAAG,OAAO,EACtB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,aAAa,CAAC,CAsFxB"}
|
|
@@ -17,7 +17,6 @@ function getCallerLine() {
|
|
|
17
17
|
return "unknown";
|
|
18
18
|
}
|
|
19
19
|
const frames = stack.split("\n").slice(1);
|
|
20
|
-
// Find the test file frame (e.g. .spec.ts, .test.ts)
|
|
21
20
|
const testFrame = frames.find((f) => /\.(spec|test)\.[jt]sx?:/.test(f));
|
|
22
21
|
if (!testFrame) {
|
|
23
22
|
return "unknown";
|
|
@@ -27,7 +26,6 @@ function getCallerLine() {
|
|
|
27
26
|
}
|
|
28
27
|
function attachScreenshot(screenshot, pageDescription) {
|
|
29
28
|
try {
|
|
30
|
-
// test.info() is only available during a Playwright test run
|
|
31
29
|
const { test } = require("@playwright/test");
|
|
32
30
|
const testInfo = test.info();
|
|
33
31
|
const slug = pageDescription
|
|
@@ -38,8 +36,6 @@ function attachScreenshot(screenshot, pageDescription) {
|
|
|
38
36
|
.replace(/(^-|-$)/g, "");
|
|
39
37
|
const line = getCallerLine();
|
|
40
38
|
const attachmentName = `toLookRight-L${line}-${slug}`;
|
|
41
|
-
// Write to a temp file so the attachment has a path (required by empirical reporter).
|
|
42
|
-
// Playwright copies it into test-results/<test>/attachments/ on attach.
|
|
43
39
|
const tmpFile = path_1.default.join(os_1.default.tmpdir(), `${attachmentName}-${Date.now()}.png`);
|
|
44
40
|
fs_1.default.writeFileSync(tmpFile, screenshot);
|
|
45
41
|
testInfo.attach(attachmentName, {
|
|
@@ -47,9 +43,7 @@ function attachScreenshot(screenshot, pageDescription) {
|
|
|
47
43
|
contentType: "image/png",
|
|
48
44
|
});
|
|
49
45
|
}
|
|
50
|
-
catch {
|
|
51
|
-
// Not in a Playwright test context, skip attachment
|
|
52
|
-
}
|
|
46
|
+
catch { }
|
|
53
47
|
}
|
|
54
48
|
const SYSTEM_PROMPT = `
|
|
55
49
|
You are a software QA tester who specializes in visual testing. You look at a
|
|
@@ -79,8 +73,6 @@ async function toLookRight(target, pageDescription) {
|
|
|
79
73
|
attachScreenshot(screenshot, pageDescription);
|
|
80
74
|
const base64Image = screenshot.toString("base64");
|
|
81
75
|
const model = "gpt-4o";
|
|
82
|
-
// Same api-worker proxy the overlay-dismissal agent uses, so a test run needs
|
|
83
|
-
// no OpenAI key of its own; undefined falls back to the SDK's env defaults.
|
|
84
76
|
const openai = new openai_1.default({ maxRetries: 5, ...(0, api_worker_client_1.llmProxyOpenAIConfig)() });
|
|
85
77
|
const completion = await openai.chat.completions.create({
|
|
86
78
|
model,
|
package/dist/test/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,MAAM,EACN,IAAI,EACJ,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,QAAQ,EACT,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,6BAA6B,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,KAAK,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,MAAM,EACN,IAAI,EACJ,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,QAAQ,EACT,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,6BAA6B,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAA8B,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,cAAc,CAAC;QACvB,UAAU,QAAQ,CAAC,CAAC;YAClB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAC7C,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;SACnE;KACF;CACF;AAED,QAAA,MAAM,YAAY,mBAA6B,OAAO,MAAM,0CAG3D,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,QAAQ,CAAC;IACb,yBAAyB,EAAE,CACzB,OAAO,CAAC,EAAE,qBAAqB,KAC5B,OAAO,CAAC;QAAE,OAAO,EAAE,cAAc,CAAC;QAAC,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;IACtD,UAAU,EAAE,IAAI,CAAC;CAClB,CAAC;AAIF,QAAA,MAAM,eAAe,WACX,QAAQ,CACd,kBAAkB,GAAG,qBAAqB,EAC1C,oBAAoB,GAAG,uBAAuB,CAC/C,YACQ,mBAAmB,uHA6G7B,CAAC;AAEF,OAAO,EACL,eAAe,EACf,YAAY,EACZ,6BAA6B,EAC7B,aAAa,GACd,CAAC"}
|
package/dist/test/index.js
CHANGED
|
@@ -17,23 +17,13 @@ const extendExpect = function (expectInstance) {
|
|
|
17
17
|
return expectInstance;
|
|
18
18
|
};
|
|
19
19
|
exports.extendExpect = extendExpect;
|
|
20
|
-
// Track pages per test to save videos with labels
|
|
21
20
|
const testPages = new Map();
|
|
22
|
-
const
|
|
23
|
-
mousePointerHighlighter: true,
|
|
24
|
-
locatorHighlighter: true,
|
|
25
|
-
visionMethods: true,
|
|
26
|
-
agentCapabilities: true,
|
|
27
|
-
};
|
|
28
|
-
const baseTestFixture = function (testFn, options = defaultOptions) {
|
|
21
|
+
const baseTestFixture = function (testFn, options = {}) {
|
|
29
22
|
const coverageEnabled = options.collectCoverage ?? false;
|
|
30
|
-
// Playwright draws the cursor, target box and action title into the video.
|
|
31
|
-
// 100ms per action keeps them visible without the default 500ms slowdown.
|
|
32
|
-
const showActions = options.mousePointerHighlighter === false ? undefined : { duration: 100 };
|
|
33
23
|
const recordVideoOptions = (dir) => ({
|
|
34
24
|
dir,
|
|
35
25
|
size: { width: 1280, height: 720 },
|
|
36
|
-
showActions,
|
|
26
|
+
showActions: { duration: 100 },
|
|
37
27
|
});
|
|
38
28
|
const extendedTestFn = testFn.extend({
|
|
39
29
|
context: async ({ browser }, use, testInfo) => {
|
|
@@ -57,10 +47,7 @@ const baseTestFixture = function (testFn, options = defaultOptions) {
|
|
|
57
47
|
await context.close();
|
|
58
48
|
},
|
|
59
49
|
page: async ({ page }, use) => {
|
|
60
|
-
(0, scripts_1.injectLocatorHighlightScripts)(page, extendedTestFn,
|
|
61
|
-
...defaultOptions,
|
|
62
|
-
...options,
|
|
63
|
-
});
|
|
50
|
+
(0, scripts_1.injectLocatorHighlightScripts)(page, extendedTestFn, options);
|
|
64
51
|
await use(page);
|
|
65
52
|
},
|
|
66
53
|
kv: async ({}, use) => {
|
|
@@ -82,7 +69,6 @@ const baseTestFixture = function (testFn, options = defaultOptions) {
|
|
|
82
69
|
return { context: pageContext, page: customPage };
|
|
83
70
|
}
|
|
84
71
|
await use(createContext);
|
|
85
|
-
// Store pages for video renaming
|
|
86
72
|
if (!testPages.has(testInfo.testId)) {
|
|
87
73
|
testPages.set(testInfo.testId, []);
|
|
88
74
|
}
|
|
@@ -98,7 +84,6 @@ const baseTestFixture = function (testFn, options = defaultOptions) {
|
|
|
98
84
|
await use();
|
|
99
85
|
const pages = testPages.get(testInfo.testId) || [];
|
|
100
86
|
const usedLabels = new Set();
|
|
101
|
-
// Save videos with custom labels using saveAs
|
|
102
87
|
for (let i = 0; i < pages.length; i++) {
|
|
103
88
|
const page = pages[i];
|
|
104
89
|
if (!page) {
|
|
@@ -121,9 +106,7 @@ const baseTestFixture = function (testFn, options = defaultOptions) {
|
|
|
121
106
|
});
|
|
122
107
|
await video.delete();
|
|
123
108
|
}
|
|
124
|
-
catch (e) {
|
|
125
|
-
// Skip if video not available
|
|
126
|
-
}
|
|
109
|
+
catch (e) { }
|
|
127
110
|
}
|
|
128
111
|
testPages.delete(testInfo.testId);
|
|
129
112
|
},
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.addAgentCapabilities = addAgentCapabilities;
|
|
4
|
-
const click_1 = require("./pw-locator-patch/
|
|
5
|
-
const hover_1 = require("./pw-locator-patch/
|
|
4
|
+
const click_1 = require("./pw-locator-patch/actions/click");
|
|
5
|
+
const hover_1 = require("./pw-locator-patch/actions/hover");
|
|
6
6
|
function applyPatchForAutoDismissOverlay(page, testFn) {
|
|
7
7
|
const LocatorClass = page.locator("").constructor;
|
|
8
8
|
(0, click_1.patchClick)(LocatorClass, testFn);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Page } from "@playwright/test";
|
|
2
|
-
import {
|
|
2
|
+
import { PageScriptOpts } from "../types";
|
|
3
3
|
import { TestFn } from "./types";
|
|
4
|
-
export declare function injectLocatorHighlightScripts(page: Page, testFn: TestFn,
|
|
4
|
+
export declare function injectLocatorHighlightScripts(page: Page, testFn: TestFn, { visionMethods, agentCapabilities }?: PageScriptOpts): void;
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -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,
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
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":"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,QAsDf"}
|
|
@@ -4,7 +4,6 @@ exports.patchClick = patchClick;
|
|
|
4
4
|
const dismiss_overlays_1 = require("../dismiss-overlays");
|
|
5
5
|
const utils_1 = require("../dismiss-overlays/utils");
|
|
6
6
|
const utils_2 = require("../utils");
|
|
7
|
-
// Static flag to track if click has been patched
|
|
8
7
|
const isClickPatched = new WeakMap();
|
|
9
8
|
function patchClick(LocatorClass, testFn) {
|
|
10
9
|
if (isClickPatched.get(LocatorClass)) {
|
|
@@ -23,19 +22,15 @@ function patchClick(LocatorClass, testFn) {
|
|
|
23
22
|
overlayAttemptsRemaining--;
|
|
24
23
|
try {
|
|
25
24
|
let result = await originalClick.apply(this, [options]);
|
|
26
|
-
// If click is successful, we can save overlay dismissal code to cache and return
|
|
27
25
|
await overlayDismiss.saveToCache();
|
|
28
26
|
return result;
|
|
29
27
|
}
|
|
30
28
|
catch (error) {
|
|
31
29
|
originalError = error;
|
|
32
30
|
if (originalError instanceof Error) {
|
|
33
|
-
// Overwrite the stack trace to show the original click (remove patch)
|
|
34
31
|
Error.captureStackTrace(originalError, LocatorClass.prototype.click);
|
|
35
32
|
}
|
|
36
33
|
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
34
|
throw originalError;
|
|
40
35
|
}
|
|
41
36
|
if (!(0, dismiss_overlays_1.isErrorSupported)(originalError.message)) {
|
|
@@ -45,7 +40,6 @@ function patchClick(LocatorClass, testFn) {
|
|
|
45
40
|
throw originalError;
|
|
46
41
|
}
|
|
47
42
|
await overlayDismiss.run(originalError, reporter, testFn);
|
|
48
|
-
// Dismissal attempt finished (implicitly successful if no error thrown)
|
|
49
43
|
reporter(`Overlay dismissal attempted, retrying original action.`);
|
|
50
44
|
}
|
|
51
45
|
}
|
|
@@ -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 +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;
|
|
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;AAMF,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"}
|
|
@@ -11,16 +11,13 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
11
11
|
const path_1 = __importDefault(require("path"));
|
|
12
12
|
exports.CACHE_FILE = path_1.default.join(process.cwd(), ".empiricalrun", `overlay-cache.json`);
|
|
13
13
|
function normalizeString(str) {
|
|
14
|
-
// Replace all whitespace sequences with a single space
|
|
15
14
|
return str.replace(/\s+/g, " ").trim();
|
|
16
15
|
}
|
|
17
16
|
async function setCodeToCache({ dom, text, code, }) {
|
|
18
17
|
if (!dom && !text) {
|
|
19
|
-
// At least one of the two is required
|
|
20
18
|
return;
|
|
21
19
|
}
|
|
22
20
|
if (process.env.TEST_GEN_TOKEN) {
|
|
23
|
-
// No caching for test gen sessions (we don't want steps to get committed)
|
|
24
21
|
return;
|
|
25
22
|
}
|
|
26
23
|
const obj = {
|
|
@@ -52,7 +49,6 @@ async function setCodeToCache({ dom, text, code, }) {
|
|
|
52
49
|
}
|
|
53
50
|
async function executeFromCache({ page, dom, text, }) {
|
|
54
51
|
if (!dom && !text) {
|
|
55
|
-
// At least one of the two is required
|
|
56
52
|
return { success: false };
|
|
57
53
|
}
|
|
58
54
|
try {
|
|
@@ -66,7 +62,6 @@ async function executeFromCache({ page, dom, text, }) {
|
|
|
66
62
|
}
|
|
67
63
|
try {
|
|
68
64
|
console.log(`Executing from cache: "${match.code}" for element: ${dom}`);
|
|
69
|
-
// Ref: https://davidwalsh.name/async-function-class
|
|
70
65
|
const AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
|
|
71
66
|
const codeToExecute = addOverlayOption(match.code);
|
|
72
67
|
const exec = new AsyncFunction("page", codeToExecute);
|
|
@@ -85,12 +80,10 @@ async function executeFromCache({ page, dom, text, }) {
|
|
|
85
80
|
function addOverlayOption(code) {
|
|
86
81
|
return code.replace(/\.(click|hover)(\s*\(\s*)(\{[^}]*\})?(\s*\))(;)?/g, (match, action, openParen, options, closeParen, semicolon) => {
|
|
87
82
|
if (options) {
|
|
88
|
-
// If options exist, add isExecutingForOverlayDismiss to them
|
|
89
83
|
const optionsObj = options.replace(/\s*}\s*$/, "");
|
|
90
84
|
return `.${action}${openParen}${optionsObj}, isExecutingForOverlayDismiss: true }${closeParen}${semicolon || ""}`;
|
|
91
85
|
}
|
|
92
86
|
else {
|
|
93
|
-
// If no options, add them with isExecutingForOverlayDismiss
|
|
94
87
|
return `.${action}${openParen}{ isExecutingForOverlayDismiss: true }${closeParen}${semicolon || ""}`;
|
|
95
88
|
}
|
|
96
89
|
});
|
|
@@ -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,
|
|
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,CAqDf;YAEa,QAAQ;CA+BvB;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,GACnB,cAAc,GAAG,SAAS,CAiC5B"}
|
|
@@ -33,9 +33,7 @@ class OverlayDismissAgent {
|
|
|
33
33
|
try {
|
|
34
34
|
element = extractInterceptingElement(originalError.message);
|
|
35
35
|
}
|
|
36
|
-
catch {
|
|
37
|
-
// Ignoring this error
|
|
38
|
-
}
|
|
36
|
+
catch { }
|
|
39
37
|
const description = (0, utils_1.overlayDescription)(element) ?? "unknown";
|
|
40
38
|
const testName = testFn.info().title;
|
|
41
39
|
reporter(`Attempting to auto-dismiss overlay: ${description}`);
|
|
@@ -96,13 +94,7 @@ class OverlayDismissAgent {
|
|
|
96
94
|
// only once in a particular test run.
|
|
97
95
|
// Ran into this here: https://empirical.run/quizizz-tests/sessions/2825
|
|
98
96
|
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
97
|
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
98
|
openAIClientConfig: (0, api_worker_client_1.llmProxyOpenAIConfig)(),
|
|
107
99
|
});
|
|
108
100
|
this.cachingCandidates.push({
|
|
@@ -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,
|
|
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"}
|
|
@@ -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,+
|
|
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,+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"}
|
|
@@ -29,7 +29,7 @@ async function textContent(pageRef, element) {
|
|
|
29
29
|
let endTag;
|
|
30
30
|
const match = startTag.match(/^<\s*([^\s>]+)/);
|
|
31
31
|
if (match) {
|
|
32
|
-
const tagName = match[1];
|
|
32
|
+
const tagName = match[1];
|
|
33
33
|
endTag = `</${tagName}>`;
|
|
34
34
|
}
|
|
35
35
|
if (!startTag || !endTag) {
|
|
@@ -41,18 +41,15 @@ async function textContent(pageRef, element) {
|
|
|
41
41
|
const parser = new DOMParser();
|
|
42
42
|
const doc = parser.parseFromString(htmlString, "text/html");
|
|
43
43
|
const tempEl = doc.body.firstElementChild;
|
|
44
|
-
let selector = tempEl.tagName.toLowerCase();
|
|
45
|
-
// If there's an id, add it (id is unique and very specific)
|
|
44
|
+
let selector = tempEl.tagName.toLowerCase();
|
|
46
45
|
if (tempEl.id) {
|
|
47
46
|
selector += `#${CSS.escape(tempEl.id)}`;
|
|
48
47
|
}
|
|
49
|
-
// Add classes individually, escaping each one
|
|
50
48
|
if (tempEl.classList.length > 0) {
|
|
51
49
|
Array.from(tempEl.classList).forEach((cls) => {
|
|
52
50
|
selector += `.${CSS.escape(cls)}`;
|
|
53
51
|
});
|
|
54
52
|
}
|
|
55
|
-
// Add other attributes, being careful with escaping
|
|
56
53
|
Array.from(tempEl.attributes).forEach((attr) => {
|
|
57
54
|
if (attr.name === "id" || attr.name === "class") {
|
|
58
55
|
return;
|
|
@@ -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;
|
|
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
|
-
}
|