@dev-blinq/cucumber-js 1.0.30 → 1.0.32-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/download-install.js +167 -0
- package/lib/api/gherkin.js +47 -1
- package/lib/api/gherkin.js.map +1 -1
- package/lib/configuration/axios_client.d.ts +1 -0
- package/lib/configuration/axios_client.js +40 -0
- package/lib/configuration/axios_client.js.map +1 -0
- package/lib/formatter/api.d.ts +2 -0
- package/lib/formatter/api.js +53 -0
- package/lib/formatter/api.js.map +1 -0
- package/lib/formatter/bvt_analysis_formatter.d.ts +1 -0
- package/lib/formatter/bvt_analysis_formatter.js +49 -11
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.d.ts +12 -3
- package/lib/formatter/feature_data_format.js +96 -8
- package/lib/formatter/feature_data_format.js.map +1 -1
- package/lib/formatter/helpers/report_generator.d.ts +26 -3
- package/lib/formatter/helpers/report_generator.js +167 -21
- package/lib/formatter/helpers/report_generator.js.map +1 -1
- package/lib/formatter/helpers/upload_serivce.d.ts +3 -0
- package/lib/formatter/helpers/upload_serivce.js +91 -13
- package/lib/formatter/helpers/upload_serivce.js.map +1 -1
- package/lib/formatter/helpers/uploader.js +84 -10
- package/lib/formatter/helpers/uploader.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/package.json +6 -2
|
@@ -1,14 +1,23 @@
|
|
|
1
|
+
import { TableCell } from '@cucumber/messages';
|
|
1
2
|
declare const generateTestData: (featureFileContent: string, vars?: any, fakeData?: {
|
|
2
3
|
var: string;
|
|
3
4
|
fake: string;
|
|
4
|
-
}[]) => {
|
|
5
|
+
}[], projectDir?: string) => {
|
|
5
6
|
newContent: string;
|
|
6
7
|
variables: any;
|
|
7
8
|
otherFakeData: {
|
|
8
9
|
var: string;
|
|
9
|
-
fake:
|
|
10
|
+
fake: any;
|
|
10
11
|
}[];
|
|
11
12
|
changed: boolean;
|
|
12
13
|
fakeIndex: number;
|
|
13
14
|
};
|
|
14
|
-
|
|
15
|
+
declare const generateExamplesFromFunction: (data: string, feature_path: string, functionName: string, functionFile: string) => {
|
|
16
|
+
newData: string;
|
|
17
|
+
mjsData: any;
|
|
18
|
+
};
|
|
19
|
+
declare const generateExamplesFromFunctionGherkin: (headers: readonly TableCell[], values: readonly TableCell[], mjsData: any) => {
|
|
20
|
+
header: string;
|
|
21
|
+
value: any;
|
|
22
|
+
}[];
|
|
23
|
+
export { generateTestData, generateExamplesFromFunction, generateExamplesFromFunctionGherkin, };
|
|
@@ -1,16 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateTestData = void 0;
|
|
6
|
+
exports.generateExamplesFromFunctionGherkin = exports.generateExamplesFromFunction = exports.generateTestData = void 0;
|
|
4
7
|
const faker_1 = require("@faker-js/faker");
|
|
5
|
-
const
|
|
6
|
-
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const json5_1 = __importDefault(require("json5"));
|
|
11
|
+
const generateTestData = (featureFileContent, vars, fakeData, projectDir) => {
|
|
12
|
+
const regexp = /\{\{([^}]*\([^)]*\))\}\}/g;
|
|
7
13
|
const variableRegex = /^([a-zA-Z0-9_]*)=(.*)/g;
|
|
8
14
|
let newContent = featureFileContent;
|
|
9
15
|
let match;
|
|
16
|
+
if (!projectDir) {
|
|
17
|
+
projectDir = process.cwd();
|
|
18
|
+
}
|
|
19
|
+
const namespacePath = path_1.default.join(projectDir, 'features', 'step_definitions', 'namespaces.json');
|
|
20
|
+
let namespaces = fs_1.default.existsSync(namespacePath)
|
|
21
|
+
? JSON.parse(fs_1.default.readFileSync(namespacePath, 'utf-8'))
|
|
22
|
+
: [];
|
|
23
|
+
if (!Array.isArray(namespaces)) {
|
|
24
|
+
namespaces = [];
|
|
25
|
+
}
|
|
10
26
|
const matches = [];
|
|
11
27
|
// collect all matches
|
|
12
28
|
while ((match = regexp.exec(featureFileContent)) !== null) {
|
|
13
|
-
|
|
29
|
+
// match[0] is the full match, match[1] is the first capturing group
|
|
30
|
+
// Eg:- match[0] = {{name}}, match[1] = name
|
|
31
|
+
if (!namespaces.includes(match[1].split('.')[0]))
|
|
32
|
+
matches.push(match);
|
|
14
33
|
}
|
|
15
34
|
// find all variables in the matches
|
|
16
35
|
const variables = { ...vars };
|
|
@@ -43,7 +62,7 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
|
|
|
43
62
|
}
|
|
44
63
|
for (const key in variables) {
|
|
45
64
|
const variable = variables[key];
|
|
46
|
-
const fake =
|
|
65
|
+
const fake = getFakeString(variable.toFake.substring(2, variable.toFake.length - 2));
|
|
47
66
|
newContent = newContent.replaceAll(`{{${variable.var}}}`, fake);
|
|
48
67
|
variables[key].fake = fake;
|
|
49
68
|
}
|
|
@@ -53,10 +72,14 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
|
|
|
53
72
|
const duplicateFakeData = fakeData ? [...fakeData] : [];
|
|
54
73
|
let fakeIndex = 0;
|
|
55
74
|
while ((match = regexp.exec(featureFileContent)) !== null) {
|
|
75
|
+
if (namespaces.includes(match[1].split('.')[0]))
|
|
76
|
+
continue;
|
|
56
77
|
try {
|
|
57
|
-
const fake = duplicateFakeData &&
|
|
78
|
+
const fake = duplicateFakeData &&
|
|
79
|
+
duplicateFakeData.length > 0 &&
|
|
80
|
+
duplicateFakeData[0].var === match[0]
|
|
58
81
|
? duplicateFakeData.shift().fake
|
|
59
|
-
:
|
|
82
|
+
: getFakeString(match[0].substring(2, match[0].length - 2));
|
|
60
83
|
otherFakeData.push({
|
|
61
84
|
var: match[0],
|
|
62
85
|
fake,
|
|
@@ -66,7 +89,7 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
|
|
|
66
89
|
}
|
|
67
90
|
catch (err) {
|
|
68
91
|
// eslint-disable-next-line no-console
|
|
69
|
-
console.log('unknown faker variable:' + match[0])
|
|
92
|
+
//console.log('unknown faker variable:' + match[0])
|
|
70
93
|
}
|
|
71
94
|
}
|
|
72
95
|
return {
|
|
@@ -78,4 +101,69 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
|
|
|
78
101
|
};
|
|
79
102
|
};
|
|
80
103
|
exports.generateTestData = generateTestData;
|
|
104
|
+
const getFakeString = (content) => {
|
|
105
|
+
const faking = content.split('(')[0].split('.');
|
|
106
|
+
const argument = content.substring(content.indexOf('(') + 1, content.indexOf(')'));
|
|
107
|
+
let fakeFunc = faker_1.faker;
|
|
108
|
+
faking.forEach((f) => {
|
|
109
|
+
fakeFunc = fakeFunc[f];
|
|
110
|
+
});
|
|
111
|
+
try {
|
|
112
|
+
return fakeFunc(json5_1.default.parse(argument));
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
return fakeFunc(argument);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const getDefinitionFunction = (feature_path, functionName, functionFile) => {
|
|
119
|
+
const mjsFiles = fs_1.default
|
|
120
|
+
.readdirSync(path_1.default.join(feature_path, '../step_definitions'))
|
|
121
|
+
.filter((file) => file === `${functionFile}.js`);
|
|
122
|
+
if (mjsFiles.length === 0) {
|
|
123
|
+
throw new Error(`File ${functionFile} not found in step_definitions folder`);
|
|
124
|
+
}
|
|
125
|
+
const [mjsData] = mjsFiles.map((file) => {
|
|
126
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
127
|
+
const { [functionName]: func } = require(path_1.default.join(feature_path, '../step_definitions', file));
|
|
128
|
+
if (!func)
|
|
129
|
+
throw new Error(`Function ${functionName} not found in file ${file}`);
|
|
130
|
+
return func();
|
|
131
|
+
});
|
|
132
|
+
return mjsData;
|
|
133
|
+
};
|
|
134
|
+
const generateExamplesFromFunction = (data, feature_path, functionName, functionFile) => {
|
|
135
|
+
const examples = data.split('Examples:')[1].split('\n').slice(1);
|
|
136
|
+
const headers = examples[0]
|
|
137
|
+
.split('|')
|
|
138
|
+
.map((header) => header.trim())
|
|
139
|
+
.filter((header) => header !== '');
|
|
140
|
+
const values = examples[1]
|
|
141
|
+
.split('|')
|
|
142
|
+
.map((value) => value.trim())
|
|
143
|
+
.filter((header) => header !== '');
|
|
144
|
+
const mjsData = getDefinitionFunction(feature_path, functionName, functionFile);
|
|
145
|
+
const newExamples = headers.map((header) => {
|
|
146
|
+
if (mjsData[header]) {
|
|
147
|
+
return mjsData[header];
|
|
148
|
+
}
|
|
149
|
+
return values[headers.indexOf(header)];
|
|
150
|
+
});
|
|
151
|
+
let newExamplesString = data.split('Examples:')[1];
|
|
152
|
+
newExamples.forEach((example, index) => {
|
|
153
|
+
newExamplesString = newExamplesString.replace(values[index], example);
|
|
154
|
+
});
|
|
155
|
+
const newData = data.replace(data.split('Examples:')[1], newExamplesString);
|
|
156
|
+
return { newData, mjsData };
|
|
157
|
+
};
|
|
158
|
+
exports.generateExamplesFromFunction = generateExamplesFromFunction;
|
|
159
|
+
const generateExamplesFromFunctionGherkin = (headers, values, mjsData) => {
|
|
160
|
+
const newExamples = headers.map(({ value: header }, index) => {
|
|
161
|
+
if (mjsData[header]) {
|
|
162
|
+
return { header, value: mjsData[header] };
|
|
163
|
+
}
|
|
164
|
+
return { header, value: values[index].value };
|
|
165
|
+
});
|
|
166
|
+
return newExamples;
|
|
167
|
+
};
|
|
168
|
+
exports.generateExamplesFromFunctionGherkin = generateExamplesFromFunctionGherkin;
|
|
81
169
|
//# sourceMappingURL=feature_data_format.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature_data_format.js","sourceRoot":"","sources":["../../src/formatter/feature_data_format.ts"],"names":[],"mappings":"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","sourcesContent":["import { faker } from '@faker-js/faker'\n\nconst generateTestData = (\n featureFileContent: string,\n vars?: any,\n fakeData?: {\n var: string\n fake: string\n }[]\n) => {\n const regexp = /\\{\\{([^}]+)\\}\\}/g\n const variableRegex = /^([a-zA-Z0-9_]*)=(.*)/g\n let newContent = featureFileContent\n let match: RegExpExecArray\n const matches = []\n // collect all matches\n while ((match = regexp.exec(featureFileContent)) !== null) {\n matches.push(match)\n }\n // find all variables in the matches\n const variables: any = { ...vars }\n\n if (Object.keys(variables).length > 0) {\n for (let i = 0; i < matches.length; i++) {\n const _match = matches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n newContent = newContent.replaceAll(`{{${variable.var}}}`, variable.fake)\n }\n } else {\n for (let i = 0; i < matches.length; i++) {\n const _match = matches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n variables[variableMatch[1]] = {\n var: variableMatch[1],\n toFake: variableMatch[2],\n }\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n const fake = faker.helpers.fake(`{{${variable.toFake}}}`)\n newContent = newContent.replaceAll(`{{${variable.var}}}`, fake)\n variables[key].fake = fake\n }\n }\n\n regexp.lastIndex = 0\n const otherFakeData = []\n const duplicateFakeData = fakeData ? [...fakeData] : []\n let fakeIndex = 0\n\n while ((match = regexp.exec(featureFileContent)) !== null) {\n try {\n const fake =\n duplicateFakeData && duplicateFakeData.length > 0\n ? duplicateFakeData.shift().fake\n : faker.helpers.fake(match[0])\n otherFakeData.push({\n var: match[0],\n fake,\n })\n newContent = newContent.replace(match[0], fake)\n fakeIndex++\n } catch (err) {\n // eslint-disable-next-line no-console\n console.log('unknown faker variable:' + match[0])\n }\n }\n\n return {\n newContent,\n variables,\n otherFakeData,\n changed: newContent !== featureFileContent,\n fakeIndex,\n }\n}\n\n//let result = generateTestData(\"/Users/guyarieli/Documents/GitHub/ai-qa/cucumber_demo/features/create_issues.feature\");\n//console.log(result.newContent);\nexport { generateTestData }\n"]}
|
|
1
|
+
{"version":3,"file":"feature_data_format.js","sourceRoot":"","sources":["../../src/formatter/feature_data_format.ts"],"names":[],"mappings":"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","sourcesContent":["import { faker } from '@faker-js/faker'\nimport fs from 'fs'\nimport path from 'path'\nimport { TableCell } from '@cucumber/messages'\nimport JSON5 from 'json5'\n\nconst generateTestData = (\n featureFileContent: string,\n vars?: any,\n fakeData?: {\n var: string\n fake: string\n }[],\n projectDir?: string\n) => {\n const regexp = /\\{\\{([^}]*\\([^)]*\\))\\}\\}/g\n const variableRegex = /^([a-zA-Z0-9_]*)=(.*)/g\n let newContent = featureFileContent\n let match: RegExpExecArray\n if (!projectDir) {\n projectDir = process.cwd()\n }\n const namespacePath = path.join(\n projectDir,\n 'features',\n 'step_definitions',\n 'namespaces.json'\n )\n let namespaces: string[] = fs.existsSync(namespacePath)\n ? JSON.parse(fs.readFileSync(namespacePath, 'utf-8'))\n : []\n if (!Array.isArray(namespaces)) {\n namespaces = []\n }\n const matches = []\n // collect all matches\n while ((match = regexp.exec(featureFileContent)) !== null) {\n // match[0] is the full match, match[1] is the first capturing group\n // Eg:- match[0] = {{name}}, match[1] = name\n if (!namespaces.includes(match[1].split('.')[0])) matches.push(match)\n }\n // find all variables in the matches\n const variables: any = { ...vars }\n\n if (Object.keys(variables).length > 0) {\n for (let i = 0; i < matches.length; i++) {\n const _match = matches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n newContent = newContent.replaceAll(`{{${variable.var}}}`, variable.fake)\n }\n } else {\n for (let i = 0; i < matches.length; i++) {\n const _match = matches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n variables[variableMatch[1]] = {\n var: variableMatch[1],\n toFake: variableMatch[2],\n }\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n const fake = getFakeString(\n variable.toFake.substring(2, variable.toFake.length - 2)\n )\n newContent = newContent.replaceAll(`{{${variable.var}}}`, fake)\n variables[key].fake = fake\n }\n }\n\n regexp.lastIndex = 0\n const otherFakeData = []\n const duplicateFakeData = fakeData ? [...fakeData] : []\n let fakeIndex = 0\n while ((match = regexp.exec(featureFileContent)) !== null) {\n if (namespaces.includes(match[1].split('.')[0])) continue\n try {\n const fake =\n duplicateFakeData &&\n duplicateFakeData.length > 0 &&\n duplicateFakeData[0].var === match[0]\n ? duplicateFakeData.shift().fake\n : getFakeString(match[0].substring(2, match[0].length - 2))\n otherFakeData.push({\n var: match[0],\n fake,\n })\n newContent = newContent.replace(match[0], fake)\n fakeIndex++\n } catch (err) {\n // eslint-disable-next-line no-console\n //console.log('unknown faker variable:' + match[0])\n }\n }\n\n return {\n newContent,\n variables,\n otherFakeData,\n changed: newContent !== featureFileContent,\n fakeIndex,\n }\n}\n\nconst getFakeString = (content: string) => {\n const faking = content.split('(')[0].split('.')\n const argument = content.substring(\n content.indexOf('(') + 1,\n content.indexOf(')')\n )\n let fakeFunc: any = faker\n faking.forEach((f: string) => {\n fakeFunc = fakeFunc[f]\n })\n\n try {\n return fakeFunc(JSON5.parse(argument))\n } catch (error) {\n return fakeFunc(argument)\n }\n}\n\nconst getDefinitionFunction = (\n feature_path: string,\n functionName: string,\n functionFile: string\n) => {\n const mjsFiles = fs\n .readdirSync(path.join(feature_path, '../step_definitions'))\n .filter((file) => file === `${functionFile}.js`)\n\n if (mjsFiles.length === 0) {\n throw new Error(`File ${functionFile} not found in step_definitions folder`)\n }\n\n const [mjsData] = mjsFiles.map((file) => {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { [functionName]: func } = require(path.join(\n feature_path,\n '../step_definitions',\n file\n ))\n if (!func)\n throw new Error(`Function ${functionName} not found in file ${file}`)\n\n return func()\n })\n\n return mjsData\n}\n\nconst generateExamplesFromFunction = (\n data: string,\n feature_path: string,\n functionName: string,\n functionFile: string\n) => {\n const examples = data.split('Examples:')[1].split('\\n').slice(1)\n const headers = examples[0]\n .split('|')\n .map((header) => header.trim())\n .filter((header) => header !== '')\n const values = examples[1]\n .split('|')\n .map((value) => value.trim())\n .filter((header) => header !== '')\n\n const mjsData = getDefinitionFunction(\n feature_path,\n functionName,\n functionFile\n )\n\n const newExamples = headers.map((header) => {\n if (mjsData[header]) {\n return mjsData[header]\n }\n return values[headers.indexOf(header)]\n })\n\n let newExamplesString = data.split('Examples:')[1]\n newExamples.forEach((example, index) => {\n newExamplesString = newExamplesString.replace(values[index], example)\n })\n\n const newData = data.replace(data.split('Examples:')[1], newExamplesString)\n\n return { newData, mjsData }\n}\n\nconst generateExamplesFromFunctionGherkin = (\n headers: readonly TableCell[],\n values: readonly TableCell[],\n mjsData: any\n) => {\n const newExamples = headers.map(({ value: header }, index) => {\n if (mjsData[header]) {\n return { header, value: mjsData[header] }\n }\n return { header, value: values[index].value }\n })\n\n return newExamples\n}\n\nexport {\n generateTestData,\n generateExamplesFromFunction,\n generateExamplesFromFunctionGherkin,\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as messages from '@cucumber/messages';
|
|
2
2
|
type JsonTimestamp = number;
|
|
3
|
-
type JsonStepType = 'Unknown' | 'Context' | 'Action' | 'Outcome';
|
|
3
|
+
type JsonStepType = 'Unknown' | 'Context' | 'Action' | 'Outcome' | 'Conjunction';
|
|
4
4
|
export type JsonResultUnknown = {
|
|
5
5
|
status: 'UNKNOWN';
|
|
6
6
|
};
|
|
@@ -48,12 +48,22 @@ type JsonCommand = {
|
|
|
48
48
|
text: string;
|
|
49
49
|
screenshotId?: string;
|
|
50
50
|
result: JsonCommandResult;
|
|
51
|
+
webLog?: webLog[];
|
|
52
|
+
netWorkLog?: any[];
|
|
53
|
+
};
|
|
54
|
+
type webLog = {
|
|
55
|
+
type: string;
|
|
56
|
+
text: string;
|
|
57
|
+
location: string;
|
|
58
|
+
time: string;
|
|
51
59
|
};
|
|
52
60
|
export type JsonStep = {
|
|
61
|
+
keyword: string;
|
|
53
62
|
type: JsonStepType;
|
|
54
63
|
text: string;
|
|
55
64
|
commands: JsonCommand[];
|
|
56
65
|
result: JsonStepResult;
|
|
66
|
+
data?: any;
|
|
57
67
|
};
|
|
58
68
|
export type RetrainStats = {
|
|
59
69
|
result: JsonTestResult;
|
|
@@ -70,19 +80,29 @@ export type JsonTestProgress = {
|
|
|
70
80
|
steps: JsonStep[];
|
|
71
81
|
result: JsonTestResult;
|
|
72
82
|
retrainStats?: RetrainStats;
|
|
83
|
+
webLog: any;
|
|
84
|
+
networkLog: any;
|
|
73
85
|
};
|
|
74
86
|
export type JsonReport = {
|
|
75
87
|
testCases: JsonTestProgress[];
|
|
76
88
|
result: JsonReportResult;
|
|
89
|
+
env: {
|
|
90
|
+
name: string;
|
|
91
|
+
baseUrl: string;
|
|
92
|
+
};
|
|
77
93
|
};
|
|
78
94
|
export default class ReportGenerator {
|
|
79
95
|
private report;
|
|
80
96
|
private gherkinDocumentMap;
|
|
97
|
+
private stepMap;
|
|
81
98
|
private pickleMap;
|
|
82
99
|
private testCaseMap;
|
|
83
100
|
private testStepMap;
|
|
84
|
-
private
|
|
85
|
-
private
|
|
101
|
+
private stepReportMap;
|
|
102
|
+
private testCaseReportMap;
|
|
103
|
+
private scenarioIterationCountMap;
|
|
104
|
+
private logs;
|
|
105
|
+
private networkLog;
|
|
86
106
|
reportFolder: null | string;
|
|
87
107
|
handleMessage(envelope: messages.Envelope): void;
|
|
88
108
|
getReport(): JsonReport;
|
|
@@ -92,10 +112,13 @@ export default class ReportGenerator {
|
|
|
92
112
|
private getTimeStamp;
|
|
93
113
|
private onTestRunStarted;
|
|
94
114
|
private onTestCase;
|
|
115
|
+
private _findScenario;
|
|
116
|
+
private _getParameters;
|
|
95
117
|
private onTestCaseStarted;
|
|
96
118
|
private onTestStepStarted;
|
|
97
119
|
private onAttachment;
|
|
98
120
|
private onTestStepFinished;
|
|
121
|
+
getLogFileContent(): any;
|
|
99
122
|
private getTestCaseResult;
|
|
100
123
|
private onTestCaseFinished;
|
|
101
124
|
private onTestRunFinished;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
3
8
|
class ReportGenerator {
|
|
4
9
|
constructor() {
|
|
5
10
|
this.report = {
|
|
@@ -7,13 +12,21 @@ class ReportGenerator {
|
|
|
7
12
|
status: 'UNKNOWN',
|
|
8
13
|
},
|
|
9
14
|
testCases: [],
|
|
15
|
+
env: {
|
|
16
|
+
name: '',
|
|
17
|
+
baseUrl: '',
|
|
18
|
+
},
|
|
10
19
|
};
|
|
11
20
|
this.gherkinDocumentMap = new Map();
|
|
21
|
+
this.stepMap = new Map();
|
|
12
22
|
this.pickleMap = new Map();
|
|
13
23
|
this.testCaseMap = new Map();
|
|
14
24
|
this.testStepMap = new Map();
|
|
15
|
-
this.
|
|
16
|
-
this.
|
|
25
|
+
this.stepReportMap = new Map();
|
|
26
|
+
this.testCaseReportMap = new Map();
|
|
27
|
+
this.scenarioIterationCountMap = new Map();
|
|
28
|
+
this.logs = [];
|
|
29
|
+
this.networkLog = [];
|
|
17
30
|
this.reportFolder = null;
|
|
18
31
|
}
|
|
19
32
|
handleMessage(envelope) {
|
|
@@ -87,7 +100,7 @@ class ReportGenerator {
|
|
|
87
100
|
return this.report;
|
|
88
101
|
}
|
|
89
102
|
handleParseError(parseError) {
|
|
90
|
-
const { message
|
|
103
|
+
const { message } = parseError;
|
|
91
104
|
const timestamp = new Date().getTime();
|
|
92
105
|
this.report.result = {
|
|
93
106
|
status: 'FAILED',
|
|
@@ -98,6 +111,32 @@ class ReportGenerator {
|
|
|
98
111
|
}
|
|
99
112
|
onGherkinDocument(doc) {
|
|
100
113
|
this.gherkinDocumentMap.set(doc.uri, doc);
|
|
114
|
+
doc.feature.children.forEach((child) => {
|
|
115
|
+
if (child.scenario) {
|
|
116
|
+
child.scenario.steps.forEach((step) => {
|
|
117
|
+
this.stepMap.set(step.id, step);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else if (child.background) {
|
|
121
|
+
child.background.steps.forEach((step) => {
|
|
122
|
+
this.stepMap.set(step.id, step);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
else if (child.rule) {
|
|
126
|
+
child.rule.children.forEach((child) => {
|
|
127
|
+
if (child.scenario) {
|
|
128
|
+
child.scenario.steps.forEach((step) => {
|
|
129
|
+
this.stepMap.set(step.id, step);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else if (child.background) {
|
|
133
|
+
child.background.steps.forEach((step) => {
|
|
134
|
+
this.stepMap.set(step.id, step);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
});
|
|
101
140
|
}
|
|
102
141
|
onPickle(pickle) {
|
|
103
142
|
this.pickleMap.set(pickle.id, pickle);
|
|
@@ -117,6 +156,37 @@ class ReportGenerator {
|
|
|
117
156
|
this.testStepMap.set(testStep.id, testStep);
|
|
118
157
|
});
|
|
119
158
|
}
|
|
159
|
+
_findScenario(doc, scenarioId) {
|
|
160
|
+
for (const child of doc.feature.children) {
|
|
161
|
+
if (child.scenario && child.scenario.id === scenarioId) {
|
|
162
|
+
return child.scenario;
|
|
163
|
+
}
|
|
164
|
+
if (child.rule) {
|
|
165
|
+
for (const scenario of child.rule.children) {
|
|
166
|
+
if (scenario.scenario && scenario.scenario.id === scenarioId) {
|
|
167
|
+
return scenario.scenario;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
throw new Error(`scenario "${scenarioId}" not found`);
|
|
173
|
+
}
|
|
174
|
+
_getParameters(scenario, exampleId) {
|
|
175
|
+
const parameters = {};
|
|
176
|
+
if (scenario.examples.length === 0)
|
|
177
|
+
return parameters;
|
|
178
|
+
for (const examples of scenario.examples) {
|
|
179
|
+
for (const tableRow of examples.tableBody) {
|
|
180
|
+
if (tableRow.id === exampleId) {
|
|
181
|
+
for (let i = 0; i < examples.tableHeader.cells.length; i++) {
|
|
182
|
+
parameters[examples.tableHeader.cells[i].value] =
|
|
183
|
+
tableRow.cells[i].value;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return parameters;
|
|
189
|
+
}
|
|
120
190
|
onTestCaseStarted(testCaseStarted) {
|
|
121
191
|
const { testCaseId, id, timestamp } = testCaseStarted;
|
|
122
192
|
const testCase = this.testCaseMap.get(testCaseId);
|
|
@@ -129,67 +199,112 @@ class ReportGenerator {
|
|
|
129
199
|
if (doc === undefined)
|
|
130
200
|
throw new Error(`gherkinDocument with uri ${pickle.uri} not found`);
|
|
131
201
|
const featureName = doc.feature.name;
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
202
|
+
const scenarioId = pickle.astNodeIds[0];
|
|
203
|
+
const scenario = this._findScenario(doc, scenarioId);
|
|
204
|
+
const scenarioName = scenario.name;
|
|
205
|
+
if (!this.scenarioIterationCountMap.has(scenarioId)) {
|
|
206
|
+
this.scenarioIterationCountMap.set(scenarioId, 1);
|
|
207
|
+
}
|
|
208
|
+
const parameters = this._getParameters(scenario, pickle.astNodeIds[1]);
|
|
209
|
+
console.log(`Running scenario ${scenarioName} iteration ${this.scenarioIterationCountMap.get(scenarioId)} with parameters:\n${JSON.stringify(parameters, null, 4)}\n
|
|
210
|
+
`);
|
|
211
|
+
this.scenarioIterationCountMap.set(scenarioId, this.scenarioIterationCountMap.get(scenarioId) + 1);
|
|
212
|
+
const steps = pickle.steps.map((pickleStep) => {
|
|
213
|
+
const stepId = pickleStep.astNodeIds[0];
|
|
214
|
+
const step = this.stepMap.get(stepId);
|
|
215
|
+
this.stepReportMap.set(pickleStep.id, {
|
|
216
|
+
type: step.keywordType,
|
|
217
|
+
keyword: step.keyword,
|
|
136
218
|
text: step.text,
|
|
137
219
|
commands: [],
|
|
138
220
|
result: {
|
|
139
221
|
status: 'UNKNOWN',
|
|
140
222
|
},
|
|
141
223
|
});
|
|
142
|
-
return this.
|
|
224
|
+
return this.stepReportMap.get(pickleStep.id);
|
|
143
225
|
});
|
|
144
|
-
this.
|
|
226
|
+
this.testCaseReportMap.set(id, {
|
|
145
227
|
id,
|
|
146
228
|
uri: pickle.uri,
|
|
147
229
|
featureName,
|
|
148
230
|
scenarioName,
|
|
149
|
-
|
|
150
|
-
parameters: {},
|
|
231
|
+
parameters,
|
|
151
232
|
steps,
|
|
152
233
|
result: {
|
|
153
234
|
status: 'STARTED',
|
|
154
235
|
startTime: this.getTimeStamp(timestamp),
|
|
155
236
|
},
|
|
237
|
+
webLog: [],
|
|
238
|
+
networkLog: [],
|
|
156
239
|
});
|
|
157
|
-
this.report.testCases.push(this.
|
|
240
|
+
this.report.testCases.push(this.testCaseReportMap.get(id));
|
|
158
241
|
}
|
|
159
242
|
onTestStepStarted(testStepStarted) {
|
|
160
|
-
const { testStepId, timestamp
|
|
243
|
+
const { testStepId, timestamp } = testStepStarted;
|
|
161
244
|
const testStep = this.testStepMap.get(testStepId);
|
|
162
245
|
if (testStep === undefined)
|
|
163
246
|
throw new Error(`testStep with id ${testStepId} not found`);
|
|
164
247
|
if (testStep.pickleStepId === undefined)
|
|
165
248
|
return;
|
|
166
|
-
const stepProgess = this.
|
|
249
|
+
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
167
250
|
stepProgess.result = {
|
|
168
251
|
status: 'STARTED',
|
|
169
252
|
startTime: this.getTimeStamp(timestamp),
|
|
170
253
|
};
|
|
171
254
|
}
|
|
172
255
|
onAttachment(attachment) {
|
|
173
|
-
const {
|
|
256
|
+
const { testStepId, body, mediaType } = attachment;
|
|
174
257
|
if (mediaType === 'text/plain') {
|
|
175
258
|
this.reportFolder = body.replaceAll('\\', '/');
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (mediaType === 'application/json+env') {
|
|
262
|
+
const data = JSON.parse(body);
|
|
263
|
+
this.report.env = data;
|
|
264
|
+
}
|
|
265
|
+
if (mediaType === 'application/json+log') {
|
|
266
|
+
const log = JSON.parse(body);
|
|
267
|
+
if (this.logs.length < 1000)
|
|
268
|
+
this.logs.push(log);
|
|
269
|
+
}
|
|
270
|
+
if (mediaType === 'application/json+network') {
|
|
271
|
+
const networkLog = JSON.parse(body);
|
|
272
|
+
if (this.networkLog.length < 1000)
|
|
273
|
+
this.networkLog.push(networkLog);
|
|
176
274
|
}
|
|
177
275
|
const testStep = this.testStepMap.get(testStepId);
|
|
178
276
|
if (testStep.pickleStepId === undefined)
|
|
179
277
|
return;
|
|
180
|
-
const stepProgess = this.
|
|
278
|
+
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
181
279
|
if (mediaType === 'application/json') {
|
|
182
280
|
const command = JSON.parse(body);
|
|
183
281
|
stepProgess.commands.push(command);
|
|
184
282
|
}
|
|
185
283
|
}
|
|
186
284
|
onTestStepFinished(testStepFinished) {
|
|
187
|
-
const { testStepId,
|
|
285
|
+
const { testStepId, testStepResult, timestamp } = testStepFinished;
|
|
188
286
|
const testStep = this.testStepMap.get(testStepId);
|
|
189
|
-
if (testStep.pickleStepId === undefined)
|
|
287
|
+
if (testStep.pickleStepId === undefined) {
|
|
288
|
+
if (testStepResult.status === 'FAILED') {
|
|
289
|
+
console.error(`Before/After hook failed with message: ${testStepResult.message}`);
|
|
290
|
+
}
|
|
190
291
|
return;
|
|
191
|
-
|
|
292
|
+
}
|
|
293
|
+
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
192
294
|
const prevStepResult = stepProgess.result;
|
|
295
|
+
let data = {};
|
|
296
|
+
const reportFolder = this.reportFolder;
|
|
297
|
+
if (reportFolder === null) {
|
|
298
|
+
throw new Error('"reportFolder" is "null". Failed to run BVT hooks. Please retry after running "Generate All" or "Record Scenario" ');
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
if (fs_1.default.existsSync(path_1.default.join(reportFolder, 'data.json'))) {
|
|
302
|
+
data = JSON.parse(fs_1.default.readFileSync(path_1.default.join(reportFolder, 'data.json'), 'utf8'));
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
console.log('Error reading data.json');
|
|
307
|
+
}
|
|
193
308
|
stepProgess.result = {
|
|
194
309
|
status: testStepResult.status,
|
|
195
310
|
startTime: prevStepResult.startTime,
|
|
@@ -197,6 +312,33 @@ class ReportGenerator {
|
|
|
197
312
|
message: testStepResult.message,
|
|
198
313
|
// exception: testStepResult.exception,
|
|
199
314
|
};
|
|
315
|
+
if (Object.keys(data).length > 0) {
|
|
316
|
+
stepProgess.data = data;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
getLogFileContent() {
|
|
320
|
+
let projectPath = process.cwd();
|
|
321
|
+
if (process.env.PROJECT_PATH) {
|
|
322
|
+
projectPath = process.env.PROJECT_PATH;
|
|
323
|
+
}
|
|
324
|
+
const logFolder = path_1.default.join(projectPath, 'logs', 'web');
|
|
325
|
+
if (!fs_1.default.existsSync(logFolder)) {
|
|
326
|
+
return [];
|
|
327
|
+
}
|
|
328
|
+
let nextId = 1;
|
|
329
|
+
while (fs_1.default.existsSync(path_1.default.join(logFolder, `${nextId}.json`))) {
|
|
330
|
+
nextId++;
|
|
331
|
+
}
|
|
332
|
+
if (nextId === 1) {
|
|
333
|
+
return [];
|
|
334
|
+
}
|
|
335
|
+
try {
|
|
336
|
+
const logFileContent = fs_1.default.readFileSync(path_1.default.join(logFolder, `${nextId - 1}.json`), 'utf8');
|
|
337
|
+
return JSON.parse(logFileContent);
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
return [];
|
|
341
|
+
}
|
|
200
342
|
}
|
|
201
343
|
getTestCaseResult(steps) {
|
|
202
344
|
for (const step of steps) {
|
|
@@ -222,7 +364,7 @@ class ReportGenerator {
|
|
|
222
364
|
}
|
|
223
365
|
onTestCaseFinished(testCaseFinished) {
|
|
224
366
|
const { testCaseStartedId, timestamp } = testCaseFinished;
|
|
225
|
-
const testProgress = this.
|
|
367
|
+
const testProgress = this.testCaseReportMap.get(testCaseStartedId);
|
|
226
368
|
const prevResult = testProgress.result;
|
|
227
369
|
const steps = Object.values(testProgress.steps);
|
|
228
370
|
const result = this.getTestCaseResult(steps);
|
|
@@ -231,9 +373,13 @@ class ReportGenerator {
|
|
|
231
373
|
startTime: prevResult.startTime,
|
|
232
374
|
endTime: this.getTimeStamp(timestamp),
|
|
233
375
|
};
|
|
376
|
+
testProgress.webLog = this.logs;
|
|
377
|
+
testProgress.networkLog = this.networkLog;
|
|
378
|
+
this.networkLog = [];
|
|
379
|
+
this.logs = [];
|
|
234
380
|
}
|
|
235
381
|
onTestRunFinished(testRunFinished) {
|
|
236
|
-
const { timestamp, success,
|
|
382
|
+
const { timestamp, success, message } = testRunFinished;
|
|
237
383
|
const prevResult = this.report.result;
|
|
238
384
|
this.report.result = {
|
|
239
385
|
status: success ? 'PASSED' : 'FAILED',
|