@empiricalrun/test-gen 0.22.9 → 0.22.11

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,17 @@
1
1
  # @empiricalrun/test-gen
2
2
 
3
+ ## 0.22.11
4
+
5
+ ### Patch Changes
6
+
7
+ - 6771494: fix: handle dollar sign in generated code
8
+
9
+ ## 0.22.10
10
+
11
+ ### Patch Changes
12
+
13
+ - 5c43cd8: feat: support master agent to edit tests inside a describe block
14
+
3
15
  ## 0.22.9
4
16
 
5
17
  ### Patch Changes
@@ -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;AAUvD,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,iBAuCzE;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,EACrB,UAAyC,GAC1C,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,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;AAUvD,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,iBA+CzE;AAwCD,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,EACrB,UAAyC,GAC1C,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,8EASA"}
@@ -33,14 +33,14 @@ async function prepareFileForBrowsingAgent(genConfig) {
33
33
  }
34
34
  if (name && steps && steps.length) {
35
35
  const existingContents = await fs_extra_1.default.readFile(specPath, "utf-8");
36
- const testBlock = (0, web_1.getTypescriptTestBlock)(name, existingContents);
36
+ const { testBlock, parentDescribe } = (0, web_1.getTypescriptTestBlock)(name, existingContents);
37
37
  const mergedSteps = prepareBrowsingAgentTask(steps);
38
38
  let newContents = existingContents;
39
39
  if (testBlock) {
40
40
  logger.log("appending to existing test block");
41
41
  // test scenario is already present
42
- const updateTestBlock = (0, web_1.appendToTestBlock)(testBlock, createTestGenBlock(mergedSteps)).replace("test(", "test.only("); // mark the test as test.only
43
- newContents = existingContents.replace(testBlock, updateTestBlock);
42
+ const updatedTestBlock = (0, web_1.appendToTestBlock)(testBlock, createTestGenBlock(mergedSteps));
43
+ newContents = newContentsWithTestOnly(existingContents, testBlock, updatedTestBlock, parentDescribe);
44
44
  }
45
45
  else {
46
46
  logger.log("creating new test block");
@@ -52,6 +52,18 @@ async function prepareFileForBrowsingAgent(genConfig) {
52
52
  }
53
53
  }
54
54
  exports.prepareFileForBrowsingAgent = prepareFileForBrowsingAgent;
55
+ function newContentsWithTestOnly(existingContents, originalTestBlock, updatedTestBlock, parentDescribeBlock) {
56
+ if (!parentDescribeBlock) {
57
+ const testMarkedAsOnly = updatedTestBlock.replace("test(", "test.only(");
58
+ return existingContents.replace(originalTestBlock, testMarkedAsOnly);
59
+ }
60
+ else {
61
+ const updatedDescribeBlock = parentDescribeBlock.replace(originalTestBlock, updatedTestBlock);
62
+ // TODO: this should only happen when the describe block has "serial" execution
63
+ const describeMarkedAsOnly = updatedDescribeBlock.replace("test.describe(", "test.describe.only(");
64
+ return existingContents.replace(parentDescribeBlock, describeMarkedAsOnly);
65
+ }
66
+ }
55
67
  function createTestBlockForCreateTest(name, steps) {
56
68
  return `
57
69
  test.only("${name}", async ({page}) => {
@@ -70,7 +70,7 @@ async function generateTest(testCase, file, options) {
70
70
  const [prependContent, strippedContent] = await (0, web_1.stripAndPrependImports)(response, testCase?.name);
71
71
  let updatedContent = prependContent + contents + `\n\n${strippedContent}`;
72
72
  if (isUpdate) {
73
- const testBlock = (0, web_1.getTypescriptTestBlock)(testCase?.name, contents);
73
+ const { testBlock } = (0, web_1.getTypescriptTestBlock)(testCase?.name, contents);
74
74
  contents = contents.replace(testBlock, `\n\n${strippedContent}`);
75
75
  updatedContent = prependContent + contents;
76
76
  }
@@ -1,4 +1,7 @@
1
- export declare function getTypescriptTestBlock(scenarioName: string, content: string): string | undefined;
1
+ export declare function getTypescriptTestBlock(scenarioName: string, content: string): {
2
+ testBlock: string | undefined;
3
+ parentDescribe: string | undefined;
4
+ };
2
5
  export declare function appendToTestBlock(testBlock: string, content: string): string;
3
6
  export declare function validateTypescript(filePath: string): string[];
4
7
  export declare function stripAndPrependImports(content: string, testName: string): Promise<(string | undefined)[]>;
@@ -7,4 +10,5 @@ export declare function formatCode(filePath: string): Promise<void>;
7
10
  export declare function addNewImport(contents: string, modules: string[], pkg: string): string;
8
11
  export declare function removeTestOnly(filePath: string): Promise<void>;
9
12
  export declare function getFixtureImportPath(filePath: string): string;
13
+ export declare function replaceCreateTestWithNewCode(filePath: string, contents: string, generatedCode: string): string;
10
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/bin/utils/platform/web/index.ts"],"names":[],"mappings":"AAMA,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAYpB;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG5E;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAwD7D;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,mCAOjB;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,iBAShD;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,iBAQhD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,UAE5E;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,iBAIpD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,UAcpD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/bin/utils/platform/web/index.ts"],"names":[],"mappings":"AAMA,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;EAwB3E;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG5E;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAwD7D;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,mCAUjB;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,iBAShD;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,iBAQhD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,UAE5E;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,iBAMpD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,UAcpD;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,UAsBtB"}
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getFixtureImportPath = exports.removeTestOnly = exports.addNewImport = exports.formatCode = exports.lintErrors = exports.stripAndPrependImports = exports.validateTypescript = exports.appendToTestBlock = exports.getTypescriptTestBlock = void 0;
6
+ exports.replaceCreateTestWithNewCode = exports.getFixtureImportPath = exports.removeTestOnly = exports.addNewImport = exports.formatCode = exports.lintErrors = exports.stripAndPrependImports = exports.validateTypescript = exports.appendToTestBlock = exports.getTypescriptTestBlock = void 0;
7
7
  const eslint_1 = require("eslint");
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
9
  const prettier_1 = __importDefault(require("prettier"));
@@ -12,10 +12,17 @@ const typescript_1 = __importDefault(require("typescript"));
12
12
  function getTypescriptTestBlock(scenarioName, content) {
13
13
  const project = new ts_morph_1.Project();
14
14
  const sourceFile = project.createSourceFile("test.ts", content);
15
- const testFunction = sourceFile.getFirstDescendant((node) => !!(node.isKind(ts_morph_1.SyntaxKind.CallExpression) &&
15
+ const testFunctionNode = sourceFile.getFirstDescendant((node) => !!(node.isKind(ts_morph_1.SyntaxKind.CallExpression) &&
16
16
  node.getExpression().getText() === "test" &&
17
17
  node.getArguments()[0]?.getText().includes(scenarioName)));
18
- return testFunction?.getText();
18
+ // TODO: support files that have 2 describe blocks with the same test name in them
19
+ const describeBlockNode = sourceFile.getFirstDescendant((node) => !!(node.isKind(ts_morph_1.SyntaxKind.CallExpression) &&
20
+ node.getExpression().getText() === "test.describe" &&
21
+ node.getText().includes(scenarioName)));
22
+ return {
23
+ testBlock: testFunctionNode?.getText(),
24
+ parentDescribe: describeBlockNode?.getText(),
25
+ };
19
26
  }
20
27
  exports.getTypescriptTestBlock = getTypescriptTestBlock;
21
28
  function appendToTestBlock(testBlock, content) {
@@ -77,7 +84,7 @@ exports.validateTypescript = validateTypescript;
77
84
  async function stripAndPrependImports(content, testName) {
78
85
  const importRegexp = /import\s+\{[^}]*\}\s+from\s+["'][^"']+["'];?/g;
79
86
  const imports = content.match(importRegexp);
80
- const strippedContent = getTypescriptTestBlock(testName, content);
87
+ const { testBlock: strippedContent } = getTypescriptTestBlock(testName, content);
81
88
  const prependContent = (imports?.join("\n") || "") + "\n\n";
82
89
  return [prependContent, strippedContent];
83
90
  }
@@ -109,7 +116,9 @@ function addNewImport(contents, modules, pkg) {
109
116
  exports.addNewImport = addNewImport;
110
117
  async function removeTestOnly(filePath) {
111
118
  const contents = await fs_extra_1.default.readFile(filePath, "utf8");
112
- const updatedContent = contents.replace(/test\.only/, "test");
119
+ const updatedContent = contents
120
+ .replace("test.only(", "test(")
121
+ .replace("test.describe.only(", "test.describe(");
113
122
  return fs_extra_1.default.writeFile(filePath, updatedContent);
114
123
  }
115
124
  exports.removeTestOnly = removeTestOnly;
@@ -129,3 +138,18 @@ function getFixtureImportPath(filePath) {
129
138
  return fixturesPath;
130
139
  }
131
140
  exports.getFixtureImportPath = getFixtureImportPath;
141
+ function replaceCreateTestWithNewCode(filePath, contents, generatedCode) {
142
+ const project = new ts_morph_1.Project();
143
+ const sourceFile = project.createSourceFile("test.ts", contents);
144
+ const createTestNode = sourceFile.getFirstDescendant((node) => !!(node.isKind(ts_morph_1.SyntaxKind.CallExpression) &&
145
+ node.getExpression().getText() === "createTest"));
146
+ const updatedTestFile = contents.replace(createTestNode?.getText(), function () {
147
+ // str.replace treats characters like $ differently
148
+ // Using a function helps us avoid special handling
149
+ // https://stackoverflow.com/a/28103073
150
+ return "\n" + generatedCode;
151
+ });
152
+ const importStatement = `import { test, expect } from "${getFixtureImportPath(filePath)}";`;
153
+ return importStatement + "\n" + updatedTestFile;
154
+ }
155
+ exports.replaceCreateTestWithNewCode = replaceCreateTestWithNewCode;
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AASA,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;CA8B1C;AAED,wBAAsB,gBAAgB,kBAAK"}
@@ -26,9 +26,8 @@ class FileService {
26
26
  const testFilePath = path_1.default.resolve(process.cwd(), this.filePath);
27
27
  if (testFilePath) {
28
28
  const testFile = fs_1.default.readFileSync(testFilePath, "utf-8");
29
- const updatedTestFile = testFile.replace(/await createTest\([\s\S]*?\);\n/, "\n" + generatedCode);
30
- const importStatement = `import { test, expect } from "${(0, web_1.getFixtureImportPath)(testFilePath)}";`;
31
- fs_1.default.writeFileSync(testFilePath, importStatement + "\n" + updatedTestFile, "utf-8");
29
+ const newContents = (0, web_1.replaceCreateTestWithNewCode)(testFilePath, testFile, generatedCode);
30
+ fs_1.default.writeFileSync(testFilePath, newContents, "utf-8");
32
31
  await (0, web_1.lintErrors)(testFilePath);
33
32
  return res.send({ success: true });
34
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.22.9",
3
+ "version": "0.22.11",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"