@empiricalrun/test-gen 0.66.1 → 0.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/agent/browsing/run.js +4 -4
  3. package/dist/agent/browsing/utils.d.ts +1 -0
  4. package/dist/agent/browsing/utils.d.ts.map +1 -1
  5. package/dist/agent/browsing/utils.js +5 -4
  6. package/dist/agent/chat/index.d.ts +1 -0
  7. package/dist/agent/chat/index.d.ts.map +1 -1
  8. package/dist/agent/chat/index.js +1 -0
  9. package/dist/agent/chat/prompt/index.d.ts.map +1 -1
  10. package/dist/agent/chat/prompt/index.js +3 -1
  11. package/dist/agent/cua/pw-codegen/pw-pause/for-recorder.d.ts +14 -0
  12. package/dist/agent/cua/pw-codegen/pw-pause/for-recorder.d.ts.map +1 -0
  13. package/dist/agent/cua/pw-codegen/pw-pause/for-recorder.js +62 -0
  14. package/dist/agent/cua/pw-codegen/pw-pause/index.d.ts.map +1 -1
  15. package/dist/agent/cua/pw-codegen/pw-pause/index.js +19 -15
  16. package/dist/agent/cua/pw-codegen/pw-pause/types.d.ts +14 -0
  17. package/dist/agent/cua/pw-codegen/pw-pause/types.d.ts.map +1 -0
  18. package/dist/agent/cua/pw-codegen/pw-pause/types.js +2 -0
  19. package/dist/artifacts/utils.d.ts +1 -1
  20. package/dist/artifacts/utils.d.ts.map +1 -1
  21. package/dist/artifacts/utils.js +5 -5
  22. package/dist/auth/api-client.d.ts +12 -0
  23. package/dist/auth/api-client.d.ts.map +1 -0
  24. package/dist/auth/api-client.js +133 -0
  25. package/dist/auth/cli-auth.d.ts +18 -0
  26. package/dist/auth/cli-auth.d.ts.map +1 -0
  27. package/dist/auth/cli-auth.js +184 -0
  28. package/dist/auth/index.d.ts +4 -0
  29. package/dist/auth/index.d.ts.map +1 -0
  30. package/dist/auth/index.js +17 -0
  31. package/dist/auth/token-store.d.ts +15 -0
  32. package/dist/auth/token-store.d.ts.map +1 -0
  33. package/dist/auth/token-store.js +149 -0
  34. package/dist/bin/index.js +98 -1
  35. package/dist/bin/utils/index.d.ts +2 -1
  36. package/dist/bin/utils/index.d.ts.map +1 -1
  37. package/dist/bin/utils/index.js +34 -5
  38. package/dist/browser-injected-scripts/annotate-elements.js +1 -4
  39. package/dist/file/client.d.ts +1 -0
  40. package/dist/file/client.d.ts.map +1 -1
  41. package/dist/file/client.js +3 -0
  42. package/dist/file/server.d.ts +2 -0
  43. package/dist/file/server.d.ts.map +1 -1
  44. package/dist/file/server.js +9 -0
  45. package/dist/index.d.ts +1 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +16 -0
  48. package/dist/recorder/display.d.ts +2 -0
  49. package/dist/recorder/display.d.ts.map +1 -0
  50. package/dist/recorder/display.js +50 -0
  51. package/dist/recorder/index.d.ts +4 -0
  52. package/dist/recorder/index.d.ts.map +1 -0
  53. package/dist/recorder/index.js +108 -0
  54. package/dist/recorder/request.d.ts +6 -0
  55. package/dist/recorder/request.d.ts.map +1 -0
  56. package/dist/recorder/request.js +55 -0
  57. package/dist/recorder/temp-files.d.ts +3 -0
  58. package/dist/recorder/temp-files.d.ts.map +1 -0
  59. package/dist/recorder/temp-files.js +39 -0
  60. package/dist/recorder/upload.d.ts +2 -0
  61. package/dist/recorder/upload.d.ts.map +1 -0
  62. package/dist/recorder/upload.js +85 -0
  63. package/dist/recorder/validation.d.ts +2 -0
  64. package/dist/recorder/validation.d.ts.map +1 -0
  65. package/dist/recorder/validation.js +24 -0
  66. package/package.json +2 -1
  67. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @empiricalrun/test-gen
