@empiricalrun/test-gen 0.46.1 → 0.46.3

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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # @empiricalrun/test-gen
2
2
 
3
+ ## 0.46.3
4
+
5
+ ### Patch Changes
6
+
7
+ - f26142f: fix: browsing agent giving wrong executed action
8
+ - 112b429: test: enable parallel test execution in playwright
9
+
10
+ ## 0.46.2
11
+
12
+ ### Patch Changes
13
+
14
+ - 9770fd6: test: fill action with multiple pages
15
+ - c723f61: fix: auto fix didnt work
16
+ - e6d6174: chore: remove sentry from worker, service and test-gen
17
+
3
18
  ## 0.46.1
4
19
 
5
20
  ### Patch Changes
@@ -7,6 +7,10 @@ export type BrowsingAgentOptions = Partial<TestGenConfigOptions> & {
7
7
  disallowedStrings?: string[];
8
8
  };
9
9
  };
10
+ export type BrowserAgentAction = {
11
+ action: string;
12
+ code: string | undefined;
13
+ };
10
14
  export declare function executeTaskUsingBrowsingAgent({ action, page, actions, llm, options, trace, }: {
11
15
  action: string;
12
16
  page: Page;
@@ -14,5 +18,5 @@ export declare function executeTaskUsingBrowsingAgent({ action, page, actions, l
14
18
  llm: LLM;
15
19
  trace?: TraceClient;
16
20
  options: BrowsingAgentOptions;
17
- }): Promise<string[] | undefined>;
21
+ }): Promise<BrowserAgentAction | undefined>;
18
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,GAAG,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAQlD,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,GAAG;IACjE,YAAY,CAAC,EAAE;QACb,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC9B,CAAC;CACH,CAAC;AAEF,wBAAsB,6BAA6B,CAAC,EAClD,MAAM,EACN,IAAI,EACJ,OAAO,EACP,GAAG,EACH,OAAO,EACP,KAAK,GACN,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,iBAAiB,CAAC;IAC3B,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,oBAAoB,CAAC;CAC/B,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,CAiEhC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,GAAG,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAQlD,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,GAAG;IACjE,YAAY,CAAC,EAAE;QACb,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC9B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B,CAAC;AAEF,wBAAsB,6BAA6B,CAAC,EAClD,MAAM,EACN,IAAI,EACJ,OAAO,EACP,GAAG,EACH,OAAO,EACP,KAAK,GACN,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,iBAAiB,CAAC;IAC3B,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,oBAAoB,CAAC;CAC/B,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAoE1C"}
@@ -9,7 +9,7 @@ const html_1 = require("../../utils/html");
9
9
  const utils_1 = require("../utils");
10
10
  const o1_completion_1 = require("./o1-completion");
