@empiricalrun/test-gen 0.27.10 → 0.28.2

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,30 @@
1
1
  # @empiricalrun/test-gen
2
2
 
3
+ ## 0.28.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 90dba16: feat: sanitize html attributes (e.g. style) to reduce input tokens
8
+ - 178d285: fix: use suites information in coding agent for update flow
9
+
10
+ ## 0.28.1
11
+
12
+ ### Patch Changes
13
+
14
+ - a6fe36d: fix: incomplete llm response at the time of fixing ts errors
15
+
16
+ ## 0.28.0
17
+
18
+ ### Minor Changes
19
+
20
+ - a3761d0: feat: support test block extraction via suites param
21
+ - 7ab94df: feat: add support for downloading latest build during test gen workflow
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies [cc12707]
26
+ - @empiricalrun/reporter@0.18.2
27
+
3
28
  ## 0.27.10
4
29
 
5
30
  ### 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;AAWvD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAK5C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,MAAM,CAKhD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,UAIvD;AAmDD;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,aAAa,GACvB,OAAO,CAAC,MAAM,CAAC,CA+BjB;AAyBD,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,iBAiBxD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,QA6BjD;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAM1E;AAWD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,oBAAoB,GACrC,OAAO,CAAC,MAAM,CAAC,CA8CjB;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;AAWvD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAK5C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,MAAM,CAKhD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,UAIvD;AAqDD;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,aAAa,GACvB,OAAO,CAAC,MAAM,CAAC,CAmCjB;AAyBD,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,iBAiBxD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,QA6BjD;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAM1E;AAWD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,oBAAoB,GACrC,OAAO,CAAC,MAAM,CAAC,CA8CjB;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"}
@@ -52,10 +52,12 @@ async function prepareFileForUpdateScenario(genConfig) {
52
52
  testCode: codePrompt,
53
53
  pomCode: pomPrompt,
54
54
  testCase: testCase,
55
- options: genConfig.options,
56
55
  });
57
56
  const testFileContent = await fs_extra_1.default.readFile(specPath, "utf-8");
58
- const { testBlock, testNode } = (0, web_1.getTypescriptTestBlock)(name, testFileContent);
57
+ const { testBlock, testNode } = (0, web_1.getTypescriptTestBlock)({
58
+ scenarioName: name,
59
+ content: testFileContent,
60
+ });
59
61
  const parentDescribe = (0, web_1.findFirstSerialDescribeBlock)(testNode);
60
62
  // add test.only / describe.only to the spec file so that only that block is executed
61
63
  const updatedTestFileContent = newContentsWithTestOnly(testFileContent, testBlock, testBlock, parentDescribe?.getText() || "");
