@dev-blinq/cucumber_client 1.0.1352-dev → 1.0.1352-stage
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/bin/assets/bundled_scripts/recorder.js +107 -107
- package/bin/assets/preload/css_gen.js +10 -10
- package/bin/assets/preload/recorderv3.js +3 -1
- package/bin/assets/preload/toolbar.js +27 -29
- package/bin/assets/preload/unique_locators.js +1 -1
- package/bin/assets/preload/yaml.js +288 -275
- package/bin/assets/scripts/aria_snapshot.js +223 -220
- package/bin/assets/scripts/dom_attr.js +329 -329
- package/bin/assets/scripts/dom_parent.js +169 -174
- package/bin/assets/scripts/event_utils.js +94 -94
- package/bin/assets/scripts/pw.js +2050 -1949
- package/bin/assets/scripts/recorder.js +13 -23
- package/bin/assets/scripts/snapshot_capturer.js +153 -146
- package/bin/assets/scripts/unique_locators.js +941 -815
- package/bin/assets/scripts/yaml.js +796 -783
- package/bin/assets/templates/_hooks_template.txt +41 -0
- package/bin/assets/templates/utils_template.txt +2 -45
- package/bin/client/apiTest/apiTest.js +6 -0
- package/bin/client/cli_helpers.js +11 -13
- package/bin/client/code_cleanup/utils.js +5 -1
- package/bin/client/code_gen/api_codegen.js +2 -2
- package/bin/client/code_gen/code_inversion.js +107 -2
- package/bin/client/code_gen/page_reflection.js +839 -906
- package/bin/client/code_gen/playwright_codeget.js +25 -11
- package/bin/client/cucumber/feature.js +89 -27
- package/bin/client/cucumber/feature_data.js +2 -2
- package/bin/client/cucumber/project_to_document.js +9 -3
- package/bin/client/cucumber/steps_definitions.js +6 -3
- package/bin/client/cucumber_selector.js +17 -1
- package/bin/client/local_agent.js +6 -5
- package/bin/client/parse_feature_file.js +23 -26
- package/bin/client/playground/projects/env.json +2 -2
- package/bin/client/project.js +186 -196
- package/bin/client/recorderv3/bvt_recorder.js +202 -89
- package/bin/client/recorderv3/implemented_steps.js +17 -12
- package/bin/client/recorderv3/index.js +59 -54
- package/bin/client/recorderv3/network.js +22 -5
- package/bin/client/recorderv3/scriptTest.js +1 -1
- package/bin/client/recorderv3/services.js +4 -16
- package/bin/client/recorderv3/step_runner.js +318 -209
- package/bin/client/recorderv3/step_utils.js +475 -16
- package/bin/client/recorderv3/update_feature.js +28 -29
- package/bin/client/recording.js +1 -0
- package/bin/client/run_cucumber.js +1 -1
- package/bin/client/scenario_report.js +0 -5
- package/bin/client/test_scenario.js +0 -1
- package/bin/client/upload-service.js +3 -2
- package/bin/client/utils/socket_logger.js +132 -0
- package/bin/index.js +2 -0
- package/bin/logger.js +3 -2
- package/bin/min/consoleApi.min.cjs +2 -3
- package/bin/min/injectedScript.min.cjs +16 -16
- package/package.json +21 -12
|
@@ -4,6 +4,7 @@ import { StepsDefinitions } from "../cucumber/steps_definitions.js";
|
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { CodePage } from "./page_reflection.js";
|
|
6
6
|
import { convertToIdentifier, escapeNonPrintables } from "./utils.js";
|
|
7
|
+
import socketLogger from "../utils/socket_logger.js";
|
|
7
8
|
const findElementIdentifier = (node, step, userData, elements) => {
|
|
8
9
|
if (node.key) {
|
|
9
10
|
// incase of rerunning implemented steps
|
|
@@ -12,6 +13,13 @@ const findElementIdentifier = (node, step, userData, elements) => {
|
|
|
12
13
|
|
|
13
14
|
let elementIdentifier = null;
|
|
14
15
|
const keys = Object.keys(elements);
|
|
16
|
+
|
|
17
|
+
for (let i = 0; i < keys.length; i++) {
|
|
18
|
+
const element_key = keys[i];
|
|
19
|
+
const element = elements[element_key];
|
|
20
|
+
element["element_key"] = element_key;
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
let name = node.name;
|
|
16
24
|
if (!name && step.dataKey) {
|
|
17
25
|
name = step.dataKey;
|
|
@@ -92,11 +100,16 @@ const splitToLocatorsGroups = (locators) => {
|
|
|
92
100
|
const _generateCodeFromCommand = (step, elements, userData) => {
|
|
93
101
|
let elementsChanged = false;
|
|
94
102
|
|
|
95
|
-
let elementIdentifier =
|
|
103
|
+
let elementIdentifier = step.locators?.element_key;
|
|
96
104
|
let locatorObject = step.locators;
|
|
97
105
|
// handle element
|
|
98
106
|
let element_name = null;
|
|
99
107
|
let allStrategyLocators = null;
|
|
108
|
+
const codeLines = [];
|
|
109
|
+
|
|
110
|
+
if (_isCodeGenerationStep(step) === false)
|
|
111
|
+
return { codeLines, elements: elementsChanged ? elements : null, elementIdentifier, allStrategyLocators };
|
|
112
|
+
|
|
100
113
|
if (_isCodeGenerationStep(step) && step.type !== Types.VERIFY_PAGE_SNAPSHOT) {
|
|
101
114
|
allStrategyLocators = step.allStrategyLocators ?? splitToLocatorsGroups(step.locators);
|
|
102
115
|
let node = null;
|
|
@@ -130,18 +143,20 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
130
143
|
let locatorObjectClone = JSON.parse(JSON.stringify(locatorObject));
|
|
131
144
|
element_name = locatorObjectClone.element_name;
|
|
132
145
|
delete locatorObjectClone.element_name;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
146
|
+
if (!elementIdentifier) {
|
|
147
|
+
keys.forEach((key) => {
|
|
148
|
+
let elementClone = JSON.parse(JSON.stringify(elements[key]));
|
|
149
|
+
delete elementClone.element_name;
|
|
150
|
+
if (JSON.stringify(elementClone) === JSON.stringify(locatorObjectClone)) {
|
|
151
|
+
elementIdentifier = key;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
140
155
|
if (!elementIdentifier) {
|
|
141
156
|
elementIdentifier = findElementIdentifier(node, step, userData, elements);
|
|
142
157
|
}
|
|
143
158
|
const withoutAllStrategyLocators = excludeKey(locatorObject, "allStrategyLocators");
|
|
144
|
-
elements[elementIdentifier] = withoutAllStrategyLocators;
|
|
159
|
+
elements[elementIdentifier] = { ...withoutAllStrategyLocators, element_key: elementIdentifier };
|
|
145
160
|
elementsChanged = true;
|
|
146
161
|
}
|
|
147
162
|
let optionElement = null;
|
|
@@ -157,8 +172,6 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
157
172
|
}
|
|
158
173
|
}
|
|
159
174
|
|
|
160
|
-
const codeLines = [];
|
|
161
|
-
|
|
162
175
|
let line = null;
|
|
163
176
|
let comment = null;
|
|
164
177
|
let input = null;
|
|
@@ -716,6 +729,7 @@ const generateCode = (recording, codePage, userData, projectDir, methodName) =>
|
|
|
716
729
|
}
|
|
717
730
|
let elements = {};
|
|
718
731
|
if (!codePage) {
|
|
732
|
+
socketLogger.info("CodePage is null");
|
|
719
733
|
console.log("codePage is null");
|
|
720
734
|
} else {
|
|
721
735
|
elements = codePage.getVariableDeclarationAsObject("elements");
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { IdGenerator } from "@cucumber/messages";
|
|
2
|
+
import { AstBuilder, GherkinClassicTokenMatcher, Parser, compile } from "@cucumber/gherkin";
|
|
1
3
|
import { loadConfiguration, loadSupport, runCucumber } from "@dev-blinq/cucumber-js/api";
|
|
2
4
|
import fs from "fs";
|
|
3
|
-
|
|
5
|
+
import os from "os";
|
|
6
|
+
import path from "path";
|
|
4
7
|
import { parseStepTextParameters, toCucumberExpression, unEscapeNonPrintables } from "./utils.js";
|
|
5
|
-
import
|
|
6
|
-
import { IdGenerator } from "@cucumber/messages";
|
|
8
|
+
import stream from "stream";
|
|
7
9
|
import { testStringForRegex } from "../recorderv3/update_feature.js";
|
|
8
|
-
import
|
|
10
|
+
import { generateTestData } from "./feature_data.js";
|
|
11
|
+
import socketLogger from "../utils/socket_logger.js";
|
|
9
12
|
class DataTable {
|
|
10
13
|
constructor(dataTableDocument) {
|
|
11
14
|
if (!dataTableDocument) {
|
|
@@ -372,6 +375,11 @@ class Examples {
|
|
|
372
375
|
return null;
|
|
373
376
|
}
|
|
374
377
|
let value = this.tableBody[0].cells[parameterIndex].value;
|
|
378
|
+
if (!value) {
|
|
379
|
+
console.warn(`Parameter ${parameterName} not found in examples table body, or it is empty`);
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
|
|
375
383
|
return unEscapeNonPrintables(value); // While editing in recorder, we need to remove backslashes
|
|
376
384
|
}
|
|
377
385
|
}
|
|
@@ -449,29 +457,7 @@ class Scenario {
|
|
|
449
457
|
return this.scenarioText;
|
|
450
458
|
}
|
|
451
459
|
}
|
|
452
|
-
const scenarioResolution = async (featureFilePath) => {
|
|
453
|
-
if (!fs.existsSync(featureFilePath)) {
|
|
454
|
-
throw new Error(`Feature file ${featureFilePath} does not exist`);
|
|
455
|
-
}
|
|
456
|
-
const newId = IdGenerator.uuid();
|
|
457
|
-
const builder = new AstBuilder(newId);
|
|
458
|
-
const matcher = new GherkinClassicTokenMatcher();
|
|
459
|
-
|
|
460
|
-
const parser = new Parser(builder, matcher);
|
|
461
|
-
|
|
462
|
-
// normalize the path to start with featuers/ if it's not cut the featureFielPath to only the part after features/
|
|
463
|
-
let uri = featureFilePath.startsWith("features/")
|
|
464
|
-
? featureFilePath
|
|
465
|
-
: "features/" + featureFilePath.split("features/")[1];
|
|
466
|
-
|
|
467
|
-
const featureFileContent = fs.readFileSync(featureFilePath, "utf8");
|
|
468
|
-
const gherkinDocument = parser.parse(featureFileContent, newId);
|
|
469
460
|
|
|
470
|
-
const feature = new Feature(gherkinDocument, featureFileContent);
|
|
471
|
-
//const scenario = feature.getScenario(scenarioName);
|
|
472
|
-
//return scenario;
|
|
473
|
-
return feature;
|
|
474
|
-
};
|
|
475
461
|
const getDocumentAndPickel = (featureName, featureContent, scenarioName) => {
|
|
476
462
|
const newId = IdGenerator.uuid();
|
|
477
463
|
const builder = new AstBuilder(newId);
|
|
@@ -484,12 +470,88 @@ const getDocumentAndPickel = (featureName, featureContent, scenarioName) => {
|
|
|
484
470
|
|
|
485
471
|
const gherkinDocument = parser.parse(featureContent, newId);
|
|
486
472
|
const pickles = compile(gherkinDocument, uri, newId);
|
|
487
|
-
|
|
488
473
|
// Step 3: Find the specific scenario Pickle
|
|
489
474
|
const pickle = pickles.find((pickle) => {
|
|
490
475
|
return pickle.name === scenarioName;
|
|
491
476
|
});
|
|
492
477
|
return { gherkinDocument, pickle };
|
|
493
478
|
};
|
|
479
|
+
const scenarioResolution = async (featureFilePath) => {
|
|
480
|
+
if (!fs.existsSync(featureFilePath)) {
|
|
481
|
+
throw new Error(`Feature file ${featureFilePath} does not exist`);
|
|
482
|
+
}
|
|
483
|
+
const featureFileContent = fs.readFileSync(featureFilePath, "utf8");
|
|
484
|
+
let tmpDir = null;
|
|
485
|
+
try {
|
|
486
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "ai-qa"));
|
|
487
|
+
const tmpFeaturePath = path.join(tmpDir, "features");
|
|
488
|
+
fs.mkdirSync(tmpFeaturePath);
|
|
489
|
+
const tmpFeatureFilePath = path.join(tmpFeaturePath, path.basename(featureFilePath));
|
|
490
|
+
let result = generateTestData(featureFilePath);
|
|
491
|
+
if (result.changed) {
|
|
492
|
+
fs.writeFileSync(tmpFeatureFilePath, result.newContent);
|
|
493
|
+
console.log("Fake data was generated for this scenario");
|
|
494
|
+
console.log("Variables:");
|
|
495
|
+
for (let key in result.variables) {
|
|
496
|
+
console.log(`${key}: ${result.variables[key].fake}`);
|
|
497
|
+
}
|
|
498
|
+
console.log("Other fake data:");
|
|
499
|
+
for (let i = 0; i < result.otherFakeData.length; i++) {
|
|
500
|
+
console.log(`${result.otherFakeData[i].var}: ${result.otherFakeData[i].fake}`);
|
|
501
|
+
}
|
|
502
|
+
} else {
|
|
503
|
+
fs.copyFileSync(featureFilePath, tmpFeatureFilePath);
|
|
504
|
+
}
|
|
505
|
+
const writable = new stream.Writable({
|
|
506
|
+
write: function (chunk, encoding, next) {
|
|
507
|
+
//console.log(chunk.toString());
|
|
508
|
+
next();
|
|
509
|
+
},
|
|
510
|
+
});
|
|
511
|
+
const environment = { cwd: tmpDir, stdout: writable, stderr: writable };
|
|
512
|
+
// load configuration from a particular file, and override a specific option
|
|
513
|
+
const provided = {
|
|
514
|
+
default: "--publish-quiet",
|
|
515
|
+
require: [tmpDir],
|
|
516
|
+
failFast: false,
|
|
517
|
+
};
|
|
494
518
|
|
|
519
|
+
let gherkinDocument = null;
|
|
520
|
+
const { runConfiguration } = await loadConfiguration({ provided }, environment);
|
|
521
|
+
// load the support code upfront
|
|
522
|
+
const support = await loadSupport(runConfiguration, environment);
|
|
523
|
+
// run cucumber, using the support code we loaded already
|
|
524
|
+
await runCucumber({ ...runConfiguration, support }, environment, function (event) {
|
|
525
|
+
// if (event.source) {
|
|
526
|
+
// scenarioInfo.source = event.source.data;
|
|
527
|
+
// }
|
|
528
|
+
// if (event.pickle && event.pickle.name === scenarioName) {
|
|
529
|
+
// scenarioInfo.pickle = event.pickle;
|
|
530
|
+
// }
|
|
531
|
+
if (event.gherkinDocument) {
|
|
532
|
+
gherkinDocument = event.gherkinDocument;
|
|
533
|
+
}
|
|
534
|
+
//console.log(event);
|
|
535
|
+
//console.log(JSON.stringify(event, null, 2));
|
|
536
|
+
// console.log("");
|
|
537
|
+
});
|
|
538
|
+
const feature = new Feature(gherkinDocument, featureFileContent);
|
|
539
|
+
//const scenario = feature.getScenario(scenarioName);
|
|
540
|
+
//return scenario;
|
|
541
|
+
return feature;
|
|
542
|
+
} finally {
|
|
543
|
+
try {
|
|
544
|
+
if (tmpDir) {
|
|
545
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
546
|
+
}
|
|
547
|
+
} catch (e) {
|
|
548
|
+
socketLogger.error(
|
|
549
|
+
`An error has occurred while removing the temp folder at ${tmpDir}. Please remove it manually. Error: ${e}`
|
|
550
|
+
);
|
|
551
|
+
console.error(
|
|
552
|
+
`An error has occurred while removing the temp folder at ${tmpDir}. Please remove it manually. Error: ${e}`
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
};
|
|
495
557
|
export { Feature, Scenario, Step, DataTable, Examples, scenarioResolution, getDocumentAndPickel };
|
|
@@ -4,7 +4,13 @@ import { AstBuilder, GherkinClassicTokenMatcher, Parser } from "@cucumber/gherki
|
|
|
4
4
|
import { Feature } from "./feature.js";
|
|
5
5
|
import { StepsDefinitions } from "./steps_definitions.js";
|
|
6
6
|
|
|
7
|
-
export const projectDocument = (
|
|
7
|
+
export const projectDocument = (
|
|
8
|
+
folder,
|
|
9
|
+
featureName = null,
|
|
10
|
+
scenarioName = null,
|
|
11
|
+
supressErrors = false,
|
|
12
|
+
errors = []
|
|
13
|
+
) => {
|
|
8
14
|
const uuidFn = () => (23212).toString(16);
|
|
9
15
|
const builder = new AstBuilder(uuidFn);
|
|
10
16
|
const matcher = new GherkinClassicTokenMatcher();
|
|
@@ -15,7 +21,7 @@ export const projectDocument = (folder, featureName = null, scenarioName = null,
|
|
|
15
21
|
// read all the feature files in the project folder under features folder
|
|
16
22
|
let featureFiles = [];
|
|
17
23
|
const featuresDir = path.join(folder, "features");
|
|
18
|
-
featureFiles = fs.readdirSync(featuresDir).filter((file) => {
|
|
24
|
+
featureFiles = fs.readdirSync(featuresDir, { recursive: true }).filter((file) => {
|
|
19
25
|
return file.endsWith(".feature");
|
|
20
26
|
});
|
|
21
27
|
const documents = [];
|
|
@@ -59,4 +65,4 @@ export const projectDocument = (folder, featureName = null, scenarioName = null,
|
|
|
59
65
|
// const documents = projectDocument(projectDir, featureName, scenarioName, true, errors);
|
|
60
66
|
// const args = process.argv.slice(2);
|
|
61
67
|
|
|
62
|
-
// console.log(JSON.stringify(documents));
|
|
68
|
+
// console.log(JSON.stringify(documents));
|
|
@@ -45,7 +45,10 @@ class StepsDefinitions {
|
|
|
45
45
|
if (method && expression.keyword && pattern && expression.methodName) {
|
|
46
46
|
this.steps[pattern] = {
|
|
47
47
|
// file: path.join(this.isTemp ? "__temp_features" : "features", mjsFile),
|
|
48
|
-
file: path.join(
|
|
48
|
+
file: path.join(
|
|
49
|
+
this.isTemp ? (process.env.tempFeaturesFolderPath ?? "__temp_features") : "features",
|
|
50
|
+
mjsFile
|
|
51
|
+
),
|
|
49
52
|
functionName: expression.methodName,
|
|
50
53
|
name: pattern,
|
|
51
54
|
source: this.findKey(method.codePart, "source"),
|
|
@@ -56,7 +59,7 @@ class StepsDefinitions {
|
|
|
56
59
|
}
|
|
57
60
|
load(print = true, supressErrors = false, errors = []) {
|
|
58
61
|
const mjsFiles = findFilesWithExtension(
|
|
59
|
-
path.join(this.baseFolder, this.isTemp ? process.env.tempFeaturesFolderPath ?? "__temp_features" : "features"),
|
|
62
|
+
path.join(this.baseFolder, this.isTemp ? (process.env.tempFeaturesFolderPath ?? "__temp_features") : "features"),
|
|
60
63
|
"mjs"
|
|
61
64
|
);
|
|
62
65
|
// console.log({ mjsFiles });
|
|
@@ -64,7 +67,7 @@ class StepsDefinitions {
|
|
|
64
67
|
const mjsFile = mjsFiles[i];
|
|
65
68
|
const filePath = path.join(
|
|
66
69
|
this.baseFolder,
|
|
67
|
-
this.isTemp ? process.env.tempFeaturesFolderPath ?? "__temp_features" : "features",
|
|
70
|
+
this.isTemp ? (process.env.tempFeaturesFolderPath ?? "__temp_features") : "features",
|
|
68
71
|
mjsFile
|
|
69
72
|
);
|
|
70
73
|
const codePage = new CodePage(filePath);
|
|
@@ -6,6 +6,7 @@ import crypto from "crypto";
|
|
|
6
6
|
import { findFilesWithExtension } from "./cucumber/steps_definitions.js";
|
|
7
7
|
import fs from "fs";
|
|
8
8
|
//import { spawn } from "child_process";
|
|
9
|
+
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
9
10
|
|
|
10
11
|
if (process.argv.length < 3) {
|
|
11
12
|
console.log("Usage: node cucumber_selector.js <projectsDir> --all");
|
|
@@ -100,8 +101,8 @@ if (process.argv.includes("--scenario-name")) {
|
|
|
100
101
|
}
|
|
101
102
|
const projectName = selectedScenario.featureFile.split(path.sep)[0];
|
|
102
103
|
let deleteMjsFiles = readlineSync.keyInYN("Delete mjs file?");
|
|
104
|
+
let stepsPath = path.join(selectedScenario.projectsDir, projectName, "features", "step_definitions");
|
|
103
105
|
if (deleteMjsFiles) {
|
|
104
|
-
let stepsPath = path.join(selectedScenario.projectsDir, projectName, "features", "step_definitions");
|
|
105
106
|
if (fs.existsSync(stepsPath)) {
|
|
106
107
|
// delete all the *.mjs files
|
|
107
108
|
let files = fs.readdirSync(stepsPath);
|
|
@@ -112,6 +113,21 @@ if (deleteMjsFiles) {
|
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
}
|
|
116
|
+
// copy utils file to the steps directory
|
|
117
|
+
const utilsPath = path.join(__dirname, "../assets/templates/utils_template.txt");
|
|
118
|
+
const utilsContent = fs.readFileSync(utilsPath, "utf8");
|
|
119
|
+
const utilsFileName = stepsPath + "/utils.mjs";
|
|
120
|
+
// if stepsPath directory doesn't exist create it
|
|
121
|
+
if (!fs.existsSync(stepsPath)) {
|
|
122
|
+
fs.mkdirSync(stepsPath, { recursive: true });
|
|
123
|
+
}
|
|
124
|
+
fs.writeFileSync(utilsFileName, utilsContent, "utf8");
|
|
125
|
+
// copy hooks file to the steps directory
|
|
126
|
+
const hooksTemplateFilePath = path.join(__dirname, "../assets/templates/_hooks_template.txt");
|
|
127
|
+
const hooksContent = fs.readFileSync(hooksTemplateFilePath, "utf8");
|
|
128
|
+
const hooksFilePath = path.join(stepsPath, "_hooks.mjs");
|
|
129
|
+
fs.writeFileSync(hooksFilePath, hooksContent, "utf8");
|
|
130
|
+
|
|
115
131
|
process.env.PROJECT_PATH = path.join(selectedScenario.projectsDir, projectName);
|
|
116
132
|
//chanks[currentChank][index];
|
|
117
133
|
console.log("Running scenario:");
|
|
@@ -267,7 +267,7 @@ class LocalAgent {
|
|
|
267
267
|
null,
|
|
268
268
|
true,
|
|
269
269
|
null,
|
|
270
|
-
|
|
270
|
+
-1,
|
|
271
271
|
null,
|
|
272
272
|
initScript
|
|
273
273
|
);
|
|
@@ -696,6 +696,7 @@ class LocalAgent {
|
|
|
696
696
|
stepDiff: stepResult,
|
|
697
697
|
});
|
|
698
698
|
page.removeUnusedElements();
|
|
699
|
+
page.mergeSimilarElements();
|
|
699
700
|
agent.scenarioReport.updateLastStep({
|
|
700
701
|
code: {
|
|
701
702
|
cleanFileNames: page.cleanFileNames,
|
|
@@ -809,12 +810,12 @@ class LocalAgent {
|
|
|
809
810
|
} catch (err) {
|
|
810
811
|
logger.error("Error reading memory file: " + err.message);
|
|
811
812
|
}
|
|
812
|
-
const screenshot = await agent.getScreenshot(agent.context);
|
|
813
|
+
//const screenshot = await agent.getScreenshot(agent.context);
|
|
813
814
|
// check if the popup is open
|
|
814
815
|
const popupResult = await agent.context.web.closeUnexpectedPopups(null, null);
|
|
815
816
|
if (nodes) {
|
|
816
817
|
nodes.memory = memory;
|
|
817
|
-
nodes.screenshot = screenshot;
|
|
818
|
+
//nodes.screenshot = screenshot;
|
|
818
819
|
if (popupResult.rerun === true) {
|
|
819
820
|
nodes.rerun = true;
|
|
820
821
|
}
|
|
@@ -971,7 +972,7 @@ class LocalAgent {
|
|
|
971
972
|
async createNewStepLocal(
|
|
972
973
|
featureName,
|
|
973
974
|
cucumberStep,
|
|
974
|
-
|
|
975
|
+
comments,
|
|
975
976
|
userData,
|
|
976
977
|
firstStep,
|
|
977
978
|
previousTasks,
|
|
@@ -1087,7 +1088,7 @@ class LocalAgent {
|
|
|
1087
1088
|
previousTasks,
|
|
1088
1089
|
scenarioDocument,
|
|
1089
1090
|
scenarioStepIndex,
|
|
1090
|
-
comments
|
|
1091
|
+
comments,
|
|
1091
1092
|
featureFileText,
|
|
1092
1093
|
recover,
|
|
1093
1094
|
dumpConfig: this.dumpConfig,
|
|
@@ -1,37 +1,34 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let id =0;
|
|
9
|
-
const uuidFn = () => (++id).toString(16)
|
|
10
|
-
const builder = new AstBuilder(uuidFn)
|
|
11
|
-
const matcher = new GherkinClassicTokenMatcher()
|
|
1
|
+
import { AstBuilder, GherkinClassicTokenMatcher, Parser } from "@cucumber/gherkin";
|
|
2
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
3
|
+
import { loadArgs, showUsage, validateCLIArg } from "./cli_helpers.js";
|
|
4
|
+
let id = 0;
|
|
5
|
+
const uuidFn = () => (++id).toString(16);
|
|
6
|
+
const builder = new AstBuilder(uuidFn);
|
|
7
|
+
const matcher = new GherkinClassicTokenMatcher();
|
|
12
8
|
|
|
13
|
-
const parser = new Parser(builder, matcher)
|
|
9
|
+
const parser = new Parser(builder, matcher);
|
|
14
10
|
|
|
15
11
|
const parseFeatureFile = (featureFilePath) => {
|
|
16
|
-
const source = readFileSync(featureFilePath,
|
|
17
|
-
const gherkinDocument = parser.parse(source)
|
|
18
|
-
return gherkinDocument
|
|
19
|
-
}
|
|
12
|
+
const source = readFileSync(featureFilePath, "utf8");
|
|
13
|
+
const gherkinDocument = parser.parse(source);
|
|
14
|
+
return gherkinDocument;
|
|
15
|
+
};
|
|
20
16
|
|
|
21
|
-
const args = loadArgs()
|
|
22
|
-
const featureFilePath = args[0]
|
|
23
|
-
const outputFilePath = args[1]
|
|
24
|
-
const usage =
|
|
17
|
+
const args = loadArgs();
|
|
18
|
+
const featureFilePath = args[0];
|
|
19
|
+
const outputFilePath = args[1];
|
|
20
|
+
const usage =
|
|
21
|
+
"Usage: node parse_feature_file.js <featureFilePath> [<outputFilePath>] \n\nExample: node parseFeatureFile.js ./features/my.feature ./features/my.feature.json\n\n";
|
|
25
22
|
try {
|
|
26
|
-
validateCLIArg(featureFilePath,
|
|
23
|
+
validateCLIArg(featureFilePath, "featureFilePath");
|
|
27
24
|
} catch (error) {
|
|
28
|
-
showUsage(error, usage)
|
|
25
|
+
showUsage(error, usage);
|
|
29
26
|
}
|
|
30
|
-
const gherkinDocument = parseFeatureFile(featureFilePath)
|
|
27
|
+
const gherkinDocument = parseFeatureFile(featureFilePath);
|
|
31
28
|
if (outputFilePath) {
|
|
32
|
-
writeFileSync(outputFilePath, JSON.stringify(gherkinDocument, null, 2))
|
|
29
|
+
writeFileSync(outputFilePath, JSON.stringify(gherkinDocument, null, 2));
|
|
33
30
|
} else {
|
|
34
|
-
console.log(JSON.stringify(gherkinDocument, null, 2))
|
|
31
|
+
console.log(JSON.stringify(gherkinDocument, null, 2));
|
|
35
32
|
}
|
|
36
33
|
|
|
37
|
-
export { parseFeatureFile }
|
|
34
|
+
export { parseFeatureFile };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
}
|
|
2
|
+
"baseUrl": "https://google.com"
|
|
3
|
+
}
|