@dev-blinq/cucumber_client 1.0.1224-dev → 1.0.1226-dev

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.
@@ -10,6 +10,7 @@ import * as t from "@babel/types";
10
10
 
11
11
  import { CucumberExpression, ParameterTypeRegistry } from "@cucumber/cucumber-expressions";
12
12
  import { existsSync, readFileSync, writeFileSync } from "fs";
13
+ import { getAiConfig } from "../code_gen/page_reflection";
13
14
  const STEP_KEYWORDS = new Set(["Given", "When", "Then"]);
14
15
 
15
16
  /**
@@ -293,7 +294,11 @@ export function removeUnusedElementsKeys(ast, supportFilePath) {
293
294
  * @param {Array<{keyword: string, pattern: string}>} stepDefinitions
294
295
  */
295
296
  export async function removeUnusedStepDefinitions(filePath, stepDefinitions) {
296
- const supportFilePath = filePath.replace(".mjs", ".json");
297
+ let supportFilePath = filePath.replace(".mjs", ".json");
298
+ const config = getAiConfig();
299
+ if (config && config.locatorsMetadataDir) {
300
+ supportFilePath = path.join(config.locatorsMetadataDir, path.basename(supportFilePath));
301
+ }
297
302
  const ast = await parse(filePath);
298
303
  removeStepDefinitions(stepDefinitions, ast);
299
304
  removeUnusedDeclarations(ast);
@@ -58,6 +58,9 @@ for (let i = 0; i < scenarioReport.stepsProgress.length; i++) {
58
58
  page.addCucumberStep(keyword, step.cucumberLine, methodName, step.recording.steps.length);
59
59
 
60
60
  page.removeUnusedElements();
61
+ if (generateCodeResult.locatorsMetadata) {
62
+ page.addLocatorsMetadata(generateCodeResult.locatorsMetadata);
63
+ }
61
64
  await page.save();
62
65
  set.add(page.sourceFileName);
63
66
  }
@@ -22,6 +22,18 @@ function unescapeFromComment(text) {
22
22
  .replace(/\*\\/g, "*/") // Unescape comment-closing sequence
23
23
  .replace(/\\\\/g, "\\"); // Unescape backslashes
24
24
  }
25
+ let ai_config = null;
26
+ export function getAiConfig() {
27
+ if (ai_config) {
28
+ return ai_config;
29
+ }
30
+ try {
31
+ ai_config = JSON.parse(readFileSync("ai_config.json", "utf8"));
32
+ } catch (e) {
33
+ ai_config = {};
34
+ }
35
+ return ai_config;
36
+ }
25
37
  class CodePage {
26
38
  constructor(sourceFileName = null) {
27
39
  this.sourceFileName = sourceFileName;
@@ -224,13 +236,12 @@ this.imports[2].node.source.value
224
236
  params = paramsObj.map((param) => param.name);
225
237
  }
226
238
  firstFind = false;
227
- }
239
+ }
228
240
  stepPaths.push(method.path);
229
-
230
241
  }
231
242
  }
232
243
  if (foundMethod) {
233
- templates.push({ pattern, methodName, params, stepType, paths: stepPaths});
244
+ templates.push({ pattern, methodName, params, stepType, paths: stepPaths });
234
245
  }
235
246
  }
236
247
  }
@@ -481,7 +492,16 @@ this.imports[2].node.source.value
481
492
  }
