@testomatio/reporter 0.8.0-beta.8 → 0.8.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/README.md CHANGED
@@ -20,11 +20,24 @@ For testcafe use testcafe reporter:
20
20
  npm i testcafe-reporter-testomatio
21
21
  ```
22
22
 
23
+ For newman use:
24
+
25
+ ```bash
26
+ npm i newman-reporter-testomatio --save-dev
27
+ ```
28
+
29
+ >`newman` and `newman-reporter-testomatio` should be installed in the same directory.
30
+ \
31
+ If you run your tests using globally installed newman (`newman run ...`), intall `newman-reporter-testomatio` globally too (`npm i newman-reporter-testomatio -g`).
32
+ \
33
+ If you use locally installed newman (within the project) (`npx newman run ...`), install `newman-reporter-testomatio` locally (`npm i newman-reporter-testomatio`).
34
+ You can verify installed packages via `npm list` or `npm list -g`.
35
+
23
36
  ## Usage
24
37
 
25
38
  ### CodeceptJS
26
39
 
27
- Make sure you load all your tests using [check-test](https://github.com/testomatio/check-tests#cli).
40
+ Make sure you load all your tests using [check-tests](https://github.com/testomatio/check-tests#cli).
28
41
 
29
42
  Add plugin to [codecept conf](https://github.com/testomatio/reporter/blob/master/example/codecept/codecept.conf.js#L23):
30
43
 
@@ -81,7 +94,7 @@ TESTOMATIO={API_KEY} npx playwright test
81
94
 
82
95
  ### Mocha
83
96
 
84
- Load the test using using `check-test` if not done already. Get the test id from testomat account and add it to your mocha test like in this [example](https://github.com/testomatio/reporter/blob/master/example/mocha/test/index.test.js#L4).
97
+ Load the test using using `check-tests` if not done already. Get the test id from testomat account and add it to your mocha test like in this [example](https://github.com/testomatio/reporter/blob/master/example/mocha/test/index.test.js#L4).
85
98
 
86
99
  Run the following command from you project folder:
87
100
 
@@ -91,7 +104,7 @@ mocha --reporter ./node_modules/testomat-reporter/lib/adapter/mocha.js --reporte
91
104
 
92
105
  ### Jest
93
106
 
94
- Load the test using using `check-test`. Add the test id to your tests like in this [example](https://github.com/testomatio/reporter/blob/master/example/jest/index.test.js#L1).
107
+ Load the test using using `check-tests`. Add the test id to your tests like in this [example](https://github.com/testomatio/reporter/blob/master/example/jest/index.test.js#L1).
95
108
 
96
109
  Add the following line to [jest.config.js](https://github.com/testomatio/reporter/blob/master/example/jest/jest.config.js#L100):
97
110
 
@@ -113,7 +126,7 @@ TESTOMATIO={API_KEY} ./node_modules/.bin/cucumber-js --format ./node_modules/@te
113
126
 
114
127
  ### TestCafe
115
128
 
116
- Load the test using using `check-test`.
129
+ Load the test using using `check-tests`.
117
130
 
118
131
  Run the following command from you project folder:
119
132
 
@@ -121,9 +134,20 @@ Run the following command from you project folder:
121
134
  TESTOMATIO={API_KEY} npx testcafe chrome -r testomatio
122
135
  ```
123
136
 
137
+ ### Newman (Postman)
138
+
139
+ Run collection and specify `testomatio` as reporter:
140
+
141
+ ```bash
142
+ TESTOMATIO={API_KEY} npx newman run {collection_name.json} -r testomatio
143
+ ```
144
+
145
+ > _`check-tests` not supported for newman for now, tests will be created on testomatio by default_
146
+
147
+
124
148
  ### Cypress
125
149
 
126
- Load the test using using `check-test`.
150
+ Load the test using using `check-tests`.
127
151
 
128
152
  Register our `cypress-plugin` in `cypress/plugins/index.js`:
129
153
 
@@ -151,7 +175,7 @@ TESTOMATIO={API_KEY} npx cypress run
151
175
 
152
176
  ### Protractor
153
177
 
154
- Load the test using using `check-test`.
178
+ Load the test using using `check-tests`.
155
179
 