11
11
  async function executeTaskUsingBrowsingAgent({ action, page, actions, llm, options, trace, }) {
12
- let generatedCodeSteps = [];
12
+ let generatedCodeSteps;
13
13
  const tools = actions.getBrowsingActionSchemas();
14
14
  const testgenUpdatesReporter = new reporter_1.TestGenUpdatesReporter();
15
15
  const browsingAgentSpan = trace?.span({
@@ -55,11 +55,14 @@ async function executeTaskUsingBrowsingAgent({ action, page, actions, llm, optio
55
55
  const toolCallsSpan = browsingAgentSpan?.span({ name: "tool-calls" });
56
56
  for (const i in toolCalls) {
57
57
  const toolCall = toolCalls[i];
58
+ const args = (0, utils_1.parseJson)(toolCall.function.arguments);
58
59
  try {
59
60
  const code = await actions.executeAction(toolCall.function.name, (0, utils_1.parseJson)(toolCall.function.arguments), toolCallsSpan);
60
- if (code) {
61
- generatedCodeSteps.push(code);
62
- }
61
+ generatedCodeSteps = {
62
+ // Passing reason as action, in order to pass the correct action that took place to runtime planner
63
+ action: args.reason,
64
+ code,
65
+ };
63
66
  }
64
67
  catch (e) {
65
68
  void testgenUpdatesReporter.sendMessage(e.message);
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/run.ts"],"names":[],"mappings":"AAmBA,KAAK,iBAAiB,GAAG;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,6BAA6B,CAAC,EAClD,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,OAAO,GACR,EAAE,iBAAiB,iBA8EnB"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/run.ts"],"names":[],"mappings":"AAkBA,KAAK,iBAAiB,GAAG;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,6BAA6B,CAAC,EAClD,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,OAAO,GACR,EAAE,iBAAiB,iBA6EnB"}
@@ -1,33 +1,9 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
6
  exports.generateTestsUsingMasterAgent = void 0;
30
- const Sentry = __importStar(require("@sentry/node"));
31
7
  const detect_port_1 = __importDefault(require("detect-port"));
32
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
33
9
  const web_1 = require("../../bin/utils/platform/web");
@@ -80,7 +56,6 @@ async function generateTestsUsingMasterAgent({ testFilePath, filePathToUpdate, p
80
56
  PAGE_VAR_NAME: pageVar || "page",
81
57
  DISPLAY: ":99",
82
58
  },
83
- span: Sentry.getActiveSpan(),
84
59
  });
85
60
  }
86
61
  catch (e) {
@@ -10,27 +10,31 @@ const path_1 = __importDefault(require("path"));
10
10
  const utils_1 = require("../../browsing/utils");
11
11
  const element_annotation_1 = require("../element-annotation");
12
12
  const run_1 = require("../run");
13
- let server;
14
- let PORT = 2345;
15
- test_1.test.beforeAll(async () => {
16
- server = http_server_1.default.createServer({
17
- root: path_1.default.join(process.cwd(), "test-data"),
18
- });
19
- // Start the server
20
- await new Promise((resolve) => {
21
- server.listen(PORT, () => {
22
- console.log(`Server running at http://localhost:${PORT}`);
23
- resolve(true);
24
- });
25
- });
26
- });
27
- test_1.test.afterAll(() => {
28
- if (server) {
29
- server.close();
30
- }
13
+ const test = test_1.test.extend({
14
+ server: [
15
+ // eslint-disable-next-line no-empty-pattern
16
+ async ({}, use, workerInfo) => {
17
+ const port = 2345 + workerInfo.workerIndex;
18
+ const server = http_server_1.default.createServer({
19
+ root: path_1.default.join(process.cwd(), "test-data"),
20
+ });
21
+ await new Promise((resolve) => {
22
+ server.listen(port, () => {
23
+ console.log(`Server running at http://localhost:${port}`);
24
+ resolve();
25
+ });
26
+ });
27
+ await use({
28
+ port,
29
+ baseURL: `http://localhost:${port}`,
30
+ });
31
+ server.close();
32
+ },
33
+ { scope: "worker" },
34
+ ],
31
35
  });
32
- (0, test_1.test)("able to scroll and interact with elements", async ({ page }) => {
33
- await page.goto(`http://localhost:${PORT}/blog-page.html`);
36
+ test("able to scroll and interact with elements", async ({ page, server }) => {
37
+ await page.goto(`${server.baseURL}/blog-page.html`);
34
38
  const response = await (0, run_1.createTestUsingMasterAgent)({
35
39
  task: `fill test@test.com into the email field and click the submit`,
36
40
  page,
@@ -41,8 +45,8 @@ test_1.test.afterAll(() => {
41
45
  (0, test_1.expect)(response.code).toContain("await page.getByPlaceholder('Enter your email').fill(\"test@test.com\")");
42
46
  (0, test_1.expect)(response.code).toContain("await page.getByRole('button', { name: 'Subscribe' }).click()");
43
47
  });
44
- (0, test_1.test)("scroll when element does not exist", async ({ page }) => {
45
- await page.goto(`http://localhost:${PORT}/blog-page.html`);
48
+ test("scroll when element does not exist", async ({ page, server }) => {
49
+ await page.goto(`${server.baseURL}/blog-page.html`);
46
50
  const response = await (0, run_1.createTestUsingMasterAgent)({
47
51
  task: `click search button`,
48
52
  page,
@@ -52,8 +56,8 @@ test_1.test.afterAll(() => {
52
56
  (0, test_1.expect)(response.importPaths.length).toBe(0);
53
57
  (0, test_1.expect)(response.code.length).toBe(0);
54
58
  });
55
- (0, test_1.test)("agent can click icons accurately", async ({ page }) => {
56
- await page.goto(`http://localhost:${PORT}/icons-navbar.html`);
59
+ test("agent can click icons accurately", async ({ page, server }) => {
60
+ await page.goto(`${server.baseURL}/icons-navbar.html`);
57
61
  await (0, test_1.expect)(page.getByText("select an icon")).toBeVisible();
58
62
  const response = await (0, run_1.createTestUsingMasterAgent)({
59
63
  task: `click on the gear icon`,
@@ -72,9 +76,9 @@ test_1.test.afterAll(() => {
72
76
  (0, test_1.expect)(icons.length).toBe(4); // 1 for each unique icon
73
77
  fs_1.default.unlinkSync(iconsRegistryFile);
74
78
  });
75
- (0, test_1.test)("annotate and enrich annotations correctly", async ({ page }) => {
79
+ test("annotate and enrich annotations correctly", async ({ page, server }) => {
76
80
  await (0, utils_1.injectPwLocatorGenerator)(page);
77
- await page.goto(`http://localhost:${PORT}/iframe-elements.html`);
81
+ await page.goto(`${server.baseURL}/iframe-elements.html`);
78
82
  const { annotationKeys: keys } = await (0, element_annotation_1.getAnnotationKeys)({
79
83
  page,
80
84
  preference: {
@@ -92,3 +96,24 @@ test_1.test.afterAll(() => {
92
96
  // 2 clickable divs: 1 in main frame, 1 in iframe
93
97
  (0, test_1.expect)(keys.filter((k) => k.text.includes("Lorem Ipsum")).length).toBe(2);
94
98
  });
99
+ test("fill action with multiple pages", async ({ context }) => {
100
+ const page1 = await context.newPage();
101
+ const page2 = await context.newPage();
102
+ const response = await (0, run_1.createTestUsingMasterAgent)({
103
+ task: `goto empirical.run on page1 and goto google.com in page2. Enter text empirical on page2 and click on search.`,
104
+ page: page2,
105
+ options: {},
106
+ scopeVars: {
107
+ context,
108
+ page1,
109
+ page2,
110
+ },
111
+ });
112
+ (0, test_1.expect)(response.code).toBeTruthy();
113
+ console.log(response.code);
114
+ const lines = response.code.split("\n");
115
+ (0, test_1.expect)(lines.find((l) => l.match(/^await page1\.goto(.+)empirical\.run/))).toBeTruthy();
116
+ (0, test_1.expect)(lines.find((l) => l.match(/^await page2\.goto(.+)google\.com/))).toBeTruthy();
117
+ (0, test_1.expect)(lines.find((l) => l.match(/^await page2(.+)fill(.+)empirical/))).toBeTruthy();
118
+ (0, test_1.expect)(lines.find((l) => l.match(/^await page2(.+)click/))).toBeTruthy();
119
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/master/run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAqBlC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EACL,oBAAoB,EAErB,MAAM,aAAa,CAAC;AA6BrB,wBAAsB,0BAA0B,CAAC,EAC/C,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,SAAS,GACV,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;;;GA8XA"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/master/run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAqBlC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EACL,oBAAoB,EAErB,MAAM,aAAa,CAAC;AA6BrB,wBAAsB,0BAA0B,CAAC,EAC/C,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,SAAS,GACV,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;;;GAmYA"}
@@ -282,7 +282,7 @@ async function createTestUsingMasterAgent({ task, page, testCase, specPath, opti
282
282
  }
283
283
  }
284
284
  else {
285
- generatedCodeSteps = await (0, browsing_1.executeTaskUsingBrowsingAgent)({
285
+ const browserAction = await (0, browsing_1.executeTaskUsingBrowsingAgent)({
286
286
  trace: masterAgentActionSpan,
287
287
  action: output.action,
288
288
  page,
@@ -290,6 +290,12 @@ async function createTestUsingMasterAgent({ task, page, testCase, specPath, opti
290
290
  llm,
291
291
  actions,
292
292
  });
293
+ if (browserAction) {
294
+ output.action = browserAction.action;
295
+ if (browserAction.code) {
296
+ generatedCodeSteps.push(browserAction.code);
297
+ }
298
+ }
293
299
  }
294
300
  }
295
301
  // resetting error count as there is a successful action
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import "../initSentry";
2
+ export {};
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":";AAEA,OAAO,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":""}
package/dist/bin/index.js CHANGED
@@ -1,35 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
- Object.defineProperty(o, "default", { enumerable: true, value: v });
16
- }) : function(o, v) {
17
- o["default"] = v;
18
- });
19
- var __importStar = (this && this.__importStar) || function (mod) {
20
- if (mod && mod.__esModule) return mod;
21
- var result = {};
22
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
- __setModuleDefault(result, mod);
24
- return result;
25
- };
26
3
  var __importDefault = (this && this.__importDefault) || function (mod) {
27
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
28
5
  };
29
6
  Object.defineProperty(exports, "__esModule", { value: true });
30
- require("../initSentry");
31
7
  const llm_1 = require("@empiricalrun/llm");
32
- const Sentry = __importStar(require("@sentry/node"));
33
8
  const commander_1 = require("commander");
34
9
  const dotenv_1 = __importDefault(require("dotenv"));
35
10
  const run_1 = require("../agent/browsing/run");
@@ -51,7 +26,6 @@ dotenv_1.default.config({
51
26
  });
52
27
  const flushEvents = async () => {
53
28
  await (0, llm_1.flushAllTraces)();
54
- await Sentry.flush();
55
29
  };
56
30
  process.on("beforeExit", async () => await flushEvents());
57
31
  process.on("exit", async () => await flushEvents());
@@ -64,7 +38,7 @@ async function resolveAgentUsingTask({ testCase, trace, }) {
64
38
  });
65
39
  return response;
66
40
  }
67
- async function runAgent(testGenConfig, testGenToken, span) {
41
+ async function runAgent(testGenConfig, testGenToken) {
68
42
  const logger = new logger_1.CustomLogger();
69
43
  const { specPath, testCase } = testGenConfig;
70
44
  if (process.env.LOG_URL) {
@@ -72,7 +46,6 @@ async function runAgent(testGenConfig, testGenToken, span) {
72
46
  void new reporter_1.TestGenUpdatesReporter().sendLogUrl(process.env.LOG_URL);
73
47
  }
74
48
  catch (e) {
75
- span?.recordException(e);
76
49
  console.warn("Failed to send log url to test gen update", e);
77
50
  }
78
51
  }
@@ -120,7 +93,7 @@ async function runAgent(testGenConfig, testGenToken, span) {
120
93
  if (testGenConfig.testErrorDiagnosis &&
121
94
  testGenConfig.testErrorDiagnosis.failingLine &&
122
95
  // TODO: fix this hardcoding of user prompt - ideally its an auto fix intent
123
- testCase.steps[0] == "Can you please fix the test") {
96
+ testCase.steps[0]?.toLowerCase().trim() == "can you please fix the test") {
124
97
  const { task: updatedTask } = await (0, diagnosis_agent_1.createTaskUsingFailureDiagnosis)({
125
98
  options: testGenConfig.options,
126
99
  trace,
@@ -178,69 +151,62 @@ async function runAgent(testGenConfig, testGenToken, span) {
178
151
  return agent;
179
152
  }
180
153
  (async function main() {
181
- await Sentry.continueTrace({ sentryTrace: utils_2.sentryTrace, baggage: utils_2.baggage }, async () => {
182
- await Sentry.startSpan({ name: "test-gen" }, async (span) => {
183
- const program = new commander_1.Command();
184
- program
185
- .option("--token <token>", "Test generation token")
186
- .option("--name <test-name>", "Name of the test case")
187
- .option("--prompt <prompt>", "Prompt for the test case")
188
- .option("--file <test-file>", "File path of the test case (inside tests dir)")
189
- .option("--suites <suites>", "Comma separated list of describe blocks")
190
- .parse(process.argv);
191
- const options = program.opts();
192
- (0, utils_2.validateCliOptions)(options);
193
- const testGenConfig = options.token
194
- ? (0, scenarios_1.loadTestConfigs)(options.token)
195
- : (0, scenarios_1.buildTestConfigFromOptions)(options);
196
- const testGenToken = options.token
197
- ? options.token
198
- : (0, scenarios_1.buildTokenFromOptions)(options);
199
- (0, reporter_1.setReporterConfig)({
200
- projectRepoName: testGenConfig.options?.metadata.projectRepoName,
201
- testSessionId: testGenConfig.options?.metadata.testSessionId,
202
- generationId: testGenConfig.options?.metadata.generationId,
203
- });
204
- (0, session_1.setSessionDetails)({
205
- testCaseId: testGenConfig.testCase.id,
206
- sessionId: testGenConfig.options?.metadata.testSessionId,
207
- generationId: testGenConfig.options?.metadata.generationId,
208
- projectRepoName: testGenConfig.options?.metadata.projectRepoName,
209
- });
210
- let testGenFailed = false;
211
- let agentUsed;
212
- try {
213
- // download the build if it exists
214
- await (0, test_build_1.downloadBuild)(testGenConfig.build || {});
215
- agentUsed = await runAgent(testGenConfig, testGenToken);
216
- }
217
- catch (e) {
218
- span.recordException(e);
219
- Sentry.captureException(e);
220
- testGenFailed = true;
221
- new logger_1.CustomLogger().error(`Failed to generate test for the scenario. ${process.env.LOG_URL ? `[view log](${process.env.LOG_URL})` : ""}`, e?.message, e?.stack);
222
- }
223
- if (agentUsed &&
224
- agentUsed !== "code" &&
225
- agentUsed !== "plan" &&
226
- testGenConfig.testCase.name &&
227
- testGenConfig.options) {
228
- await new reporter_1.TestGenUpdatesReporter().reportGenAssets({
229
- projectRepoName: testGenConfig.options.metadata.projectRepoName,
230
- testName: testGenConfig.testCase.name,
231
- });
232
- }
233
- // TODO: move these reporters to a better lifecycle
234
- await (0, llm_1.flushAllTraces)();
235
- await (0, logger_1.waitForLogsToFlush)();
236
- await (0, session_1.endSession)();
237
- span.end();
238
- if (testGenFailed) {
239
- process.exit(1);
240
- }
241
- else {
242
- process.exit(0);
243
- }
244
- });
154
+ const program = new commander_1.Command();
155
+ program
156
+ .option("--token <token>", "Test generation token")
157
+ .option("--name <test-name>", "Name of the test case")
158
+ .option("--prompt <prompt>", "Prompt for the test case")
159
+ .option("--file <test-file>", "File path of the test case (inside tests dir)")
160
+ .option("--suites <suites>", "Comma separated list of describe blocks")
161
+ .parse(process.argv);
162
+ const options = program.opts();
163
+ (0, utils_2.validateCliOptions)(options);
164
+ const testGenConfig = options.token
165
+ ? (0, scenarios_1.loadTestConfigs)(options.token)
166
+ : (0, scenarios_1.buildTestConfigFromOptions)(options);
167
+ const testGenToken = options.token
168
+ ? options.token
169
+ : (0, scenarios_1.buildTokenFromOptions)(options);
170
+ (0, reporter_1.setReporterConfig)({
171
+ projectRepoName: testGenConfig.options?.metadata.projectRepoName,
172
+ testSessionId: testGenConfig.options?.metadata.testSessionId,
173
+ generationId: testGenConfig.options?.metadata.generationId,
245
174
  });
175
+ (0, session_1.setSessionDetails)({
176
+ testCaseId: testGenConfig.testCase.id,
177
+ sessionId: testGenConfig.options?.metadata.testSessionId,
178
+ generationId: testGenConfig.options?.metadata.generationId,
179
+ projectRepoName: testGenConfig.options?.metadata.projectRepoName,
180
+ });
181
+ let testGenFailed = false;
182
+ let agentUsed;
183
+ try {
184
+ // download the build if it exists
185
+ await (0, test_build_1.downloadBuild)(testGenConfig.build || {});
186
+ agentUsed = await runAgent(testGenConfig, testGenToken);
187
+ }
188
+ catch (e) {
189
+ testGenFailed = true;
190
+ new logger_1.CustomLogger().error(`Failed to generate test for the scenario. ${process.env.LOG_URL ? `[view log](${process.env.LOG_URL})` : ""}`, e?.message, e?.stack);
191
+ }
192
+ if (agentUsed &&
193
+ agentUsed !== "code" &&
194
+ agentUsed !== "plan" &&
195
+ testGenConfig.testCase.name &&
196
+ testGenConfig.options) {
197
+ await new reporter_1.TestGenUpdatesReporter().reportGenAssets({
198
+ projectRepoName: testGenConfig.options.metadata.projectRepoName,
199
+ testName: testGenConfig.testCase.name,
200
+ });
201
+ }
202
+ // TODO: move these reporters to a better lifecycle
203
+ await (0, llm_1.flushAllTraces)();
204
+ await (0, logger_1.waitForLogsToFlush)();
205
+ await (0, session_1.endSession)();
206
+ if (testGenFailed) {
207
+ process.exit(1);
208
+ }
209
+ else {
210
+ process.exit(0);
211
+ }
246
212
  })();
@@ -1,5 +1,3 @@
1
- export declare const sentryTrace: string | undefined;
2
- export declare const baggage: string | undefined;
3
1
  export interface CliOptions {
4
2
  token?: string;
5
3
  name?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bin/utils/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,oBAA2B,CAAC;AACpD,eAAO,MAAM,OAAO,oBAA6B,CAAC;AAElD,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAS5D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bin/utils/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAS5D"}
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateCliOptions = exports.baggage = exports.sentryTrace = void 0;
4
- exports.sentryTrace = process.env.SENTRY_TRACE;
5
- exports.baggage = process.env.SENTRY_BAGGAGE;
3
+ exports.validateCliOptions = void 0;
6
4
  function validateCliOptions(options) {
7
5
  const hasToken = !!options.token;
8
6
  const hasNameAndFile = !!options.name && !!options.file && !!options.prompt;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-build/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAWnD;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAa/D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-build/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAUnD;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAY/D"}
@@ -1,33 +1,9 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
6
  exports.downloadBuild = void 0;
30
- const Sentry = __importStar(require("@sentry/node"));
31
7
  const fs_extra_1 = __importDefault(require("fs-extra"));
32
8
  const logger_1 = require("../bin/logger");
33
9
  const exec_1 = require("../utils/exec");
@@ -48,7 +24,6 @@ async function downloadBuild(build) {
48
24
  logger.log(`Downloading build from ${build.url}`);
49
25
  await (0, exec_1.cmd)(`npm run download ${build.url}`.split(" "), {
50
26
  env: { ...Object(process.env) },
51
- span: Sentry.getActiveSpan(),
52
27
  });
53
28
  }
54
29
  }
@@ -1,6 +1,4 @@
1
- import * as Sentry from "@sentry/node";
2
1
  export declare function cmd(command: string[], options: {
3
2
  env?: Record<string, string>;
4
- span?: Sentry.Span;
5
3
  }): Promise<number>;
6
4
  //# sourceMappingURL=exec.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AAMvC,wBAAsB,GAAG,CACvB,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAA;CAAE,GAC5D,OAAO,CAAC,MAAM,CAAC,CA+CjB"}
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAGA,wBAAsB,GAAG,CACvB,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACxC,OAAO,CAAC,MAAM,CAAC,CAuCjB"}
@@ -1,77 +1,44 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
6
  exports.cmd = void 0;
30
- const Sentry = __importStar(require("@sentry/node"));
31
7
  const child_process_1 = require("child_process");
32
8
  const process_1 = __importDefault(require("process"));
33
- const utils_1 = require("../bin/utils");
34
9
  async function cmd(command, options) {
35
- return Sentry.continueTrace({ sentryTrace: utils_1.sentryTrace, baggage: utils_1.baggage }, async () => {
36
- return Sentry.startSpan({ name: "test-gen" }, async (span) => {
37
- let errorLogs = [];
38
- return new Promise((resolveFunc, rejectFunc) => {
39
- if (!command[0]) {
40
- rejectFunc(new Error("Command cannot be empty"));
41
- return;
42
- }
43
- let p = (0, child_process_1.spawn)(command[0], command.slice(1), {
44
- env: { ...process_1.default.env, ...options.env },
45
- });
46
- p.stdout.on("data", (x) => {
47
- const log = x.toString();
48
- if (log.includes("Error")) {
49
- errorLogs.push(log);
50
- }
51
- process_1.default.stdout.write(log);
52
- });
53
- p.stderr.on("data", (x) => {
54
- const log = x.toString();
55
- process_1.default.stderr.write(log);
56
- errorLogs.push(log);
57
- });
58
- p.on("error", async (err) => {
59
- span?.recordException(err);
60
- Sentry.captureException(err);
61
- rejectFunc(err);
62
- });
63
- p.on("exit", async (code) => {
64
- if (code !== 0) {
65
- const errorMessage = errorLogs.slice(-3).join("\n");
66
- span?.recordException(errorMessage);
67
- Sentry.captureException(new Error(errorMessage));
68
- rejectFunc(new Error(errorMessage));
69
- }
70
- else {
71
- resolveFunc(code ?? 1);
72
- }
73
- });
74
- });
10
+ let errorLogs = [];
11
+ return new Promise((resolveFunc, rejectFunc) => {
12
+ if (!command[0]) {
13
+ rejectFunc(new Error("Command cannot be empty"));
14
+ return;
15
+ }
16
+ let p = (0, child_process_1.spawn)(command[0], command.slice(1), {
17
+ env: { ...process_1.default.env, ...options.env },
18
+ });
19
+ p.stdout.on("data", (x) => {
20
+ const log = x.toString();
21
+ if (log.includes("Error")) {
22
+ errorLogs.push(log);
23
+ }
24
+ process_1.default.stdout.write(log);
25
+ });
26
+ p.stderr.on("data", (x) => {
27
+ const log = x.toString();
28
+ process_1.default.stderr.write(log);
29
+ errorLogs.push(log);
30
+ });
31
+ p.on("error", async (err) => {
32
+ rejectFunc(err);
33
+ });
34
+ p.on("exit", async (code) => {
35
+ if (code !== 0) {
36
+ const errorMessage = errorLogs.slice(-3).join("\n");
37
+ rejectFunc(new Error(errorMessage));
38
+ }
39
+ else {
40
+ resolveFunc(code ?? 1);
41
+ }
75
42
  });
76
43
  });
77
44
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.46.1",
3
+ "version": "0.46.3",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -47,7 +47,6 @@
47
47
  "dependencies": {
48
48
  "@actions/core": "^1.10.1",
49
49
  "@babel/parser": "^7.26.3",
50
- "@sentry/node": "^8.54.0",
51
50
  "@types/sanitize-html": "^2.11.0",
52
51
  "commander": "^12.1.0",
53
52
  "detect-port": "^1.6.1",
@@ -74,9 +73,9 @@
74
73
  "ts-morph": "^23.0.0",
75
74
  "tsx": "^4.16.2",
76
75
  "typescript": "^5.3.3",
76
+ "@empiricalrun/llm": "^0.9.35",
77
77
  "@empiricalrun/r2-uploader": "^0.3.8",
78
- "@empiricalrun/reporter": "^0.23.1",
79
- "@empiricalrun/llm": "^0.9.35"
78
+ "@empiricalrun/reporter": "^0.23.1"
80
79
  },
81
80
  "devDependencies": {
82
81
  "@playwright/test": "1.47.1",
@@ -92,7 +91,7 @@
92
91
  "js-levenshtein": "^1.1.6",
93
92
  "playwright": "1.47.1",
94
93
  "ts-patch": "^3.3.0",
95
- "@empiricalrun/shared-types": "0.0.4"
94
+ "@empiricalrun/shared-types": "0.0.5"
96
95
  },
97
96
  "scripts": {
98
97
  "dev": "tspc --build --watch",
@@ -8,5 +8,7 @@ export default defineConfig({
8
8
  testDir: "./dist/.",
9
9
  testMatch: "**/*.spec.js",
10
10
  // Setting large timeout as master agent takes time to run.
11
- timeout: 120_000,
11
+ timeout: 240_000,
12
+ fullyParallel: true,
13
+ workers: "50%",
12
14
  });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=initSentry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"initSentry.d.ts","sourceRoot":"","sources":["../src/initSentry.ts"],"names":[],"mappings":""}
@@ -1,37 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- const Sentry = __importStar(require("@sentry/node"));
27
- Sentry.init({
28
- enabled: process.env.NODE_ENV === "production",
29
- dsn: "https://87e61b11ede1431d7156bcd26da997cc@o4506822020235264.ingest.us.sentry.io/4508806031015936",
30
- tracesSampleRate: 1.0,
31
- serverName: "test-gen",
32
- debug: process.env.NODE_ENV === "development",
33
- integrations: [Sentry.consoleIntegration(), Sentry.httpIntegration()],
34
- clientReportFlushInterval: 2000,
35
- shutdownTimeout: 5000,
36
- enableTracing: true,
37
- });