482
493
  addLocatorsMetadata(locatorsMetadata) {
483
494
  // create a file name based on the source file name replace .mjs with .json
484
- const locatorsMetadataFileName = this.sourceFileName.replace(".mjs", ".json");
495
+ let locatorsMetadataFileName = this.sourceFileName.replace(".mjs", ".json");
496
+ const config = getAiConfig();
497
+ if (config && config.locatorsMetadataDir) {
498
+ // if config.locatorsMetadataDir is set, use it to create the file path
499
+ locatorsMetadataFileName = path.join(config.locatorsMetadataDir, path.basename(locatorsMetadataFileName));
500
+ // check if the directory exists, if not create it
501
+ if (!existsSync(path.dirname(locatorsMetadataFileName))) {
502
+ mkdirSync(path.dirname(locatorsMetadataFileName), { recursive: true });
503
+ }
504
+ }
485
505
  let metadata = {};
486
506
  // try to read the file to metadata, protect with try catch
487
507
  try {
@@ -782,7 +802,7 @@ function getPath(comment) {
782
802
  if (index === -1) {
783
803
  return null;
784
804
  }
785
- return comment.substring(index).split('\n')[0].substring(6);
805
+ return comment.substring(index).split("\n")[0].substring(6);
786
806
  }
787
807
 
788
808
  class CodePart {
@@ -62,6 +62,12 @@ const _isCodeGenerationStep = (step) => {
62
62
  }
63
63
  return false;
64
64
  };
65
+ // Note: this function is used to exclude a key from an object
66
+ // Please move it to utils and use it as a reusable function ...
67
+ function excludeKey(obj, keyToRemove) {
68
+ const { [keyToRemove]: _, ...rest } = obj;
69
+ return rest;
70
+ }
65
71
  const splitToLocatorsGroups = (locators) => {
66
72
  const no_text = locators.locators.filter((locator) => locator.mode === "NO_TEXT");
67
73
  const ignore_digit = locators.locators.filter((locator) => locator.mode === "IGNORE_DIGIT");
@@ -131,7 +137,8 @@ const _generateCodeFromCommand = (step, elements, userData) => {
131
137
  if (!elementIdentifier) {
132
138
  elementIdentifier = findElementIdentifier(node, step, userData, elements);
133
139
  }
134
- elements[elementIdentifier] = locatorObject;
140
+ const withoutAllStrategyLocators = excludeKey(locatorObject, "allStrategyLocators");
141
+ elements[elementIdentifier] = withoutAllStrategyLocators;
135
142
  elementsChanged = true;
136
143
  }
137
144
  let optionElement = null;
@@ -655,6 +655,7 @@ class LocalAgent {
655
655
 
656
656
  let page = agent.project.getPage(agent.pageName, true);
657
657
  const generateCodeResult = generateCode(recording, page, userData, agent.project.rootFolder, methodName);
658
+
658
659
  if (generateCodeResult.simple === true) {
659
660
  agent.sendDone("generateStepCode", null);
660
661
  break;
@@ -707,6 +708,9 @@ class LocalAgent {
707
708
  cucumberStep: agent.cucumberStep,
708
709
  },
709
710
  });
711
+ if (generateCodeResult.locatorsMetadata) {
712
+ page.addLocatorsMetadata(generateCodeResult.locatorsMetadata);
713
+ }
710
714
  await page.save();
711
715
  agent.scenarioReport.updateLastStep({
712
716
  recording: command.data.recording,
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
2
2
  import path from "path";
3
3
  import url from "url";
4
4
  import logger from "../../logger.js";
5
- import { CodePage } from "../code_gen/page_reflection.js";
5
+ import { CodePage, getAiConfig } from "../code_gen/page_reflection.js";
6
6
  import { generateCode, generatePageName } from "../code_gen/playwright_codeget.js";
7
7
  import { invertCodeToCommand } from "../code_gen/code_inversion.js";
8
8
  import { Step } from "../cucumber/feature.js";
@@ -187,7 +187,17 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
187
187
 
188
188
  const getLocatorsJson = (file) => {
189
189
  if (!file) return {};
190
- const locatorsFilePath = file.replace(".mjs", ".json");
190
+ let locatorsFilePath = file.replace(".mjs", ".json");
191
+ const originLocatorsFilePath = locatorsFilePath;
192
+ const config = getAiConfig();
193
+ if (config && config.locatorsMetadataDir) {
194
+ // if config.locatorsMetadataDir is set, use it to create the file path
195
+ locatorsFilePath = path.join(config.locatorsMetadataDir, path.basename(locatorsFilePath));
196
+ if (!existsSync(locatorsFilePath)) {
197
+ // if the file does not exist in the config directory, use the original path
198
+ locatorsFilePath = originLocatorsFilePath;
199
+ }
200
+ }
191
201
  if (!existsSync(locatorsFilePath)) {
192
202
  return {};
193
203
  }
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync, writeFileSync } from "fs";
1
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
2
2
  import logger from "../logger.js";
3
3
  import path from "path";
4
4
  import { scenarioResolution } from "./cucumber/feature.js";
@@ -236,6 +236,15 @@ const runCucumber = async (
236
236
 
237
237
  let scenarioId = findNextIdInFolder("./reports");
238
238
  let scenarioPath = "./reports" + "/" + scenarioId;
239
+ const dataFilePath = path.join(scenarioPath, "data.json");
240
+ mkdirSync(path.dirname(dataFilePath), { recursive: true });
241
+ if (process.env.NODE_ENV_BLINQ === "local") {
242
+ let dataPath = aiAgent.project.rootFolder + "/data/data.json";
243
+ if (existsSync(dataPath)) {
244
+ const poolData = JSON.parse(readFileSync(dataPath, "utf-8"));
245
+ writeFileSync(dataFilePath, JSON.stringify(poolData, null, 2), "utf-8");
246
+ }
247
+ }
239
248
  result.scenarioPath = scenarioPath;
240
249
  aiAgent.initTestData(envFile, path.join(scenarioPath, "data.json"));
241
250
  let featureFileRelative = path.relative(projectDir, fullFeatureFilePath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev-blinq/cucumber_client",
3
- "version": "1.0.1224-dev",
3
+ "version": "1.0.1226-dev",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -28,7 +28,7 @@
28
28
  "@cucumber/tag-expressions": "^6.1.1",
29
29
  "@dev-blinq/cucumber-js": "1.0.172-dev",
30
30
  "@faker-js/faker": "^8.1.0",
31
- "automation_model": "1.0.735-dev",
31
+ "automation_model": "1.0.737-dev",
32
32
  "axios": "^1.7.4",
33
33
  "chokidar": "^3.6.0",
34
34
  "create-require": "^1.1.1",