@dev-blinq/cucumber-js 1.0.14 → 1.0.16-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/convert_configuration.js +1 -0
- package/lib/api/convert_configuration.js.map +1 -1
- package/lib/api/gherkin.js +42 -1
- package/lib/api/gherkin.js.map +1 -1
- package/lib/api/run_cucumber.d.ts +1 -1
- package/lib/api/run_cucumber.js +10 -10
- package/lib/api/run_cucumber.js.map +1 -1
- package/lib/api/types.d.ts +5 -3
- package/lib/api/types.js.map +1 -1
- package/lib/cli/helpers.d.ts +8 -6
- package/lib/cli/helpers.js +27 -6
- package/lib/cli/helpers.js.map +1 -1
- package/lib/cli/index.js +7 -2
- package/lib/cli/index.js.map +1 -1
- package/lib/configuration/argv_parser.js +4 -2
- package/lib/configuration/argv_parser.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/configuration/default_configuration.js +2 -0
- package/lib/configuration/default_configuration.js.map +1 -1
- package/lib/configuration/types.d.ts +2 -0
- package/lib/configuration/types.js.map +1 -1
- package/lib/formatter/bvt_analysis_formatter.d.ts +3 -3
- package/lib/formatter/bvt_analysis_formatter.js +105 -115
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.d.ts +10 -1
- package/lib/formatter/feature_data_format.js +58 -2
- package/lib/formatter/feature_data_format.js.map +1 -1
- package/lib/formatter/helpers/formatters.js +1 -3
- package/lib/formatter/helpers/formatters.js.map +1 -1
- package/lib/formatter/helpers/report_generator.d.ts +22 -3
- package/lib/formatter/helpers/report_generator.js +151 -21
- package/lib/formatter/helpers/report_generator.js.map +1 -1
- package/lib/formatter/helpers/upload_serivce.d.ts +5 -1
- package/lib/formatter/helpers/upload_serivce.js +73 -12
- package/lib/formatter/helpers/upload_serivce.js.map +1 -1
- package/lib/formatter/helpers/uploader.d.ts +4 -1
- package/lib/formatter/helpers/uploader.js +62 -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 -4
- package/lib/formatter/bvt_formatter.d.ts +0 -6
- package/lib/formatter/bvt_formatter.js +0 -25
- package/lib/formatter/bvt_formatter.js.map +0 -1
|
@@ -4,42 +4,103 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.RunUploadService = void 0;
|
|
7
|
-
const
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
|
+
const axios_client_1 = require("../../configuration/axios_client");
|
|
8
10
|
class RunUploadService {
|
|
9
11
|
constructor(runsApiBaseURL, accessToken) {
|
|
10
12
|
this.runsApiBaseURL = runsApiBaseURL;
|
|
11
13
|
this.accessToken = accessToken;
|
|
12
14
|
}
|
|
13
15
|
async createRunDocument(name) {
|
|
14
|
-
const runDocResult = await
|
|
15
|
-
name,
|
|
16
|
+
const runDocResult = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/create', {
|
|
17
|
+
name: name ? name : 'TEST',
|
|
16
18
|
}, {
|
|
17
19
|
headers: {
|
|
18
|
-
Authorization:
|
|
19
|
-
|
|
20
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
21
|
+
'x-source': 'cucumber_js',
|
|
20
22
|
},
|
|
21
23
|
});
|
|
22
24
|
if (runDocResult.status !== 200) {
|
|
23
|
-
throw new Error(
|
|
25
|
+
throw new Error('Failed to create run document in the server');
|
|
24
26
|
}
|
|
25
27
|
if (runDocResult.data.status !== true) {
|
|
26
|
-
throw new Error(
|
|
28
|
+
throw new Error('Failed to create run document in the server');
|
|
27
29
|
}
|
|
28
30
|
return runDocResult.data.run;
|
|
29
31
|
}
|
|
30
32
|
async upload(formData) {
|
|
31
|
-
const response = await
|
|
33
|
+
const response = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/upload', formData, {
|
|
32
34
|
headers: {
|
|
33
35
|
...formData.getHeaders(),
|
|
34
|
-
Authorization:
|
|
35
|
-
|
|
36
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
37
|
+
'x-source': 'cucumber_js',
|
|
36
38
|
},
|
|
37
39
|
});
|
|
38
40
|
if (response.status !== 200) {
|
|
39
|
-
throw new Error(
|
|
41
|
+
throw new Error('Failed to upload run to the server');
|
|
40
42
|
}
|
|
41
43
|
if (response.data.status !== true) {
|
|
42
|
-
throw new Error(
|
|
44
|
+
throw new Error('Failed to upload run to the server');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async getPreSignedUrls(fileUris, runId) {
|
|
48
|
+
const response = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/generateuploadurls', {
|
|
49
|
+
fileUris,
|
|
50
|
+
runId,
|
|
51
|
+
}, {
|
|
52
|
+
headers: {
|
|
53
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
54
|
+
'x-source': 'cucumber_js',
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
if (response.status !== 200) {
|
|
58
|
+
throw new Error('Failed to get pre-signed urls for the files');
|
|
59
|
+
}
|
|
60
|
+
if (response.data.status !== true) {
|
|
61
|
+
throw new Error('Failed to get pre-signed urls for the files');
|
|
62
|
+
}
|
|
63
|
+
return response.data.uploadUrls;
|
|
64
|
+
}
|
|
65
|
+
async uploadFile(filePath, preSignedUrl) {
|
|
66
|
+
const fileStream = (0, fs_1.createReadStream)(filePath);
|
|
67
|
+
let success = true;
|
|
68
|
+
try {
|
|
69
|
+
const fileStats = await promises_1.default.stat(filePath);
|
|
70
|
+
const fileSize = fileStats.size;
|
|
71
|
+
await axios_client_1.axiosClient.put(preSignedUrl, fileStream, {
|
|
72
|
+
headers: {
|
|
73
|
+
'Content-Type': 'application/octet-stream',
|
|
74
|
+
'Content-Length': fileSize,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
if (process.env.NODE_ENV_BLINQ === 'dev') {
|
|
80
|
+
console.error('Error uploading file:', error);
|
|
81
|
+
}
|
|
82
|
+
success = false;
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
fileStream.close();
|
|
86
|
+
}
|
|
87
|
+
return success;
|
|
88
|
+
}
|
|
89
|
+
async uploadComplete(runId, report) {
|
|
90
|
+
const response = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/uploadcomplete', {
|
|
91
|
+
runId,
|
|
92
|
+
report,
|
|
93
|
+
}, {
|
|
94
|
+
headers: {
|
|
95
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
96
|
+
'x-source': 'cucumber_js',
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
if (response.status !== 200) {
|
|
100
|
+
throw new Error('Failed to mark run as complete');
|
|
101
|
+
}
|
|
102
|
+
if (response.data.status !== true) {
|
|
103
|
+
throw new Error('Failed to mark run as complete');
|
|
43
104
|
}
|
|
44
105
|
}
|
|
45
106
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload_serivce.js","sourceRoot":"","sources":["../../../src/formatter/helpers/upload_serivce.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"upload_serivce.js","sourceRoot":"","sources":["../../../src/formatter/helpers/upload_serivce.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport FormData from 'form-data'\nimport { createReadStream } from 'fs'\nimport fs from 'fs/promises'\nimport { JsonReport } from './report_generator'\nimport { axiosClient } from '../../configuration/axios_client'\n\nclass RunUploadService {\n constructor(private runsApiBaseURL: string, private accessToken: string) {}\n async createRunDocument(name: string) {\n const runDocResult = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/create',\n {\n name: name ? name : 'TEST',\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (runDocResult.status !== 200) {\n throw new Error('Failed to create run document in the server')\n }\n if (runDocResult.data.status !== true) {\n throw new Error('Failed to create run document in the server')\n }\n return runDocResult.data.run\n }\n async upload(formData: FormData) {\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/upload',\n formData,\n {\n headers: {\n ...formData.getHeaders(),\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (response.status !== 200) {\n throw new Error('Failed to upload run to the server')\n }\n if (response.data.status !== true) {\n throw new Error('Failed to upload run to the server')\n }\n }\n async getPreSignedUrls(fileUris: string[], runId: string) {\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/generateuploadurls',\n {\n fileUris,\n runId,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (response.status !== 200) {\n throw new Error('Failed to get pre-signed urls for the files')\n }\n if (response.data.status !== true) {\n throw new Error('Failed to get pre-signed urls for the files')\n }\n\n return response.data.uploadUrls\n }\n\n async uploadFile(filePath: string, preSignedUrl: string) {\n const fileStream = createReadStream(filePath)\n let success = true\n try {\n const fileStats = await fs.stat(filePath)\n const fileSize = fileStats.size\n\n await axiosClient.put(preSignedUrl, fileStream, {\n headers: {\n 'Content-Type': 'application/octet-stream',\n 'Content-Length': fileSize,\n },\n })\n\n } catch (error) {\n if (process.env.NODE_ENV_BLINQ === 'dev') {\n console.error('Error uploading file:', error)\n }\n success = false\n } finally {\n fileStream.close()\n }\n return success\n }\n async uploadComplete(runId: string, report: JsonReport) {\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/uploadcomplete',\n {\n runId,\n report,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (response.status !== 200) {\n throw new Error('Failed to mark run as complete')\n }\n if (response.data.status !== true) {\n throw new Error('Failed to mark run as complete')\n }\n }\n}\n\nexport { RunUploadService }\n"]}
|
|
@@ -3,6 +3,9 @@ export default class ReportUploader {
|
|
|
3
3
|
private uploadService;
|
|
4
4
|
private reportGenerator;
|
|
5
5
|
constructor(reportGenerator: ReportGenerator);
|
|
6
|
-
uploadRun(report: JsonReport): Promise<
|
|
6
|
+
uploadRun(report: JsonReport, runName: string): Promise<{
|
|
7
|
+
runId: any;
|
|
8
|
+
projectId: any;
|
|
9
|
+
}>;
|
|
7
10
|
createZip(reportFolder: string | null, report: JsonReport): Promise<string>;
|
|
8
11
|
}
|
|
@@ -2,14 +2,31 @@
|
|
|
2
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
|
+
var _a, _b;
|
|
5
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
7
|
const upload_serivce_1 = require("./upload_serivce");
|
|
7
8
|
const form_data_1 = __importDefault(require("form-data"));
|
|
8
9
|
const fs_1 = __importDefault(require("fs"));
|
|
9
10
|
const jszip_1 = __importDefault(require("jszip"));
|
|
10
11
|
const path_1 = __importDefault(require("path"));
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
let URL;
|
|
13
|
+
switch (process.env.NODE_ENV_BLINQ) {
|
|
14
|
+
case 'stage':
|
|
15
|
+
URL = 'https://stage.api.blinq.io/api/runs';
|
|
16
|
+
break;
|
|
17
|
+
case 'dev':
|
|
18
|
+
URL = 'https://dev.api.blinq.io/api/runs';
|
|
19
|
+
break;
|
|
20
|
+
case 'local':
|
|
21
|
+
URL = 'http://localhost:5001/api/runs';
|
|
22
|
+
break;
|
|
23
|
+
default:
|
|
24
|
+
URL = 'https://api.blinq.io/api/runs';
|
|
25
|
+
}
|
|
26
|
+
const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
|
|
27
|
+
const BATCH_SIZE = 10;
|
|
28
|
+
const MAX_RETRIES = 3;
|
|
29
|
+
const REPORT_SERVICE_TOKEN = (_b = process.env.TOKEN) !== null && _b !== void 0 ? _b : process.env.REPORT_SERVICE_TOKEN;
|
|
13
30
|
class ReportUploader {
|
|
14
31
|
constructor(reportGenerator) {
|
|
15
32
|
this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
|
|
@@ -18,26 +35,57 @@ class ReportUploader {
|
|
|
18
35
|
}
|
|
19
36
|
this.reportGenerator = reportGenerator;
|
|
20
37
|
}
|
|
21
|
-
async uploadRun(report) {
|
|
22
|
-
const runDoc = await this.uploadService.createRunDocument(
|
|
38
|
+
async uploadRun(report, runName) {
|
|
39
|
+
const runDoc = await this.uploadService.createRunDocument(runName);
|
|
23
40
|
const runDocId = runDoc._id;
|
|
24
|
-
const formData = new form_data_1.default();
|
|
25
41
|
const reportFolder = this.reportGenerator.reportFolder;
|
|
26
42
|
if (!fs_1.default.existsSync(reportFolder)) {
|
|
27
43
|
fs_1.default.mkdirSync(reportFolder);
|
|
28
44
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
45
|
+
if (process.env.NODE_ENV_BLINQ === 'local') {
|
|
46
|
+
const formData = new form_data_1.default();
|
|
47
|
+
const zipPath = await this.createZip(reportFolder, report);
|
|
48
|
+
formData.append(runDocId, fs_1.default.readFileSync(zipPath), 'report.zip');
|
|
49
|
+
await this.uploadService.upload(formData);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const fileUris = getFileUrisScreenShotDir(reportFolder);
|
|
53
|
+
try {
|
|
54
|
+
const preSignedUrls = await this.uploadService.getPreSignedUrls(fileUris, runDocId);
|
|
55
|
+
for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {
|
|
56
|
+
const batch = fileUris.slice(i, Math.min(i + BATCH_SIZE, fileUris.length));
|
|
57
|
+
await Promise.all(batch
|
|
58
|
+
.filter((fileUri) => preSignedUrls[fileUri])
|
|
59
|
+
.map(async (fileUri) => {
|
|
60
|
+
for (let j = 0; j < MAX_RETRIES; j++) {
|
|
61
|
+
const success = await this.uploadService.uploadFile(path_1.default.join(reportFolder, fileUri), preSignedUrls[fileUri]);
|
|
62
|
+
if (success) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
console.error('Failed to upload file:', fileUri);
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
await this.uploadService.uploadComplete(runDocId, report);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
throw new Error('Failed to upload all the files');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { runId: runDoc._id, projectId: runDoc.project_id };
|
|
33
76
|
}
|
|
34
77
|
async createZip(reportFolder, report) {
|
|
78
|
+
if (reportFolder === null) {
|
|
79
|
+
console.error('report folder is empty');
|
|
80
|
+
console.error('it is likey that there are no scenarios to run');
|
|
81
|
+
throw new Error('Empty report folder');
|
|
82
|
+
}
|
|
35
83
|
const zip = new jszip_1.default();
|
|
36
84
|
zip.file('report.json', JSON.stringify(report, null, 2));
|
|
37
85
|
const folder = zip.folder('screenshots');
|
|
38
86
|
const files = fs_1.default.readdirSync(path_1.default.join(reportFolder, 'screenshots'));
|
|
39
87
|
files.forEach((file) => {
|
|
40
|
-
folder.file(file, fs_1.default.readFileSync(path_1.default.join(reportFolder, file)));
|
|
88
|
+
folder.file(file, fs_1.default.readFileSync(path_1.default.join(reportFolder, 'screenshots', file)));
|
|
41
89
|
});
|
|
42
90
|
const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' });
|
|
43
91
|
// save zip file
|
|
@@ -48,4 +96,8 @@ class ReportUploader {
|
|
|
48
96
|
}
|
|
49
97
|
}
|
|
50
98
|
exports.default = ReportUploader;
|
|
99
|
+
const getFileUrisScreenShotDir = (reportFolder) => {
|
|
100
|
+
const files = fs_1.default.readdirSync(path_1.default.join(reportFolder, 'screenshots'));
|
|
101
|
+
return files.map((file) => ['screenshots', file].join('/'));
|
|
102
|
+
};
|
|
51
103
|
//# sourceMappingURL=uploader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploader.js","sourceRoot":"","sources":["../../../src/formatter/helpers/uploader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"uploader.js","sourceRoot":"","sources":["../../../src/formatter/helpers/uploader.ts"],"names":[],"mappings":"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","sourcesContent":["import ReportGenerator, { JsonReport } from './report_generator'\nimport { RunUploadService } from './upload_serivce'\n\nimport FormData from 'form-data'\nimport fs from 'fs'\nimport JSZip from 'jszip'\nimport path from 'path'\n\nlet URL\n\nswitch (process.env.NODE_ENV_BLINQ) {\n case 'stage':\n URL = 'https://stage.api.blinq.io/api/runs'\n break\n case 'dev':\n URL = 'https://dev.api.blinq.io/api/runs'\n break\n case 'local':\n URL = 'http://localhost:5001/api/runs'\n break\n default:\n URL = 'https://api.blinq.io/api/runs'\n}\n\nconst REPORT_SERVICE_URL = process.env.REPORT_SERVICE_URL ?? URL\nconst BATCH_SIZE = 10\nconst MAX_RETRIES = 3\nconst REPORT_SERVICE_TOKEN =\n process.env.TOKEN ?? process.env.REPORT_SERVICE_TOKEN\n\nexport default class ReportUploader {\n private uploadService = new RunUploadService(\n REPORT_SERVICE_URL,\n REPORT_SERVICE_TOKEN\n )\n private reportGenerator: ReportGenerator\n constructor(reportGenerator: ReportGenerator) {\n if (!REPORT_SERVICE_URL || !REPORT_SERVICE_TOKEN) {\n throw new Error('REPORT_SERVICE_URL and REPORT_SERVICE_TOKEN must be set')\n }\n this.reportGenerator = reportGenerator\n }\n\n async uploadRun(report: JsonReport, runName: string) {\n const runDoc = await this.uploadService.createRunDocument(runName)\n const runDocId = runDoc._id\n const reportFolder = this.reportGenerator.reportFolder\n if (!fs.existsSync(reportFolder)) {\n fs.mkdirSync(reportFolder)\n }\n if (process.env.NODE_ENV_BLINQ === 'local') {\n const formData = new FormData()\n const zipPath = await this.createZip(reportFolder, report)\n formData.append(runDocId, fs.readFileSync(zipPath), 'report.zip')\n await this.uploadService.upload(formData)\n } else {\n const fileUris = getFileUrisScreenShotDir(reportFolder)\n try {\n const preSignedUrls = await this.uploadService.getPreSignedUrls(\n fileUris,\n runDocId\n )\n for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {\n const batch = fileUris.slice(\n i,\n Math.min(i + BATCH_SIZE, fileUris.length)\n )\n await Promise.all(\n batch\n .filter((fileUri) => preSignedUrls[fileUri])\n .map(async (fileUri) => {\n for (let j = 0; j < MAX_RETRIES; j++) {\n const success = await this.uploadService.uploadFile(\n path.join(reportFolder, fileUri),\n preSignedUrls[fileUri]\n )\n if (success) {\n return\n }\n }\n console.error('Failed to upload file:', fileUri)\n })\n )\n }\n await this.uploadService.uploadComplete(runDocId, report)\n } catch (err) {\n throw new Error('Failed to upload all the files')\n }\n }\n return { runId: runDoc._id, projectId: runDoc.project_id }\n }\n async createZip(reportFolder: string | null, report: JsonReport) {\n if (reportFolder === null) {\n console.error('report folder is empty')\n console.error('it is likey that there are no scenarios to run')\n throw new Error('Empty report folder')\n }\n const zip = new JSZip()\n zip.file('report.json', JSON.stringify(report, null, 2))\n const folder = zip.folder('screenshots')\n const files = fs.readdirSync(path.join(reportFolder, 'screenshots'))\n files.forEach((file) => {\n folder.file(\n file,\n fs.readFileSync(path.join(reportFolder, 'screenshots', file))\n )\n })\n const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' })\n // save zip file\n const zipPath = path.join(reportFolder, 'report.zip')\n fs.writeFileSync(zipPath, zipBuffer)\n fs.writeFileSync(\n path.join(reportFolder, 'report.json'),\n JSON.stringify(report, null, 2)\n )\n return zipPath\n }\n}\nconst getFileUrisScreenShotDir = (reportFolder: string) => {\n const files = fs.readdirSync(path.join(reportFolder, 'screenshots'))\n\n return files.map((file) => ['screenshots', file].join('/'))\n}\n"]}
|
package/lib/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "1.0.
|
|
1
|
+
export declare const version = "1.0.16-stage";
|
package/lib/version.js
CHANGED
package/lib/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAAA,2BAA2B;AACd,QAAA,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAAA,2BAA2B;AACd,QAAA,OAAO,GAAG,cAAc,CAAA","sourcesContent":["// Generated by genversion.\nexport const version = '1.0.16-stage'\n"]}
|
package/package.json
CHANGED
|
@@ -8,9 +8,7 @@
|
|
|
8
8
|
"gherkin",
|
|
9
9
|
"tests"
|
|
10
10
|
],
|
|
11
|
-
|
|
12
|
-
"version": "1.0.14",
|
|
13
|
-
|
|
11
|
+
"version": "1.0.16-stage",
|
|
14
12
|
"homepage": "https://github.com/blinq-io/cucumber-js",
|
|
15
13
|
"author": "blinq.io",
|
|
16
14
|
"contributors": [
|
|
@@ -62,6 +60,7 @@
|
|
|
62
60
|
"@cucumber/messages": "22.0.0",
|
|
63
61
|
"@cucumber/tag-expressions": "5.0.1",
|
|
64
62
|
"@faker-js/faker": "^8.0.2",
|
|
63
|
+
"@types/tunnel": "^0.0.7",
|
|
65
64
|
"assertion-error-formatter": "^3.0.0",
|
|
66
65
|
"axios": "^1.6.2",
|
|
67
66
|
"capital-case": "^1.0.4",
|
|
@@ -90,6 +89,8 @@
|
|
|
90
89
|
"strip-ansi": "6.0.1",
|
|
91
90
|
"supports-color": "^8.1.1",
|
|
92
91
|
"tmp": "^0.2.1",
|
|
92
|
+
"tmp-promise": "^3.0.3",
|
|
93
|
+
"tunnel": "^0.0.6",
|
|
93
94
|
"util-arity": "^1.1.0",
|
|
94
95
|
"verror": "^1.10.0",
|
|
95
96
|
"xmlbuilder": "^15.1.1",
|
|
@@ -183,7 +184,8 @@
|
|
|
183
184
|
"update-dependencies": "npx npm-check-updates --upgrade"
|
|
184
185
|
},
|
|
185
186
|
"bin": {
|
|
186
|
-
"cucumber-js": "bin/cucumber.js"
|
|
187
|
+
"cucumber-js": "bin/cucumber.js",
|
|
188
|
+
"download-install": "bin/download-install.js"
|
|
187
189
|
},
|
|
188
190
|
"license": "MIT",
|
|
189
191
|
"files": [
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const _1 = __importDefault(require("."));
|
|
7
|
-
const report_generator_1 = __importDefault(require("./helpers/report_generator"));
|
|
8
|
-
const uploader_1 = __importDefault(require("./helpers/uploader"));
|
|
9
|
-
class BVTFormatter extends _1.default {
|
|
10
|
-
constructor(options) {
|
|
11
|
-
super(options);
|
|
12
|
-
this.reportGenerator = new report_generator_1.default();
|
|
13
|
-
this.uploader = new uploader_1.default(this.reportGenerator);
|
|
14
|
-
options.eventBroadcaster.on('envelope', async (envelope) => {
|
|
15
|
-
this.reportGenerator.handleMessage(envelope);
|
|
16
|
-
if (envelope.testRunFinished) {
|
|
17
|
-
const report = this.reportGenerator.getReport();
|
|
18
|
-
// this.log(JSON.stringify(report, null, 2))
|
|
19
|
-
await this.uploader.uploadRun(report);
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
exports.default = BVTFormatter;
|
|
25
|
-
//# sourceMappingURL=bvt_formatter.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bvt_formatter.js","sourceRoot":"","sources":["../../src/formatter/bvt_formatter.ts"],"names":[],"mappings":";;;;;AACA,yCAAgD;AAChD,kFAAwD;AACxD,kEAA+C;AAE/C,MAAqB,YAAa,SAAQ,UAAS;IAGjD,YAAY,OAA0B;QACpC,KAAK,CAAC,OAAO,CAAC,CAAA;QAHR,oBAAe,GAAG,IAAI,0BAAe,EAAE,CAAA;QACvC,aAAQ,GAAG,IAAI,kBAAc,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QAGzD,OAAO,CAAC,gBAAgB,CAAC,EAAE,CACzB,UAAU,EACV,KAAK,EAAE,QAA2B,EAAE,EAAE;YACpC,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;YAC5C,IAAI,QAAQ,CAAC,eAAe,EAAE;gBAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAA;gBAC/C,4CAA4C;gBAE5C,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;aACtC;QACH,CAAC,CACF,CAAA;IACH,CAAC;CACF;AAlBD,+BAkBC","sourcesContent":["import * as messages from '@cucumber/messages'\nimport Formatter, { IFormatterOptions } from '.'\nimport ReportGenerator from './helpers/report_generator'\nimport ReportUploader from './helpers/uploader'\n\nexport default class BVTFormatter extends Formatter {\n private reportGenerator = new ReportGenerator()\n private uploader = new ReportUploader(this.reportGenerator)\n constructor(options: IFormatterOptions) {\n super(options)\n options.eventBroadcaster.on(\n 'envelope',\n async (envelope: messages.Envelope) => {\n this.reportGenerator.handleMessage(envelope)\n if (envelope.testRunFinished) {\n const report = this.reportGenerator.getReport()\n // this.log(JSON.stringify(report, null, 2))\n\n await this.uploader.uploadRun(report)\n }\n }\n )\n }\n}\n"]}
|