@testomatio/reporter 1.0.0 → 1.0.1-6.1

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,6 +1,97 @@
1
+ <!-- pending release updates -->
2
+ # 1.0.16.1
3
+
4
+ Renamed `TESTOMATIO_STACK_FILTER` to `TESTOMATIO_STACK_IGNORE`
5
+
6
+ # 1.0.16
7
+
8
+ * Addded [stack trace configuration](./docs/stacktrace.md) and documentation:
9
+
10
+ ```
11
+ TESTOMATIO_STACK_IGNORE="tests/support/**.js" <actual-run-command>
12
+ ```
13
+ * Jest: fixed reporting tests without a suite title
14
+
15
+ # 1.0.15
16
+
17
+ * Attach Run to Jira Issue via `TESTOMATIO_JIRA_ID` env variable:
18
+
19
+ ```
20
+ TESTOMATIO_JIRA_ID=TST-12 <actual run command>
21
+ ```
22
+
23
+ * Mocha - removed requirement of TESTOMATIO API Key
24
+
25
+ # 1.0.14
26
+
27
+ * Execute tests by tag names. Use this filter to select tests associated with specific tags.
28
+
29
+ ```bash
30
+ TESTOMATIO={API_KEY} npx start-test-run -c 'actual run command' --filter 'testomatio:tag-name=smoke'
31
+ ```
32
+
33
+ * more instruction you can find in docs/pipes/testomatio.md
34
+
35
+ # 1.0.13
36
+
37
+ * JUnit improvements
38
+ * Match test from source code by adding Test ID as a comment:
39
+
40
+ ```java
41
+ // @T8acca9eb
42
+ ```
43
+ * Match test from output by adding Test ID as output:
44
+
45
+ ```java
46
+ System.out.println("tid://@T8acca9eb");
47
+ ```
48
+ * Support for suite before and after output
49
+ * Improved support for artifacts
50
+
51
+ # 1.0.12
52
+
53
+ & Logger refactoring by @olexandr13 in #208
54
+ * fix undefined logs by @olexandr13 in #210
55
+
56
+ # 1.0.11
57
+
58
+ * fix steps duplication for codecept report by @olexandr13 in #209
59
+
60
+ # 1.0.10
61
+
62
+ * Added `TESTOMATIO_PUBLISH=1` variable to automatically publish run report
63
+
64
+ # 1.0.9
65
+
66
+ * Support XUnit format
67
+ * Improved support for parametrized Java tests
68
+
69
+ # 1.0.8
70
+
71
+ * Fixed `Can't read push of undefined` when logging steps
72
+
73
+ # 1.0.6
74
+
75
+ * Testomat.io. Auto-detect current build url and report it to Testomat.io. Manually url can be set with `BUILD_URL` variable:
76
+
77
+ ```
78
+ BUILD_URL=https://.... TESTOMATIO=apiKey <actual test command>
79
+ ```
80
+
81
+ # 1.0.5
82
+
83
+ * Fix "create tests" params processing for testomatio pipe
84
+
85
+ # 1.0.4
86
+
87
+ * Fixed parallel run
88
+
89
+ # 1.0.3
90
+
91
+ * Fixed reporting parallel runs
92
+
1
93
  # 1.0.0
2
94
 
3
- <!-- pending release updates -->
4
95
 