156
180
  Add the following lines to [conf.js](https://github.com/angular/protractor/blob/5.4.1/example/conf.js):
157
181
 
@@ -173,7 +197,7 @@ TESTOMATIO={API_KEY} npx start-test-run -c 'npx protractor conf.js'
173
197
 
174
198
  ### WebdriverIO
175
199
 
176
- Load the test using using `check-test`.
200
+ Load the test using using `check-tests`.
177
201
 
178
202
  Add the following lines to [wdio.conf.js](https://webdriver.io/docs/configurationfile/):
179
203
 
@@ -208,6 +232,30 @@ Run the following command from you project folder:
208
232
  TESTOMATIO={API_KEY} npx start-test-run -c 'npx wdio wdio.conf.js'
209
233
  ```
210
234
 
235
+ ## Pipes
236
+ Pipes allow you to get report inside different systems (e.g. Pull request comment, database etc)
237
+ For now next pipes available:
238
+
239
+ ### GitHub
240
+ This pipe adds comment with run report to GitHub Pull Request.
241
+
242
+ To use it:
243
+ 1. run your tests using github actions in Pull Request
244
+ 2. pass `GH_PAT` (GitHub Personal Access Token) as environment variable.
245
+
246
+ > Last report (comment) will be replaced with the new one.
247
+ To leave previous report pass `GITHUB_KEEP_OUTDATED_REPORTS=1` env variable.
248
+
249
+ ### GitLab
250
+ This pipe adds comment with run report to GitLab Merge Request.
251
+
252
+ To use it:
253
+ 1. run your tests in Merge Request (pipeline trigger should be `merge_request`)
254
+ 2. pass `GITLAB_PAT` (GitLab Personal Access Token) as environment variable.
255
+
256
+ > Last report (comment) will be replaced with the new one.
257
+ To leave previous report pass `GITLAB_KEEP_OUTDATED_REPORTS=1` env variable.
258
+
211
259
  ## JUnit Reports
212
260
 
213
261
  > **Notice** JUnit reports are supported since 0.6.0
@@ -408,6 +456,23 @@ Add environments to run by providing `TESTOMATIO_ENV` as comma seperated values:
408
456
  TESTOMATIO={API_KEY} TESTOMATIO_ENV="Windows, Chrome" <actual run command>
409
457
  ```
410
458
 
459
+ ### Save test results to .csv file
460
+ Add an env to run by specifying the `TESTOMATIO_CSV_FILENAME` variable.
461
+
462
+ 1) using default report name:
463
+
464
+ ```bash
465
+ TESTOMATIO={API_KEY} TESTOMATIO_CSV_FILENAME="report.csv" <actual run command>
466
+ ```
467
+
468
+ 2) using unique report name:
469
+
470
+ ```bash
471
+ TESTOMATIO={API_KEY} TESTOMATIO_CSV_FILENAME="test.csv" <actual run command>
472
+ ```
473
+ _It's create a new /export folder with csv files_
474
+
475
+
411
476
  ### Attaching Test Artifacts
412
477
 
413
478
  To save a test artifacts (screenshots and videos) of a failed test use S3 storage.
@@ -520,3 +585,8 @@ If you want to finish a run started by `--launch` use `--finish` option. `TESTOM
520
585
  ```bash
521
586
  TESTOMATIO={API_KEY} TESTOMATIO_RUN={RUN_ID} npx start-test-run --finish
