@testomatio/reporter 0.4.1 → 0.4.5

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/Changelog.md CHANGED
@@ -1,3 +1,22 @@
1
+ # 0.4.5
2
+
3
+ * Fixed "Total XX artifacts publicly uploaded to S3 bucket" when no S3 bucket is configured
4
+ * Improved S3 connection error messages
5
+
6
+ # 0.4.4
7
+
8
+ * Fixed returning 0 exit code when a process fails when running tests in parallel via `start-test-run`. Previously was using the last exit code returned by a process. Currently prefers the highest exit code that was returned by a process.
9
+
10
+ # 0.4.3
11
+
12
+ * Added `TESTOMATIO_DISABLE_ARTIFACTS` env variable to disable publishing artifacts.
13
+
14
+ # 0.4.2
15
+
16
+ * print version of reporter
17
+ * print number of uploaded artifacts
18
+ * print access mode for uploaded artifacts
19
+
1
20
  # 0.4.1
2
21
 
3
22
  Added `global.testomatioArtifacts = []` array which can be used to add arbitrary artifacts to a report.
package/README.md CHANGED
@@ -248,6 +248,12 @@ global.testomatioArtifacts.push({ name: 'Screenshot', path: 'img/file.png' });
248
248
 
249
249
  Artifacts will be uploaded for the current test when it is finished.
250
250
 
251
+ To disable uploading artifacts add `TESTOMATIO_DISABLE_ARTIFACTS` environment variable:
252
+
253
+ ```
254
+ TESTOMATIO_DISABLE_ARTIFACTS=1
255
+ ```
256
+
251
257
 
252
258
  ## Starting an Empty Run
253
259
 
@@ -7,6 +7,7 @@ const chalk = require("chalk");
7
7
  const TestomatClient = require("../client");
8
8
  const { FAILED } = require("../constants");
9
9
  const TRConstants = require("../constants");
10
+ const upload = require("../fileUploader");
10
11
  const Output = require("../output");
11
12
 
12
13
  let currentMetaStep = [];
@@ -87,8 +88,8 @@ module.exports = (config) => {
87
88
  });
88
89
 
89
90
  event.dispatcher.on(event.all.result, async () => {
90
- if (videos.length) {
91
- console.log(TRConstants.APP_PREFIX, `🎞️ Uploading ${videos.length} videos...`);
91
+ if (videos.length && upload.isEnabled()) {
92
+ console.log(TRConstants.APP_PREFIX, `🎞️ Uploading ${videos.length} videos...`);
92
93
 
93
94
  let promises = [];
94
95
  for (const video of videos) {
@@ -5,6 +5,7 @@ const path = require('path');
5
5
  const fs = require('fs');
6
6
  const Status = require('../constants');
7
7
  const TestomatioClient = require("../client");
8
+ const upload = require("../fileUploader");
8
9
  const { parseTest } = require('../util');
9
10
 
10
11
  class TestomatioReporter {
@@ -75,8 +76,8 @@ class TestomatioReporter {
75
76
  async onEnd(result) {
76
77
  if (!this.client) return;
77
78
 
78
- if (this.videos.length) {
79
- console.log(Status.APP_PREFIX, `🎞️ Uploading ${this.videos.length} videos...`);
79
+ if (this.videos.length && upload.isEnabled()) {
80
+ console.log(Status.APP_PREFIX, `🎞️ Uploading ${this.videos.length} videos...`);
80
81
 
81
82
  let promises = [];
82
83
  for (const video of this.videos) {
@@ -43,6 +43,8 @@ program
43
43
  return;
44
44
  }
45
45
 
46
+ let exitCode = 0;
47
+
46
48
  const testCmds = command.split(" ");
47
49
  console.log(APP_PREFIX, `🚀 Running`, chalk.green(command));
48
50
 
@@ -55,7 +57,9 @@ program
55
57
  "⚠️ ",
56
58
  `Runner exited with ${chalk.bold(code)}, report is ignored`
57
59
  );
58
- process.exitCode = code;
60
+
61
+ if (code > exitCode) exitCode = code;
62
+ process.exitCode = exitCode;
59
63
  });
60
64
 
61
65
  return;
@@ -71,7 +75,9 @@ program
71
75
  console.log(APP_PREFIX, emoji, `Runner exited with ${chalk.bold(code)}`);
72
76
  const status = code === 0 ? "passed" : "failed";
73
77
  client.updateRunStatus(status, true);
74
- process.exitCode = code;
78
+
79
+ if (code > exitCode) exitCode = code;
80
+ process.exitCode = exitCode;
75
81
  });
76
82
  });
77
83
  });
package/lib/client.js CHANGED
@@ -2,13 +2,15 @@ const axios = require("axios");
2
2
  const JsonCycle = require("json-cycle");
3
3
  const { URL } = require("url");
4
4
  const createCallsiteRecord = require("callsite-record");
5
- const { sep } = require("path");
5
+ const { sep, join } = require("path");
6
+ const fs = require("fs");
6
7
  const chalk = require("chalk");
7
- const { uploadFile } = require("./fileUploader");
8
+ const upload = require("./fileUploader");
8
9
  const { PASSED, FAILED, FINISHED, APP_PREFIX } = require("./constants");
9
10
 
10
11
  const TESTOMAT_URL = process.env.TESTOMATIO_URL || "https://app.testomat.io";
11
- const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN } = process.env;
12
+ const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN } =
13
+ process.env;
12
14
 