5
96
  * Added [`TESTOMATIO_SHARED_RUN` option](https://github.com/testomatio/reporter/blob/master/docs/pipes.md#reporting-parallel-execution-to-to-same-run) to use a shared run for parallel executions
6
97
  * Reworked [documentation](https://github.com/testomatio/reporter/tree/master#readme).
package/README.md CHANGED
@@ -11,12 +11,13 @@ Testomat.io Reporter (this npm package) supports:
11
11
 
12
12
  * 🏄 Integarion with all popular [JavaScript/TypeScript frameworks](./docs/frameworks.md)
13
13
  * 🗄️ Screenshots, videos, traces [uploaded into S3 bucket](./docs/artifacts.md)
14
- * 🔎 Stack traces and error messages
15
- * 🐙 [GitHub](./docs/pipes.md#github-pipe) & [GitLab](./docs/pipes.md#gitlab-pipe) integration
14
+ * 🔎 [Stack traces](./docs/stacktrace.md) and error messages
15
+ * 🐙 [GitHub](./docs/pipes/github.md) & [GitLab](./docs/pipes/gitlab.md) integration
16
16
  * 🚅 Realtime reports
17
17
  * 🗃️ Other test frameworks supported via [JUNit XML](./docs/junit.md)
18
18
  * 🚶‍♀️ Steps *(work in progress)*
19
- * ☁️ Custom properties and metadata *(work in progress)*
19
+ * 📄 [Logger](./docs/logger.md) *(work in progress, supports Jest for now)*
20
+ * ☁️ Custom properties and metadata *(work in progress)*
20
21
  * 💯 Free & open-source.
21
22
  * 📊 Public and private Run reports on cloud via [Testomat.io App](https://testomat.io) 👇
22
23
 
@@ -64,7 +65,7 @@ yarn add @testomatio/reporter --dev
64
65
 
65
66
  ### 1️⃣ Attach Reporter to the Test Runner
66
67
 
67
- * #### [Playwright](./docs/frameworks.md#playwright)
68
+ * #### [Playwright](./docs/frameworks.md#playwright)
68
69
  * #### [CodeceptJS](./docs/frameworks.md#CodeceptJS)
69
70
  * #### [Cypress](./docs/frameworks.md#Cypress)
70
71
  * #### [Jest](./docs/frameworks.md#Jest)
@@ -84,13 +85,13 @@ or any [other via JUnit](./docs/junit.md) report....
84
85
 
85
86
  ### 2️⃣ Configure Reports
86
87
 
87
- * [Create report on Testomat.io](./docs/pipes.md#testomatio-pipe).
88
- * [Create brief summary report for GitHub Pull Request](./docs/pipes.md#github-pipe) 👇
89
- * [Create brief summary report for GitLab Merge Request](./docs/pipes.md#gitlab-pipe).
90
- * [Configure other pipes](./docs/pipes.md) for other ways to process test results output.
88
+ * [Create report on Testomat.io](./docs/pipes/testomatio.md).
89
+ * [Create brief summary report for GitHub Pull Request](./docs/pipes/github.md) 👇
90
+ * [Create brief summary report for GitLab Merge Request](./docs/pipes/gitlab.md).
91
+ * [Configure other pipes](./docs/pipes/md) for other ways to process test results output.
91
92
 
92
93
 
93
- ![GitHub report](./docs/images/github.png)
94
+ ![GitHub report](./docs/pipes/images/github.png)
94
95
 
95
96
  GitHub report published as a comment to Pull Request:
96
97
 
@@ -99,7 +100,11 @@ GitHub report published as a comment to Pull Request:
99
100
  1. Create bucket on AWS, Google Cloud, or any other cloud storage provider supporting S3 protocol.
100
101
  2. [Pass S3 credentials](./docs/artifacts.md) to reporter to enable artifacts uploading.
101
102
 
102
- ### 4️⃣ Add to CI Pipeline
103
+ ### 4️⃣ Use Logger
104
+
105
+ Intercept your logger messages or log anything with our [Logger](./docs/logger.md) (_work in progress_).
106
+
107
+ ### 5️⃣ Add to CI Pipeline
103
108
 
104
109
  After you tested reporter locally add it to your CI pipeline.
105
110
 
@@ -116,9 +121,14 @@ Bring this reporter on CI and never lose test results again!
116
121
 
117
122
  * 🛠️ [Frameworks](./docs/frameworks.md)
118
123
  * ⛲ [Pipes](./docs/pipes.md)
124
+ * [Testomat.io](./docs/pipes/testomatio.md)
125
+ * [GitHub](./docs/pipes/github.md)
126
+ * [Gitlab](./docs/pipes/gitlab.md)
127
+ * [CSV](./docs/pipes/csv.md)
119
128
  * 📓 [JUnit](./docs/junit.md)
120
129
  * 🗄️ [Artifacts](./docs/artifacts.md)
121
130
  * 🔂 [Workflows](./docs/workflows.md)
131
+ * 🖊️ [Logger](./docs/logger.md)
122
132
 
123
133
  ## Development
124
134
 
@@ -4,27 +4,32 @@ const fs = require('fs');
4
4
  const os = require('os');
5
5
  const uuid = require('uuid');
6
6
  const { TESTOMAT_ARTIFACT_SUFFIX } = require('./constants');
7
- const { specificTestInfo } = require('./util');
7
+ const { specificTestInfo } = require('./utils/utils');
8
8
 
9
9
  class ArtifactStorage {
10
-
10
+
11
11
  constructor(params) {
12
- this._tmpPrefix = "tsmt_reporter";
13
12
  this.isFile = false;
14
13
  this.isMemory = true;
15
14
  this.storage = params?.toFile;
16
15
 
17
16
  if (this.storage) {
17
+ // this is fine to use when you start saving artifacts;
18
+ // but when you need to retrieve them, you will not know if there is "isFile" param,
19
+ // because you need to create a new instance of ArtifactStorage inside client
20
+ // so the solution is make it opposite to isMemory (which will be retrieved from global)
18
21
  this.isFile = true;
19
22
  this.isMemory = false;
20
- this.tmpDirFullpath = this.createTestomatTmpDir(this._tmpPrefix);
23
+ this.tmpDirFullpath = this.createTestomatTmpDir(ArtifactStorage._tmpPrefix);
21
24
  debug('SAVE to tmp folder mode enabled!');
22
25
  }
23
26
  }
24
27
 
25
28
  static async storeToFile(tmpDirName, artifact, testSuffix = "test") {
29
+ // this assumes to use multiple files for each test. do we really want this?
26
30
  const suffix = TESTOMAT_ARTIFACT_SUFFIX + uuid.v4() + testSuffix;
27
31
  const dirpath = join(os.tmpdir(), tmpDirName);
32
+ // why json?
28
33
  const filepath = resolve(dirpath, `${suffix}.json`);
29
34
 
30
35
  return fs.promises.appendFile(filepath, JSON.stringify(artifact));
@@ -34,6 +39,7 @@ class ArtifactStorage {
34
39
  // TODO: mode for different pre-hooks. As variant - "all-tests" || "only_fail"
35
40
  // const mode = process.env.TESTOMAT_ARTIFACTS || "only_fail";
36
41
 
42
+ // you save the artifact without specifying its source - test id
37
43
  if (Array.isArray(global.testomatioArtifacts)) {
38
44
  debug("Saving artifacts to global storage");
39
45
 
@@ -71,6 +77,7 @@ class ArtifactStorage {
71
77
  return list;
72
78
  }
73
79
 
80
+ // returns all the content from all files; do we really need it?
74
81
  async tmpContents() {
75
82
  const contents = [];
76
83
 
@@ -103,8 +110,9 @@ class ArtifactStorage {
103
110
  }
104
111
  }
105
112
 
113
+ // no need to use multiple dirs; we can implement it later if required
106
114
  static tmpTestomatDirNames() {
107
- const subname = this._tmpPrefix || "tsmt_reporter";
115
+ const subname = ArtifactStorage._tmpPrefix || "tsmt_reporter";
108
116
 
109
117
  return fs.readdirSync(os.tmpdir(), { withFileTypes: true })
110
118
  .filter((item) => item.isDirectory())
@@ -113,6 +121,7 @@ class ArtifactStorage {
113
121
  }
114
122
 
115
123
  cleanup() {
124
+ // when you do a cleanup, I know nothing about isFile param
116
125
  if (this.isFile && this.tmpDirFullpath) {
117
126
  const tmpDirNames = ArtifactStorage.tmpTestomatDirNames();
118
127
 
@@ -128,4 +137,6 @@ class ArtifactStorage {
128
137
  }
129
138
  }
130
139
 
140
+ ArtifactStorage._tmpPrefix = "tsmt_reporter";
141
+
131
142
  module.exports = ArtifactStorage;
@@ -1,9 +1,9 @@
1
1
  const debug = require('debug')('@testomatio/reporter:adapter:codeceptjs');
2
2
  const chalk = require('chalk');
3
3
  const TestomatClient = require('../client');
4
- const { STATUS, APP_PREFIX } = require('../constants');
4
+ const { STATUS, APP_PREFIX, TESTOMAT_TMP_STORAGE } = require('../constants');
5
5
  const upload = require('../fileUploader');
6
- const Output = require('../output');
6
+ const { parseTest: getIdFromTestTitle, fileSystem } = require('../utils/utils');
7
7
 
8
8
  if (!global.codeceptjs) {
9
9
  // eslint-disable-next-line global-require, import/no-extraneous-dependencies
@@ -16,9 +16,9 @@ let currentMetaStep = [];
16
16
  let error;
17
17
  let stepShift = 0;
18
18
 
19
- const output = new Output({
20
- filterFn: stack => !stack.includes('codeceptjs/lib/output'), // output from codeceptjs
21
- });
19
+ // const output = new Output({
20
+ // filterFn: stack => !stack.includes('codeceptjs/lib/output'), // output from codeceptjs
21
+ // });
22
22
 
23
23
  let stepStart = new Date();
24
24
 
@@ -51,24 +51,36 @@ function CodeceptReporter(config) {
51
51
 
52
52
  recorder.startUnlessRunning();
53
53
 
54
+ global.testomatioRunningEnvironment = 'codeceptjs';
55
+
54
56
  // Listening to events
55
57
  event.dispatcher.on(event.all.before, () => {
58
+ // clear tmp dir
59
+ fileSystem.clearDir(TESTOMAT_TMP_STORAGE.mainDir);
60
+
56
61
  recorder.add('Creating new run', () => client.createRun());
57
62
  videos = [];
58
63
  traces = [];
64
+
65
+ if (!global.testomatioDataStore) global.testomatioDataStore = {};
59
66
  });
60
67
 
61
68
  event.dispatcher.on(event.test.before, () => {
62
69
  recorder.add(() => {
63
70
  currentMetaStep = [];
64
- output.reset();
65
- output.start();
71
+ // output.reset();
72
+ // output.start();
66
73
  stepShift = 0;
67
74
  });
75
+
76
+ if (!global.testomatioDataStore) global.testomatioDataStore = {};
77
+ // reset steps
78
+ global.testomatioDataStore.steps = [];
68
79
  });
69
80
 
70
81
  event.dispatcher.on(event.test.started, test => {
71
82
  testTimeMap[test.id] = Date.now();
83
+ if (global.testomatioDataStore) global.testomatioDataStore.currentlyRunningTestId = getIdFromTestTitle(test.title);
72
84
  });
73
85
 
74
86
  event.dispatcher.on(event.all.result, async () => {
@@ -97,10 +109,10 @@ function CodeceptReporter(config) {
97
109
  suite_title: test.parent && test.parent.title,
98
110
  message: testObj.message,
99
111
  time: getDuration(test),
100
- steps: output.text(),
112
+ steps: global.testomatioDataStore.steps.join('\n') || null,
101
113
  test_id: testId,
102
114
  });
103
- output.stop();
115
+ // output.stop();
104
116
  });
105
117
 
106
118
  event.dispatcher.on(event.test.failed, (test, err) => {
@@ -125,7 +137,7 @@ function CodeceptReporter(config) {
125
137
  time: 0,
126
138
  });
127
139
  }
128
- output.stop();
140
+ // output.stop();
129
141
  });
130
142
 
131
143
  event.dispatcher.on(event.test.after, test => {
@@ -141,32 +153,33 @@ function CodeceptReporter(config) {
141
153
 
142
154
  const files = [];
143
155
  if (artifacts.screenshot) files.push({ path: artifacts.screenshot, type: 'image/png' });
144
- // todo: video must be uploaded later....
156
+ // todo: video must be uploaded later....
145
157
 
146
-
147
- const reportTestPromise = client.addTestRun(STATUS.FAILED, {
148
- ...stripExampleFromTitle(title),
149
- test_id: testId,
150
- suite_title: test.parent && test.parent.title,
151
- error,
152
- message: testObj.message,
153
- time: getDuration(test),
154
- files,
155
- steps: output.text(),
156
- }).then(pipes => {
157
- testId = pipes.filter(p => p.pipe.includes('Testomatio'))[0]?.result?.data?.test_id;
158
-
159
- debug("artifacts", artifacts);
160
-
161
- for (const aid in artifacts) {
162
- if (aid.startsWith('video')) videos.push({ testId, title, path: artifacts[aid], type: 'video/webm' });
163
- if (aid.startsWith('trace')) traces.push({ testId, title, path: artifacts[aid], type: 'application/zip' });
164
- }
165
- });
158
+ const reportTestPromise = client
159
+ .addTestRun(STATUS.FAILED, {
160
+ ...stripExampleFromTitle(title),
161
+ test_id: testId,
162
+ suite_title: test.parent && test.parent.title,
163
+ error,
164
+ message: testObj.message,
165
+ time: getDuration(test),
166
+ files,
167
+ steps: global.testomatioDataStore?.steps?.join('\n') || null,
168
+ })
169
+ .then(pipes => {
170
+ testId = pipes.filter(p => p.pipe.includes('Testomatio'))[0]?.result?.data?.test_id;
171
+
172
+ debug('artifacts', artifacts);
173
+
174
+ for (const aid in artifacts) {
175
+ if (aid.startsWith('video')) videos.push({ testId, title, path: artifacts[aid], type: 'video/webm' });
176
+ if (aid.startsWith('trace')) traces.push({ testId, title, path: artifacts[aid], type: 'application/zip' });
177
+ }
178
+ });
166
179
 
167
180
  reportTestPromises.push(reportTestPromise);
168
181
 
169
- output.stop();
182
+ // output.stop();
170
183
  });
171
184
 
172
185
  event.dispatcher.on(event.test.skipped, test => {
@@ -182,7 +195,7 @@ function CodeceptReporter(config) {
182
195
  message: testObj.message,
183
196
  time: getDuration(test),
184
197
  });
185
- output.stop();
198
+ // output.stop();
186
199
  });
187
200
 
188
201
  event.dispatcher.on(event.step.started, step => {
@@ -207,30 +220,37 @@ function CodeceptReporter(config) {
207
220
  // eslint-disable-next-line no-continue
208
221
  if (!metaSteps[i]) continue;
209
222
  if (metaSteps[i].isBDD()) {
210
- output.push(repeat(stepShift) + chalk.bold(metaSteps[i].toString()) + metaSteps[i].comment);
223
+ // output.push(repeat(stepShift) + chalk.bold(metaSteps[i].toString()) + metaSteps[i].comment);
224
+ global.testomatioDataStore?.steps?.push(
225
+ repeat(stepShift) + chalk.bold(metaSteps[i].toString()) + metaSteps[i].comment,
226
+ );
211
227
  } else {
212
- output.push(repeat(stepShift) + chalk.green.bold(metaSteps[i].toString()));
228
+ // output.push(repeat(stepShift) + chalk.green.bold(metaSteps[i].toString()));
229
+ global.testomatioDataStore?.steps?.push(repeat(stepShift) + chalk.green.bold(metaSteps[i].toString()));
213
230
  }
214
231
  }
215
232
  }
216
233
  currentMetaStep = metaSteps;
217
234
  stepShift = 2 * shift;
218
235
 
219
- const durationMs = (+new Date() - (+stepStart));
236
+ const durationMs = +new Date() - (+stepStart);
220
237
  let duration = '';
221
238
  if (durationMs) {
222
239
  duration = repeat(1) + chalk.grey(`(${durationMs}ms)`);
223
240
  }
224
241
 
225
242
  if (step.status === STATUS.FAILED) {
226
- output.push(repeat(stepShift) + chalk.red(step.toString()) + duration);
243
+ // output.push(repeat(stepShift) + chalk.red(step.toString()) + duration);
244
+ global.testomatioDataStore?.steps?.push(repeat(stepShift) + chalk.red(step.toString()) + duration);
227
245
  } else {
228
- output.push(repeat(stepShift) + step.toString() + duration);
246
+ // output.push(repeat(stepShift) + step.toString() + duration);
247
+ global.testomatioDataStore?.steps?.push(repeat(stepShift) + step.toString() + duration);
229
248
  }
230
249
  });
231
250
 
232
251
  event.dispatcher.on(event.step.comment, step => {
233
- output.push(chalk.cyan.bold(step.toString()));
252
+ // output.push(chalk.cyan.bold(step.toString()));
253
+ global.testomatioDataStore?.steps?.push(chalk.cyan.bold(step.toString()));
234
254
  });
235
255
  }
236
256