522
587
  ```
588
+
589
+ ### Debug logs
590
+ Pass `DEBUG` variable with module name e.g. `DEBUG=@testomatio/reporter:pipe:github`.
591
+ (Module name could be taken directly from the required module code).
592
+ To log all debug info pass `DEBUG=*`.
@@ -0,0 +1,131 @@
1
+ const debug = require('debug')('@testomatio/reporter:storage');
2
+ const { join, resolve } = require('path');
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const uuid = require('uuid');
6
+ const { TESTOMAT_ARTIFACT_SUFFIX } = require('./constants');
7
+ const { specificTestInfo } = require('./util');
8
+
9
+ class ArtifactStorage {
10
+
11
+ constructor(params) {
12
+ this._tmpPrefix = "tsmt_reporter";
13
+ this.isFile = false;
14
+ this.isMemory = true;
15
+ this.storage = params?.toFile;
16
+
17
+ if (this.storage) {
18
+ this.isFile = true;
19
+ this.isMemory = false;
20
+ this.tmpDirFullpath = this.createTestomatTmpDir(this._tmpPrefix);
21
+ debug('SAVE to tmp folder mode enabled!');
22
+ }
23
+ }
24
+
25
+ static async storeToFile(tmpDirName, artifact, testSuffix = "test") {
26
+ const suffix = TESTOMAT_ARTIFACT_SUFFIX + uuid.v4() + testSuffix;
27
+ const dirpath = join(os.tmpdir(), tmpDirName);
28
+ const filepath = resolve(dirpath, `${suffix}.json`);
29
+
30
+ return fs.promises.appendFile(filepath, JSON.stringify(artifact));
31
+ }
32
+
33
+ static async artifact(artifact, context) {
34
+ // TODO: mode for different pre-hooks. As variant - "all-tests" || "only_fail"
35
+ // const mode = process.env.TESTOMAT_ARTIFACTS || "only_fail";
36
+
37
+ if (Array.isArray(global.testomatioArtifacts)) {
38
+ debug("Saving artifacts to global storage");
39
+
40
+ global.testomatioArtifacts.push(artifact);
41
+ }
42
+
43
+ if (global?.testomatioArtifacts === undefined) {
44
+ const tmpDirNames = ArtifactStorage.tmpTestomatDirNames();
45
+
46
+ const testSuffix = specificTestInfo(context.test);
47
+
48
+ if (Array.isArray(tmpDirNames) && tmpDirNames.length) {
49
+ debug("Saving artifacts to memory tmp folder");
50
+
51
+ return ArtifactStorage.storeToFile(tmpDirNames[tmpDirNames.length - 1], artifact, testSuffix);
52
+ }
53
+ }
54
+ }
55
+
56
+ async artifactByTestName(test) {
57
+ const list = [];
58
+
59
+ if (this.isFile && this.tmpDirFullpath) {
60
+ const files = fs.readdirSync(this.tmpDirFullpath);
61
+
62
+ for (const file of files) {
63
+ if (file.includes(test)) {
64
+ const buff = await fs.promises.readFile(`${this.tmpDirFullpath }/${ file}`);
65
+
66
+ list.push(JSON.parse(buff.toString()));
67
+ }
68
+ }
69
+ }
70
+
71
+ return list;
72
+ }
73
+
74
+ async tmpContents() {
75
+ const contents = [];
76
+
77
+ if (this.isFile && this.tmpDirFullpath) {
78
+ const files = fs.readdirSync(this.tmpDirFullpath);
79
+
80
+ for (const file of files) {
81
+ const buff = await fs.promises.readFile(`${this.tmpDirFullpath }/${ file}`);
82
+ const content = buff.toString();
83
+
84
+ contents.push(content);
85
+ }
86
+ }
87
+
88
+ return contents;
89
+ }
90
+
91
+ createTestomatTmpDir(clientPrefix) {
92
+ return fs.mkdtempSync(join(os.tmpdir(), clientPrefix));
93
+ }
94
+
95
+ clearTmpDirByName(name) {
96
+ const tmpDirPath = join(os.tmpdir(), name);
97
+
98
+ if (fs.existsSync(tmpDirPath)) {
99
+ fs.rmSync(tmpDirPath, { recursive: true });
100
+ debug(` Testomat tmpDir = ${tmpDirPath} was deleted successfully!`);
101
+
102
+
103
+ }
104
+ }
105
+
106
+ static tmpTestomatDirNames() {
107
+ const subname = this._tmpPrefix || "tsmt_reporter";
108
+
109
+ return fs.readdirSync(os.tmpdir(), { withFileTypes: true })
110
+ .filter((item) => item.isDirectory())
111
+ .map((item) => item.name)
112
+ .filter((name) => name.includes(subname));
113
+ }
114
+
115
+ cleanup() {
116
+ if (this.isFile && this.tmpDirFullpath) {
117
+ const tmpDirNames = ArtifactStorage.tmpTestomatDirNames();
118
+
119
+ if (Array.isArray(tmpDirNames) && tmpDirNames.length) {
120
+ for (const name of tmpDirNames) {
121
+ this.clearTmpDirByName(name);
122
+ }
123
+ }
124
+ }
125
+ else {
126
+ debug("The tmp folder has not been created! Nothing to delete");
127
+ }
128
+ }
129
+ }
130
+
131
+ module.exports = ArtifactStorage;
@@ -1,15 +1,15 @@
1
+ const chalk = require('chalk');
2
+ const TestomatClient = require('../client');
3
+ const { STATUS, APP_PREFIX } = require('../constants');
4
+ const upload = require('../fileUploader');
5
+ const Output = require('../output');
6
+
1
7
  if (!global.codeceptjs) {
2
8
  // eslint-disable-next-line global-require, import/no-extraneous-dependencies
3
9
  global.codeceptjs = require('codeceptjs');
4
10
  }
5
11
 
6
12
  const { event, recorder, codecept } = global.codeceptjs;
7
- const chalk = require('chalk');
8
- const TestomatClient = require('../client');
9
- const { FAILED } = require('../constants');
10
- const TRConstants = require('../constants');
11
- const upload = require('../fileUploader');
12
- const Output = require('../output');
13
13
 
14
14
  let currentMetaStep = [];
15
15
  let error;
@@ -35,11 +35,6 @@ function CodeceptReporter(config) {
35
35
  const testTimeMap = {};
36
36
  const { apiKey } = config;
37
37
 
38
- if (!apiKey) {
39
- console.log('TESTOMATIO key is empty, ignoring reports');
40
- return;
41
- }
42
-
43
38
  const getDuration = test => {
44
39
  if (testTimeMap[test.id]) {
45
40
  return Date.now() - testTimeMap[test.id];
@@ -72,16 +67,17 @@ function CodeceptReporter(config) {
72
67
  });
73
68
 
74
69
  event.dispatcher.on(event.all.result, async () => {
75
- if (videos.length && upload.isArtifactsEnabled) {
76
- console.log(TRConstants.APP_PREFIX, `🎞️ Uploading ${videos.length} videos...`);
70
+ if (videos.length && upload.isArtifactsEnabled()) {
71
+ console.log(APP_PREFIX, `🎞️ Uploading ${videos.length} videos...`);
77
72
 
78
73
  const promises = [];
79
74
  for (const video of videos) {
80
75
  const { testId, title, path, type } = video;
81
76
  const file = { path, type, title };
82
77
  promises.push(
83
- client.addTestRun(testId, undefined, {
78
+ client.addTestRun(undefined, {
84
79
  ...stripExampleFromTitle(title),
80
+ test_id: testId,
85
81
  files: [file],
86
82
  }),
87
83
  );
@@ -89,7 +85,7 @@ function CodeceptReporter(config) {
89
85
  await Promise.all(promises);
90
86
  }
91
87
 
92
- const status = failedTests.length === 0 ? TRConstants.PASSED : TRConstants.FAILED;
88
+ const status = failedTests.length === 0 ? STATUS.PASSED : STATUS.FAILED;
93
89
  client.updateRunStatus(status);
94
90
  });
95
91
 
@@ -100,12 +96,13 @@ function CodeceptReporter(config) {
100
96
  }
101
97
  const testId = parseTest(tags);
102
98
  const testObj = getTestAndMessage(title);
103
- client.addTestRun(testId, TRConstants.PASSED, {
99
+ client.addTestRun(STATUS.PASSED, {
104
100
  ...stripExampleFromTitle(title),
105
101
  suite_title: test.parent && test.parent.title,
106
102
  message: testObj.message,
107
103
  time: getDuration(test),
108
104
  steps: output.text(),
105
+ test_id: testId,
109
106
  });
110
107
  output.stop();
111
108
  });
@@ -124,9 +121,10 @@ function CodeceptReporter(config) {
124
121
  failedTests.push(id || title);
125
122
  const testId = parseTest(tags);
126
123
 
127
- client.addTestRun(testId, TRConstants.FAILED, {
124
+ client.addTestRun(STATUS.FAILED, {
128
125
  ...stripExampleFromTitle(title),
129
126
  suite_title: suite.title,
127
+ test_id: testId,
130
128
  error,
131
129
  time: 0,
132
130
  });
@@ -135,7 +133,7 @@ function CodeceptReporter(config) {
135
133
  });
136
134
 
137
135
  event.dispatcher.on(event.test.after, test => {
138
- if (test.state && test.state !== FAILED) return;
136
+ if (test.state && test.state !== STATUS.FAILED) return;
139
137
  if (test.err) error = test.err;
140
138
  const { id, tags, title, artifacts } = test;
141
139
  failedTests.push(id || title);
@@ -154,8 +152,9 @@ function CodeceptReporter(config) {
154
152
  if (aid.startsWith('trace')) files.push({ testId: id, title, path: artifacts[aid], type: 'application/zip' });
155
153
  }
156
154
 
157
- client.addTestRun(testId, TRConstants.FAILED, {
155
+ client.addTestRun(STATUS.FAILED, {
158
156
  ...stripExampleFromTitle(title),
157
+ test_id: testId,
159
158
  suite_title: test.parent && test.parent.title,
160
159
  error,
161
160
  message: testObj.message,
@@ -172,8 +171,9 @@ function CodeceptReporter(config) {
172
171
 
173
172
  const testId = parseTest(tags);
174
173
  const testObj = getTestAndMessage(title);
175
- client.addTestRun(testId, TRConstants.SKIPPED, {
174
+ client.addTestRun(STATUS.SKIPPED, {
176
175
  ...stripExampleFromTitle(title),
176
+ test_id: testId,
177
177
  suite_title: test.parent && test.parent.title,
178
178
  message: testObj.message,
179
179
  time: getDuration(test),
@@ -212,12 +212,13 @@ function CodeceptReporter(config) {
212
212
  currentMetaStep = metaSteps;
213
213
  stepShift = 2 * shift;
214
214
 
215
- let duration = new Date() - stepStart;
216
- if (duration) {
217
- duration = repeat(1) + chalk.grey(`(${duration}ms)`);
215
+ const durationMs = (+new Date() - (+stepStart));
216
+ let duration = '';
217
+ if (durationMs) {
218
+ duration = repeat(1) + chalk.grey(`(${durationMs}ms)`);
218
219
  }
219
220
 
220
- if (step.status === TRConstants.FAILED) {
221
+ if (step.status === STATUS.FAILED) {
221
222
  output.push(repeat(stepShift) + chalk.red(step.toString()) + duration);
222
223
  } else {
223
224
  output.push(repeat(stepShift) + step.toString() + duration);
@@ -2,7 +2,8 @@
2
2
  const { Formatter, formatterHelpers } = require("@cucumber/cucumber");
3
3
  const chalk = require('chalk');
4
4
  const fs = require('fs');
5
- const { TestomatClient, TRConstants } = require('../../reporter');
5
+ const { STATUS } = require('../../constants');
6
+ const TestomatClient = require('../../client');
6
7
 
7
8
  const { GherkinDocumentParser, PickleParser } = formatterHelpers
8
9
  const {
@@ -19,7 +20,7 @@ class CucumberReporter extends Formatter {
19
20
  this.cases = [];
20
21
 
21
22
  this.client = new TestomatClient();
22
- this.status = TRConstants.PASSED;
23
+ this.status = STATUS.PASSED;
23
24
 
24
25
  }
25
26
 
@@ -33,7 +34,8 @@ class CucumberReporter extends Formatter {
33
34
  const testCaseAttempt = this.eventDataCollector.getTestCaseAttempt(testCaseFinished.testCaseStartedId);
34
35
 
35
36
  let example;
36
- let status = TRConstants.PASSED;
37
+
38
+ let status = STATUS.PASSED;
37
39
  let color = 'green';
38
40
  let message;
39
41
 
@@ -41,22 +43,23 @@ class CucumberReporter extends Formatter {
41
43
 
42
44
  if (testCaseAttempt.worstTestStepResult) {
43
45
  if (testCaseAttempt.worstTestStepResult.status === 'SKIPPED') {
44
- status = TRConstants.SKIPPED;
46
+ status = STATUS.SKIPPED;
45
47
  }
46
48
  if (testCaseAttempt.worstTestStepResult.status === 'UNDEFINED') {
47
- status = TRConstants.SKIPPED;
49
+ status = STATUS.SKIPPED;
48
50
  message = 'Undefined steps. Implement missing steps and rerun this scenario';
49
51
  }
50
52
  if (testCaseAttempt.worstTestStepResult.status === 'FAILED') {
51
53
  message = testCaseAttempt?.worstTestStepResult?.message;
52
- status = TRConstants.FAILED;
54
+ status = STATUS.FAILED;
53
55
  }
54
56
  color = getStatusColor(testCaseAttempt.worstTestStepResult.status);
55
- if (status !== TRConstants.PASSED) this.failures.push(testCaseAttempt);
57
+ if (status !== STATUS.PASSED) this.failures.push(testCaseAttempt);
56
58
  }
57
59
 
58
60
  if (testCaseAttempt.pickle.astNodeIds.length > 1) {
59
61
  example = getExample(testCaseAttempt);
62
+ // @ts-ignore
60
63
  testCaseAttempt.example = example;
61
64
  }
62
65
 
@@ -70,8 +73,8 @@ class CucumberReporter extends Formatter {
70
73
  if (message) cliMessage += chalk.gray(message.split('\n')[0]);
71
74
  console.log(cliMessage);
72
75
 
73
- if (status !== TRConstants.PASSED && status !== TRConstants.SKIPPED) {
74
- this.status = TRConstants.FAILED;
76
+ if (status !== STATUS.PASSED && status !== STATUS.SKIPPED) {
77
+ this.status = STATUS.FAILED;
75
78
  }
76
79
 
77
80
  const time = Object.values(testCaseAttempt.stepResults)
@@ -80,12 +83,13 @@ class CucumberReporter extends Formatter {
80
83
 
81
84
  if (!this.client) return;
82
85
 
83
- this.client.addTestRun(testId, status, {
86
+ this.client.addTestRun(status, {
84
87
  // error: testCaseAttempt.worstTestStepResult.message,
85
88
  message,
86
89
  steps: getSteps(testCaseAttempt).map(s => s.toString()).join('\n').trim(),
87
90
  example: { ...example},
88
91
  title: scenario,
92
+ test_id: testId,
89
93
  time,
90
94
  });
91
95
  }
@@ -121,9 +125,9 @@ class CucumberReporter extends Formatter {
121
125
 
122
126
  if (!this.client) return;
123
127
 
124
- this.client.updateRunStatus(testRunFinished.success ? TRConstants.PASSED : TRConstants.FAILED)
128
+ this.client.updateRunStatus(testRunFinished.success ? STATUS.PASSED : STATUS.FAILED)
125
129
  }
126
- };
130
+ }
127
131
 
128
132
  function getSteps(tc) {
129
133
  const stepIds = Object.keys(tc.stepResults);
@@ -1,8 +1,9 @@
1
- // eslint-disable-next-line import/no-unresolved
1
+ // eslint-disable-next-line global-require, import/no-extraneous-dependencies, import/no-unresolved
2
2
  const { Formatter } = require('cucumber');
3
3
  const chalk = require('chalk');
4
- const { TestomatClient, TRConstants } = require('../../reporter');
5
4
  const { parseTest } = require('../../util');
5
+ const { STATUS } = require('../../constants');
6
+ const TestomatClient = require('../../client');
6
7
 
7
8
  const createTestomatFormatter = apiKey => {
8
9
  if (!apiKey || apiKey === '') {
@@ -92,18 +93,18 @@ const createTestomatFormatter = apiKey => {
92
93
  if (!apiKey) return;
93
94
 
94
95
  this.client = new TestomatClient({ apiKey });
95
- this.status = TRConstants.PASSED;
96
+ this.status = STATUS.PASSED.toString();
96
97
 
97
98
  options.eventBroadcaster.on('gherkin-document', addDocument);
98
- options.eventBroadcaster.on('test-run-started', () => this.client.createRun());
99
+ options.eventBroadcaster.on('test-run-started', () => this?.client?.createRun());
99
100
  options.eventBroadcaster.on('test-case-finished', this.onTestCaseFinished.bind(this));
100
- options.eventBroadcaster.on('test-run-finished', () => this.client.updateRunStatus(this.status));
101
+ options.eventBroadcaster.on('test-run-finished', () => this?.client?.updateRunStatus(this.status));
101
102
  }
102
103
 
103
104
  onTestCaseFinished(event) {
104
105
  const scenario = getScenario(event.sourceLocation);
105
106
  const testId = getTestId(scenario);
106
- const status = event.result.status === 'undefined' ? TRConstants.SKIPPED : event.result.status;
107
+ const status = event.result.status === 'undefined' ? STATUS.SKIPPED : event.result.status;
107
108
 
108
109
  let example = getDataTableMap(scenario, event.sourceLocation);
109
110
  if (example) example = JSON.parse(example);
@@ -120,14 +121,17 @@ const createTestomatFormatter = apiKey => {
120
121
  message = 'Undefined steps. Implement missing steps and rerun this scenario';
121
122
  }
122
123
  console.log(cliMessage);
123
- if (status !== TRConstants.PASSED && status !== TRConstants.SKIPPED) {
124
- this.status = TRConstants.FAILED;
124
+ if (status !== STATUS.PASSED && status !== STATUS.SKIPPED) {
125
+ this.status = STATUS.FAILED;
125
126
  }
126
- this.client.addTestRun(testId, status, {
127
- error: event.result.exception,
127
+
128
+ this.client?.addTestRun(status, {
129
+ error: event.result.exception instanceof Error ? event.result.exception : undefined,
128
130
  message,
129
131
  example,
132
+ test_id: testId,
130
133
  title: getTitle(scenario),
134
+ suite_title: getTitle(getFeature(event.sourceLocation.uri)),
131
135
  });
132
136
  }
133
137
  };
@@ -1,4 +1,4 @@
1
- const TRConstants = require('../../constants');
1
+ const { STATUS } = require('../../constants');
2
2
  const { parseTest, parseSuite } = require('../../util');
3
3
  const TestomatClient = require('../../client');
4
4
 
@@ -57,16 +57,16 @@ const testomatioReporter = on => {
57
57
 
58
58
  let state;
59
59
  switch (test.state) {
60
- case 'passed': state = TRConstants.PASSED; break;
61
- case 'failed': state = TRConstants.FAILED; break;
60
+ case 'passed': state = STATUS.PASSED; break;
61
+ case 'failed': state = STATUS.FAILED; break;
62
62
  case 'skipped':
63
63
  case 'pending':
64
64
  default:
65
- state = TRConstants.SKIPPED;
65
+ state = STATUS.SKIPPED;
66
66
  }
67
67
 
68
- addSpecTestsPromises.push(client.addTestRun(testId, state, {
69
- title, time, example, error, files, suite_title: suiteTitle, suite_id: suiteId
68
+ addSpecTestsPromises.push(client.addTestRun(state, {
69
+ title, time, example, error, files, suite_title: suiteTitle, test_id: testId, suite_id: suiteId
70
70
  }));
71
71
  }
72
72
 
@@ -74,7 +74,7 @@ const testomatioReporter = on => {
74
74
  });
75
75
 
76
76
  on('after:run', async results => {
77
- const status = results.totalFailed ? TRConstants.FAILED : TRConstants.PASSED;
77
+ const status = results.totalFailed ? STATUS.FAILED : STATUS.PASSED;
78
78
  await client.updateRunStatus(status);
79
79
  });
80
80
  };
@@ -1,6 +1,6 @@
1
1
  const TestomatClient = require('../client');
2
2
  const { parseTest, ansiRegExp } = require('../util');
3
- const { PASSED, FAILED } = require('../constants');
3
+ const { STATUS } = require('../constants');
4
4
 
5
5
  class JasmineReporter {
6
6
  constructor(options) {
@@ -32,13 +32,14 @@ class JasmineReporter {
32
32
  errorMessage = `${errorMessage}Failure: ${result.failedExpectations[i].message}\n`;
33
33
  errorMessage = `${errorMessage}\n ${result.failedExpectations[i].stack}`;
34
34
  }
35
- console.log(`${title} : ${PASSED}`);
35
+ console.log(`${title} : ${STATUS.PASSED}`);
36
36
  console.log(errorMessage);
37
37
  const testId = parseTest(title);
38
38
  errorMessage = errorMessage.replace(ansiRegExp(), '');
39
- this.client.addTestRun(testId, status, {
39
+ this.client.addTestRun(status, {
40
40
  error: result.failedExpectations[0],
41
41
  message: errorMessage,
42
+ test_id: testId,
42
43
  title,
43
44
  time: this.getDuration(result),
44
45
  });
@@ -48,7 +49,7 @@ class JasmineReporter {
48
49
  if (!this.client) return;
49
50
 
50
51
  const { overallStatus } = suiteInfo;
51
- const status = overallStatus === 'failed' ? FAILED : PASSED;
52
+ const status = overallStatus === 'failed' ? STATUS.FAILED : STATUS.PASSED;
52
53
 
53
54
  this.client.updateRunStatus(status).then(() => done);
54
55
  }