@dev-blinq/cucumber-js 1.0.96-dev → 1.0.96-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 +22 -2
- package/lib/cli/validate_node_engine_version.js +3 -1
- package/lib/cli/validate_node_engine_version.js.map +1 -1
- package/lib/configuration/axios_client.js +1 -1
- package/lib/configuration/axios_client.js.map +1 -1
- package/lib/formatter/api.js +7 -1
- package/lib/formatter/api.js.map +1 -1
- package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
- package/lib/formatter/bvt_analysis_formatter.js +214 -76
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.js +3 -1
- package/lib/formatter/feature_data_format.js.map +1 -1
- package/lib/formatter/helpers/constants.d.ts +50 -0
- package/lib/formatter/helpers/constants.js +60 -0
- package/lib/formatter/helpers/constants.js.map +1 -0
- package/lib/formatter/helpers/report_generator.d.ts +32 -2
- package/lib/formatter/helpers/report_generator.js +342 -15
- package/lib/formatter/helpers/report_generator.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_formatter.js +1 -1
- package/lib/formatter/helpers/test_case_attempt_formatter.js.map +1 -1
- package/lib/formatter/helpers/upload_serivce.d.ts +16 -0
- package/lib/formatter/helpers/upload_serivce.js +158 -0
- package/lib/formatter/helpers/upload_serivce.js.map +1 -1
- package/lib/formatter/helpers/uploader.d.ts +2 -1
- package/lib/formatter/helpers/uploader.js +29 -3
- package/lib/formatter/helpers/uploader.js.map +1 -1
- package/lib/formatter/summary_formatter.js +4 -0
- package/lib/formatter/summary_formatter.js.map +1 -1
- package/lib/runtime/test_case_runner.d.ts +1 -0
- package/lib/runtime/test_case_runner.js +10 -1
- package/lib/runtime/test_case_runner.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 +4 -2
package/bin/download-install.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
/* eslint-disable no-undef */
|
|
1
4
|
const { argv } = require('node:process')
|
|
2
5
|
const fs = require('fs')
|
|
3
6
|
const path = require('path')
|
|
@@ -16,8 +19,14 @@ const getSSoUrl = () => {
|
|
|
16
19
|
return 'https://dev.api.blinq.io/api/auth'
|
|
17
20
|
case 'stage':
|
|
18
21
|
return 'https://stage.api.blinq.io/api/auth'
|
|
19
|
-
|
|
22
|
+
case 'prod':
|
|
23
|
+
return 'https://api.blinq.io/api/auth'
|
|
24
|
+
case null:
|
|
25
|
+
return 'https://api.blinq.io/api/auth'
|
|
26
|
+
case undefined:
|
|
20
27
|
return 'https://api.blinq.io/api/auth'
|
|
28
|
+
default:
|
|
29
|
+
return `${process.env.NODE_ENV_BLINQ}/api/auth`
|
|
21
30
|
}
|
|
22
31
|
}
|
|
23
32
|
|
|
@@ -48,8 +57,14 @@ const getWorkSpaceUrl = () => {
|
|
|
48
57
|
return 'https://dev.api.blinq.io/api/workspace'
|
|
49
58
|
case "stage":
|
|
50
59
|
return 'https://stage.api.blinq.io/api/workspace'
|
|
51
|
-
|
|
60
|
+
case 'prod':
|
|
61
|
+
return 'https://api.blinq.io/api/workspace'
|
|
62
|
+
case null:
|
|
52
63
|
return 'https://api.blinq.io/api/workspace'
|
|
64
|
+
case undefined:
|
|
65
|
+
return 'https://api.blinq.io/api/workspace'
|
|
66
|
+
default:
|
|
67
|
+
return `${process.env.NODE_ENV_BLINQ}/api/workspace`
|
|
53
68
|
}
|
|
54
69
|
}
|
|
55
70
|
|
|
@@ -137,6 +152,11 @@ const downloadAndInstall = async (extractPath, token) => {
|
|
|
137
152
|
},
|
|
138
153
|
})
|
|
139
154
|
|
|
155
|
+
if (res.status !== 200) {
|
|
156
|
+
console.error('Error: Unable to fetch workspace')
|
|
157
|
+
process.exit(1)
|
|
158
|
+
}
|
|
159
|
+
|
|
140
160
|
const zip = await JSZip.loadAsync(res.data)
|
|
141
161
|
for (const filename of Object.keys(zip.files)) {
|
|
142
162
|
const fileData = zip.files[filename]
|
|
@@ -17,7 +17,9 @@ function validateNodeEngineVersion(currentVersion, onError, onWarning, readPacka
|
|
|
17
17
|
onError(`Cucumber can only run on Node.js versions ${requiredVersions}. This Node.js version is ${currentVersion}`);
|
|
18
18
|
}
|
|
19
19
|
else if (!semver_1.default.satisfies(currentVersion, testedVersions)) {
|
|
20
|
-
onWarning(
|
|
20
|
+
// onWarning(
|
|
21
|
+
// `This Node.js version (${currentVersion}) has not been tested with this version of Cucumber; it should work normally, but please raise an issue if you see anything unexpected.`
|
|
22
|
+
// )
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
exports.validateNodeEngineVersion = validateNodeEngineVersion;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate_node_engine_version.js","sourceRoot":"","sources":["../../src/cli/validate_node_engine_version.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAmB;AACnB,gDAAuB;AACvB,oDAA2B;AAO3B,MAAM,qBAAqB,GAAsB,GAAG,EAAE,CACpD,IAAI,CAAC,KAAK,CACR,YAAE;KACC,YAAY,CAAC,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;KACjE,QAAQ,EAAE,CACd,CAAA;AAEH,SAAgB,yBAAyB,CACvC,cAAsB,EACtB,OAAkC,EAClC,SAAoC,EACpC,kBAAqC,qBAAqB;IAE1D,MAAM,gBAAgB,GAAG,eAAe,EAAE,CAAC,OAAO,CAAC,IAAI,CAAA;IACvD,MAAM,cAAc,GAAG,eAAe,EAAE,CAAC,aAAa,CAAC,IAAI,CAAA;IAC3D,IAAI,CAAC,gBAAM,CAAC,SAAS,CAAC,cAAc,EAAE,gBAAgB,CAAC,EAAE;QACvD,OAAO,CACL,6CAA6C,gBAAgB,6BAA6B,cAAc,EAAE,CAC3G,CAAA;KACF;SAAM,IAAI,CAAC,gBAAM,CAAC,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC,EAAE;QAC5D,
|
|
1
|
+
{"version":3,"file":"validate_node_engine_version.js","sourceRoot":"","sources":["../../src/cli/validate_node_engine_version.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAmB;AACnB,gDAAuB;AACvB,oDAA2B;AAO3B,MAAM,qBAAqB,GAAsB,GAAG,EAAE,CACpD,IAAI,CAAC,KAAK,CACR,YAAE;KACC,YAAY,CAAC,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;KACjE,QAAQ,EAAE,CACd,CAAA;AAEH,SAAgB,yBAAyB,CACvC,cAAsB,EACtB,OAAkC,EAClC,SAAoC,EACpC,kBAAqC,qBAAqB;IAE1D,MAAM,gBAAgB,GAAG,eAAe,EAAE,CAAC,OAAO,CAAC,IAAI,CAAA;IACvD,MAAM,cAAc,GAAG,eAAe,EAAE,CAAC,aAAa,CAAC,IAAI,CAAA;IAC3D,IAAI,CAAC,gBAAM,CAAC,SAAS,CAAC,cAAc,EAAE,gBAAgB,CAAC,EAAE;QACvD,OAAO,CACL,6CAA6C,gBAAgB,6BAA6B,cAAc,EAAE,CAC3G,CAAA;KACF;SAAM,IAAI,CAAC,gBAAM,CAAC,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC,EAAE;QAC5D,aAAa;QACb,qLAAqL;QACrL,IAAI;KACL;AACH,CAAC;AAjBD,8DAiBC","sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport semver from 'semver'\n\ntype PackageJSON = {\n engines: { node: string }\n enginesTested: { node: string }\n}\n\nconst readActualPackageJSON: () => PackageJSON = () =>\n JSON.parse(\n fs\n .readFileSync(path.resolve(__dirname, '..', '..', 'package.json'))\n .toString()\n )\n\nexport function validateNodeEngineVersion(\n currentVersion: string,\n onError: (message: string) => void,\n onWarning: (message: string) => void,\n readPackageJSON: () => PackageJSON = readActualPackageJSON\n): void {\n const requiredVersions = readPackageJSON().engines.node\n const testedVersions = readPackageJSON().enginesTested.node\n if (!semver.satisfies(currentVersion, requiredVersions)) {\n onError(\n `Cucumber can only run on Node.js versions ${requiredVersions}. This Node.js version is ${currentVersion}`\n )\n } else if (!semver.satisfies(currentVersion, testedVersions)) {\n // onWarning(\n // `This Node.js version (${currentVersion}) has not been tested with this version of Cucumber; it should work normally, but please raise an issue if you see anything unexpected.`\n // )\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"axios_client.js","sourceRoot":"","sources":["../../src/configuration/axios_client.ts"],"names":[],"mappings":";;;;;;AAAA,+BAA+B;AAC/B,kDAAyB;AACzB,oDAA6C;AAG7C,MAAM,QAAQ,GAAG,GAAiB,EAAE;IAClC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE;QACtB,OAAO,IAAI,CAAA;KACZ;IAED,MAAM,KAAK,GAAkB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAA;IAC9C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;IAC1B,MAAM,WAAW,GAAiB;QAChC,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;KACvB,CAAA;IAED,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAA;IAElC,IAAI,QAAQ,IAAI,QAAQ,EAAE;QACxB,WAAW,CAAC,SAAS,GAAG,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAA;KAClD;IACD,OAAO,gBAAM,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;AACrD,CAAC,CAAA;AAED,MAAM,iBAAiB,GAAG,GAAG,EAAE;IAC7B,IAAI;QACF,MAAM,KAAK,GAAmB,QAAQ,EAAE,CAAA;QACxC,OAAO,eAAK,CAAC,MAAM,CAAC;YAClB,
|
|
1
|
+
{"version":3,"file":"axios_client.js","sourceRoot":"","sources":["../../src/configuration/axios_client.ts"],"names":[],"mappings":";;;;;;AAAA,+BAA+B;AAC/B,kDAAyB;AACzB,oDAA6C;AAG7C,MAAM,QAAQ,GAAG,GAAiB,EAAE;IAClC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE;QACtB,OAAO,IAAI,CAAA;KACZ;IAED,MAAM,KAAK,GAAkB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAA;IAC9C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;IAC1B,MAAM,WAAW,GAAiB;QAChC,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;KACvB,CAAA;IAED,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAA;IAElC,IAAI,QAAQ,IAAI,QAAQ,EAAE;QACxB,WAAW,CAAC,SAAS,GAAG,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAA;KAClD;IACD,OAAO,gBAAM,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;AACrD,CAAC,CAAA;AAED,MAAM,iBAAiB,GAAG,GAAG,EAAE;IAC7B,IAAI;QACF,MAAM,KAAK,GAAmB,QAAQ,EAAE,CAAA;QACxC,OAAO,eAAK,CAAC,MAAM,CAAC;YAClB,UAAU,EAAE,KAAK;YACjB,KAAK,EAAE,KAAK;SACb,CAAC,CAAA;KACH;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC1B,MAAM,IAAI,KAAK,CACb,+BACE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAC1D,EAAE,CACH,CAAA;KACF;AACH,CAAC,CAAA;AAEY,QAAA,WAAW,GAAG,iBAAiB,EAAE,CAAA","sourcesContent":["/* eslint-disable no-console */\nimport axios from 'axios'\nimport tunnel, { ProxyOptions } from 'tunnel'\nimport { Agent } from 'http'\n\nconst getProxy = (): Agent | null => {\n if (!process.env.PROXY) {\n return null\n }\n\n const proxy: string | null = process.env.PROXY\n const url = new URL(proxy)\n const proxyObject: ProxyOptions = {\n host: url.hostname,\n port: Number(url.port),\n }\n\n const { username, password } = url\n\n if (username && password) {\n proxyObject.proxyAuth = `${username}:${password}`\n }\n return tunnel.httpsOverHttp({ proxy: proxyObject })\n}\n\nconst createAxiosClient = () => {\n try {\n const agent: string | Agent = getProxy()\n return axios.create({\n httpsAgent: agent,\n proxy: false,\n })\n } catch (error) {\n console.log(error.message)\n throw new Error(\n `Error creating axios client ${\n error instanceof Error ? error.message : error.response.data\n }`\n )\n }\n}\n\nexport const axiosClient = createAxiosClient()\n"]}
|
package/lib/formatter/api.js
CHANGED
|
@@ -14,8 +14,14 @@ const getSSoUrl = () => {
|
|
|
14
14
|
return 'https://dev.api.blinq.io/api/auth';
|
|
15
15
|
case 'stage':
|
|
16
16
|
return 'https://stage.api.blinq.io/api/auth';
|
|
17
|
-
|
|
17
|
+
case 'prod':
|
|
18
|
+
return 'https://api.blinq.io/api/auth';
|
|
19
|
+
case null:
|
|
18
20
|
return 'https://api.blinq.io/api/auth';
|
|
21
|
+
case undefined:
|
|
22
|
+
return 'https://api.blinq.io/api/auth';
|
|
23
|
+
default:
|
|
24
|
+
return `${process.env.NODE_ENV_BLINQ}/api/auth`;
|
|
19
25
|
}
|
|
20
26
|
};
|
|
21
27
|
const getProxy = () => {
|
package/lib/formatter/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/formatter/api.ts"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,oDAA2B;AAE3B,MAAM,SAAS,GAAG,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/formatter/api.ts"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,oDAA2B;AAE3B,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,QAAQ,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE;QAClC,KAAK,OAAO;YACV,OAAO,gCAAgC,CAAA;QACzC,KAAK,KAAK;YACR,OAAO,mCAAmC,CAAA;QAC5C,KAAK,OAAO;YACV,OAAO,qCAAqC,CAAA;QAC9C,KAAK,MAAM;YACT,OAAO,+BAA+B,CAAA;QACxC,KAAK,IAAI;YACP,OAAO,+BAA+B,CAAA;QACxC,KAAK,SAAS;YACZ,OAAO,+BAA+B,CAAA;QACxC;YACE,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW,CAAA;KAClD;AACH,CAAC,CAAA;AACD,MAAM,QAAQ,GAAG,GAAG,EAAE;IACpB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE;QACtB,OAAO,IAAI,CAAA;KACZ;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAA;IAC/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;IAC1B,MAAM,WAAW,GAAG;QAClB,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;KACvB,CAAA;IAED,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAA;IAElC,IAAI,QAAQ,IAAI,QAAQ,EAAE;QACxB,YAAY;QACZ,WAAW,CAAC,SAAS,GAAG,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAA;KAClD;IACD,OAAO,gBAAM,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;AACrD,CAAC,CAAA;AAED,MAAM,qBAAqB,GAAG,KAAK,EAAE,UAAkB,EAAE,EAAE;IACzD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,YAAY,GAAG,GAAG,MAAM,wBAAwB,CAAA;IACtD,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAAC,YAAY,EAAE;QAC9C,UAAU;QACV,SAAS,EAAE,QAAQ,EAAE;QACrB,KAAK,EAAE,KAAK;KACb,CAAC,CAAA;IACF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE;QAC3B,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAA;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;KAChB;IACD,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC,CAAA;AAEQ,sDAAqB","sourcesContent":["import axios from 'axios'\nimport tunnel from 'tunnel'\n\nconst getSSoUrl = () => {\n switch (process.env.NODE_ENV_BLINQ) {\n case 'local':\n return 'http://localhost:5000/api/auth'\n case 'dev':\n return 'https://dev.api.blinq.io/api/auth'\n case 'stage':\n return 'https://stage.api.blinq.io/api/auth'\n case 'prod':\n return 'https://api.blinq.io/api/auth'\n case null:\n return 'https://api.blinq.io/api/auth'\n case undefined:\n return 'https://api.blinq.io/api/auth'\n default:\n return `${process.env.NODE_ENV_BLINQ}/api/auth`\n }\n}\nconst getProxy = () => {\n if (!process.env.PROXY) {\n return null\n }\n\n const proxy = process.env.PROXY\n const url = new URL(proxy)\n const proxyObject = {\n host: url.hostname,\n port: Number(url.port),\n }\n\n const { username, password } = url\n\n if (username && password) {\n //@ts-ignore\n proxyObject.proxyAuth = `${username}:${password}`\n }\n return tunnel.httpsOverHttp({ proxy: proxyObject })\n}\n\nconst getProjectByAccessKey = async (access_key: string) => {\n const ssoUrl = getSSoUrl()\n const accessKeyUrl = `${ssoUrl}/getProjectByAccessKey`\n const response = await axios.post(accessKeyUrl, {\n access_key,\n httpAgent: getProxy(),\n proxy: false,\n })\n if (response.status !== 200) {\n console.error('Error: Invalid access key')\n process.exit(1)\n }\n return response.data\n}\n\nexport { getProjectByAccessKey }\n"]}
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import Formatter, { IFormatterOptions } from '.';
|
|
2
|
+
import ReportGenerator, { JsonTestResult } from './helpers/report_generator';
|
|
3
|
+
export declare let globalReportLink: string;
|
|
2
4
|
export default class BVTAnalysisFormatter extends Formatter {
|
|
5
|
+
static reportGenerator: ReportGenerator;
|
|
6
|
+
static reRunFailedStepsIndex: {
|
|
7
|
+
testCaseId: string;
|
|
8
|
+
failedStepIndex: number;
|
|
9
|
+
}[] | null;
|
|
3
10
|
private reportGenerator;
|
|
4
11
|
private uploader;
|
|
5
12
|
private exit;
|
|
6
13
|
private START;
|
|
7
14
|
private runName;
|
|
15
|
+
private failedStepsIndex;
|
|
16
|
+
private summaryFormatter;
|
|
17
|
+
private rootCauseArray;
|
|
8
18
|
constructor(options: IFormatterOptions);
|
|
19
|
+
private sendEvent;
|
|
9
20
|
private uploadReport;
|
|
10
21
|
finished(): Promise<any>;
|
|
11
22
|
private analyzeReport;
|
|
@@ -13,7 +24,8 @@ export default class BVTAnalysisFormatter extends Formatter {
|
|
|
13
24
|
private processTestCase;
|
|
14
25
|
private uploadFinalReport;
|
|
15
26
|
private retrain;
|
|
27
|
+
private rerun;
|
|
16
28
|
private call_cucumber_client;
|
|
17
|
-
private logReportLink;
|
|
18
29
|
private getAppDataDir;
|
|
19
30
|
}
|
|
31
|
+
export declare function logReportLink(runId: string, projectId: string, status: JsonTestResult): string;
|
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.logReportLink = exports.globalReportLink = void 0;
|
|
6
7
|
const child_process_1 = require("child_process");
|
|
7
8
|
const fs_1 = require("fs");
|
|
8
9
|
const promises_1 = require("fs/promises");
|
|
@@ -14,36 +15,76 @@ const report_generator_1 = __importDefault(require("./helpers/report_generator")
|
|
|
14
15
|
const uploader_1 = __importDefault(require("./helpers/uploader"));
|
|
15
16
|
const os_1 = __importDefault(require("os"));
|
|
16
17
|
const api_1 = require("./api");
|
|
18
|
+
const summary_formatter_1 = __importDefault(require("./summary_formatter"));
|
|
19
|
+
const constants_1 = require("./helpers/constants");
|
|
20
|
+
const axios_client_1 = require("../configuration/axios_client");
|
|
21
|
+
const util_1 = require("util");
|
|
22
|
+
const child_process_2 = require("child_process");
|
|
17
23
|
//User token
|
|
18
24
|
const TOKEN = process.env.TOKEN;
|
|
25
|
+
exports.globalReportLink = '';
|
|
19
26
|
class BVTAnalysisFormatter extends _1.default {
|
|
20
27
|
constructor(options) {
|
|
21
28
|
super(options);
|
|
22
29
|
this.reportGenerator = new report_generator_1.default();
|
|
23
30
|
this.uploader = new uploader_1.default(this.reportGenerator);
|
|
24
31
|
this.exit = false;
|
|
32
|
+
this.rootCauseArray = [];
|
|
33
|
+
this.summaryFormatter = new summary_formatter_1.default(options);
|
|
34
|
+
BVTAnalysisFormatter.reportGenerator = this.reportGenerator;
|
|
35
|
+
this.rootCauseArray = [];
|
|
36
|
+
this.failedStepsIndex = [];
|
|
37
|
+
BVTAnalysisFormatter.reRunFailedStepsIndex = process.env.RERUN
|
|
38
|
+
? JSON.parse(process.env.RERUN)
|
|
39
|
+
: null;
|
|
25
40
|
if (!TOKEN && process.env.BVT_FORMATTER === 'ANALYSIS') {
|
|
26
41
|
throw new Error('TOKEN must be set');
|
|
27
42
|
}
|
|
28
|
-
|
|
29
|
-
|
|
43
|
+
this.sendEvent(constants_1.ActionEvents.cli_run_tests);
|
|
44
|
+
options.eventBroadcaster.on('envelope', async (envelope, data) => {
|
|
45
|
+
if ((0, value_checker_1.doesHaveValue)(envelope.testCaseFinished) && data) {
|
|
46
|
+
const { rootCause, report } = data;
|
|
47
|
+
if (!rootCause.status) {
|
|
48
|
+
console.error(`Root cause: ${rootCause.failClass}\n, ${rootCause.analysis}\nfailing step: ${rootCause.failedStep}`);
|
|
49
|
+
this.rootCauseArray.push({ rootCause, report });
|
|
50
|
+
this.failedStepsIndex.push({
|
|
51
|
+
testCaseId: report.id,
|
|
52
|
+
failedStepIndex: rootCause.failedStep,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
await this.reportGenerator.handleMessage(envelope);
|
|
30
58
|
if ((0, value_checker_1.doesHaveValue)(envelope.meta) &&
|
|
31
59
|
(0, value_checker_1.doesHaveValue)(envelope.meta.runName)) {
|
|
32
60
|
this.runName = envelope.meta.runName;
|
|
33
61
|
}
|
|
34
62
|
if ((0, value_checker_1.doesHaveValue)(envelope.testRunFinished)) {
|
|
35
|
-
const report = this.reportGenerator.getReport();
|
|
36
63
|
this.START = Date.now();
|
|
37
64
|
if (process.env.BVT_FORMATTER === 'ANALYSIS') {
|
|
38
|
-
await this.analyzeReport(
|
|
65
|
+
await this.analyzeReport();
|
|
39
66
|
}
|
|
40
67
|
else {
|
|
41
|
-
await this.uploadReport(report)
|
|
68
|
+
// await this.uploadReport(report)
|
|
42
69
|
}
|
|
43
70
|
this.exit = true;
|
|
44
71
|
}
|
|
45
72
|
});
|
|
46
73
|
}
|
|
74
|
+
sendEvent(event) {
|
|
75
|
+
axios_client_1.axiosClient
|
|
76
|
+
.post(`${constants_1.SERVICES_URI.STORAGE}/event`, {
|
|
77
|
+
event,
|
|
78
|
+
}, {
|
|
79
|
+
headers: {
|
|
80
|
+
Authorization: `Bearer ${TOKEN}`,
|
|
81
|
+
'x-source': 'cucumber_js',
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
.catch((err) => {
|
|
85
|
+
// Error with events, ignoring
|
|
86
|
+
});
|
|
87
|
+
}
|
|
47
88
|
async uploadReport(report) {
|
|
48
89
|
const uploadSuccessful = await this.uploadFinalReport(report);
|
|
49
90
|
if (uploadSuccessful && report.result.status !== 'FAILED') {
|
|
@@ -54,77 +95,80 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
54
95
|
async finished() {
|
|
55
96
|
await new Promise((resolve) => {
|
|
56
97
|
const checkInterval = setInterval(() => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
98
|
+
let anyRem;
|
|
99
|
+
if (process.env.UPLOADING_TEST_CASE) {
|
|
100
|
+
anyRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
anyRem = undefined;
|
|
104
|
+
}
|
|
105
|
+
if (this.exit && (!anyRem || anyRem.length === 0)) {
|
|
106
|
+
// clearInterval(checkInterval)
|
|
107
|
+
// resolve(null)
|
|
108
|
+
if (this.reportGenerator.getReport().result.status === 'FAILED') {
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
process.exit(0);
|
|
113
|
+
}
|
|
60
114
|
}
|
|
61
115
|
}, 100); // check every 100ms
|
|
62
116
|
});
|
|
63
117
|
}
|
|
64
|
-
async analyzeReport(
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
process.exit(0);
|
|
118
|
+
async analyzeReport() {
|
|
119
|
+
if (this.rootCauseArray.length === 0 ||
|
|
120
|
+
process.env.NO_RETRAIN === 'false') {
|
|
121
|
+
if (this.rootCauseArray.length === 0) {
|
|
122
|
+
this.log('No test failed. No need to retrain\n');
|
|
70
123
|
}
|
|
71
|
-
process.
|
|
124
|
+
if (process.env.NO_RETRAIN === 'false') {
|
|
125
|
+
this.log('Retraining is skipped since the failed step contains an API request\n');
|
|
126
|
+
}
|
|
127
|
+
// const uploadSuccessful = await this.uploadFinalReport(report)
|
|
128
|
+
// process.exit(0)
|
|
129
|
+
this.exit = true;
|
|
130
|
+
return;
|
|
72
131
|
}
|
|
73
132
|
//checking if the type of report.result is JsonResultFailed or not
|
|
74
133
|
this.log('Some tests failed, starting the retraining...\n');
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
await this.uploadFinalReport(report);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
const finalReport = await this.processTestCases(report);
|
|
81
|
-
const uploadSuccessful = await this.uploadFinalReport(finalReport);
|
|
82
|
-
if (finalReport.result.status !== 'FAILED' && uploadSuccessful) {
|
|
83
|
-
process.exit(0);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
134
|
+
await this.processTestCases();
|
|
135
|
+
if (this.reportGenerator.getReport().result.status === 'FAILED') {
|
|
86
136
|
process.exit(1);
|
|
87
137
|
}
|
|
138
|
+
process.exit(0);
|
|
88
139
|
}
|
|
89
|
-
async processTestCases(
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
const modifiedTestCase = await this.processTestCase(testCase, report);
|
|
93
|
-
finalTestCases.push(modifiedTestCase);
|
|
140
|
+
async processTestCases() {
|
|
141
|
+
for (const { rootCause, report } of this.rootCauseArray) {
|
|
142
|
+
await this.processTestCase(rootCause, report);
|
|
94
143
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
async processTestCase(testCase, report) {
|
|
108
|
-
if (testCase.result.status === 'PASSED') {
|
|
109
|
-
return testCase;
|
|
144
|
+
}
|
|
145
|
+
async processTestCase(rootCause, report) {
|
|
146
|
+
const failedTestSteps = rootCause.failedStep;
|
|
147
|
+
if (BVTAnalysisFormatter.reRunFailedStepsIndex &&
|
|
148
|
+
BVTAnalysisFormatter.reRunFailedStepsIndex.length > 0) {
|
|
149
|
+
const previousRun = BVTAnalysisFormatter.reRunFailedStepsIndex[0];
|
|
150
|
+
if (previousRun.failedStepIndex === failedTestSteps) {
|
|
151
|
+
console.log('Same step has failed again, skipping retraining');
|
|
152
|
+
BVTAnalysisFormatter.reRunFailedStepsIndex.shift();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
BVTAnalysisFormatter.reRunFailedStepsIndex.shift();
|
|
110
156
|
}
|
|
111
|
-
const
|
|
112
|
-
.map((step, i) => (step.result.status === 'FAILED' ? i : null))
|
|
113
|
-
.filter((i) => i !== null);
|
|
114
|
-
const retrainStats = await this.retrain(failedTestSteps, testCase);
|
|
157
|
+
const retrainStats = await this.retrain(failedTestSteps, report);
|
|
115
158
|
if (!retrainStats) {
|
|
116
|
-
return
|
|
159
|
+
return;
|
|
117
160
|
}
|
|
118
|
-
|
|
119
|
-
...
|
|
161
|
+
await this.uploader.modifyTestCase({
|
|
162
|
+
...report,
|
|
120
163
|
retrainStats,
|
|
121
|
-
};
|
|
164
|
+
});
|
|
165
|
+
await this.rerun(report);
|
|
122
166
|
}
|
|
123
167
|
async uploadFinalReport(finalReport) {
|
|
124
168
|
let success = true;
|
|
125
169
|
try {
|
|
126
170
|
const { projectId, runId } = await this.uploader.uploadRun(finalReport, this.runName);
|
|
127
|
-
|
|
171
|
+
logReportLink(runId, projectId, finalReport.result);
|
|
128
172
|
}
|
|
129
173
|
catch (err) {
|
|
130
174
|
this.log('Error uploading report\n');
|
|
@@ -133,6 +177,14 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
133
177
|
}
|
|
134
178
|
success = false;
|
|
135
179
|
}
|
|
180
|
+
finally {
|
|
181
|
+
try {
|
|
182
|
+
(0, fs_1.writeFileSync)(path_1.default.join(this.reportGenerator.reportFolder, 'report.json'), JSON.stringify(finalReport, null, 2), 'utf-8');
|
|
183
|
+
}
|
|
184
|
+
catch (e) {
|
|
185
|
+
console.error('failed to write report.json to local disk');
|
|
186
|
+
}
|
|
187
|
+
}
|
|
136
188
|
//this.log(JSON.stringify(finalReport, null, 2))
|
|
137
189
|
return success;
|
|
138
190
|
}
|
|
@@ -145,6 +197,49 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
145
197
|
}
|
|
146
198
|
return await this.call_cucumber_client(failedTestCases, testCase);
|
|
147
199
|
}
|
|
200
|
+
async rerun(report) {
|
|
201
|
+
await new Promise((resolve) => {
|
|
202
|
+
// Default to system Node.js
|
|
203
|
+
let node_path = process.argv.shift();
|
|
204
|
+
// Use bundled Node if running from recorder app on macOS or Windows
|
|
205
|
+
const isFromRecorderApp = process.env.FROM_RECORDER_APP === 'true';
|
|
206
|
+
const isSupportedPlatform = process.platform === 'darwin' || process.platform === 'win32';
|
|
207
|
+
if (isFromRecorderApp && isSupportedPlatform) {
|
|
208
|
+
node_path = process.execPath;
|
|
209
|
+
}
|
|
210
|
+
const args = [
|
|
211
|
+
path_1.default.join(process.cwd(), 'node_modules', '@dev-blinq', 'cucumber-js', 'bin', 'cucumber.js'),
|
|
212
|
+
'--name',
|
|
213
|
+
`^${report.scenarioName}$`,
|
|
214
|
+
'--exit',
|
|
215
|
+
'--format',
|
|
216
|
+
'bvt',
|
|
217
|
+
'--run-name',
|
|
218
|
+
`${report.scenarioName}@debug`,
|
|
219
|
+
path_1.default.join(process.cwd(), report.uri),
|
|
220
|
+
];
|
|
221
|
+
const envVars = {
|
|
222
|
+
...process.env,
|
|
223
|
+
RERUN: JSON.stringify(this.failedStepsIndex),
|
|
224
|
+
};
|
|
225
|
+
// Inject Electron node env only if using bundled node
|
|
226
|
+
if (node_path === process.execPath) {
|
|
227
|
+
envVars.ELECTRON_RUN_AS_NODE = '1';
|
|
228
|
+
}
|
|
229
|
+
const cucumberClient = (0, child_process_1.spawn)(node_path, args, {
|
|
230
|
+
env: envVars,
|
|
231
|
+
});
|
|
232
|
+
cucumberClient.stdout.on('data', (data) => {
|
|
233
|
+
console.log(data.toString());
|
|
234
|
+
});
|
|
235
|
+
cucumberClient.stderr.on('data', (data) => {
|
|
236
|
+
console.error(data.toString());
|
|
237
|
+
});
|
|
238
|
+
cucumberClient.on('close', () => {
|
|
239
|
+
resolve();
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
}
|
|
148
243
|
async call_cucumber_client(stepsToRetrain, testCase) {
|
|
149
244
|
return new Promise((resolve, reject) => {
|
|
150
245
|
const cucumber_client_path = path_1.default.resolve(process.cwd(), 'node_modules', '@dev-blinq', 'cucumber_client', 'bin', 'client', 'cucumber.js');
|
|
@@ -153,7 +248,7 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
153
248
|
path_1.default.join(process.cwd(), testCase.uri),
|
|
154
249
|
`${testCase.scenarioName}`,
|
|
155
250
|
'undefined',
|
|
156
|
-
`${stepsToRetrain
|
|
251
|
+
`${stepsToRetrain},`,
|
|
157
252
|
];
|
|
158
253
|
if (process.env.BLINQ_ENV) {
|
|
159
254
|
args.push(`--env=${process.env.BLINQ_ENV}`);
|
|
@@ -166,13 +261,24 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
166
261
|
(0, tmp_1.tmpName)(async (err, name) => {
|
|
167
262
|
const tempFile = path_1.default.join(this.getAppDataDir(), 'blinq.io', '.temp', path_1.default.basename(name));
|
|
168
263
|
console.log('File path: ', tempFile);
|
|
264
|
+
if (!(0, fs_1.existsSync)(path_1.default.dirname(tempFile))) {
|
|
265
|
+
await (0, promises_1.mkdir)(path_1.default.dirname(tempFile), { recursive: true });
|
|
266
|
+
}
|
|
169
267
|
await (0, promises_1.writeFile)(tempFile, '', 'utf-8');
|
|
170
268
|
args.push(`--temp-file=${tempFile}`);
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
269
|
+
// Determine node path
|
|
270
|
+
const isFromRecorderApp = process.env.FROM_RECORDER_APP === 'true';
|
|
271
|
+
const isSupportedPlatform = process.platform === 'darwin' || process.platform === 'win32';
|
|
272
|
+
const node_path = isFromRecorderApp && isSupportedPlatform ? process.execPath : 'node';
|
|
273
|
+
const envVars = {
|
|
274
|
+
...process.env,
|
|
275
|
+
TEMP_FILE_PATH: tempFile,
|
|
276
|
+
};
|
|
277
|
+
if (node_path === process.execPath) {
|
|
278
|
+
envVars.ELECTRON_RUN_AS_NODE = '1';
|
|
279
|
+
}
|
|
280
|
+
const cucumberClient = (0, child_process_1.spawn)(node_path, [cucumber_client_path, ...args], {
|
|
281
|
+
env: envVars,
|
|
176
282
|
});
|
|
177
283
|
cucumberClient.stdout.on('data', (data) => {
|
|
178
284
|
console.log(data.toString());
|
|
@@ -189,26 +295,21 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
189
295
|
}
|
|
190
296
|
else {
|
|
191
297
|
this.log('Error retraining\n');
|
|
192
|
-
|
|
298
|
+
try {
|
|
299
|
+
const reportData = (0, fs_1.readFileSync)(tempFile, 'utf-8');
|
|
300
|
+
const retrainStats = JSON.parse(reportData);
|
|
301
|
+
await (0, promises_1.unlink)(tempFile);
|
|
302
|
+
resolve(retrainStats);
|
|
303
|
+
}
|
|
304
|
+
catch (e) {
|
|
305
|
+
this.log('Error reading scenario report\n ' + e);
|
|
306
|
+
resolve(null);
|
|
307
|
+
}
|
|
193
308
|
}
|
|
194
309
|
});
|
|
195
310
|
});
|
|
196
311
|
});
|
|
197
312
|
}
|
|
198
|
-
logReportLink(runId, projectId) {
|
|
199
|
-
let reportLinkBaseUrl = 'https://app.blinq.io';
|
|
200
|
-
if (process.env.NODE_ENV_BLINQ === 'local') {
|
|
201
|
-
reportLinkBaseUrl = 'http://localhost:3000';
|
|
202
|
-
}
|
|
203
|
-
else if (process.env.NODE_ENV_BLINQ === 'dev') {
|
|
204
|
-
reportLinkBaseUrl = 'https://dev.app.blinq.io';
|
|
205
|
-
}
|
|
206
|
-
else if (process.env.NODE_ENV_BLINQ === 'stage') {
|
|
207
|
-
reportLinkBaseUrl = 'https://stage.app.blinq.io';
|
|
208
|
-
}
|
|
209
|
-
const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`;
|
|
210
|
-
this.log(`Report link: ${reportLink}\n`);
|
|
211
|
-
}
|
|
212
313
|
getAppDataDir() {
|
|
213
314
|
if (process.env.BLINQ_APPDATA_DIR) {
|
|
214
315
|
return process.env.BLINQ_APPDATA_DIR;
|
|
@@ -229,4 +330,41 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
229
330
|
}
|
|
230
331
|
}
|
|
231
332
|
exports.default = BVTAnalysisFormatter;
|
|
333
|
+
function logReportLink(runId, projectId, status) {
|
|
334
|
+
let reportLinkBaseUrl = 'https://app.blinq.io';
|
|
335
|
+
if (process.env.NODE_ENV_BLINQ === 'local') {
|
|
336
|
+
reportLinkBaseUrl = 'http://localhost:3000';
|
|
337
|
+
}
|
|
338
|
+
else if (process.env.NODE_ENV_BLINQ === 'dev') {
|
|
339
|
+
reportLinkBaseUrl = 'https://dev.app.blinq.io';
|
|
340
|
+
}
|
|
341
|
+
else if (process.env.NODE_ENV_BLINQ === 'stage') {
|
|
342
|
+
reportLinkBaseUrl = 'https://stage.app.blinq.io';
|
|
343
|
+
}
|
|
344
|
+
else if (process.env.NODE_ENV_BLINQ === 'prod') {
|
|
345
|
+
reportLinkBaseUrl = 'https://app.blinq.io';
|
|
346
|
+
}
|
|
347
|
+
else if (!process.env.NODE_ENV_BLINQ) {
|
|
348
|
+
reportLinkBaseUrl = 'https://app.blinq.io';
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
reportLinkBaseUrl = process.env.NODE_ENV_BLINQ.replace('api', 'app');
|
|
352
|
+
}
|
|
353
|
+
const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`;
|
|
354
|
+
exports.globalReportLink = reportLink;
|
|
355
|
+
try {
|
|
356
|
+
publishReportLinkToGuacServer(reportLink, status.status === 'PASSED');
|
|
357
|
+
}
|
|
358
|
+
catch (err) {
|
|
359
|
+
// Error with events, ignoring
|
|
360
|
+
}
|
|
361
|
+
return reportLink;
|
|
362
|
+
}
|
|
363
|
+
exports.logReportLink = logReportLink;
|
|
364
|
+
function publishReportLinkToGuacServer(reportLink, result) {
|
|
365
|
+
if ((0, fs_1.existsSync)('/tmp/report_publish.sh')) {
|
|
366
|
+
const execAsync = (0, util_1.promisify)(child_process_2.exec);
|
|
367
|
+
execAsync('sh /tmp/report_publish.sh ' + reportLink + ' ' + result);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
232
370
|
//# sourceMappingURL=bvt_analysis_formatter.js.map
|