@dev-blinq/cucumber-js 1.0.89-dev → 1.0.89-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 +40 -13
- package/lib/configuration/axios_client.js +1 -1
- package/lib/configuration/axios_client.js.map +1 -1
- package/lib/formatter/api.d.ts +2 -0
- package/lib/formatter/api.js +59 -0
- package/lib/formatter/api.js.map +1 -0
- package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
- package/lib/formatter/bvt_analysis_formatter.js +197 -72
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.js +14 -2
- 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 +31 -2
- package/lib/formatter/helpers/report_generator.js +329 -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 +15 -0
- package/lib/formatter/helpers/upload_serivce.js +165 -13
- 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 +30 -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
|
@@ -79,7 +79,7 @@ function formatStep({ colorFns, testStep, printAttachments, }) {
|
|
|
79
79
|
else if (fileName) {
|
|
80
80
|
message = `: ${fileName}`;
|
|
81
81
|
}
|
|
82
|
-
text += (
|
|
82
|
+
//text += indentString(`Attachment (${mediaType})${message}\n`, 4)
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
85
|
const message = getStepMessage(testStep);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test_case_attempt_formatter.js","sourceRoot":"","sources":["../../../src/formatter/helpers/test_case_attempt_formatter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"test_case_attempt_formatter.js","sourceRoot":"","sources":["../../../src/formatter/helpers/test_case_attempt_formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import indentString from 'indent-string'\nimport * as messages from '@cucumber/messages'\nimport figures from 'figures'\nimport { formatLocation } from './location_helpers'\nimport {\n IParsedTestStep,\n parseTestCaseAttempt,\n} from './test_case_attempt_parser'\nimport { formatStepArgument } from './step_argument_formatter'\nimport { IColorFns } from '../get_color_fns'\nimport { doesHaveValue, valueOrDefault } from '../../value_checker'\nimport { ITestCaseAttempt } from './event_data_collector'\nimport StepDefinitionSnippetBuilder from '../step_definition_snippet_builder'\nimport { ISupportCodeLibrary } from '../../support_code_library_builder/types'\n\nconst CHARACTERS: Map<messages.TestStepResultStatus, string> = new Map([\n [messages.TestStepResultStatus.AMBIGUOUS, figures.cross],\n [messages.TestStepResultStatus.FAILED, figures.cross],\n [messages.TestStepResultStatus.PASSED, figures.tick],\n [messages.TestStepResultStatus.PENDING, '?'],\n [messages.TestStepResultStatus.SKIPPED, '-'],\n [messages.TestStepResultStatus.UNDEFINED, '?'],\n])\n\nfunction getStepMessage(testStep: IParsedTestStep): string {\n switch (testStep.result.status) {\n case messages.TestStepResultStatus.AMBIGUOUS:\n case messages.TestStepResultStatus.FAILED:\n return testStep.result.message\n case messages.TestStepResultStatus.UNDEFINED:\n return `${\n 'Undefined. Implement with the following snippet:' + '\\n\\n'\n }${indentString(testStep.snippet, 2)}\\n`\n case messages.TestStepResultStatus.PENDING:\n return 'Pending'\n }\n return ''\n}\n\ninterface IFormatStepRequest {\n colorFns: IColorFns\n testStep: IParsedTestStep\n printAttachments?: boolean\n}\n\nfunction formatStep({\n colorFns,\n testStep,\n printAttachments,\n}: IFormatStepRequest): string {\n const {\n name,\n result: { status },\n actionLocation,\n attachments,\n } = testStep\n const colorFn = colorFns.forStatus(status)\n const identifier = testStep.keyword + valueOrDefault(testStep.text, '')\n let text = colorFn(`${CHARACTERS.get(status)} ${identifier}`)\n if (doesHaveValue(name)) {\n text += colorFn(` (${name})`)\n }\n if (doesHaveValue(actionLocation)) {\n text += ` # ${colorFns.location(formatLocation(actionLocation))}`\n }\n text += '\\n'\n if (doesHaveValue(testStep.argument)) {\n const argumentsText = formatStepArgument(testStep.argument)\n text += indentString(`${colorFn(argumentsText)}\\n`, 4)\n }\n if (valueOrDefault(printAttachments, true)) {\n attachments.forEach(({ body, mediaType, fileName }) => {\n let message = ''\n if (mediaType === 'text/plain') {\n message = `: ${body}`\n } else if (fileName) {\n message = `: ${fileName}`\n }\n //text += indentString(`Attachment (${mediaType})${message}\\n`, 4)\n })\n }\n const message = getStepMessage(testStep)\n if (message !== '') {\n text += `${indentString(colorFn(message), 4)}\\n`\n }\n return text\n}\n\nexport interface IFormatTestCaseAttemptRequest {\n colorFns: IColorFns\n testCaseAttempt: ITestCaseAttempt\n snippetBuilder: StepDefinitionSnippetBuilder\n supportCodeLibrary: ISupportCodeLibrary\n printAttachments?: boolean\n}\n\nexport function formatTestCaseAttempt({\n colorFns,\n snippetBuilder,\n supportCodeLibrary,\n testCaseAttempt,\n printAttachments,\n}: IFormatTestCaseAttemptRequest): string {\n const parsed = parseTestCaseAttempt({\n snippetBuilder,\n testCaseAttempt,\n supportCodeLibrary,\n })\n let text = `Scenario: ${parsed.testCase.name}`\n text += getAttemptText(parsed.testCase.attempt, testCaseAttempt.willBeRetried)\n text += ` # ${colorFns.location(\n formatLocation(parsed.testCase.sourceLocation)\n )}\\n`\n parsed.testSteps.forEach((testStep) => {\n text += formatStep({ colorFns, testStep, printAttachments })\n })\n return `${text}\\n`\n}\n\nfunction getAttemptText(attempt: number, willBeRetried: boolean): string {\n if (attempt > 0 || willBeRetried) {\n const numberStr = (attempt + 1).toString()\n const retriedStr = willBeRetried ? ', retried' : ''\n return ` (attempt ${numberStr}${retriedStr})`\n }\n return ''\n}\n"]}
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import FormData from 'form-data';
|
|
2
|
+
import { JsonTestProgress } from './report_generator';
|
|
3
|
+
export interface RootCauseProps {
|
|
4
|
+
status: boolean;
|
|
5
|
+
analysis: string;
|
|
6
|
+
failedStep: number;
|
|
7
|
+
failClass: string;
|
|
8
|
+
}
|
|
9
|
+
export interface FinishTestCaseResponse {
|
|
10
|
+
status: true;
|
|
11
|
+
rootCause: RootCauseProps;
|
|
12
|
+
report: JsonTestProgress;
|
|
13
|
+
}
|
|
2
14
|
declare class RunUploadService {
|
|
3
15
|
private runsApiBaseURL;
|
|
4
16
|
private accessToken;
|
|
@@ -6,7 +18,10 @@ declare class RunUploadService {
|
|
|
6
18
|
createRunDocument(name: string): Promise<any>;
|
|
7
19
|
upload(formData: FormData): Promise<void>;
|
|
8
20
|
getPreSignedUrls(fileUris: string[], runId: string): Promise<any>;
|
|
21
|
+
uploadTestCase(testCaseReport: JsonTestProgress, runId: string, projectId: string, reportFolder: string, rerunId?: string): Promise<FinishTestCaseResponse>;
|
|
9
22
|
uploadFile(filePath: string, preSignedUrl: string): Promise<boolean>;
|
|
10
23
|
uploadComplete(runId: string, projectId: string): Promise<void>;
|
|
24
|
+
modifyTestCase(runId: string, projectId: string, testProgressReport: JsonTestProgress): Promise<void>;
|
|
25
|
+
createStatus(status: string): Promise<void>;
|
|
11
26
|
}
|
|
12
27
|
export { RunUploadService };
|
|
@@ -2,32 +2,49 @@
|
|
|
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
|
exports.RunUploadService = void 0;
|
|
7
8
|
const fs_1 = require("fs");
|
|
8
9
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
10
|
const axios_client_1 = require("../../configuration/axios_client");
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const bvt_analysis_formatter_1 = require("../bvt_analysis_formatter");
|
|
13
|
+
const constants_1 = require("./constants");
|
|
14
|
+
const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
|
|
15
|
+
const BATCH_SIZE = 10;
|
|
16
|
+
const MAX_RETRIES = 3;
|
|
17
|
+
const REPORT_SERVICE_TOKEN = (_b = process.env.TOKEN) !== null && _b !== void 0 ? _b : process.env.REPORT_SERVICE_TOKEN;
|
|
10
18
|
class RunUploadService {
|
|
11
19
|
constructor(runsApiBaseURL, accessToken) {
|
|
12
20
|
this.runsApiBaseURL = runsApiBaseURL;
|
|
13
21
|
this.accessToken = accessToken;
|
|
14
22
|
}
|
|
15
23
|
async createRunDocument(name) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
try {
|
|
25
|
+
const runDocResult = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/create', {
|
|
26
|
+
name: name ? name : 'TEST',
|
|
27
|
+
}, {
|
|
28
|
+
headers: {
|
|
29
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
30
|
+
'x-source': 'cucumber_js',
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
if (runDocResult.status !== 200) {
|
|
34
|
+
throw new Error('Failed to create run document in the server');
|
|
35
|
+
}
|
|
36
|
+
if (runDocResult.data.status !== true) {
|
|
37
|
+
throw new Error('Failed to create run document in the server');
|
|
38
|
+
}
|
|
39
|
+
return runDocResult.data.run;
|
|
26
40
|
}
|
|
27
|
-
|
|
28
|
-
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error.response && error.response.status === 403) {
|
|
43
|
+
console.log('Warning: Your trial plan has ended. Cannot create or upload reports.');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
throw new Error('Failed to create run document in the server: ' + error);
|
|
29
47
|
}
|
|
30
|
-
return runDocResult.data.run;
|
|
31
48
|
}
|
|
32
49
|
async upload(formData) {
|
|
33
50
|
const response = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/upload', formData, {
|
|
@@ -70,6 +87,82 @@ class RunUploadService {
|
|
|
70
87
|
}
|
|
71
88
|
return response.data.uploadUrls;
|
|
72
89
|
}
|
|
90
|
+
async uploadTestCase(testCaseReport, runId, projectId, reportFolder, rerunId) {
|
|
91
|
+
const fileUris = [];
|
|
92
|
+
//iterate over all the files in the JsonCommand.screenshotId and insert them into the fileUris array
|
|
93
|
+
for (const step of testCaseReport.steps) {
|
|
94
|
+
for (const command of step.commands) {
|
|
95
|
+
if (command.screenshotId) {
|
|
96
|
+
fileUris.push('screenshots' + '/' + String(command.screenshotId) + '.png');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (step.traceFilePath) {
|
|
100
|
+
fileUris.push('trace' + '/' + step.traceFilePath);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (testCaseReport.logFileId) {
|
|
104
|
+
fileUris.push('editorLogs' + '/' + 'testCaseLog_' + testCaseReport.logFileId + '.log');
|
|
105
|
+
}
|
|
106
|
+
// console.log({ fileUris })
|
|
107
|
+
const preSignedUrls = await this.getPreSignedUrls(fileUris, runId);
|
|
108
|
+
//upload all the files in the fileUris array
|
|
109
|
+
try {
|
|
110
|
+
for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {
|
|
111
|
+
const batch = fileUris.slice(i, Math.min(i + BATCH_SIZE, fileUris.length));
|
|
112
|
+
await Promise.all(batch
|
|
113
|
+
.filter((fileUri) => preSignedUrls[fileUri])
|
|
114
|
+
.map(async (fileUri) => {
|
|
115
|
+
for (let j = 0; j < MAX_RETRIES; j++) {
|
|
116
|
+
if ((0, fs_1.existsSync)(path_1.default.join(reportFolder, fileUri))) {
|
|
117
|
+
const success = await this.uploadFile(path_1.default.join(reportFolder, fileUri), preSignedUrls[fileUri]);
|
|
118
|
+
if (success) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const success = await this.uploadFile(path_1.default.join(reportFolder, fileUri), preSignedUrls[fileUri]);
|
|
123
|
+
if (success) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
console.error('Failed to upload file:', fileUri);
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
// writeFileSync("report.json", JSON.stringify(testCaseReport, null, 2))
|
|
131
|
+
const { data } = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/createNewTestCase', {
|
|
132
|
+
runId,
|
|
133
|
+
projectId,
|
|
134
|
+
testProgressReport: testCaseReport,
|
|
135
|
+
browser: process.env.BROWSER ? process.env.BROWSER : 'chromium',
|
|
136
|
+
mode: process.env.MODE === 'cloud' ? 'cloud' : 'local',
|
|
137
|
+
rerunId,
|
|
138
|
+
}, {
|
|
139
|
+
headers: {
|
|
140
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
141
|
+
'x-source': 'cucumber_js',
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
try {
|
|
145
|
+
await axios_client_1.axiosClient.post(`${constants_1.SERVICES_URI.STORAGE}/event`, {
|
|
146
|
+
event: constants_1.ActionEvents.upload_report,
|
|
147
|
+
}, {
|
|
148
|
+
headers: {
|
|
149
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
150
|
+
'x-source': 'cucumber_js',
|
|
151
|
+
'x-bvt-project-id': projectId,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
// no event tracking
|
|
157
|
+
}
|
|
158
|
+
(0, bvt_analysis_formatter_1.logReportLink)(runId, projectId, testCaseReport.result);
|
|
159
|
+
return data;
|
|
160
|
+
}
|
|
161
|
+
catch (e) {
|
|
162
|
+
console.error(`failed to upload the test case: ${testCaseReport.id} ${e}`);
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
73
166
|
async uploadFile(filePath, preSignedUrl) {
|
|
74
167
|
const fileStream = (0, fs_1.createReadStream)(filePath);
|
|
75
168
|
let success = true;
|
|
@@ -98,6 +191,8 @@ class RunUploadService {
|
|
|
98
191
|
const response = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/uploadCompletion', {
|
|
99
192
|
runId,
|
|
100
193
|
projectId,
|
|
194
|
+
browser: process.env.BROWSER ? process.env.BROWSER : 'chromium',
|
|
195
|
+
mode: process.env.MODE === 'cloud' ? 'cloud' : 'local',
|
|
101
196
|
}, {
|
|
102
197
|
headers: {
|
|
103
198
|
Authorization: 'Bearer ' + this.accessToken,
|
|
@@ -110,6 +205,63 @@ class RunUploadService {
|
|
|
110
205
|
if (response.data.status !== true) {
|
|
111
206
|
throw new Error('Failed to mark run as complete');
|
|
112
207
|
}
|
|
208
|
+
try {
|
|
209
|
+
await axios_client_1.axiosClient.post(`${constants_1.SERVICES_URI.STORAGE}/event`, {
|
|
210
|
+
event: constants_1.ActionEvents.upload_report,
|
|
211
|
+
}, {
|
|
212
|
+
headers: {
|
|
213
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
214
|
+
'x-source': 'cucumber_js',
|
|
215
|
+
'x-bvt-project-id': projectId,
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
// no event tracking
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async modifyTestCase(runId, projectId, testProgressReport) {
|
|
224
|
+
try {
|
|
225
|
+
const res = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/modifyTestCase', {
|
|
226
|
+
runId,
|
|
227
|
+
projectId,
|
|
228
|
+
testProgressReport,
|
|
229
|
+
}, {
|
|
230
|
+
headers: {
|
|
231
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
232
|
+
'x-source': 'cucumber_js',
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
if (res.status !== 200) {
|
|
236
|
+
throw new Error('');
|
|
237
|
+
}
|
|
238
|
+
if (res.data.status !== true) {
|
|
239
|
+
throw new Error('');
|
|
240
|
+
}
|
|
241
|
+
(0, bvt_analysis_formatter_1.logReportLink)(runId, projectId, testProgressReport.result);
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
console.error(`failed to modify the test case: ${testProgressReport.id} ${e}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async createStatus(status) {
|
|
248
|
+
if (!process.env.UUID) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/scenarios/status', {
|
|
253
|
+
status: { status },
|
|
254
|
+
uuid: process.env.UUID,
|
|
255
|
+
}, {
|
|
256
|
+
headers: {
|
|
257
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
258
|
+
'x-source': 'cucumber_js',
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
console.log('Failed to send status to the server, ignoring it');
|
|
264
|
+
}
|
|
113
265
|
}
|
|
114
266
|
}
|
|
115
267
|
exports.RunUploadService = RunUploadService;
|
|
@@ -1 +1 @@
|
|
|
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 === 401) {\n console.log('Warning: Your trial plan has ended. Cannot upload reports and perform retraining');\n throw new Error('Warning: Your trial plan has ended. Cannot upload reports and perform retraining')\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 === 403) {\n console.log('Warning: Your trial plan has ended. Cannot upload reports and perform retraining');\n throw new Error('Warning: Your trial plan has ended. Cannot upload reports and perform retraining')\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 } 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, projectId: string) {\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/uploadCompletion',\n {\n runId,\n projectId,\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"]}
|
|
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, existsSync, write, writeFileSync } from 'fs'\nimport fs from 'fs/promises'\n\nimport { JsonReport, JsonTestProgress } from './report_generator'\nimport { axiosClient } from '../../configuration/axios_client'\nimport path from 'path'\nimport { logReportLink } from '../bvt_analysis_formatter'\nimport { ActionEvents, SERVICES_URI } from './constants'\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 interface RootCauseProps {\n status: boolean\n analysis: string\n failedStep: number\n failClass: string\n}\n\nexport interface FinishTestCaseResponse {\n status: true\n rootCause: RootCauseProps\n report: JsonTestProgress\n}\n\nclass RunUploadService {\n constructor(private runsApiBaseURL: string, private accessToken: string) {}\n async createRunDocument(name: string) {\n try {\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 } catch (error) {\n if (error.response && error.response.status === 403) {\n console.log(\n 'Warning: Your trial plan has ended. Cannot create or upload reports.'\n )\n process.exit(1)\n }\n throw new Error('Failed to create run document in the server: ' + error)\n }\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 === 401) {\n console.log(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\n )\n throw new Error(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\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 === 403) {\n console.log(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\n )\n throw new Error(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\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 uploadTestCase(\n testCaseReport: JsonTestProgress,\n runId: string,\n projectId: string,\n reportFolder: string,\n rerunId?: string\n ) {\n const fileUris = []\n //iterate over all the files in the JsonCommand.screenshotId and insert them into the fileUris array\n for (const step of testCaseReport.steps) {\n for (const command of step.commands) {\n if (command.screenshotId) {\n fileUris.push(\n 'screenshots' + '/' + String(command.screenshotId) + '.png'\n )\n }\n }\n if (step.traceFilePath) {\n fileUris.push('trace' + '/' + step.traceFilePath)\n }\n }\n if (testCaseReport.logFileId) {\n fileUris.push(\n 'editorLogs' + '/' + 'testCaseLog_' + testCaseReport.logFileId + '.log'\n )\n }\n // console.log({ fileUris })\n const preSignedUrls = await this.getPreSignedUrls(fileUris, runId)\n //upload all the files in the fileUris array\n try {\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 if (existsSync(path.join(reportFolder, fileUri))) {\n const success = await this.uploadFile(\n path.join(reportFolder, fileUri),\n preSignedUrls[fileUri]\n )\n if (success) {\n return\n }\n }\n const success = await this.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\n // writeFileSync(\"report.json\", JSON.stringify(testCaseReport, null, 2))\n const { data } = await axiosClient.post<FinishTestCaseResponse>(\n this.runsApiBaseURL + '/cucumber-runs/createNewTestCase',\n {\n runId,\n projectId,\n testProgressReport: testCaseReport,\n browser: process.env.BROWSER ? process.env.BROWSER : 'chromium',\n mode: process.env.MODE === 'cloud' ? 'cloud' : 'local',\n rerunId,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n\n try {\n await axiosClient.post(\n `${SERVICES_URI.STORAGE}/event`,\n {\n event: ActionEvents.upload_report,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n 'x-bvt-project-id': projectId,\n },\n }\n )\n } catch (error) {\n // no event tracking\n }\n logReportLink(runId, projectId, testCaseReport.result)\n return data\n } catch (e) {\n console.error(`failed to upload the test case: ${testCaseReport.id} ${e}`)\n return null\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 } 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, projectId: string) {\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/uploadCompletion',\n {\n runId,\n projectId,\n browser: process.env.BROWSER ? process.env.BROWSER : 'chromium',\n mode: process.env.MODE === 'cloud' ? 'cloud' : 'local',\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 try {\n await axiosClient.post(\n `${SERVICES_URI.STORAGE}/event`,\n {\n event: ActionEvents.upload_report,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n 'x-bvt-project-id': projectId,\n },\n }\n )\n } catch (error) {\n // no event tracking\n }\n }\n async modifyTestCase(\n runId: string,\n projectId: string,\n testProgressReport: JsonTestProgress\n ) {\n try {\n const res = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/modifyTestCase',\n {\n runId,\n projectId,\n testProgressReport,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (res.status !== 200) {\n throw new Error('')\n }\n if (res.data.status !== true) {\n throw new Error('')\n }\n logReportLink(runId, projectId, testProgressReport.result)\n } catch (e) {\n console.error(\n `failed to modify the test case: ${testProgressReport.id} ${e}`\n )\n }\n }\n async createStatus(status: string) {\n if (!process.env.UUID) {\n return\n }\n\n try {\n await axiosClient.post(\n this.runsApiBaseURL + '/scenarios/status',\n {\n status: { status },\n uuid: process.env.UUID,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n } catch (error) {\n console.log('Failed to send status to the server, ignoring it')\n }\n }\n}\n\nexport { RunUploadService }\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import ReportGenerator, { JsonReport } from './report_generator';
|
|
1
|
+
import ReportGenerator, { JsonReport, JsonTestProgress } from './report_generator';
|
|
2
2
|
export default class ReportUploader {
|
|
3
3
|
private uploadService;
|
|
4
4
|
private reportGenerator;
|
|
@@ -7,5 +7,6 @@ export default class ReportUploader {
|
|
|
7
7
|
runId: any;
|
|
8
8
|
projectId: any;
|
|
9
9
|
}>;
|
|
10
|
+
modifyTestCase(testCase: JsonTestProgress): Promise<void>;
|
|
10
11
|
createZip(reportFolder: string | null, report: JsonReport): Promise<string>;
|
|
11
12
|
}
|
|
@@ -36,7 +36,13 @@ const URL = process.env.NODE_ENV_BLINQ === 'dev'
|
|
|
36
36
|
? 'https://dev.api.blinq.io/api/runs'
|
|
37
37
|
: process.env.NODE_ENV_BLINQ === 'local'
|
|
38
38
|
? 'http://localhost:5001/api/runs'
|
|
39
|
-
:
|
|
39
|
+
: process.env.NODE_ENV_BLINQ === 'stage'
|
|
40
|
+
? 'https://stage.api.blinq.io/api/runs'
|
|
41
|
+
: process.env.NODE_ENV_BLINQ === 'prod'
|
|
42
|
+
? 'https://api.blinq.io/api/runs'
|
|
43
|
+
: !process.env.NODE_ENV_BLINQ
|
|
44
|
+
? 'https://api.blinq.io/api/runs'
|
|
45
|
+
: `${process.env.NODE_ENV_BLINQ}/api/runs`;
|
|
40
46
|
const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
|
|
41
47
|
const BATCH_SIZE = 10;
|
|
42
48
|
const MAX_RETRIES = 3;
|
|
@@ -65,8 +71,10 @@ class ReportUploader {
|
|
|
65
71
|
}
|
|
66
72
|
else {
|
|
67
73
|
const fileUris = [
|
|
68
|
-
...
|
|
74
|
+
...getFileUris(reportFolder, 'screenshots'),
|
|
75
|
+
...getFileUris(reportFolder, 'trace'),
|
|
69
76
|
'report.json',
|
|
77
|
+
'network.json',
|
|
70
78
|
];
|
|
71
79
|
try {
|
|
72
80
|
const preSignedUrls = await this.uploadService.getPreSignedUrls(fileUris, runDocId);
|
|
@@ -92,6 +100,17 @@ class ReportUploader {
|
|
|
92
100
|
}
|
|
93
101
|
return { runId: runDoc._id, projectId: runDoc.project_id };
|
|
94
102
|
}
|
|
103
|
+
async modifyTestCase(testCase) {
|
|
104
|
+
const runId = process.env.RUN_ID;
|
|
105
|
+
if (!runId) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const projectId = process.env.PROJECT_ID;
|
|
109
|
+
if (!projectId) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
await this.uploadService.modifyTestCase(runId, projectId, testCase);
|
|
113
|
+
}
|
|
95
114
|
async createZip(reportFolder, report) {
|
|
96
115
|
if (reportFolder === null) {
|
|
97
116
|
console.error('report folder is empty');
|
|
@@ -108,7 +127,7 @@ class ReportUploader {
|
|
|
108
127
|
const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' });
|
|
109
128
|
// save zip file
|
|
110
129
|
const zipPath = path_1.default.join(reportFolder, 'report.zip');
|
|
111
|
-
fs_1.default.writeFileSync(zipPath, zipBuffer);
|
|
130
|
+
fs_1.default.writeFileSync(zipPath, new Uint8Array(zipBuffer));
|
|
112
131
|
fs_1.default.writeFileSync(path_1.default.join(reportFolder, 'report.json'), JSON.stringify(report, null, 2));
|
|
113
132
|
return zipPath;
|
|
114
133
|
}
|
|
@@ -118,4 +137,12 @@ const getFileUrisScreenShotDir = (reportFolder) => {
|
|
|
118
137
|
const files = fs_1.default.readdirSync(path_1.default.join(reportFolder, 'screenshots'));
|
|
119
138
|
return files.map((file) => ['screenshots', file].join('/'));
|
|
120
139
|
};
|
|
140
|
+
const getFileUris = (reportFolder, targetFolder) => {
|
|
141
|
+
const resultFolder = path_1.default.join(reportFolder, targetFolder);
|
|
142
|
+
if (!fs_1.default.existsSync(resultFolder)) {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
const files = fs_1.default.readdirSync(resultFolder);
|
|
146
|
+
return files.map((file) => [targetFolder, file].join('/'));
|
|
147
|
+
};
|
|
121
148
|
//# sourceMappingURL=uploader.js.map
|
|
@@ -1 +1 @@
|
|
|
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, { writeFileSync } from 'fs'\nimport JSZip from 'jszip'\nimport path from 'path'\nconst URL =\n process.env.NODE_ENV_BLINQ === 'dev'\n ? 'https://dev.api.blinq.io/api/runs'\n : process.env.NODE_ENV_BLINQ === 'local'\n ? 'http://localhost:5001/api/runs'\n : 'https://api.blinq.io/api/runs'\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 writeFileSync(\n path.join(reportFolder, 'report.json'),\n JSON.stringify(report, null, 2)\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 = [\n ...getFileUrisScreenShotDir(reportFolder),\n 'report.json',\n ]\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, runDoc.project_id)\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"]}
|
|
1
|
+
{"version":3,"file":"uploader.js","sourceRoot":"","sources":["../../../src/formatter/helpers/uploader.ts"],"names":[],"mappings":"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","sourcesContent":["import axios from 'axios'\nimport ReportGenerator, {\n JsonReport,\n JsonTestProgress,\n} from './report_generator'\nimport { RunUploadService } from './upload_serivce'\n\nimport FormData from 'form-data'\nimport fs, { writeFileSync } from 'fs'\nimport JSZip from 'jszip'\nimport path from 'path'\nconst URL =\n process.env.NODE_ENV_BLINQ === 'dev'\n ? 'https://dev.api.blinq.io/api/runs'\n : process.env.NODE_ENV_BLINQ === 'local'\n ? 'http://localhost:5001/api/runs'\n : process.env.NODE_ENV_BLINQ === 'stage'\n ? 'https://stage.api.blinq.io/api/runs'\n : process.env.NODE_ENV_BLINQ === 'prod'\n ? 'https://api.blinq.io/api/runs'\n : !process.env.NODE_ENV_BLINQ\n ? 'https://api.blinq.io/api/runs'\n : `${process.env.NODE_ENV_BLINQ}/api/runs`\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 writeFileSync(\n path.join(reportFolder, 'report.json'),\n JSON.stringify(report, null, 2)\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 = [\n ...getFileUris(reportFolder, 'screenshots'),\n ...getFileUris(reportFolder, 'trace'),\n 'report.json',\n 'network.json',\n ]\n try {\n const preSignedUrls = await this.uploadService.getPreSignedUrls(\n fileUris,\n runDocId\n )\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, runDoc.project_id)\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\n async modifyTestCase(testCase: JsonTestProgress) {\n const runId = process.env.RUN_ID\n if (!runId) {\n return\n }\n const projectId = process.env.PROJECT_ID\n if (!projectId) {\n return\n }\n await this.uploadService.modifyTestCase(runId, projectId, testCase)\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, new Uint8Array(zipBuffer))\n fs.writeFileSync(\n path.join(reportFolder, 'report.json'),\n JSON.stringify(report, null, 2)\n )\n return zipPath\n }\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\nconst getFileUris = (reportFolder: string, targetFolder: string) => {\n const resultFolder = path.join(reportFolder, targetFolder)\n if (!fs.existsSync(resultFolder)) {\n return []\n }\n const files = fs.readdirSync(resultFolder)\n return files.map((file) => [targetFolder, file].join('/'))\n}\n"]}
|
|
@@ -8,6 +8,7 @@ const _1 = __importDefault(require("./"));
|
|
|
8
8
|
const value_checker_1 = require("../value_checker");
|
|
9
9
|
const issue_helpers_1 = require("./helpers/issue_helpers");
|
|
10
10
|
const time_1 = require("../time");
|
|
11
|
+
const bvt_analysis_formatter_1 = require("./bvt_analysis_formatter");
|
|
11
12
|
class SummaryFormatter extends _1.default {
|
|
12
13
|
constructor(options) {
|
|
13
14
|
super(options);
|
|
@@ -43,6 +44,9 @@ class SummaryFormatter extends _1.default {
|
|
|
43
44
|
if (warnings.length > 0) {
|
|
44
45
|
this.logIssues({ issues: warnings, title: 'Warnings' });
|
|
45
46
|
}
|
|
47
|
+
if (bvt_analysis_formatter_1.globalReportLink) {
|
|
48
|
+
console.log(`Report link: ${bvt_analysis_formatter_1.globalReportLink}\n`);
|
|
49
|
+
}
|
|
46
50
|
this.log((0, helpers_1.formatSummary)({
|
|
47
51
|
colorFns: this.colorFns,
|
|
48
52
|
testCaseAttempts,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summary_formatter.js","sourceRoot":"","sources":["../../src/formatter/summary_formatter.ts"],"names":[],"mappings":";;;;;AAAA,uCAA4E;AAC5E,0CAAiD;AACjD,oDAAgD;AAGhD,2DAAuE;AACvE,kCAAmD;
|
|
1
|
+
{"version":3,"file":"summary_formatter.js","sourceRoot":"","sources":["../../src/formatter/summary_formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import { formatIssue, formatSummary, isFailure, isWarning } from './helpers'\nimport Formatter, { IFormatterOptions } from './'\nimport { doesHaveValue } from '../value_checker'\nimport * as messages from '@cucumber/messages'\nimport { ITestCaseAttempt } from './helpers/event_data_collector'\nimport { formatUndefinedParameterTypes } from './helpers/issue_helpers'\nimport { durationBetweenTimestamps } from '../time'\nimport { globalReportLink } from './bvt_analysis_formatter'\n\ninterface ILogIssuesRequest {\n issues: ITestCaseAttempt[]\n title: string\n}\n\nexport default class SummaryFormatter extends Formatter {\n public static readonly documentation: string =\n 'Summary output of feature and scenarios'\n\n constructor(options: IFormatterOptions) {\n super(options)\n let testRunStartedTimestamp: messages.Timestamp\n options.eventBroadcaster.on('envelope', (envelope: messages.Envelope) => {\n if (doesHaveValue(envelope.testRunStarted)) {\n testRunStartedTimestamp = envelope.testRunStarted.timestamp\n }\n if (doesHaveValue(envelope.testRunFinished)) {\n const testRunFinishedTimestamp = envelope.testRunFinished.timestamp\n this.logSummary(\n durationBetweenTimestamps(\n testRunStartedTimestamp,\n testRunFinishedTimestamp\n )\n )\n }\n })\n }\n\n logSummary(testRunDuration: messages.Duration): void {\n const failures: ITestCaseAttempt[] = []\n const warnings: ITestCaseAttempt[] = []\n const testCaseAttempts = this.eventDataCollector.getTestCaseAttempts()\n testCaseAttempts.forEach((testCaseAttempt) => {\n if (\n isFailure(\n testCaseAttempt.worstTestStepResult,\n testCaseAttempt.willBeRetried\n )\n ) {\n failures.push(testCaseAttempt)\n } else if (\n isWarning(\n testCaseAttempt.worstTestStepResult,\n testCaseAttempt.willBeRetried\n )\n ) {\n warnings.push(testCaseAttempt)\n }\n })\n if (this.eventDataCollector.undefinedParameterTypes.length > 0) {\n this.log(\n formatUndefinedParameterTypes(\n this.eventDataCollector.undefinedParameterTypes\n )\n )\n }\n if (failures.length > 0) {\n this.logIssues({ issues: failures, title: 'Failures' })\n }\n if (warnings.length > 0) {\n this.logIssues({ issues: warnings, title: 'Warnings' })\n }\n if (globalReportLink) {\n console.log(`Report link: ${globalReportLink}\\n`);\n }\n this.log(\n formatSummary({\n colorFns: this.colorFns,\n testCaseAttempts,\n testRunDuration,\n })\n )\n }\n\n logIssues({ issues, title }: ILogIssuesRequest): void {\n this.log(`${title}:\\n\\n`)\n issues.forEach((testCaseAttempt, index) => {\n this.log(\n formatIssue({\n colorFns: this.colorFns,\n number: index + 1,\n snippetBuilder: this.snippetBuilder,\n supportCodeLibrary: this.supportCodeLibrary,\n testCaseAttempt,\n printAttachments: this.printAttachments,\n })\n )\n })\n }\n}\n"]}
|
|
@@ -37,6 +37,7 @@ export default class TestCaseRunner {
|
|
|
37
37
|
private testStepResults;
|
|
38
38
|
private world;
|
|
39
39
|
private readonly worldParameters;
|
|
40
|
+
private reportGenerator;
|
|
40
41
|
constructor({ eventBroadcaster, stopwatch, gherkinDocument, newId, pickle, testCase, retries, skip, filterStackTraces, supportCodeLibrary, worldParameters, }: INewTestCaseRunnerOptions);
|
|
41
42
|
resetTestProgressData(): void;
|
|
42
43
|
getBeforeStepHookDefinitions(): TestStepHookDefinition[];
|
|
@@ -32,6 +32,8 @@ const step_runner_1 = __importDefault(require("./step_runner"));
|
|
|
32
32
|
const messages = __importStar(require("@cucumber/messages"));
|
|
33
33
|
const messages_1 = require("@cucumber/messages");
|
|
34
34
|
const value_checker_1 = require("../value_checker");
|
|
35
|
+
const report_generator_1 = __importDefault(require("../formatter/helpers/report_generator"));
|
|
36
|
+
const bvt_analysis_formatter_1 = __importDefault(require("../formatter/bvt_analysis_formatter"));
|
|
35
37
|
class TestCaseRunner {
|
|
36
38
|
constructor({ eventBroadcaster, stopwatch, gherkinDocument, newId, pickle, testCase, retries = 0, skip, filterStackTraces, supportCodeLibrary, worldParameters, }) {
|
|
37
39
|
this.attachmentManager = new attachment_manager_1.default(({ data, media, fileName }) => {
|
|
@@ -62,6 +64,7 @@ class TestCaseRunner {
|
|
|
62
64
|
this.supportCodeLibrary = supportCodeLibrary;
|
|
63
65
|
this.worldParameters = worldParameters;
|
|
64
66
|
this.resetTestProgressData();
|
|
67
|
+
this.reportGenerator = new report_generator_1.default();
|
|
65
68
|
}
|
|
66
69
|
resetTestProgressData() {
|
|
67
70
|
this.world = new this.supportCodeLibrary.World({
|
|
@@ -187,7 +190,13 @@ class TestCaseRunner {
|
|
|
187
190
|
willBeRetried,
|
|
188
191
|
},
|
|
189
192
|
};
|
|
190
|
-
|
|
193
|
+
const rerunId = bvt_analysis_formatter_1.default.reRunFailedStepsIndex
|
|
194
|
+
? bvt_analysis_formatter_1.default.reRunFailedStepsIndex[0].testCaseId
|
|
195
|
+
: null;
|
|
196
|
+
const data = bvt_analysis_formatter_1.default.reportGenerator
|
|
197
|
+
? await bvt_analysis_formatter_1.default.reportGenerator.handleMessage(testCaseFinished, rerunId)
|
|
198
|
+
: null;
|
|
199
|
+
this.eventBroadcaster.emit('envelope', testCaseFinished, data);
|
|
191
200
|
return willBeRetried;
|
|
192
201
|
}
|
|
193
202
|
async runHook(hookDefinition, hookParameter, isBeforeHook) {
|