@empiricalrun/test-gen 0.16.13 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @empiricalrun/test-gen
2
2
 
3
+ ## 0.17.1
4
+
5
+ ### Patch Changes
6
+
7
+ - ac0256e: feat: remove support for update flag in test gen
8
+
9
+ ## 0.17.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 914b207: fix: remove google sheet support in test gen
14
+
15
+ ### Patch Changes
16
+
17
+ - 74eefc4: fix: remove comments of browser agent
18
+
3
19
  ## 0.16.13
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -8,61 +8,29 @@ Our agents that generate Playwright tests. There are 2 agents
8
8
  ## Usage
9
9
 
10
10
  ```sh
11
- npx @empiricalrun/test-gen $args
11
+ npx @empiricalrun/test-gen TEST_GEN_TOKEN
12
12
  ```
13
13
 
14
- where `$args` can be one of the following
15
-
16
14
  ### Add new test
17
15
 
18
16
  ```sh
19
- npx @empiricalrun/test-gen base64string
17
+ npx @empiricalrun/test-gen TEST_GEN_TOKEN
20
18
  ```
21
19
 
22
20
  - This will trigger browsing agent to write a new test for this scenario
23
- - See [Base64 payload](#base64-payload)
24
-
25
- ```sh
26
- npx @empiricalrun/test-gen delete.spec.ts
27
- ```
28
-
29
- - This will trigger browsing agent to write a new test in this file
30
- - **Note** that the file must have `createTest(...)` where the scenario is specified
31
-
32
- #### Bulk add
33
-
34
- ```sh
35
- npx @empiricalrun/test-gen scenarios.yml
36
-
37
- # optional: filter for one scenario
38
- npx @empiricalrun/test-gen scenarios.yml $scenario_name
39
- ```
40
-
41
- Using yml or google spreadsheet. **Note** that this only runs the code editing agent
42
-
43
- ```yaml ./tests/scenarios.yaml
44
- dir: ./tests/ # [optional] directory where you want to create tests. Default - ./tests
45
- scenarios: # list of scenarios
46
- - name: user should be able to login successfully # name of the test case to be generated
47
- steps: # steps for the test case
48
- - cLick on "Login" button
49
- - click on input "username"
50
- - fill username as "foo@bar.com"
51
- - fill password as "bar@123"
52
- - click on "Login Button"
53
- assert: "Login successful" text should be visible # assertion
54
- ```
21
+ - See [Test gen token: Base64 payload](#test-gen-token-base64-payload)
55
22
 
56
23
  ### Update existing test
57
24
 
58
25
  ```sh
59
- npx @empiricalrun/test-gen base64string -u
26
+ npx @empiricalrun/test-gen TEST_GEN_TOKEN
60
27
  ```
61
28
 
29
+ - If the test case is already present in the file, the test gen agent will update the existing test as per the steps provided in the payload
62
30
  - This will trigger code editing agent to write a new test for this scenario
63
- - See [Base64 payload](#base64-payload)
31
+ - See [Test gen token: Base64 payload](#test-gen-token-base64-payload)
64
32
 
65
- ### Base64 payload
33
+ ### Test gen token: Base64 payload
66
34
 
67
35
  Convert this object into a base64 payload - for new and update test.
68
36
 
@@ -72,10 +40,10 @@ const scenario = {
72
40
  steps: [
73
41
  "fill in the username as foobar@gmail.com",
74
42
  "fill in the password as bazbaz",
75
- "click on the login button"
43
+ "click on the login button",
76
44
  ],
77
45
  assert: "",
78
- group: "home"
46
+ group: "home",
79
47
  };
80
- btoa(JSON.stringify(scenario))
48
+ btoa(JSON.stringify(scenario));
81
49
  ```
@@ -2,7 +2,7 @@ import { Page } from "playwright";
2
2
  import { PlaywrightTestConfig } from "playwright/test";
3
3
  import { TestGenConfig } from "../../types";
4
4
  export declare function isRegExp(obj: any): obj is RegExp;
5
- export declare function prepareBrowsingAgentTask(steps: string[], assert?: string): string;
5
+ export declare function prepareBrowsingAgentTask(steps: string[]): string;
6
6
  export declare function prepareFileForBrowsingAgent(genConfig: TestGenConfig): Promise<void>;
7
7
  export declare function injectPwLocatorGenerator(page: Page): Promise<void>;
8
8
  export declare function canRunBrowsingAgent(filePath: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AASvD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,MAAM,CAKhD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,UAIxE;AAED,wBAAsB,2BAA2B,CAAC,SAAS,EAAE,aAAa,iBAqCzE;AAiBD,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,iBASxD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,QA4BnD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAM1E;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,oBAAoB,GACrC,OAAO,CAAC,MAAM,CAAC,CAkDjB;AAED,wBAAsB,sBAAsB,CAAC,EAC3C,YAAiB,EACjB,IAAS,EACT,eAAoB,EACpB,gBAAqB,GACtB,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,8EASA"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AASvD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,MAAM,CAKhD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,UAIvD;AAED,wBAAsB,2BAA2B,CAAC,SAAS,EAAE,aAAa,iBAqCzE;AAiBD,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,iBASxD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,QA4BnD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAM1E;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,oBAAoB,GACrC,OAAO,CAAC,MAAM,CAAC,CAkDjB;AAED,wBAAsB,sBAAsB,CAAC,EAC3C,YAAiB,EACjB,IAAS,EACT,eAAoB,EACpB,gBAAqB,GACtB,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,8EASA"}
@@ -16,15 +16,15 @@ function isRegExp(obj) {
16
16
  Object.prototype.toString.call(obj) === "[object RegExp]");
17
17
  }
18
18
  exports.isRegExp = isRegExp;
19
- function prepareBrowsingAgentTask(steps, assert) {
19
+ function prepareBrowsingAgentTask(steps) {
20
20
  const sanitizedSteps = steps.map((step) => step.replace(/`/g, "\\`"));
21
- const task = `${sanitizedSteps.join("\n")}\n${assert || ""}`;
21
+ const task = `${sanitizedSteps.join("\n")}\n`;
22
22
  return task;
23
23
  }
24
24
  exports.prepareBrowsingAgentTask = prepareBrowsingAgentTask;
25
25
  async function prepareFileForBrowsingAgent(genConfig) {
26
- const { specPath, scenarios } = genConfig;
27
- const { name, steps, assert } = scenarios[0];
26
+ const { specPath, testCase } = genConfig;
27
+ const { name, steps } = testCase;
28
28
  const logger = new logger_1.CustomLogger();
29
29
  if (!fs_extra_1.default.existsSync(specPath)) {
30
30
  await fs_extra_1.default.createFile(specPath);
@@ -33,7 +33,7 @@ async function prepareFileForBrowsingAgent(genConfig) {
33
33
  if (name && steps && steps.length) {
34
34
  const existingContents = await fs_extra_1.default.readFile(specPath, "utf-8");
35
35
  const testBlock = (0, web_1.getTypescriptTestBlock)(name, existingContents);
36
- const mergedSteps = prepareBrowsingAgentTask(steps, assert);
36
+ const mergedSteps = prepareBrowsingAgentTask(steps);
37
37
  let newContents = existingContents;
38
38
  if (testBlock) {
39
39
  logger.log("appending to existing test block");
@@ -1,3 +1,3 @@
1
- import { Scenario, TestGenConfigOptions } from "../../types";
2
- export declare function generateTest(scenarios: Scenario[], file: string, isUpdate: boolean, options: TestGenConfigOptions): Promise<Scenario[]>;
1
+ import { TestCase, TestGenConfigOptions } from "../../types";
2
+ export declare function generateTest(testCase: TestCase, file: string, options: TestGenConfigOptions): Promise<TestCase[]>;
3
3
  //# sourceMappingURL=run.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/run.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAE7D,wBAAsB,YAAY,CAChC,SAAS,EAAE,QAAQ,EAAE,EACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,QAAQ,EAAE,CAAC,CAwJrB"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/run.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAE7D,wBAAsB,YAAY,CAChC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,QAAQ,EAAE,CAAC,CA8IrB"}
@@ -11,7 +11,7 @@ const context_1 = require("../../bin/utils/context");
11
11
  const web_1 = require("../../bin/utils/platform/web");
12
12
  const constants_1 = require("../../constants");
13
13
  const session_1 = require("../../session");
14
- async function generateTest(scenarios, file, isUpdate, options) {
14
+ async function generateTest(testCase, file, options) {
15
15
  const logger = new logger_1.CustomLogger();
16
16
  if (!fs_extra_1.default.existsSync(file)) {
17
17
  logger.log(`Creating a new spec file: ${file}`);
@@ -19,42 +19,96 @@ async function generateTest(scenarios, file, isUpdate, options) {
19
19
  }
20
20
  const context = await (0, context_1.contextForGeneration)(file);
21
21
  const { codePrompt, pomPrompt, testFileContent } = context;
22
- const generatedScenarios = [];
23
- for (const i in scenarios) {
24
- logger.logEmptyLine();
25
- const trace = new llm_1.LLMTracing({
26
- name: "generate-test",
27
- sessionDetails: (0, session_1.getSessionDetails)(),
28
- tags: [options.metadata.projectName, options.metadata.environment].filter((s) => !!s),
29
- });
30
- trace.event({
31
- name: "collate-files-as-text",
32
- output: {
33
- codePrompt,
34
- pomPrompt,
35
- testFileContent,
36
- },
37
- });
38
- const scenario = scenarios[i];
39
- trace.update({ input: { scenario } });
40
- logger.log("Generating test for scenario:", scenario?.name);
41
- if (!isUpdate && testFileContent.includes(`test("${scenario?.name}"`)) {
42
- logger.success("Test already exists for this scenario");
43
- trace.event({ name: "test-already-exists" });
44
- continue;
22
+ const generatedTestCases = [];
23
+ logger.logEmptyLine();
24
+ const trace = new llm_1.LLMTracing({
25
+ name: "generate-test",
26
+ sessionDetails: (0, session_1.getSessionDetails)(),
27
+ tags: [options.metadata.projectName, options.metadata.environment].filter((s) => !!s),
28
+ });
29
+ trace.event({
30
+ name: "collate-files-as-text",
31
+ output: {
32
+ codePrompt,
33
+ pomPrompt,
34
+ testFileContent,
35
+ },
36
+ });
37
+ trace.update({ input: { testCase } });
38
+ const isUpdate = testFileContent.includes(`test("${testCase?.name}"`);
39
+ const promptSpan = trace.startSpan(isUpdate ? "update-scenario-prompt" : "add-scenario-prompt");
40
+ const promptName = isUpdate ? "update-scenario" : "add-scenario";
41
+ const instruction = await (0, llm_1.getPrompt)(promptName, {
42
+ testFiles: codePrompt,
43
+ pageFiles: pomPrompt,
44
+ scenarioName: testCase.name,
45
+ scenarioSteps: testCase.steps.join("\n"),
46
+ scenarioFile: file,
47
+ });
48
+ promptSpan.end({ output: { instruction } });
49
+ const firstShotMessage = await (0, llm_1.getLLMResult)({
50
+ messages: instruction,
51
+ trace,
52
+ model: options.model || constants_1.DEFAULT_MODEL,
53
+ provider: options.modelProvider || constants_1.DEFAULT_MODEL_PROVIDER,
54
+ providerApiKey: constants_1.MODEL_API_KEYS[options.modelProvider || constants_1.DEFAULT_MODEL_PROVIDER],
55
+ modelParameters: {
56
+ ...constants_1.DEFAULT_MODEL_PARAMETERS,
57
+ ...options.modelParameters,
58
+ },
59
+ });
60
+ let response = firstShotMessage?.content || "";
61
+ logger.success("Test generated successfully!");
62
+ const readWriteFileSpan = trace.startSpan("write-to-file");
63
+ let contents = fs_extra_1.default.readFileSync(file, "utf-8");
64
+ const [prependContent, strippedContent] = await (0, web_1.stripAndPrependImports)(response);
65
+ let updatedContent = prependContent + contents + `\n\n${strippedContent}`;
66
+ if (isUpdate) {
67
+ const testBlock = (0, web_1.getTypescriptTestBlock)(testCase?.name, contents);
68
+ contents = contents.replace(testBlock, `\n\n${strippedContent}`);
69
+ updatedContent = prependContent + contents;
70
+ }
71
+ await fs_extra_1.default.writeFile(file, updatedContent, "utf-8");
72
+ readWriteFileSpan.end({ output: { updatedContent } });
73
+ logger.log("Linting generated code...");
74
+ trace.event({ name: "lint-file" });
75
+ await (0, web_1.lintErrors)(file);
76
+ const validateTypesSpan = trace.startSpan("detect-type-errors-in-file");
77
+ logger.log("Validating types...");
78
+ let errors = (0, web_1.validateTypescript)(file);
79
+ validateTypesSpan.end({ output: { errors } });
80
+ if (!errors.length) {
81
+ logger.success("Found no type issues!");
82
+ }
83
+ const maxIteration = 2;
84
+ let counter = 0;
85
+ while (errors.length > 0) {
86
+ const fileContent = fs_extra_1.default.readFileSync(file, "utf-8");
87
+ counter += 1;
88
+ if (counter > maxIteration) {
89
+ trace.event({ name: "code-fix-iteration-max-out" });
90
+ logger.error([
91
+ `Unable to fix typescript errors. Please review ${file} manually and fix the typescript errors.`,
92
+ `Run the test-gen command again, once errors are fixed.`,
93
+ `Trace: ${trace.url}`,
94
+ ].join("\n"));
95
+ break;
45
96
  }
46
- const promptSpan = trace.startSpan(isUpdate ? "update-scenario-prompt" : "add-scenario-prompt");
47
- const promptName = isUpdate ? "update-scenario" : "add-scenario";
48
- const instruction = await (0, llm_1.getPrompt)(promptName, {
49
- testFiles: codePrompt,
50
- pageFiles: pomPrompt,
51
- scenarioName: scenario.name,
52
- scenarioSteps: scenario.steps.join("\n"),
53
- assert: scenario.assert,
97
+ trace.event({ name: "Found errors fixing" });
98
+ logger.warn("Found few errors while validating types:");
99
+ errors.forEach((e) => logger.warn(e));
100
+ logger.log("Trying to fix above errors...");
101
+ const promptSpan = trace.startSpan("fix-type-errors-prompt");
102
+ const instruction = await (0, llm_1.getPrompt)("fix-file-errors-ts", {
103
+ testFiles: codePrompt || "",
104
+ pageFiles: pomPrompt || "",
54
105
  scenarioFile: file,
106
+ errors: errors,
107
+ fileContent: fileContent,
108
+ scenaioName: testCase.name,
55
109
  });
56
110
  promptSpan.end({ output: { instruction } });
57
- const firstShotMessage = await (0, llm_1.getLLMResult)({
111
+ const message = await (0, llm_1.getLLMResult)({
58
112
  messages: instruction,
59
113
  trace,
60
114
  model: options.model || constants_1.DEFAULT_MODEL,
@@ -65,88 +119,25 @@ async function generateTest(scenarios, file, isUpdate, options) {
65
119
  ...options.modelParameters,
66
120
  },
67
121
  });
68
- let response = firstShotMessage?.content || "";
69
- logger.success("Test generated successfully!");
122
+ response = message?.content || "";
70
123
  const readWriteFileSpan = trace.startSpan("write-to-file");
71
- let contents = fs_extra_1.default.readFileSync(file, "utf-8");
72
- const [prependContent, strippedContent] = await (0, web_1.stripAndPrependImports)(response);
73
- let updatedContent = prependContent + contents + `\n\n${strippedContent}`;
74
- if (isUpdate) {
75
- const testBlock = (0, web_1.getTypescriptTestBlock)(scenario?.name, contents);
76
- contents = contents.replace(testBlock, `\n\n${strippedContent}`);
77
- updatedContent = prependContent + contents;
78
- }
79
- await fs_extra_1.default.writeFile(file, updatedContent, "utf-8");
80
- readWriteFileSpan.end({ output: { updatedContent } });
81
- logger.log("Linting generated code...");
124
+ await fs_extra_1.default.writeFile(file, response, "utf-8");
125
+ readWriteFileSpan.end({ output: { response } });
82
126
  trace.event({ name: "lint-file" });
83
127
  await (0, web_1.lintErrors)(file);
84
128
  const validateTypesSpan = trace.startSpan("detect-type-errors-in-file");
85
- logger.log("Validating types...");
86
- let errors = (0, web_1.validateTypescript)(file);
129
+ errors = (0, web_1.validateTypescript)(file);
87
130
  validateTypesSpan.end({ output: { errors } });
88
131
  if (!errors.length) {
89
132
  logger.success("Found no type issues!");
90
133
  }
91
- const maxIteration = 2;
92
- let counter = 0;
93
- while (errors.length > 0) {
94
- const fileContent = fs_extra_1.default.readFileSync(file, "utf-8");
95
- counter += 1;
96
- if (counter > maxIteration) {
97
- trace.event({ name: "code-fix-iteration-max-out" });
98
- logger.error([
99
- `Unable to fix typescript errors. Please review ${file} manually and fix the typescript errors.`,
100
- `Run the test-gen command again, once errors are fixed.`,
101
- `Trace: ${trace.url}`,
102
- ].join("\n"));
103
- break;
104
- }
105
- trace.event({ name: "Found errors fixing" });
106
- logger.warn("Found few errors while validating types:");
107
- errors.forEach((e) => logger.warn(e));
108
- logger.log("Trying to fix above errors...");
109
- const promptSpan = trace.startSpan("fix-type-errors-prompt");
110
- const instruction = await (0, llm_1.getPrompt)("fix-file-errors-ts", {
111
- testFiles: codePrompt || "",
112
- pageFiles: pomPrompt || "",
113
- scenarioFile: file,
114
- errors: errors,
115
- fileContent: fileContent,
116
- scenaioName: scenario.name,
117
- });
118
- promptSpan.end({ output: { instruction } });
119
- const message = await (0, llm_1.getLLMResult)({
120
- messages: instruction,
121
- trace,
122
- model: options.model || constants_1.DEFAULT_MODEL,
123
- provider: options.modelProvider || constants_1.DEFAULT_MODEL_PROVIDER,
124
- providerApiKey: constants_1.MODEL_API_KEYS[options.modelProvider || constants_1.DEFAULT_MODEL_PROVIDER],
125
- modelParameters: {
126
- ...constants_1.DEFAULT_MODEL_PARAMETERS,
127
- ...options.modelParameters,
128
- },
129
- });
130
- response = message?.content || "";
131
- const readWriteFileSpan = trace.startSpan("write-to-file");
132
- await fs_extra_1.default.writeFile(file, response, "utf-8");
133
- readWriteFileSpan.end({ output: { response } });
134
- trace.event({ name: "lint-file" });
135
- await (0, web_1.lintErrors)(file);
136
- const validateTypesSpan = trace.startSpan("detect-type-errors-in-file");
137
- errors = (0, web_1.validateTypescript)(file);
138
- validateTypesSpan.end({ output: { errors } });
139
- if (!errors.length) {
140
- logger.success("Found no type issues!");
141
- }
142
- }
143
- trace.event({ name: "format-file" });
144
- await (0, web_1.formatCode)(file);
145
- logger.success("File formatted successfully!");
146
- logger.log(`Trace: ${trace.url}`);
147
- generatedScenarios.push(scenario);
148
- trace.update({ input: { scenario }, output: { response } });
149
134
  }
150
- return generatedScenarios;
135
+ trace.event({ name: "format-file" });
136
+ await (0, web_1.formatCode)(file);
137
+ logger.success("File formatted successfully!");
138
+ logger.log(`Trace: ${trace.url}`);
139
+ generatedTestCases.push(testCase);
140
+ trace.update({ input: { testCase }, output: { response } });
141
+ return generatedTestCases;
151
142
  }
152
143
  exports.generateTest = generateTest;
package/dist/bin/index.js CHANGED
@@ -19,40 +19,33 @@ dotenv_1.default.config({
19
19
  process.on("exit", async () => await (0, llm_1.flushAllTraces)());
20
20
  process.on("SIGINT", async () => await (0, llm_1.flushAllTraces)());
21
21
  process.on("SIGTERM", async () => await (0, llm_1.flushAllTraces)());
22
- async function runAgent(sourceFile, isUpdate, testGenConfigs) {
22
+ async function runAgent(sourceFile, testGenConfig) {
23
23
  const logger = new logger_1.CustomLogger();
24
- const generatedTestScenarios = [];
25
- const compatibleWithBrowsing = !sourceFile.startsWith("https://docs.google.com/spreadsheets");
26
- for (const testGenConfig of testGenConfigs) {
27
- const { specPath, scenarios } = testGenConfig;
28
- if (compatibleWithBrowsing && testGenConfig.options?.agent !== "code") {
29
- // this assumes we have only one scenario in test config
30
- logger.success("Generating test using browsing agent");
31
- await (0, utils_1.prepareFileForBrowsingAgent)(testGenConfig);
32
- await (0, run_1.generateTestsUsingBrowsingAgent)(specPath);
33
- await (0, reporter_1.reportTestGenVideos)({
34
- projectRepoName: testGenConfig.options.metadata.projectRepoName,
35
- });
36
- generatedTestScenarios.push(...testGenConfig.scenarios);
37
- }
38
- else {
39
- logger.success("Generating test using coding agent");
40
- const gen = await (0, run_2.generateTest)(scenarios, specPath, isUpdate, testGenConfig.options);
41
- generatedTestScenarios.push(...gen);
42
- }
24
+ const { specPath, testCase } = testGenConfig;
25
+ if (testGenConfig.options?.agent !== "code") {
26
+ // this assumes we have only one scenario in test config
27
+ logger.success("Generating test using browsing agent");
28
+ await (0, utils_1.prepareFileForBrowsingAgent)(testGenConfig);
29
+ await (0, run_1.generateTestsUsingBrowsingAgent)(specPath);
30
+ await (0, reporter_1.reportTestGenVideos)({
31
+ projectRepoName: testGenConfig.options.metadata.projectRepoName,
32
+ });
33
+ }
34
+ else {
35
+ logger.success("Generating test using coding agent");
36
+ await (0, run_2.generateTest)(testCase, specPath, testGenConfig.options);
43
37
  }
44
- return generatedTestScenarios;
45
38
  }
46
39
  (async function main() {
47
40
  const logger = new logger_1.CustomLogger({ useReporter: false });
48
41
  if (process.argv.length < 3) {
49
- logger.error("Please provide path to scenarios using command:", "npx @empiricalrun/test-gen <SCENARIOS_FILE_PATH> -u");
42
+ logger.error("Please provide path to scenarios using command:", "npx @empiricalrun/test-gen <TEST_GEN_TOKEN>");
50
43
  process.exit(1);
51
44
  }
52
- const { sourceFile, testGenConfigs, isUpdate } = await (0, utils_2.parseCliArgs)();
53
- (0, reporter_1.setReporterConfig)(testGenConfigs[0]?.options?.metadata);
54
- const generated = await runAgent(sourceFile, isUpdate, testGenConfigs);
45
+ const { sourceFile, testGenConfig } = await (0, utils_2.parseCliArgs)();
46
+ (0, reporter_1.setReporterConfig)(testGenConfig?.options?.metadata);
47
+ await runAgent(sourceFile, testGenConfig);
55
48
  // TODO: move these reporters to a better lifecycle
56
- await (0, ci_1.reportOnCI)(generated);
49
+ await (0, ci_1.reportOnCI)(testGenConfig.testCase);
57
50
  process.exit(0);
58
51
  })();
@@ -1,8 +1,7 @@
1
1
  import { TestGenConfig } from "../../types";
2
2
  export declare function parseCliArgs(scenarioOrScenariosPath?: string): Promise<{
3
3
  sourceFile: string;
4
- testGenConfigs: TestGenConfig[];
5
- isUpdate: boolean;
4
+ testGenConfig: TestGenConfig;
6
5
  }>;
7
6
  export declare function getTestConfigCliArg(): string;
8
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bin/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,wBAAsB,YAAY,CAChC,uBAAuB,GAAE,MAA8B;;;;GAWxD;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bin/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,wBAAsB,YAAY,CAChC,uBAAuB,GAAE,MAA8B;;;GASxD;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
@@ -3,12 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTestConfigCliArg = exports.parseCliArgs = void 0;
4
4
  const scenarios_1 = require("./scenarios");
5
5
  async function parseCliArgs(scenarioOrScenariosPath = getTestConfigCliArg()) {
6
- const isUpdate = process.argv.includes("-u");
7
- const testGenConfigs = await (0, scenarios_1.loadTestConfigs)(scenarioOrScenariosPath);
6
+ const testGenConfig = await (0, scenarios_1.loadTestConfigs)(scenarioOrScenariosPath);
8
7
  return {
9
8
  sourceFile: scenarioOrScenariosPath,
10
- testGenConfigs,
11
- isUpdate,
9
+ testGenConfig,
12
10
  };
13
11
  }
14
12
  exports.parseCliArgs = parseCliArgs;
@@ -1,4 +1,4 @@
1
1
  import { TestGenConfig } from "../../../types";
2
- declare function loadTestConfigs(scenariosPath: string): Promise<TestGenConfig[]>;
2
+ declare function loadTestConfigs(scenariosPath: string): Promise<TestGenConfig>;
3
3
  export { loadTestConfigs };
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/bin/utils/scenarios/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AAkF/E,iBAAe,eAAe,CAC5B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,aAAa,EAAE,CAAC,CAiC1B;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/bin/utils/scenarios/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AAUrE,iBAAe,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAY5E;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -1,112 +1,17 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.loadTestConfigs = void 0;
7
- const google_auth_library_1 = require("google-auth-library");
8
- const slugify_1 = __importDefault(require("slugify"));
9
- function isValidJSON(str) {
10
- try {
11
- JSON.parse(str);
12
- return true;
13
- }
14
- catch (e) {
15
- return false;
16
- }
17
- }
18
- /**
19
- * Method to update / add scenarios to the repo.
20
- * @param path
21
- * @returns updated paths of scenarios
22
- */
23
- async function loadScenariosFromGsheet(path) {
24
- const { GoogleSpreadsheet } = await import("google-spreadsheet");
25
- const url = new URL(path);
26
- const docId = url.pathname.split("/")[3];
27
- const searchParams = new URLSearchParams(url.hash.split("#")[1]);
28
- const sheetId = Number(searchParams.get("gid")) || 0;
29
- // TODO: use oauth 2
30
- const serviceAccountAuth = new google_auth_library_1.JWT({
31
- email: process.env.GOOGLE_SERVICE_EMAIL,
32
- key: Buffer.from(process.env.GOOGLE_SERVICE_EMAIL_PRIVATE_KEY, "base64").toString(),
33
- scopes: ["https://www.googleapis.com/auth/spreadsheets"],
34
- });
35
- const doc = new GoogleSpreadsheet(docId, serviceAccountAuth);
36
- await doc.loadInfo();
37
- const sheet = doc.sheetsById[sheetId];
38
- const rows = await sheet.getRows();
39
- const map = new Map();
40
- rows.forEach((r) => {
41
- // TODO: fix for case insensitive
42
- const category = r.get("Category");
43
- const name = r.get("Scenario");
44
- const steps = r
45
- .get("Steps")
46
- .split("\n")
47
- .map((s) => s.trim())
48
- .filter((s) => !!s.length);
49
- const assert = r.get("Assert");
50
- const specPath = category
51
- ? `./tests/${category}.spec.ts`
52
- : `./tests/${(0, slugify_1.default)(name)}.spec.ts`;
53
- const scenario = {
54
- steps,
55
- name,
56
- assert,
57
- };
58
- if (!map.get(specPath)) {
59
- map.set(specPath, [scenario]);
60
- }
61
- else {
62
- const scenarios = map.get(specPath);
63
- scenarios.push(scenario);
64
- map.set(specPath, scenarios);
65
- }
66
- });
67
- const results = [];
68
- for (const [specPath, scenarios] of map.entries()) {
69
- results.push({
70
- specPath,
71
- scenarios,
72
- });
73
- }
74
- return results;
75
- }
76
4
  async function loadTestConfigs(scenariosPath) {
77
- // google sheets generation flow
78
- // TODO: remove this whenever we are comfortable demoing using dashboard
79
- if (scenariosPath.startsWith("https://docs.google.com/spreadsheets")) {
80
- return await loadScenariosFromGsheet(scenariosPath);
81
- // dev testing flow
82
- }
83
- else if (scenariosPath.endsWith(".ts")) {
84
- return [
85
- {
86
- specPath: scenariosPath,
87
- scenarios: [],
88
- },
89
- ];
90
- // api flow
91
- }
92
- else if (isValidJSON(atob(scenariosPath))) {
93
- const str = atob(scenariosPath);
94
- const config = JSON.parse(str);
95
- const specPath = `./tests/${config.group || "index"}.spec.ts`;
96
- return [
97
- {
98
- specPath,
99
- scenarios: [
100
- {
101
- name: config.name,
102
- steps: config.steps.filter((s) => !!s),
103
- assert: config.assert,
104
- },
105
- ],
106
- options: config.options,
107
- },
108
- ];
109
- }
110
- throw Error("Invalid path for test scenarios");
5
+ const str = atob(scenariosPath);
6
+ const config = JSON.parse(str);
7
+ const specPath = `./tests/${config.group || "index"}.spec.ts`;
8
+ return {
9
+ specPath,
10
+ testCase: {
11
+ name: config.name,
12
+ steps: config.steps.filter((s) => !!s),
13
+ },
14
+ options: config.options,
15
+ };
111
16
  }
112
17
  exports.loadTestConfigs = loadTestConfigs;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAOA,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,IAAI,CAAa;gBACb,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;IAGtC,WAAW,CAAC,QAAQ,EAAE,MAAM;IAGtB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;CAmC1C;AAED,wBAAsB,gBAAgB,kBAAK"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAMA,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,IAAI,CAAa;gBACb,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;IAGtC,WAAW,CAAC,QAAQ,EAAE,MAAM;IAGtB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;CAkC1C;AAED,wBAAsB,gBAAgB,kBAAK"}
@@ -8,7 +8,6 @@ const express_1 = __importDefault(require("express"));
8
8
  const fs_1 = __importDefault(require("fs"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const web_1 = require("../bin/utils/platform/web");
11
- const string_1 = require("../utils/string");
12
11
  class FileService {
13
12
  filePath = "";
14
13
  port = 0;
@@ -21,17 +20,16 @@ class FileService {
21
20
  async startFileService() {
22
21
  const app = (0, express_1.default)();
23
22
  app.use(express_1.default.json());
24
- app.post("/test", (req, res) => {
25
- const { generatedCode, task } = req.body;
23
+ app.post("/test", async (req, res) => {
24
+ const { generatedCode } = req.body;
26
25
  try {
27
26
  const testFilePath = path_1.default.resolve(process.cwd(), this.filePath);
28
27
  if (testFilePath) {
29
28
  const testFile = fs_1.default.readFileSync(testFilePath, "utf-8");
30
- const jsComments = (0, string_1.convertTextToJsComments)(task);
31
- const updatedTestFile = testFile.replace(/await createTest\([\s\S]*?\);\n/, jsComments + "\n" + generatedCode);
29
+ const updatedTestFile = testFile.replace(/await createTest\([\s\S]*?\);\n/, "\n" + generatedCode);
32
30
  const importStatement = `import { test, expect } from "@playwright/test";`;
33
31
  fs_1.default.writeFileSync(testFilePath, importStatement + "\n" + updatedTestFile, "utf-8");
34
- (0, web_1.lintErrors)(testFilePath);
32
+ await (0, web_1.lintErrors)(testFilePath);
35
33
  return res.send({ success: true });
36
34
  }
37
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAWlC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,iBAkBnE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAWlC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,iBAiBnE"}
package/dist/index.js CHANGED
@@ -15,8 +15,7 @@ process.on("SIGTERM", async () => await (0, llm_1.flushAllTraces)());
15
15
  async function createTest(task, page, test) {
16
16
  const port = process.env.APP_PORT || 3030;
17
17
  const testConfigArg = process.env.TEST_GEN_TOKEN;
18
- const { testGenConfigs } = await (0, utils_1.parseCliArgs)(testConfigArg);
19
- const [testGenConfig] = testGenConfigs;
18
+ const { testGenConfig } = await (0, utils_1.parseCliArgs)(testConfigArg);
20
19
  (0, reporter_1.setReporterConfig)(testGenConfig.options?.metadata);
21
20
  const fileService = new client_1.default(Number(port));
22
21
  test.setTimeout(900000);
@@ -1,3 +1,3 @@
1
- import { Scenario } from "../types";
2
- export declare function reportOnCI(scenarios: Scenario[]): Promise<Scenario[]>;
1
+ import { TestCase } from "../types";
2
+ export declare function reportOnCI(testCase: TestCase): Promise<TestCase>;
3
3
  //# sourceMappingURL=ci.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ci.d.ts","sourceRoot":"","sources":["../../src/reporter/ci.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,wBAAsB,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,uBAYrD"}
1
+ {"version":3,"file":"ci.d.ts","sourceRoot":"","sources":["../../src/reporter/ci.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,wBAAsB,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAOtE"}
@@ -25,17 +25,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.reportOnCI = void 0;
27
27
  const core = __importStar(require("@actions/core"));
28
- async function reportOnCI(scenarios) {
28
+ async function reportOnCI(testCase) {
29
29
  if ("true") {
30
- const testNames = scenarios.map((s) => s.name).join(" ");
31
- const scenariosOutput = scenarios
32
- .map((s) => {
33
- return `**Scenario:** ${s.name} \n\n**Steps:**\n - ${s.steps.join("\n - ")}`;
34
- })
35
- .join("\n ----- \n");
30
+ const scenariosOutput = `**Scenario:** ${testCase.name} \n\n**Steps:**\n - ${testCase.steps.join("\n - ")}`;
36
31
  core.setOutput("summary", scenariosOutput);
37
- core.setOutput("test_names", testNames);
32
+ core.setOutput("test_names", testCase.name);
38
33
  }
39
- return scenarios;
34
+ return testCase;
40
35
  }
41
36
  exports.reportOnCI = reportOnCI;
@@ -20,13 +20,12 @@ export type TestGenConfigOptions = {
20
20
  };
21
21
  export type TestGenConfig = {
22
22
  specPath: string;
23
- scenarios: Scenario[];
23
+ testCase: TestCase;
24
24
  options?: TestGenConfigOptions;
25
25
  };
26
- export type Scenario = {
26
+ export type TestCase = {
27
27
  name: string;
28
28
  steps: string[];
29
- assert: string;
30
29
  };
31
30
  export type PlaywrightActionGenerator = (page: Page) => Action;
32
31
  export type ActionSchema = OpenAI.Chat.Completions.ChatCompletionTool;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,QAAQ,CAAC;IAChB,aAAa,EAAE,WAAW,CAAC;IAC3B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,EAAE;QACR,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,aAAa,GAAG,YAAY,CAAC;KAC3C,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;AAE/D,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC;AAEtE,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC5E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;CAC/E,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,QAAQ,CAAC;IAChB,aAAa,EAAE,WAAW,CAAC;IAC3B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,EAAE;QACR,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,aAAa,GAAG,YAAY,CAAC;KAC3C,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;AAE/D,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC;AAEtE,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC5E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;CAC/E,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.16.13",
3
+ "version": "0.17.1",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"