2
2
 
3
+ ## 0.67.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 267b012: feat: add user login in test-gen cli
8
+
9
+ ## 0.66.2
10
+
11
+ ### Patch Changes
12
+
13
+ - 45dfd06: feat: show version comparison in banner
14
+ - 7c66a47: feat: first working version of --use-recorder
15
+ - 5bc45e1: feat: create requests from recorder cli
16
+ - d0569de: fix: ensure browser agent is not stuck on page.pause
17
+ - fd719f1: feat: upload recorder video and attach to request
18
+ - a65a4d2: fix: path and ui issues
19
+
3
20
  ## 0.66.1
4
21
 
5
22
  ### Patch Changes
@@ -83,10 +83,10 @@ async function runBrowsingAgent({ testCaseName, testCaseSuites, testFilePath, fi
83
83
  if (error) {
84
84
  // Clean up the file if there is any error
85
85
  try {
86
- const fileContent = fs_1.default.readFileSync(filePathToUpdate, "utf-8");
87
- const updatedContent = (0, web_1.replaceCreateTestWithNewCode)(filePathToUpdate, fileContent, "");
88
- fs_1.default.writeFileSync(filePathToUpdate, updatedContent, "utf-8");
89
- await (0, web_1.lintErrors)(filePathToUpdate);
86
+ const fileContent = fs_1.default.readFileSync(absFilePathToUpdate, "utf-8");
87
+ const updatedContent = (0, web_1.replaceCreateTestWithNewCode)(absFilePathToUpdate, fileContent, "");
88
+ fs_1.default.writeFileSync(absFilePathToUpdate, updatedContent, "utf-8");
89
+ await (0, web_1.lintErrors)(absFilePathToUpdate);
90
90
  }
91
91
  catch (e) {
92
92
  console.error(`[generateTestsUsingMasterAgent] Failed to remove extra scripts from files post test gen error:`, e);
@@ -4,6 +4,7 @@ import { Page } from "playwright";
4
4
  import { PlaywrightTestConfig } from "playwright/test";
5
5
  export declare function isRegExp(obj: any): obj is RegExp;
6
6
  export declare function prepareBrowsingAgentTask(steps: string[]): string;
7
+ export declare function addImportForMethod(testFilePath: string, methodName: string): Promise<void>;
7
8
  export declare function replaceTodoWithCreateTest(testFilePath: string, repoDir: string): Promise<void>;
8
9
  export declare function markTestAsOnly({ testCaseName, testCaseSuites, specPath, }: {
9
10
  testCaseName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAI3D,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAsBvD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,MAAM,CAKhD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,UAIvD;AAiFD,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,iBAwBhB;AAED,wBAAsB,cAAc,CAAC,EACnC,YAAY,EACZ,cAAc,EACd,QAAQ,GACT,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB,iBAoBA;AAED,wBAAsB,yBAAyB,CAAC,EAC9C,QAAQ,EACR,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyDlB;AAyBD,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,iBA8HxD;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,CAAC,CA2B/B;AAWD,wBAAsB,oBAAoB,CACxC,gBAAgB,EAAE,oBAAoB,GACrC,OAAO,CAAC,MAAM,EAAE,CAAC,CAQnB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,oBAAoB,EACtC,gBAAgB,GAAE,MAAM,EAAU,GACjC,OAAO,CAAC,MAAM,CAAC,CA+CjB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAI3D,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAsBvD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,MAAM,CAKhD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,UAIvD;AAED,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,iBAgBnB;AAgED,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,iBAwBhB;AAED,wBAAsB,cAAc,CAAC,EACnC,YAAY,EACZ,cAAc,EACd,QAAQ,GACT,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB,iBAoBA;AAED,wBAAsB,yBAAyB,CAAC,EAC9C,QAAQ,EACR,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyDlB;AAyBD,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,iBA8HxD;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,CAAC,CA2B/B;AAWD,wBAAsB,oBAAoB,CACxC,gBAAgB,EAAE,oBAAoB,GACrC,OAAO,CAAC,MAAM,EAAE,CAAC,CAQnB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,oBAAoB,EACtC,gBAAgB,GAAE,MAAM,EAAU,GACjC,OAAO,CAAC,MAAM,CAAC,CA+CjB"}
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.isRegExp = isRegExp;
7
7
  exports.prepareBrowsingAgentTask = prepareBrowsingAgentTask;
8
+ exports.addImportForMethod = addImportForMethod;
8
9
  exports.replaceTodoWithCreateTest = replaceTodoWithCreateTest;
9
10
  exports.markTestAsOnly = markTestAsOnly;
10
11
  exports.prepareFileForMasterAgent = prepareFileForMasterAgent;
@@ -33,14 +34,14 @@ function prepareBrowsingAgentTask(steps) {
33
34
  const task = `${sanitizedSteps.join("\n")}\n`;
34
35
  return task;
35
36
  }
36
- async function addImportForCreateTest(testFilePath) {
37
+ async function addImportForMethod(testFilePath, methodName) {
37
38
  // Instead of using "@empiricalrun/test-gen", we use the local dist file
38
39
  // This is to avoid assuming that the test-gen package is installed in the project
39
40
  const importSource = path_1.default.join(__dirname, "../../../dist/index.js");
40
41
  if (!fs_1.default.existsSync(importSource)) {
41
42
  throw new Error(`createTest import source not found at ${importSource}`);
42
43
  }
43
- fs_1.default.writeFileSync(testFilePath, (0, web_1.addNewImport)(fs_1.default.readFileSync(testFilePath, "utf-8"), ["createTest"], importSource));
44
+ fs_1.default.writeFileSync(testFilePath, (0, web_1.addNewImport)(fs_1.default.readFileSync(testFilePath, "utf-8"), [methodName], importSource));
44
45
  }
45
46
  async function prepareFileForUpdateScenario({ testCase, specPath, trace, }) {
46
47
  const { name, suites } = testCase;
@@ -77,7 +78,7 @@ async function prepareFileForUpdateScenario({ testCase, specPath, trace, }) {
77
78
  },
78
79
  });
79
80
  await (0, web_1.appendScopeToCreateTest)(createTestFilePath, scopeVariables);
80
- await addImportForCreateTest(createTestFilePath);
81
+ await addImportForMethod(createTestFilePath, "createTest");
81
82
  const { pomPrompt, nonSpecFilePrompt } = await (0, context_1.contextForGeneration)(createTestFilePath);
82
83
  await (0, fix_ts_errors_1.validateAndFixTypescriptErrors)({
83
84
  trace,
@@ -106,7 +107,7 @@ async function replaceTodoWithCreateTest(testFilePath, repoDir) {
106
107
  const [, pageVarName] = todoMatch;
107
108
  const pageVariable = pageVarName || "page"; // Default to "page" if not specified
108
109
  fs_1.default.writeFileSync(absoluteTestFilePath, fileContent.replace(todoRegex, (_, __, todoText) => `await createTest("${todoText.replace(/"/g, '\\"')}", ${pageVariable});`));
109
- await addImportForCreateTest(absoluteTestFilePath);
110
+ await addImportForMethod(absoluteTestFilePath, "createTest");
110
111
  }
111
112
  async function markTestAsOnly({ testCaseName, testCaseSuites, specPath, }) {
112
113
  const testFileContent = fs_1.default.readFileSync(specPath, "utf-8");
@@ -1,4 +1,5 @@
1
1
  import { SupportedChatModels } from "@empiricalrun/shared-types";
2
+ export declare function fetchEnvironmentVariables(): Promise<Record<string, string>>;
2
3
  export declare function runChatAgentForCLI({ useDiskForChatState, selectedModel, initialPromptContent, }: {
3
4
  selectedModel: SupportedChatModels;
4
5
  useDiskForChatState: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AAkEpC,wBAAsB,kBAAkB,CAAC,EACvC,mBAAmB,EACnB,aAAa,EACb,oBAAoB,GACrB,EAAE;IACD,aAAa,EAAE,mBAAmB,CAAC;IACnC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C,iBA6HA;AAuBD,wBAAsB,wBAAwB,CAAC,EAC7C,aAAa,EACb,aAAa,GACd,EAAE;IACD,aAAa,EAAE,mBAAmB,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,iBA6DA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AAwCpC,wBAAsB,yBAAyB,IAAI,OAAO,CACxD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CACvB,CAwBA;AAED,wBAAsB,kBAAkB,CAAC,EACvC,mBAAmB,EACnB,aAAa,EACb,oBAAoB,GACrB,EAAE;IACD,aAAa,EAAE,mBAAmB,CAAC;IACnC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C,iBA6HA;AAuBD,wBAAsB,wBAAwB,CAAC,EAC7C,aAAa,EACb,aAAa,GACd,EAAE;IACD,aAAa,EAAE,mBAAmB,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,iBA6DA"}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchEnvironmentVariables = fetchEnvironmentVariables;
3
4
  exports.runChatAgentForCLI = runChatAgentForCLI;
4
5
  exports.runChatAgentForDashboard = runChatAgentForDashboard;
5
6
  const llm_1 = require("@empiricalrun/llm");
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/agent/chat/prompt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAI1C,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,mBA0GzD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/agent/chat/prompt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAI1C,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,mBA4GzD"}
@@ -67,7 +67,9 @@ ONLY when explicitly asked for by the user.
67
67
 
68
68
  1. You can't delete some steps from the test to make it pass. The test needs to accomplish its objective (which is to validate a particular user scenario)
69
69
  2. Do not add any conditional logic or try catch blocks in a test. A good test deterministically tests a user scenario
70
- 3. Trust Playwright's ability to auto-wait while taking actions on elements. For example, do not add checks on locator.isVisible() before clicking on it: Playwright already does this
70
+ 3. Trust Playwright's ability to auto-wait while taking actions on elements.
71
+ - Example 1: Do not add checks on locator.isVisible() before clicking on it: Playwright already waits for visibility on locator.click()
72
+ - Example 2: Do not add page.waitForLoadState after a page.goto: Playwright already waits for page "load" event in page.goto()
71
73
  4. Do not add waitForTimeout or waitForLoadState in a test. Playwright will automatically wait for the page to load.
72
74
  5. Try/catch blocks are a code smell for tests: you should not use them.
73
75
  6. Do not use then() or catch() syntax in a test. Use async/await only
@@ -0,0 +1,14 @@
1
+ import type { Page } from "playwright";
2
+ import { SourcesPayload } from "./types";
3
+ export declare class PlaywrightPauseCodegenForRecorder {
4
+ private sourcesCallback;
5
+ private port;
6
+ private page;
7
+ private server;
8
+ private codeForLastAction;
9
+ constructor(sourcesCallback: (code: SourcesPayload[]) => Promise<void>);
10
+ private saveCode;
11
+ initialize(page: Page): Promise<void>;
12
+ startPlaywrightCodegen(page: Page): Promise<void>;
13
+ }
14
+ //# sourceMappingURL=for-recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"for-recorder.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/for-recorder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,qBAAa,iCAAiC;IAO1C,OAAO,CAAC,eAAe;IANzB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,iBAAiB,CAAqB;gBAGpC,eAAe,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC;YAKtD,QAAQ;IAWhB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrC,sBAAsB,CAAC,IAAI,EAAE,IAAI;CAiBxC"}
@@ -0,0 +1,62 @@
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
+ exports.PlaywrightPauseCodegenForRecorder = void 0;
7
+ const express_1 = __importDefault(require("express"));
8
+ const ipc_1 = require("./ipc");
9
+ class PlaywrightPauseCodegenForRecorder {
10
+ sourcesCallback;
11
+ port = 0;
12
+ page;
13
+ server;
14
+ codeForLastAction;
15
+ constructor(sourcesCallback) {
16
+ this.sourcesCallback = sourcesCallback;
17
+ this.port = ipc_1.PW_PAUSE_IPC_PORT;
18
+ }
19
+ async saveCode(code) {
20
+ const generatedCode = code.map((c) => c.actions.join("\n")).join("\n");
21
+ if (generatedCode) {
22
+ console.log(`[PlaywrightPauseCodegen] Received code from Playwright: ${generatedCode}`);
23
+ this.codeForLastAction = generatedCode;
24
+ await this.sourcesCallback(code);
25
+ }
26
+ }
27
+ async initialize(page) {
28
+ // Start server to receive generated code from patch
29
+ const app = (0, express_1.default)();
30
+ app.use(express_1.default.json());
31
+ app.post("/sources", async (req, res) => {
32
+ const { payload } = req.body;
33
+ await this.saveCode(JSON.parse(payload));
34
+ return res.send({ success: true });
35
+ });
36
+ await new Promise((resolve) => {
37
+ this.server = app.listen(this.port, () => resolve());
38
+ });
39
+ console.log(`Server started on port ${this.port}`);
40
+ // Start page.pause experience in the page
41
+ this.page = page;
42
+ await this.startPlaywrightCodegen(page);
43
+ }
44
+ async startPlaywrightCodegen(page) {
45
+ // Similar to the same name method in the main codegen
46
+ const timerPromise = new Promise((resolve) => {
47
+ setTimeout(resolve, 1000);
48
+ });
49
+ const pausePromise = page.pause();
50
+ await timerPromise;
51
+ const evaluatePromise = page.evaluate(() => {
52
+ // @ts-ignore
53
+ console.log(window["__pw_recorderSetMode"]("recording"));
54
+ const glassPane = document.querySelector("x-pw-glass");
55
+ if (glassPane) {
56
+ glassPane.remove();
57
+ }
58
+ });
59
+ await Promise.all([pausePromise, evaluatePromise]);
60
+ }
61
+ }
62
+ exports.PlaywrightPauseCodegenForRecorder = PlaywrightPauseCodegenForRecorder;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAIjD,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE9E,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,oBAqCvD;AAiBD,qBAAa,sBAAuB,YAAW,qBAAqB;IAClE,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,iBAAiB,CAAqB;;YAMhC,QAAQ;IAOhB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrC,sBAAsB,CAAC,IAAI,EAAE,IAAI;IAsBjC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAU9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAKjD,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE9E,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,oBAuCvD;AAED,qBAAa,sBAAuB,YAAW,qBAAqB;IAClE,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,iBAAiB,CAAqB;;YAMhC,QAAQ;IAUhB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrC,sBAAsB,CAAC,IAAI,EAAE,IAAI;IAyBjC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAU9C"}
@@ -54,6 +54,7 @@ class PlaywrightPauseCodegen {
54
54
  async saveCode(code) {
55
55
  const generatedCode = code.map((c) => c.actions.join("\n")).join("\n");
56
56
  if (generatedCode) {
57
+ console.log(`[PlaywrightPauseCodegen] Received code from Playwright: ${generatedCode}`);
57
58
  this.codeForLastAction = generatedCode;
58
59
  }
59
60
  }
@@ -78,22 +79,25 @@ class PlaywrightPauseCodegen {
78
79
  // TODO: Glass pane needs to be removed on every page load
79
80
  // We use bindings that Playwright exposes to the page
80
81
  // Ref: https://github.com/microsoft/playwright/blob/e1c8e0f6b33923c95cc4b9416aefa6977b1d3c55/packages/playwright-core/src/server/recorder.ts#L191
81
- await page.evaluate(() => {
82
- setTimeout(() => {
83
- // First, we start recording
84
- // @ts-ignore
85
- console.log(window["__pw_recorderSetMode"]("recording"));
86
- // Then, we will resume the effect of pause()
87
- // @ts-ignore
88
- console.log(window["__pw_resume"]());
89
- // Then, we remove highlights that Playwright shows on the screen
90
- const glassPane = document.querySelector("x-pw-glass");
91
- if (glassPane) {
92
- glassPane.remove();
93
- }
94
- }, 1000);
82
+ const timerPromise = new Promise((resolve) => {
83
+ setTimeout(resolve, 1000);
95
84
  });
96
- await page.pause();
85
+ const pausePromise = page.pause();
86
+ await timerPromise;
87
+ const evaluatePromise = page.evaluate(() => {
88
+ // First, we start recording
89
+ // @ts-ignore
90
+ console.log(window["__pw_recorderSetMode"]("recording"));
91
+ // Then, we will resume the effect of pause()
92
+ // @ts-ignore
93
+ console.log(window["__pw_resume"]());
94
+ // Then, we remove highlights that Playwright shows on the screen
95
+ const glassPane = document.querySelector("x-pw-glass");
96
+ if (glassPane) {
97
+ glassPane.remove();
98
+ }
99
+ });
100
+ await Promise.all([pausePromise, evaluatePromise]);
97
101
  }
98
102
  async recordAction() {
99
103
  // Record action is no-op
@@ -0,0 +1,14 @@
1
+ export type SourcesPayload = {
2
+ isRecorded: boolean;
3
+ label: "library";
4
+ group: "Node.js";
5
+ id: "javascript";
6
+ text: string;
7
+ header: string;
8
+ footer: string;
9
+ actions: string[];
10
+ language: "javascript";
11
+ revealLine: number;
12
+ highlight: string[];
13
+ };
14
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,EAAE,EAAE,YAAY,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,YAAY,CAAC;IAEvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -5,7 +5,7 @@ import { JSONReport as PlaywrightJSONReport } from "@playwright/test/reporter";
5
5
  * @param report The Playwright JSON report to extract attachments from
6
6
  * @returns An array of objects containing path and contentType for each attachment
7
7
  */
8
- export declare function extractAttachmentsFromPlaywrightJSONReport(report: PlaywrightJSONReport): ArtifactInputPath[];
8
+ export declare function extractAttachmentsFromPlaywrightJSONReport(report: PlaywrightJSONReport, testNameFilter?: string): ArtifactInputPath[];
9
9
  /**
10
10
  * Scans the given repository directory for Playwright artifacts (attachments) by:
11
11
  * - Constructing the path to the Playwright report directory using the provided repoDir.
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/artifacts/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EACL,UAAU,IAAI,oBAAoB,EAGnC,MAAM,2BAA2B,CAAC;AAInC;;;;GAIG;AACH,wBAAgB,0CAA0C,CACxD,MAAM,EAAE,oBAAoB,GAC3B,iBAAiB,EAAE,CAqErB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAmCxE"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/artifacts/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EACL,UAAU,IAAI,oBAAoB,EAGnC,MAAM,2BAA2B,CAAC;AAInC;;;;GAIG;AACH,wBAAgB,0CAA0C,CACxD,MAAM,EAAE,oBAAoB,EAC5B,cAAc,CAAC,EAAE,MAAM,GACtB,iBAAiB,EAAE,CA2DrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAmCxE"}
@@ -12,7 +12,7 @@ const path_1 = __importDefault(require("path"));
12
12
  * @param report The Playwright JSON report to extract attachments from
13
13
  * @returns An array of objects containing path and contentType for each attachment
14
14
  */
15
- function extractAttachmentsFromPlaywrightJSONReport(report) {
15
+ function extractAttachmentsFromPlaywrightJSONReport(report, testNameFilter) {
16
16
  const attachments = [];
17
17
  if (!report || !report.suites || report.suites.length === 0) {
18
18
  return attachments;
@@ -26,6 +26,9 @@ function extractAttachmentsFromPlaywrightJSONReport(report) {
26
26
  if (!spec.tests) {
27
27
  return;
28
28
  }
29
+ if (testNameFilter && !testTitle.includes(testNameFilter)) {
30
+ return;
31
+ }
29
32
  for (const test of spec.tests) {
30
33
  if (!test.results) {
31
34
  continue;
@@ -38,7 +41,7 @@ function extractAttachmentsFromPlaywrightJSONReport(report) {
38
41
  // Only collect attachments that have a 'path' (i.e., not embedded content)
39
42
  if (attachment.path && attachment.contentType) {
40
43
  attachments.push({
41
- name: `${testTitle} ${attachment.name}`,
44
+ name: `${testTitle} - ${attachment.name}`,
42
45
  path: attachment.path,
43
46
  contentType: attachment.contentType,
44
47
  });
@@ -56,19 +59,16 @@ function extractAttachmentsFromPlaywrightJSONReport(report) {
56
59
  return;
57
60
  }
58
61
  for (const suite of suites) {
59
- // Process specs directly within the current suite
60
62
  if (suite.specs) {
61
63
  for (const spec of suite.specs) {
62
64
  processSpec(spec);
63
65
  }
64
66
  }
65
- // Recursively call for any nested suites
66
67
  if (suite.suites) {
67
68
  traverseSuites(suite.suites);
68
69
  }
69
70
  }
70
71
  }
71
- // Start the recursive traversal from the top-level suites
72
72
  traverseSuites(report.suites);
73
73
  return attachments;
74
74
  }
@@ -0,0 +1,12 @@
1
+ declare class APIClient {
2
+ private appUrl;
3
+ constructor();
4
+ request(endpoint: string, options?: RequestInit): Promise<Response>;
5
+ private makeRequest;
6
+ private ensureAuthenticated;
7
+ private refreshToken;
8
+ }
9
+ export declare const apiClient: APIClient;
10
+ export { APIClient };
11
+ export declare function authenticatedFetch(endpoint: string, options?: RequestInit): Promise<any>;
12
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/auth/api-client.ts"],"names":[],"mappings":"AAOA,cAAM,SAAS;IACb,OAAO,CAAC,MAAM,CAAS;;IAMjB,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,QAAQ,CAAC;YAoCN,WAAW;YAmBX,mBAAmB;YAiBnB,YAAY;CA4C3B;AAED,eAAO,MAAM,SAAS,WAAkB,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,GAAG,CAAC,CAqCd"}
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.APIClient = exports.apiClient = void 0;
4
+ exports.authenticatedFetch = authenticatedFetch;
5
+ const token_store_1 = require("./token-store");
6
+ class APIClient {
7
+ appUrl;
8
+ constructor() {
9
+ this.appUrl = process.env.DASHBOARD_DOMAIN || "https://dash.empirical.run";
10
+ }
11
+ async request(endpoint, options = {}) {
12
+ // Ensure user is authenticated
13
+ await this.ensureAuthenticated();
14
+ const tokens = await (0, token_store_1.getStoredTokens)();
15
+ if (!tokens) {
16
+ throw new Error("Not authenticated. Please run the login command first.");
17
+ }
18
+ // Make the request with the access token
19
+ const response = await this.makeRequest(endpoint, options, tokens.access_token);
20
+ // If token is expired, try refreshing and retry once
21
+ if (response.status === 401) {
22
+ console.log("Access token expired, attempting to refresh...");
23
+ const refreshed = await this.refreshToken();
24
+ if (refreshed) {
25
+ const newTokens = await (0, token_store_1.getStoredTokens)();
26
+ if (newTokens) {
27
+ return this.makeRequest(endpoint, options, newTokens.access_token);
28
+ }
29
+ }
30
+ throw new Error("Authentication failed. Please run the login command again.");
31
+ }
32
+ return response;
33
+ }
34
+ async makeRequest(endpoint, options, accessToken) {
35
+ const url = endpoint.startsWith("http")
36
+ ? endpoint
37
+ : `${this.appUrl}/api${endpoint}`;
38
+ return fetch(url, {
39
+ ...options,
40
+ headers: {
41
+ Authorization: `Bearer ${accessToken}`,
42
+ "Content-Type": "application/json",
43
+ ...options.headers,
44
+ },
45
+ });
46
+ }
47
+ async ensureAuthenticated() {
48
+ if (!(await (0, token_store_1.isAuthenticated)())) {
49
+ const tokens = await (0, token_store_1.getStoredTokens)();
50
+ if (!tokens) {
51
+ throw new Error("Not authenticated. Please run the login command first.");
52
+ }
53
+ // Token exists but is expired, try to refresh
54
+ const refreshed = await this.refreshToken();
55
+ if (!refreshed) {
56
+ throw new Error("Session expired. Please run the login command again.");
57
+ }
58
+ }
59
+ }
60
+ async refreshToken() {
61
+ const tokens = await (0, token_store_1.getStoredTokens)();
62
+ if (!tokens || !tokens.refresh_token) {
63
+ return false;
64
+ }
65
+ try {
66
+ // Use dashboard refresh endpoint instead of Supabase directly
67
+ const response = await fetch(`${this.appUrl}/api/cli/refresh`, {
68
+ method: "POST",
69
+ headers: {
70
+ "Content-Type": "application/json",
71
+ },
72
+ body: JSON.stringify({
73
+ refresh_token: tokens.refresh_token,
74
+ }),
75
+ });
76
+ if (!response.ok) {
77
+ const errorText = await response.text();
78
+ console.error("Token refresh failed:", errorText);
79
+ await (0, token_store_1.clearTokens)();
80
+ return false;
81
+ }
82
+ const data = await response.json();
83
+ // Store the new tokens (refresh token rotation means we get a new refresh token)
84
+ await (0, token_store_1.storeTokens)({
85
+ access_token: data.access_token,
86
+ refresh_token: data.refresh_token,
87
+ expires_at: data.expires_at,
88
+ user_id: data.user?.id || tokens.user_id,
89
+ user_email: data.user?.email || tokens.user_email,
90
+ });
91
+ console.log("Access token refreshed successfully via dashboard");
92
+ return true;
93
+ }
94
+ catch (error) {
95
+ console.error("Token refresh error:", error);
96
+ await (0, token_store_1.clearTokens)();
97
+ return false;
98
+ }
99
+ }
100
+ }
101
+ exports.APIClient = APIClient;
102
+ exports.apiClient = new APIClient();
103
+ async function authenticatedFetch(endpoint, options) {
104
+ try {
105
+ const response = await exports.apiClient.request(endpoint, options);
106
+ if (!response.ok) {
107
+ const errorText = await response.text();
108
+ let errorMessage;
109
+ try {
110
+ const errorJson = JSON.parse(errorText);
111
+ errorMessage =
112
+ errorJson.error || errorJson.message || "API request failed";
113
+ }
114
+ catch {
115
+ errorMessage =
116
+ errorText || `Request failed with status ${response.status}`;
117
+ }
118
+ throw new Error(errorMessage);
119
+ }
120
+ const contentType = response.headers.get("content-type");
121
+ if (contentType && contentType.includes("application/json")) {
122
+ return response.json();
123
+ }
124
+ return response.text();
125
+ }
126
+ catch (error) {
127
+ if (error.message.includes("Not authenticated") ||
128
+ error.message.includes("Please run the login command")) {
129
+ throw new Error("Authentication required. Please run: npx @empiricalrun/test-gen login");
130
+ }
131
+ throw error;
132
+ }
133
+ }
@@ -0,0 +1,18 @@
1
+ export interface AuthResult {
2
+ success: boolean;
3
+ user?: {
4
+ id: string;
5
+ email: string;
6
+ };
7
+ error?: string;
8
+ }
9
+ export declare function authenticate(): Promise<AuthResult>;
10
+ export declare function logout(): Promise<void>;
11
+ export declare function getAuthStatus(): Promise<{
12
+ authenticated: boolean;
13
+ user?: {
14
+ id: string;
15
+ email: string;
16
+ };
17
+ }>;
18
+ //# sourceMappingURL=cli-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-auth.d.ts","sourceRoot":"","sources":["../../src/auth/cli-auth.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,CAmKxD;AAED,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAE5C;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC;IAC7C,aAAa,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACtC,CAAC,CAeD"}