13
15
  if (TESTOMATIO_RUN) {
14
16
  process.env.runId = TESTOMATIO_RUN;
@@ -27,6 +29,8 @@ class TestomatClient {
27
29
  this.runId = process.env.runId;
28
30
  this.queue = Promise.resolve();
29
31
  this.axios = axios.create();
32
+ this.totalUploaded = 0;
33
+ this.version = JSON.parse(fs.readFileSync(join(__dirname, '..', 'package.json')).toString()).version;
30
34
  }
31
35
 
32
36
  /**
@@ -36,7 +40,7 @@ class TestomatClient {
36
40
  */
37
41
  createRun() {
38
42
  const { runId } = process.env;
39
- if (!this.apiKey) throw new Error('No API key is set, can\'t create run');
43
+ if (!this.apiKey) throw new Error("No API key is set, can't create run");
40
44
  const runParams = {
41
45
  api_key: this.apiKey.trim(),
42
46
  title: this.title,
@@ -50,7 +54,9 @@ class TestomatClient {
50
54
  if (!isValidUrl(TESTOMAT_URL.trim())) {
51
55
  console.log(
52
56
  APP_PREFIX,
53
- chalk.red(`Error creating report on Testomat.io, report url '${TESTOMAT_URL}' is invalid`)
57
+ chalk.red(
58
+ `Error creating report on Testomat.io, report url '${TESTOMAT_URL}' is invalid`
59
+ )
54
60
  );
55
61
  return;
56
62
  }
@@ -58,7 +64,8 @@ class TestomatClient {
58
64
  if (runId) {
59
65
  this.runId = runId;
60
66
  this.queue = this.queue.then(() =>
61
- axios.put(`${TESTOMAT_URL.trim()}/api/reporter/${runId}`, runParams));
67
+ axios.put(`${TESTOMAT_URL.trim()}/api/reporter/${runId}`, runParams)
68
+ );
62
69
  return Promise.resolve(runId);
63
70
  }
64
71
 
@@ -75,10 +82,12 @@ class TestomatClient {
75
82
  console.log(
76
83
  APP_PREFIX,
77
84
  "📊 Report created. Report ID:",
78
- this.runId
85
+ this.runId,
86
+ chalk.gray(`v${this.version}`)
79
87
  );
80
88
  process.env.runId = this.runId;
81
- }))
89
+ })
90
+ )
82
91
  .catch(() => {
83
92
  console.log(
84
93
  APP_PREFIX,
@@ -118,11 +127,7 @@ class TestomatClient {
118
127
  stack = this.formatError(error);
119
128
  }
120
129
  if (steps) {
121
- stack = stack
122
- ? `${steps}\n\n${chalk.bold.red(
123
- "################[ Failure ]################"
124
- )}\n${stack}`
125
- : steps;
130
+ stack = this.formatSteps(stack, steps);
126
131
  }
127
132
 
128
133
  if (this.runId) {
@@ -132,7 +137,7 @@ class TestomatClient {
132
137
  }
133
138
 
134
139
  for (const file of files) {
135
- uploadedFiles.push(uploadFile(file, this.runId));
140
+ uploadedFiles.push(upload.uploadFile(file, this.runId));
136
141
  }
137
142
  }
138
143
 
@@ -142,6 +147,8 @@ class TestomatClient {
142
147
 
143
148
  global.testomatioArtifacts = [];
144
149
 
150
+ this.totalUploaded += uploadedFiles.filter((n) => n).length;
151
+
145
152
  const json = JsonCycle.stringify({
146
153
  api_key: this.apiKey,
147
154
  files,
@@ -173,7 +180,7 @@ class TestomatClient {
173
180
  .catch((err) => {
174
181
  if (err.response) {
175
182
  if (err.response.status >= 400) {
176
- const data = err.response.data || { message: '' };
183
+ const data = err.response.data || { message: "" };
177
184
  console.log(
178
185
  APP_PREFIX,
179
186
  chalk.blue(title),
@@ -187,7 +194,12 @@ class TestomatClient {
187
194
  `Report couldn't be processed: ${err.response.data.message}`
188
195
  );
189
196
  } else {
190
- console.log(APP_PREFIX, chalk.blue(title), "Report couldn't be processed", err);
197
+ console.log(
198
+ APP_PREFIX,
199
+ chalk.blue(title),
200
+ "Report couldn't be processed",
201
+ err
202
+ );
191
203
  }
192
204
  });
193
205
 
@@ -220,6 +232,15 @@ class TestomatClient {
220
232
  chalk.magenta(this.runUrl)
221
233
  );
222
234
  }
235
+
236
+ if (upload.isEnabled() && this.totalUploaded > 0) {
237
+ console.log(
238
+ APP_PREFIX,
239
+ `🗄️ Total ${this.totalUploaded} artifacts ${
240
+ upload.isPrivate ? "privately" : chalk.bold("publicly")
241
+ } uploaded to S3 bucket `
242
+ );
243
+ }
223
244
  }
224
245
  })
225
246
  .catch((err) => {
@@ -228,6 +249,12 @@ class TestomatClient {
228
249
  return this.queue;
229
250
  }
230
251
 
252
+ formatSteps(stack, steps) {
253
+ return stack
254
+ ? `${steps}\n\n${chalk.bold.red("################[ Failure ]################")}\n${stack}`
255
+ : steps;
256
+ }
257
+
231
258
  formatError(error, message) {
232
259
  if (!message) message = error.message;
233
260
  if (error.inspect) message = error.inspect();
@@ -2,13 +2,22 @@ const AWS = require("aws-sdk");
2
2
  const fs = require("fs");
3
3
  const path = require("path");
4
4
  const chalk = require("chalk");
5
+ const { APP_PREFIX } = require("./constants");
6
+
7
+ const isPrivate = process.env.TESTOMATIO_PRIVATE_ARTIFACTS;
8
+
9
+ function isEnabled() {
10
+ return process.env.S3_BUCKET && !process.env.TESTOMATIO_DISABLE_ARTIFACTS;
11
+ }
5
12
 
6
13
  const uploadUsingS3 = async (filePath, runId) => {
7
14
  const region = process.env.S3_REGION;
8
15
  const bucket = process.env.S3_BUCKET;
9
16
  const accessKeyId = process.env.S3_ACCESS_KEY_ID;
10
17
  const secretAccessKey = process.env.S3_SECRET_ACCESS_KEY;
11
- const isPrivate = process.env.TESTOMATIO_PRIVATE_ARTIFACTS;
18
+ const isDisabled = process.env.TESTOMATIO_DISABLE_ARTIFACTS;
19
+
20
+ if (isDisabled) return;
12
21
 
13
22
  let contentType;
14
23
  let fileName;
@@ -28,23 +37,43 @@ const uploadUsingS3 = async (filePath, runId) => {
28
37
  const file = fs.readFileSync(filePath);
29
38
 
30
39
  fileName = `${runId}/${fileName || path.basename(filePath)}`;
40
+ const acl = isPrivate ? "private" : "public-read"
31
41
 
32
- const out = await s3
33
- .upload({
34
- Bucket: bucket,
35
- Key: fileName,
36
- Body: file,
37
- ContentType: contentType,
38
- ACL: isPrivate ? "private" : "public-read",
42
+ try {
43
+ const out = await s3
44
+ .upload({
45
+ Bucket: bucket,
46
+ Key: fileName,
47
+ Body: file,
48
+ ContentType: contentType,
49
+ ACL: acl,
50
+ })
51
+ .promise();
52
+ return out.Location;
53
+ } catch (e) {
54
+ console.log(APP_PREFIX, chalk.bold.red(`Failed uploading '${fileName}'. Please check S3 credentials`), {
55
+ accessKeyId,
56
+ secretAccessKey: secretAccessKey ? '**** (hidden) ***' : '(empty)',
57
+ region,
58
+ bucket,
59
+ acl,
60
+ endpoint: process.env.S3_ENDPOINT
39
61
  })
40
- .promise();
41
- return out.Location;
42
- };
43
62
 
63
+ console.log(APP_PREFIX, `To ${chalk.bold('disable')} artifact uploads set: TESTOMATIO_DISABLE_ARTIFACTS=1`)
64
+ if (!isPrivate) {
65
+ console.log(APP_PREFIX, `To enable ${chalk.bold('PRIVATE')} uploads set: TESTOMATIO_PRIVATE_ARTIFACTS=1`)
66
+ } else {
67
+ console.log(APP_PREFIX, `To enable ${chalk.bold('PUBLIC')} uploads remove TESTOMATIO_PRIVATE_ARTIFACTS env variable`)
68
+ }
69
+ console.log(APP_PREFIX, '---------------')
70
+ return null;
71
+ }
72
+ };
44
73
 
45
74
  const uploadFile = async (filePath, runId) => {
46
75
  try {
47
- if (process.env.S3_BUCKET) {
76
+ if (isEnabled()) {
48
77
  return uploadUsingS3(filePath, runId);
49
78
  }
50
79
  } catch (e) {
@@ -55,4 +84,6 @@ const uploadFile = async (filePath, runId) => {
55
84
 
56
85
  module.exports = {
57
86
  uploadFile,
87
+ isPrivate,
88
+ isEnabled,
58
89
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "0.4.1",
3
+ "version": "0.4.5",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "main": "./lib/reporter.js",
6
6
  "repository": "git@github.com:testomatio/reporter.git",