@@ -68,7 +70,7 @@ async function prepareFileForUpdateScenario(genConfig) {
68
70
  */
69
71
  async function prepareFileForMasterAgent(genConfig) {
70
72
  const { specPath, testCase } = genConfig;
71
- const { name } = testCase;
73
+ const { name, suites } = testCase;
72
74
  // check if the spec file exists
73
75
  // if no then create a new file with test and expect imports
74
76
  if (!fs_extra_1.default.existsSync(specPath)) {
@@ -77,7 +79,11 @@ async function prepareFileForMasterAgent(genConfig) {
77
79
  await fs_extra_1.default.writeFile(specPath, fileContentWithImports, "utf-8");
78
80
  }
79
81
  const existingContents = await fs_extra_1.default.readFile(specPath, "utf-8");
80
- const { testBlock } = (0, web_1.getTypescriptTestBlock)(name, existingContents);
82
+ const { testBlock } = (0, web_1.getTypescriptTestBlock)({
83
+ scenarioName: name,
84
+ suites,
85
+ content: existingContents,
86
+ });
81
87
  if (!testBlock) {
82
88
  const newTestBlock = await (0, create_test_block_1.createEmptyTestCaseBlock)({
83
89
  testCase: genConfig.testCase,
@@ -1 +1 @@
1
- {"version":3,"file":"create-test-block.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/create-test-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAE7D,wBAAsB,wBAAwB,CAAC,EAC7C,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,+BAmDA"}
1
+ {"version":3,"file":"create-test-block.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/create-test-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAE7D,wBAAsB,wBAAwB,CAAC,EAC7C,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,+BAsDA"}
@@ -53,7 +53,10 @@ async function createEmptyTestCaseBlock({ testCase, file, options, trace, }) {
53
53
  });
54
54
  let response = firstShotMessage?.content || "";
55
55
  markdownRemoverSpan?.end({ output: { response } });
56
- const { testBlock } = (0, web_1.getTypescriptTestBlock)(testCase.name, response);
56
+ const { testBlock } = (0, web_1.getTypescriptTestBlock)({
57
+ scenarioName: testCase.name,
58
+ content: response,
59
+ });
57
60
  console.log(`trace: ${trace?.getTraceUrl()}`);
58
61
  return testBlock;
59
62
  }
@@ -1,13 +1,12 @@
1
1
  import { TraceClient } from "@empiricalrun/llm";
2
2
  import { CustomLogger } from "../../bin/logger";
3
- import { TestCase, TestGenConfigOptions } from "../../types";
4
- export declare function validateAndFixTypescriptErrors({ trace, logger, file, testCode, pomCode, testCase, options, }: {
3
+ import { TestCase } from "../../types";
4
+ export declare function validateAndFixTypescriptErrors({ trace, logger, file, testCode, pomCode, testCase, }: {
5
5
  trace?: TraceClient;
6
6
  logger?: CustomLogger;
7
7
  file: string;
8
8
  testCode: string;
9
9
  pomCode: string;
10
10
  testCase: TestCase;
11
- options?: TestGenConfigOptions;
12
11
  }): Promise<void>;
13
12
  //# sourceMappingURL=fix-ts-errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fix-ts-errors.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/fix-ts-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAQhD,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAE7D,wBAAsB,8BAA8B,CAAC,EACnD,KAAK,EACL,MAA2B,EAC3B,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,OAAO,GACR,EAAE;IACD,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC,iBAoEA"}
1
+ {"version":3,"file":"fix-ts-errors.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/fix-ts-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAK3D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,wBAAsB,8BAA8B,CAAC,EACnD,KAAK,EACL,MAA2B,EAC3B,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,QAAQ,GACT,EAAE;IACD,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;CACpB,iBA8DA"}
@@ -5,11 +5,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.validateAndFixTypescriptErrors = void 0;
7
7
  const llm_1 = require("@empiricalrun/llm");
8
+ const generative_ai_1 = require("@google/generative-ai");
8
9
  const fs_extra_1 = __importDefault(require("fs-extra"));
10
+ const remove_markdown_1 = __importDefault(require("remove-markdown"));
9
11
  const logger_1 = require("../../bin/logger");
10
12
  const web_1 = require("../../bin/utils/platform/web");
11
- const constants_1 = require("../../constants");
12
- async function validateAndFixTypescriptErrors({ trace, logger = new logger_1.CustomLogger(), file, testCode, pomCode, testCase, options, }) {
13
+ async function validateAndFixTypescriptErrors({ trace, logger = new logger_1.CustomLogger(), file, testCode, pomCode, testCase, }) {
13
14
  const validateTypesSpan = trace?.span({ name: "detect-type-errors-in-file" });
14
15
  logger.log("Validating types...");
15
16
  let errors = (0, web_1.validateTypescript)(file);
@@ -43,20 +44,15 @@ async function validateAndFixTypescriptErrors({ trace, logger = new logger_1.Cus
43
44
  scenaioName: testCase.name,
44
45
  });
45
46
  promptSpan?.end({ output: { instruction } });
46
- const llm = new llm_1.LLM({
47
- trace,
48
- provider: options?.modelProvider || constants_1.DEFAULT_MODEL_PROVIDER,
49
- defaultModel: options?.model || constants_1.DEFAULT_MODEL,
50
- providerApiKey: constants_1.MODEL_API_KEYS[options?.modelProvider || constants_1.DEFAULT_MODEL_PROVIDER],
51
- });
52
- const message = await llm.createChatCompletion({
53
- messages: instruction,
54
- modelParameters: {
55
- ...constants_1.DEFAULT_MODEL_PARAMETERS,
56
- ...options?.modelParameters,
57
- },
58
- });
59
- const response = message?.content || "";
47
+ const genAI = new generative_ai_1.GoogleGenerativeAI(process.env.GOOGLE_API_KEY);
48
+ const model = genAI.getGenerativeModel({ model: "gemini-1.5-pro-latest" });
49
+ const prompt = instruction.map((p) => p.content);
50
+ const llmOutputTrace = trace?.span({ name: "llm-output" });
51
+ const message = await model.generateContent(prompt);
52
+ llmOutputTrace?.end({ output: { message: message.response.text() } });
53
+ const removeMarkdownSpan = trace?.span({ name: "remove-markdown" });
54
+ let response = (0, remove_markdown_1.default)(message.response.text() || "");
55
+ removeMarkdownSpan?.end({ output: { response } });
60
56
  const readWriteFileSpan = trace?.span({ name: "write-to-file" });
61
57
  await fs_extra_1.default.writeFile(file, response, "utf-8");
62
58
  readWriteFileSpan?.end({ output: { response } });
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/run.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAI7D,wBAAsB,YAAY,CAChC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,QAAQ,EAAE,CAAC,CA+FrB"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/run.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAI7D,wBAAsB,YAAY,CAChC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,QAAQ,EAAE,CAAC,CAiGrB"}
@@ -22,7 +22,11 @@ async function generateTest(testCase, file, options) {
22
22
  }
23
23
  const context = await (0, context_1.contextForGeneration)(file);
24
24
  const { codePrompt, pomPrompt, testFileContent } = context;
25
- const { testBlock } = (0, web_1.getTypescriptTestBlock)(testCase?.name, testFileContent);
25
+ const { testBlock } = (0, web_1.getTypescriptTestBlock)({
26
+ scenarioName: testCase?.name,
27
+ content: testFileContent,
28
+ suites: testCase?.suites,
29
+ });
26
30
  const isUpdate = !!testBlock;
27
31
  if (isUpdate) {
28
32
  return await (0, update_flow_1.updateTest)(testCase, file, options);
@@ -73,7 +77,7 @@ async function generateTest(testCase, file, options) {
73
77
  logger.success("Test generated successfully!");
74
78
  const readWriteFileSpan = trace.span({ name: "write-to-file" });
75
79
  let contents = fs_extra_1.default.readFileSync(file, "utf-8");
76
- const [prependContent, strippedContent] = await (0, web_1.stripAndPrependImports)(response, testCase?.name);
80
+ const [prependContent, strippedContent] = await (0, web_1.stripAndPrependImports)(response, testCase?.name, testCase?.suites);
77
81
  let updatedContent = prependContent + contents + `\n\n${strippedContent}`;
78
82
  await fs_extra_1.default.writeFile(file, updatedContent, "utf-8");
79
83
  readWriteFileSpan.end({ output: { updatedContent } });
@@ -87,7 +91,6 @@ async function generateTest(testCase, file, options) {
87
91
  testCode: codePrompt,
88
92
  pomCode: pomPrompt,
89
93
  testCase: testCase,
90
- options,
91
94
  });
92
95
  trace.event({ name: "format-file" });
93
96
  await (0, web_1.formatCode)(file);
@@ -1 +1 @@
1
- {"version":3,"file":"update-flow.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/update-flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAmB3B,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAI7D,KAAK,eAAe,GAAG,QAAQ,GAAG;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AA6GF,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,oBAAoB,GAAG,SAAS,EACzC,OAAO,GAAE,OAAc,EACvB,QAAQ,GAAE,OAAc,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CA6E5B;AAED,wBAAsB,qBAAqB,CAAC,EAC1C,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,KAAK,EACL,aAAoB,GACrB,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAiE7B"}
1
+ {"version":3,"file":"update-flow.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/update-flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAmB3B,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAI7D,KAAK,eAAe,GAAG,QAAQ,GAAG;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAgHF,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,oBAAoB,GAAG,SAAS,EACzC,OAAO,GAAE,OAAc,EACvB,QAAQ,GAAE,OAAc,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CAsF5B;AAED,wBAAsB,qBAAqB,CAAC,EAC1C,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,KAAK,EACL,aAAoB,GACrB,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAgE7B"}
@@ -15,20 +15,28 @@ const constants_1 = require("../../constants");
15
15
  const session_1 = require("../../session");
16
16
  const fix_ts_errors_1 = require("./fix-ts-errors");
17
17
  const utils_1 = require("./utils");
18
- async function applyFileChanges({ validateTypes = true, trace, testCase, fileChanges, logger, testGenOptions, pomPrompt, codePrompt, }) {
18
+ async function applyFileChanges({ validateTypes = true, trace, testCase, fileChanges, logger, pomPrompt, codePrompt, }) {
19
19
  await Promise.allSettled(fileChanges.map(async (fileChange) => {
20
20
  if (!fileChange.filePath) {
21
21
  return;
22
22
  }
23
- const { testBlock: testBlockUpdate } = (0, web_1.getTypescriptTestBlock)(testCase?.name || "", fileChange.newCode || "");
23
+ const { testBlock: testBlockUpdate } = (0, web_1.getTypescriptTestBlock)({
24
+ scenarioName: testCase?.name || "",
25
+ content: fileChange.newCode || "",
26
+ suites: testCase?.suites,
27
+ });
24
28
  if (testBlockUpdate) {
25
29
  // assuming the test case getting updated
26
30
  // maintaining the previous accuracy of the test case update
27
31
  const readWriteFileSpan = trace.span({ name: "write-to-file" });
28
32
  let contents = await fs_extra_1.default.readFile(fileChange.filePath, "utf-8");
29
- const [prependContent, strippedContent] = await (0, web_1.stripAndPrependImports)(fileChange.newCode, testCase?.name);
33
+ const [prependContent, strippedContent] = await (0, web_1.stripAndPrependImports)(fileChange.newCode, testCase?.name, testCase?.suites);
30
34
  let updatedContent = prependContent + contents + `\n\n${strippedContent}`;
31
- const { testBlock } = (0, web_1.getTypescriptTestBlock)(testCase?.name, contents);
35
+ const { testBlock } = (0, web_1.getTypescriptTestBlock)({
36
+ scenarioName: testCase?.name,
37
+ content: contents,
38
+ suites: testCase?.suites,
39
+ });
32
40
  contents = contents.replace(testBlock, `\n\n${strippedContent}`);
33
41
  updatedContent = prependContent + contents;
34
42
  await fs_extra_1.default.writeFile(fileChange.filePath, updatedContent, "utf-8");
@@ -69,7 +77,6 @@ async function applyFileChanges({ validateTypes = true, trace, testCase, fileCha
69
77
  testCode: codePrompt,
70
78
  pomCode: pomPrompt,
71
79
  testCase: testCase,
72
- options: testGenOptions,
73
80
  });
74
81
  }
75
82
  trace.event({ name: "format-file" });
@@ -106,10 +113,19 @@ async function updateTest(testCase, file, options, logging = true, validate = tr
106
113
  name: "update-scenario-prompt",
107
114
  });
108
115
  const promptName = "update-scenario";
116
+ // if describe blocks are present, we need to add them to the scenario name
117
+ // e.g. describe block: login ---> login with email
118
+ // this is help LLM navigate to the right test block
119
+ const scenarioName = testCase.suites?.length
120
+ ? testCase.suites.reduce((text, suite) => {
121
+ text += `Describe block: ${suite} ----> `;
122
+ return text;
123
+ }, "") + testCase.name
124
+ : testCase.name;
109
125
  const instruction = await (0, llm_1.getPrompt)(promptName, {
110
126
  testFiles: codePrompt,
111
127
  pageFiles: pomPrompt,
112
- scenarioName: testCase.name,
128
+ scenarioName,
113
129
  scenarioSteps: testCase.steps.join("\n"),
114
130
  scenarioFile: file,
115
131
  }, 14);
@@ -136,7 +152,6 @@ async function updateTest(testCase, file, options, logging = true, validate = tr
136
152
  testCase,
137
153
  fileChanges,
138
154
  logger,
139
- testGenOptions: options,
140
155
  pomPrompt: pomPrompt,
141
156
  codePrompt: codePrompt,
142
157
  });
@@ -201,7 +216,6 @@ async function appendCreateTestBlock({ testCase, file, options, trace, validateT
201
216
  testCase,
202
217
  fileChanges,
203
218
  logger,
204
- testGenOptions: options,
205
219
  pomPrompt: pomPrompt,
206
220
  codePrompt: codePrompt,
207
221
  validateTypes,
package/dist/bin/index.js CHANGED
@@ -12,6 +12,7 @@ const run_2 = require("../agent/codegen/run");
12
12
  const reporter_1 = require("../reporter");
13
13
  const ci_1 = require("../reporter/ci");
14
14
  const session_1 = require("../session");
15
+ const test_build_1 = require("../test-build");
15
16
  const logger_1 = require("./logger");
16
17
  const utils_2 = require("./utils");
17
18
  dotenv_1.default.config({
@@ -62,6 +63,8 @@ async function runAgent(testGenConfig) {
62
63
  generationId: testGenConfig.options?.metadata.generationId,
63
64
  });
64
65
  try {
66
+ // download the build if it exists
67
+ await (0, test_build_1.downloadBuild)(testGenConfig.build || {});
65
68
  await runAgent(testGenConfig);
66
69
  }
67
70
  catch (e) {
@@ -1,5 +1,5 @@
1
1
  import { TestGenConfig } from "../../types";
2
- export declare function parseCliArgs(scenarioOrScenariosPath?: string): Promise<{
2
+ export declare function parseCliArgs(testGenToken?: string): Promise<{
3
3
  testGenConfig: TestGenConfig;
4
4
  }>;
5
5
  export declare function getTestConfigCliArg(): string;
@@ -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;;GAQxD;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,YAAY,GAAE,MAA8B;;GAM7C;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTestConfigCliArg = exports.parseCliArgs = void 0;
4
4
  const scenarios_1 = require("./scenarios");
5
- async function parseCliArgs(scenarioOrScenariosPath = getTestConfigCliArg()) {
6
- const testGenConfig = await (0, scenarios_1.loadTestConfigs)(scenarioOrScenariosPath);
5
+ async function parseCliArgs(testGenToken = getTestConfigCliArg()) {
6
+ const testGenConfig = await (0, scenarios_1.loadTestConfigs)(testGenToken);
7
7
  return {
8
8
  testGenConfig,
9
9
  };
@@ -6,7 +6,11 @@ import { Node } from "ts-morph";
6
6
  * @param {string} content
7
7
  * @return { testBlock: string; parentDescribe: string; } testBlock - the test block content, testNode - the test function node
8
8
  */
9
- export declare function getTypescriptTestBlock(scenarioName: string, content: string): {
9
+ export declare function getTypescriptTestBlock({ scenarioName, suites, content, }: {
10
+ scenarioName: string;
11
+ suites?: string[];
12
+ content: string;
13
+ }): {
10
14
  testBlock: string | undefined;
11
15
  testNode: Node | undefined;
12
16
  };
@@ -36,7 +40,7 @@ export declare function getTypescriptTestBlock(scenarioName: string, content: st
36
40
  export declare function findFirstSerialDescribeBlock(node: Node | undefined): Node | undefined;
37
41
  export declare function appendToTestBlock(testBlock: string, content: string): string;
38
42
  export declare function validateTypescript(filePath: string): string[];
39
- export declare function stripAndPrependImports(content: string, testName: string): Promise<(string | undefined)[]>;
43
+ export declare function stripAndPrependImports(content: string, testName: string, suites: string[]): Promise<(string | undefined)[]>;
40
44
  export declare function lintErrors(filePath: string): Promise<void>;
41
45
  export declare function formatCode(filePath: string): Promise<void>;
42
46
  export declare function addNewImport(contents: string, modules: string[], pkg: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/bin/utils/platform/web/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,IAAI,EAAuB,MAAM,UAAU,CAAC;AAGxE;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACd;IACD,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,IAAI,GAAG,SAAS,CAAC;CAC5B,CAeA;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,IAAI,GAAG,SAAS,GACrB,IAAI,GAAG,SAAS,CA4BlB;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG5E;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA8C7D;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,wBAAsB,iCAAiC,CAAC,QAAQ,EAAE,MAAM,+BAmBvE;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,UA0CtB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/bin/utils/platform/web/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAqB,IAAI,EAAuB,MAAM,UAAU,CAAC;AAGxE;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,YAAY,EACZ,MAAM,EACN,OAAO,GACR,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG;IACF,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,IAAI,GAAG,SAAS,CAAC;CAC5B,CAuCA;AAwBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,IAAI,GAAG,SAAS,GACrB,IAAI,GAAG,SAAS,CA4BlB;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG5E;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA8C7D;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EAAE,mCAWjB;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,wBAAsB,iCAAiC,CAAC,QAAQ,EAAE,MAAM,+BAmBvE;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,UA0CtB"}
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.replaceCreateTestWithNewCode = exports.getPageVariableNameFromCreateTest = exports.getFixtureImportPath = exports.removeTestOnly = exports.addNewImport = exports.formatCode = exports.lintErrors = exports.stripAndPrependImports = exports.validateTypescript = exports.appendToTestBlock = exports.findFirstSerialDescribeBlock = exports.getTypescriptTestBlock = void 0;
7
7
  const eslint_1 = require("eslint");
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const lodash_isequal_1 = __importDefault(require("lodash.isequal"));
9
10
  const prettier_1 = __importDefault(require("prettier"));
10
11
  const ts_morph_1 = require("ts-morph");
11
12
  const typescript_1 = __importDefault(require("typescript"));
@@ -16,18 +17,62 @@ const typescript_1 = __importDefault(require("typescript"));
16
17
  * @param {string} content
17
18
  * @return { testBlock: string; parentDescribe: string; } testBlock - the test block content, testNode - the test function node
18
19
  */
19
- function getTypescriptTestBlock(scenarioName, content) {
20
+ function getTypescriptTestBlock({ scenarioName, suites, content, }) {
20
21
  const project = new ts_morph_1.Project();
21
22
  const sourceFile = project.createSourceFile("test.ts", content);
22
- const testFunctionNode = sourceFile.getFirstDescendant((node) => !!(node.isKind(ts_morph_1.SyntaxKind.CallExpression) &&
23
- node.getExpression().getText() === "test" &&
24
- node.getArguments()[0]?.getText().includes(scenarioName)));
23
+ // Get all test function nodes that match the scenario name
24
+ const matchingTestFunctionNodes = sourceFile
25
+ .getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression)
26
+ .filter((node) => {
27
+ return Boolean(node.getExpression().getText() === "test" &&
28
+ node.getArguments()[0]?.getText().includes(scenarioName));
29
+ });
30
+ if (!suites?.length) {
31
+ const firstNode = matchingTestFunctionNodes?.[0];
32
+ return {
33
+ testBlock: firstNode?.getText(),
34
+ testNode: firstNode,
35
+ };
36
+ }
37
+ // Iterate over each test function node and check if the suites match
38
+ for (const testNode of matchingTestFunctionNodes) {
39
+ const parentDescribes = getParentDescribeNames(testNode);
40
+ if ((0, lodash_isequal_1.default)(parentDescribes, suites)) {
41
+ // Found the matching test block
42
+ return {
43
+ testBlock: testNode.getText(),
44
+ testNode,
45
+ };
46
+ }
47
+ }
48
+ // No matching test block found
25
49
  return {
26
- testBlock: testFunctionNode?.getText(),
27
- testNode: testFunctionNode,
50
+ testBlock: undefined,
51
+ testNode: undefined,
28
52
  };
29
53
  }
30
54
  exports.getTypescriptTestBlock = getTypescriptTestBlock;
55
+ // get the names of parent describe blocks
56
+ function getParentDescribeNames(node) {
57
+ const names = [];
58
+ let current = node.getParent();
59
+ while (current) {
60
+ if (ts_morph_1.Node.isCallExpression(current)) {
61
+ const expr = current.getExpression();
62
+ if (expr.getText() === "test.describe") {
63
+ const describeBlockArguments = current.getArguments();
64
+ if (describeBlockArguments.length > 0) {
65
+ const describeBlockName = describeBlockArguments[0];
66
+ if (ts_morph_1.Node.isStringLiteral(describeBlockName)) {
67
+ names.push(describeBlockName.getLiteralText());
68
+ }
69
+ }
70
+ }
71
+ }
72
+ current = current.getParent();
73
+ }
74
+ return names.reverse(); // Reverse to get from outermost to innermost
75
+ }
31
76
  /**
32
77
  * Function to find the first 'describe' block configured with 'serial: true'
33
78
  *
@@ -121,10 +166,14 @@ function validateTypescript(filePath) {
121
166
  return errors;
122
167
  }
123
168
  exports.validateTypescript = validateTypescript;
124
- async function stripAndPrependImports(content, testName) {
169
+ async function stripAndPrependImports(content, testName, suites) {
125
170
  const importRegexp = /import\s+\{[^}]*\}\s+from\s+["'][^"']+["'];?/g;
126
171
  const imports = content.match(importRegexp);
127
- const { testBlock: strippedContent } = getTypescriptTestBlock(testName, content);
172
+ const { testBlock: strippedContent } = getTypescriptTestBlock({
173
+ scenarioName: testName,
174
+ content,
175
+ suites,
176
+ });
128
177
  const prependContent = (imports?.join("\n") || "") + "\n\n";
129
178
  return [prependContent, strippedContent];
130
179
  }
@@ -1,4 +1,4 @@
1
1
  import { TestGenConfig } from "../../../types";
2
- declare function loadTestConfigs(scenariosPath: string): Promise<TestGenConfig>;
2
+ declare function loadTestConfigs(testGenToken: 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":"AAAA,OAAO,EAAE,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AASrE,iBAAe,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAc5E;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,EAAS,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AAW5E,iBAAe,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAe3E;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadTestConfigs = void 0;
4
- async function loadTestConfigs(scenariosPath) {
5
- // scenariosPath is the testGenToken passed from ci
6
- const str = decodeURIComponent(atob(scenariosPath));
4
+ async function loadTestConfigs(testGenToken) {
5
+ const str = decodeURIComponent(atob(testGenToken));
7
6
  const config = JSON.parse(str);
8
7
  const specPath = `./tests/${config.group || "index"}.spec.ts`;
9
8
  return {
@@ -12,7 +11,9 @@ async function loadTestConfigs(scenariosPath) {
12
11
  name: config.name,
13
12
  steps: config.steps.filter((s) => !!s),
14
13
  group: config.group,
14
+ suites: config.suites,
15
15
  },
16
+ build: config.build,
16
17
  options: config.options,
17
18
  };
18
19
  }
@@ -0,0 +1,10 @@
1
+ import { Build } from "../types";
2
+ /**
3
+ * method to download the build from the URL provided in the build object
4
+ * this is only used in cases like chrome extension as of yet.
5
+ * @export
6
+ * @param {Build} build
7
+ * @return {*} {Promise<void>}
8
+ */
9
+ export declare function downloadBuild(build: Build): Promise<void>;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-build/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAOjC;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAY/D"}
@@ -0,0 +1,30 @@
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.downloadBuild = void 0;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const logger_1 = require("../bin/logger");
9
+ const exec_1 = require("../utils/exec");
10
+ /**
11
+ * method to download the build from the URL provided in the build object
12
+ * this is only used in cases like chrome extension as of yet.
13
+ * @export
14
+ * @param {Build} build
15
+ * @return {*} {Promise<void>}
16
+ */
17
+ async function downloadBuild(build) {
18
+ const logger = new logger_1.CustomLogger({ useReporter: false });
19
+ const packageJSONPath = "package.json";
20
+ const packageJsonStr = await fs_extra_1.default.readFile(packageJSONPath, "utf-8");
21
+ const packageJSONData = JSON.parse(packageJsonStr);
22
+ const buildDownloadScript = packageJSONData.scripts["download"];
23
+ if (buildDownloadScript && build?.url) {
24
+ logger.log(`Downloading build from ${build.url}`);
25
+ await (0, exec_1.cmd)(`npm run download ${build.url}`.split(" "), {
26
+ env: { ...Object(process.env) },
27
+ });
28
+ }
29
+ }
30
+ exports.downloadBuild = downloadBuild;
@@ -19,15 +19,20 @@ export type TestGenConfigOptions = {
19
19
  environment: "development" | "production";
20
20
  };
21
21
  };
22
+ export type Build = {
23
+ url?: string;
24
+ };
22
25
  export type TestGenConfig = {
23
26
  specPath: string;
24
27
  testCase: TestCase;
28
+ build?: Build;
25
29
  options?: TestGenConfigOptions;
26
30
  };
27
31
  export type TestCase = {
28
32
  name: string;
29
33
  steps: string[];
30
34
  group: string;
35
+ suites: string[];
31
36
  };
32
37
  export type PlaywrightActionGenerator = (page: Page, options?: {
33
38
  stateVariables: Record<string, any>;
@@ -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,QAAQ,CAAC;IACzB,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,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;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,CACtC,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE;IACR,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACrC,KACE,MAAM,CAAC;AAEZ,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,QAAQ,CAAC;IACzB,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,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,KAAK,GAAG;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,CACtC,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE;IACR,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACrC,KACE,MAAM,CAAC;AAEZ,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 +1 @@
1
- {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/utils/html.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,QAClB,MAAM,YACF;IACP,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B,WAwBF,CAAC"}
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/utils/html.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,QAClB,MAAM,YACF;IACP,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B,WAsCF,CAAC"}
@@ -9,18 +9,32 @@ const sanitizeHtml = (str, options = {}) => {
9
9
  let sanitizedStr = (0, sanitize_html_1.default)(str, {
10
10
  allowedTags: sanitize_html_1.default.defaults.allowedTags.concat([
11
11
  "button",
12
- "form",
13
- "img",
14
- "input",
15
- "select",
16
- "textarea",
17
12
  "div",
13
+ "form",
18
14
  "h1",
19
15
  "h2",
20
16
  "h3",
17
+ "img",
18
+ "input",
21
19
  "label",
20
+ "select",
21
+ "textarea",
22
22
  ]),
23
- allowedAttributes: false,
23
+ allowedAttributes: {
24
+ "*": [
25
+ "alt",
26
+ "aria-*",
27
+ "class",
28
+ "disabled",
29
+ "for",
30
+ "id",
31
+ "href",
32
+ "placeholder",
33
+ "role",
34
+ "selected",
35
+ "src",
36
+ ],
37
+ },
24
38
  });
25
39
  if (options.disallowedStrings) {
26
40
  options.disallowedStrings.forEach((s) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.27.10",
3
+ "version": "0.28.2",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -18,6 +18,7 @@
18
18
  "@actions/core": "^1.10.1",
19
19
  "@aws-sdk/client-s3": "^3.614.0",
20
20
  "@aws-sdk/s3-request-presigner": "^3.614.0",
21
+ "@google/generative-ai": "^0.15.0",
21
22
  "@playwright/test": "^1.44.1",
22
23
  "@types/sanitize-html": "^2.11.0",
23
24
  "commander": "^12.1.0",
@@ -29,6 +30,7 @@
29
30
  "google-auth-library": "^9.10.0",
30
31
  "google-spreadsheet": "^4.1.2",
31
32
  "ignore": "^5.3.1",
33
+ "lodash.isequal": "^4.5.0",
32
34
  "md5": "^2.3.0",
33
35
  "mime": "^4.0.4",
34
36
  "minimatch": "^10.0.1",
@@ -44,12 +46,13 @@
44
46
  "typescript": "^5.3.3",
45
47
  "@empiricalrun/llm": "^0.9.2",
46
48
  "@empiricalrun/r2-uploader": "^0.3.0",
47
- "@empiricalrun/reporter": "^0.18.1"
49
+ "@empiricalrun/reporter": "^0.18.2"
48
50
  },
49
51
  "devDependencies": {
50
52
  "@types/detect-port": "^1.3.5",
51
53
  "@types/express": "^4.17.21",
52
54
  "@types/fs-extra": "^11.0.4",
55
+ "@types/lodash.isequal": "^4.5.8",
53
56
  "@types/md5": "^2.3.5"
54
57
  },
55
58
  "scripts": {
@@ -58,6 +61,7 @@
58
61
  "clean": "tsc --build --clean",
59
62
  "lint": "eslint .",
60
63
  "test": "vitest run",
61
- "test:watch": "vitest"
64
+ "test:watch": "vitest",
65
+ "test:watch-files": "vitest $0 --watch"
62
66
  }
63
67
  }