@testomatio/reporter 1.1.0-beta-2 → 1.2.0-beta-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.
@@ -3,18 +3,16 @@ const fs = require('fs');
3
3
  const path = require('path');
4
4
  const os = require('os');
5
5
  const { join } = require('path');
6
- const { TESTOMAT_TMP_STORAGE_DIR } = require('../constants');
7
- const { fileSystem, jestHelpers, parseTest } = require('../utils/utils');
8
-
9
- const getTestIdFromTestTitle = parseTest;
6
+ const JestReporter = require('./adapter/jest');
7
+ const { TESTOMAT_TMP_STORAGE } = require('./constants');
8
+ const { fileSystem } = require('./utils/utils');
9
+ const getTestIdFromTestTitle = require('./utils/utils').parseTest;
10
10
 
11
11
  class DataStorage {
12
12
  /**
13
13
  * Creates data storage instance for specific data type.
14
14
  * Stores data to global variable or to file depending on what is applicable for current test runner
15
15
  * (running environment).
16
- * Recommend to use composition while using this class (instead of inheritance).
17
- * ! Also the class which will use data storage should be singleton (to avoid data loss).
18
16
  * @param {*} dataType storage type (like 'log', 'artifact'); could be any string, used only to define file path
19
17
  */
20
18
  constructor(dataType) {
@@ -22,35 +20,8 @@ class DataStorage {
22
20
  this.isFileStorage = true;
23
21
  this.#refreshStorageType();
24
22
 
25
- this.dataDirPath = path.join(TESTOMAT_TMP_STORAGE_DIR, this.dataType);
26
-
27
- // set test title for mocha (could not be moved to adapter)
28
- // it does not override existing hook, just add new one
29
- try {
30
- // @ts-ignore
31
- if (!beforeEach) return;
32
- // @ts-ignore-next-line
33
- beforeEach(function () {
34
- if (this.currentTest?.__mocha_id__) {
35
- global.testTitle = this.currentTest.fullTitle();
36
- }
37
- });
38
- } catch (e) {
39
- // ignore
40
- }
41
-
42
- // set test title for playwright
43
- try {
44
- // eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved
45
- const { test } = require('@playwright/test');
46
- // eslint-disable-next-line no-empty-pattern
47
- test.beforeEach(async ({}, testInfo) => {
48
- global.testTitle = testInfo.title;
49
- global.testomatioRunningEnvironment = 'playwright';
50
- });
51
- } catch (e) {
52
- // ignore
53
- }
23
+ this.dataDirPath = path.join(TESTOMAT_TMP_STORAGE.mainDir, this.dataType);
24
+ fileSystem.createDir(this.dataDirPath);
54
25
  }
55
26
 
56
27
  /**
@@ -73,18 +44,15 @@ class DataStorage {
73
44
  }
74
45
 
75
46
  /**
76
- * Puts any data to storage (file or global variable).
77
- * If file: stores data as text, if global variable – stores as array of data.
78
- * @param {*} data anything you want to store (string, object, array, etc)
47
+ * Puts any data to storage (file or global variable)
48
+ * @param {*} data anything you want to store
79
49
  * @param {*} context could be testId or any context (test, suite, etc) which is used to define testId
80
50
  * @returns
81
51
  */
82
52
  putData(data, context = null) {
83
- fileSystem.createDir(this.dataDirPath);
84
-
85
53
  this.#refreshStorageType();
86
- context = context ?? global.testTitle ?? null;
87
- let testId = this.#tryToRetrieveTestId(context) || context || null;
54
+
55
+ let testId = this.#tryToRetrieveTestId(context) || null;
88
56
 
89
57
  if (this.runningEnvironment === 'codeceptjs') {
90
58
  this.isFileStorage = false;
@@ -92,7 +60,7 @@ class DataStorage {
92
60
  }
93
61
 
94
62
  if (this.runningEnvironment === 'jest') {
95
- testId = testId ?? jestHelpers.getIdOfCurrentlyRunningTest();
63
+ testId = testId ?? JestReporter.getIdOfCurrentlyRunningTest();
96
64
  }
97
65
 
98
66
  // logs in playwright are gathered by pw framework itself
@@ -106,7 +74,7 @@ class DataStorage {
106
74
  testId = this.#tryToRetrieveTestId(global.currentlyRunningTestTitle);
107
75
 
108
76
  if (!testId) {
109
- debug(`No test id provided for "${this.dataType}" data:`, data);
77
+ debug(`No test id provided for ${this.dataType} data: ${data}`);
110
78
  return;
111
79
  }
112
80
 
@@ -119,10 +87,12 @@ class DataStorage {
119
87
 
120
88
  /**
121
89
  * Returns data, stored for specific testId (or data which was stored without test id specified).
122
- * This method will get data from global variable and/or from from file (previosly saved with put method).
90
+ * This method will get data from global variable. But if it is not available, it will try to get data from file.
91
+ * Thus, good approach is to remove file storage folder before each test run (and after, for sure).
123
92
  *
124
- * @param {*} context could be testId or any context (test title, suite, etc) which is used to define testId
125
- * @returns array of data (any type), null (if no data found for test) or string (if data type is log)
93
+ * Defining the execution environment is not guaranteed! Is used only as additional check.
94
+ * @param {*} context could be testId or any context (test, suite, etc) which is used to define testId
95
+ * @returns
126
96
  */
127
97
  getData(context) {
128
98
  this.#refreshStorageType();
@@ -130,6 +100,9 @@ class DataStorage {
130
100
  let testId = null;
131
101
  if (typeof context === 'string') {
132
102
  testId = this.#tryToRetrieveTestId(context) || context;
103
+ } else {
104
+ // TODO: derive testId from context
105
+ // testId = context...
133
106
  }
134
107
 
135
108
  if (!testId) {
@@ -137,20 +110,12 @@ class DataStorage {
137
110
  return null;
138
111
  }
139
112
 
140
- let testDataFromFile = [];
141
- let testDataFromGlobalVar = [];
113
+ let testData = '';
142
114
 
143
115
  if (global?.testomatioDataStore) {
144
- testDataFromGlobalVar = this.#getDataFromGlobalVar(testId);
116
+ testData = this.#getDataFromGlobalVar(testId);
145
117
  // these frameworks use global variable storage
146
- // if (testDataFromGlobalVar && ['cucumber', 'codeceptjs'].includes(this.runningEnvironment)) {
147
- if (testDataFromGlobalVar) {
148
- // return as string if its log data
149
- if (this.dataType === 'log' && testDataFromGlobalVar.length) return testDataFromGlobalVar.join('\n');
150
- // return as array for other data types
151
- if (testDataFromGlobalVar.length) return testDataFromGlobalVar;
152
- }
153
- // don't return nothing if no data in global variable
118
+ if (testData && ['cucumber', 'codeceptjs'].includes(this.runningEnvironment)) return testData;
154
119
  }
155
120
 
156
121
  /* condition is removed for mocha
@@ -161,16 +126,11 @@ class DataStorage {
161
126
  // if (testData) return testData;
162
127
  // }
163
128
 
164
- testDataFromFile = this.#getDataFromFile(testId);
129
+ const testDataFromFile = this.#getDataFromFile(testId);
130
+ testData += testDataFromFile || '';
165
131
 
166
- if (testDataFromFile.length) {
167
- if (this.dataType === 'log') return testDataFromFile.join('\n');
168
- return testDataFromFile;
169
- }
170
- debug(`No "${this.dataType}" data for test id ${testId} in both file and global variable`);
171
-
172
- // in case no data found for test
173
- return null;
132
+ debug(`No ${this.dataType} data for test id ${testId} in both file and global variable`);
133
+ return testData || '';
174
134
  }
175
135
 
176
136
  /**
@@ -206,63 +166,46 @@ class DataStorage {
206
166
  this.runningEnvironment = this.getRunningEnviroment();
207
167
 
208
168
  // some test frameworks do not persist global variables, thus file storage is used for them (by default)
209
- if (this.runningEnvironment === 'codeceptjs') this.isFileStorage = false;
210
- // playwrigth stores logs by itself; but file storage is used for other data types for playwright
211
- if (this.runningEnvironment === 'playwright' && this.dataType === 'log') this.isFileStorage = false;
169
+ if (['playwright', 'codeceptjs'].includes(this.runningEnvironment)) this.isFileStorage = false;
212
170
  }
213
171
 
214
- /**
215
- * @param {*} testId
216
- * @returns aray of data (any type)
217
- */
218
172
  #getDataFromGlobalVar(testId) {
219
173
  try {
220
174
  if (global?.testomatioDataStore[this.dataType]) {
221
175
  const testData = global.testomatioDataStore[this.dataType][testId];
222
- if (testData) debug(`"${this.dataType}" data for test id ${testId}:`, testData.join(', '));
223
- return testData || [];
176
+ debug(`Data for test id ${testId}:\n${testData}`);
177
+ return testData || '';
224
178
  }
225
- // debug(`No ${this.dataType} data for test id ${testId} in <global> storage`);
226
- return [];
179
+ debug(`No ${this.dataType} data for test id ${testId} in <global> storage`);
180
+ return '';
227
181
  } catch (e) {
228
182
  // there could be no data, ignore
229
183
  }
230
184
  }
231
185
 
232
- /**
233
- *
234
- * @param {*} testId
235
- * @returns array of data (any type)
236
- */
237
186
  #getDataFromFile(testId) {
238
187
  try {
239
188
  const filepath = join(this.dataDirPath, `${this.dataType}_${testId}`);
240
189
  if (fs.existsSync(filepath)) {
241
- const testDataAsText = fs.readFileSync(filepath, 'utf-8');
242
- if (testDataAsText) debug(`"${this.dataType}" data for test id ${testId}:`, testDataAsText);
243
- const testDataArr = testDataAsText?.split(os.EOL) || [];
244
- return testDataArr;
190
+ const testData = fs.readFileSync(filepath, 'utf-8');
191
+ debug(`Data for test id ${testId}:\n${testData}`);
192
+ return testData || '';
245
193
  }
246
- // debug(`No ${this.dataType} data for test id ${testId} in <file> storage`);
247
- return [];
194
+ debug(`No ${this.dataType} data for test id ${testId} in <file> storage`);
195
+ return '';
248
196
  } catch (e) {
249
197
  // there could be no data, ignore
250
198
  }
251
- return [];
199
+ return '';
252
200
  }
253
201
 
254
- /**
255
- * Puts data to global variable. Unlike the file storage, stores data in array (file storage just append as string).
256
- * @param {*} data
257
- * @param {*} testId
258
- */
259
202
  #putDataToGlobalVar(data, testId) {
260
- debug(`Saving data to global variable for test ${testId}:`, data);
203
+ debug('Saving data to global variable for test', testId, ':\n', data, '\n');
261
204
  if (!global.testomatioDataStore) global.testomatioDataStore = {};
262
205
  if (!global.testomatioDataStore?.[this.dataType]) global.testomatioDataStore[this.dataType] = {};
263
-
264
- if (!global.testomatioDataStore?.[this.dataType][testId]) global.testomatioDataStore[this.dataType][testId] = [];
265
- global.testomatioDataStore[this.dataType][testId].push(data);
206
+ global.testomatioDataStore?.[this.dataType][testId] // eslint-disable-line no-unused-expressions
207
+ ? (global.testomatioDataStore[this.dataType][testId] += `\n${data}`)
208
+ : (global.testomatioDataStore[this.dataType][testId] = data);
266
209
  }
267
210
 
268
211
  #putDataToFile(data, testId) {
@@ -272,36 +215,18 @@ class DataStorage {
272
215
  if (!fs.existsSync(this.dataDirPath)) fileSystem.createDir(this.dataDirPath);
273
216
  debug('Saving data to file for test', testId, 'to', filepath, ':\n', data, '\n');
274
217
 
275
- // append new line if file already exists (in this case its definitely includes some data)
276
- if (fs.existsSync(filepath)) {
277
- fs.appendFileSync(filepath, os.EOL + data, 'utf-8');
278
- } else {
279
- fs.writeFileSync(filepath, data, 'utf-8');
280
- }
218
+ // TODO: handle multiple invocations of JSON.stringify.
219
+ // UPD: not actual because decided not to use it - it created extra wrapping quotes "" and // (escaped slashes)
220
+ fs.appendFileSync(filepath, data + os.EOL, 'utf-8');
281
221
  }
282
222
  }
283
223
 
284
- module.exports = DataStorage;
224
+ module.exports.DataStorage = DataStorage;
285
225
 
286
226
  // TODO: consider using fs promises instead of writeSync/appendFileSync to
287
227
  // prevent blocking and improve performance (probably queue usage will be required)
288
228
 
289
229
  // TODO: rewrite client - everything regarding storing artifacts
290
230
  // TODO: try to define adapter inside client
231
+ // TODO: use .env
291
232
  // TODO: ability to intercept multiple loggers (upd: no need)
292
-
293
- /* does not work for Playwright
294
- try {
295
- const { test } = require('@playwright/test');
296
- test.beforeEach(async ({}, testInfo) => {
297
- global.testTitle = testInfo.title;
298
- global.testomatioRunningEnvironment = 'playwright';
299
- });
300
- } catch (e) {
301
- // ignore
302
- }
303
- // Playwright storage works fine only when running tests from a single file;
304
- // otherwise it is not possible to define test id/title, it is overwritten
305
- TODO: the only way implementation for Pw for now is to pass testInfo inside test
306
- // (and process this testInfo inside "put" function)
307
- */
@@ -1,6 +1,6 @@
1
1
  const chalk = require('chalk');
2
2
  const debug = require('debug')('@testomatio/reporter:logger');
3
- const DataStorage = require('./data-storage');
3
+ const { DataStorage } = require('./dataStorage');
4
4
 
5
5
  const LOG_METHODS = ['assert', 'debug', 'error', 'info', 'log', 'trace', 'warn'];
6
6
  const LEVELS = {
@@ -38,6 +38,20 @@ class Logger {
38
38
  if (!Logger.instance) {
39
39
  Logger.instance = this;
40
40
  }
41
+
42
+ // add beforeEach hook for mocha. it does not override existing hook, just add new one
43
+ try {
44
+ // @ts-ignore
45
+ if (!beforeEach) return;
46
+ // @ts-ignore-next-line
47
+ beforeEach(function () {
48
+ if (this.currentTest?.__mocha_id__) {
49
+ global.testTitle = this.currentTest.fullTitle();
50
+ }
51
+ });
52
+ } catch (e) {
53
+ // ignore
54
+ }
41
55
  }
42
56
 
43
57
  /**
@@ -47,6 +61,9 @@ class Logger {
47
61
  * @param {...any} values
48
62
  */
49
63
  step(strings, ...values) {
64
+ // get testId for mocha
65
+ const context = global.testTitle ?? null;
66
+
50
67
  let logs = '';
51
68
  for (let i = 0; i < strings.length; i++) {
52
69
  logs += strings[i];
@@ -55,7 +72,7 @@ class Logger {
55
72
  }
56
73
  }
57
74
  logs = chalk.blue(`> ${logs}`);
58
- this.#dataStorage.putData(logs);
75
+ this.#dataStorage.putData(logs, context);
59
76
  }
60
77
 
61
78
  /**
@@ -100,6 +117,11 @@ class Logger {
100
117
  templateLiteralLog(strings, ...args) {
101
118
  if (Array.isArray(strings)) strings = strings.filter(item => item !== '').map(item => item.trim());
102
119
  if (Array.isArray(args)) args = args.filter(item => item !== '');
120
+ // entity which is used to define testId
121
+ let context = null;
122
+
123
+ // get testId for mocha
124
+ context = global.testTitle ?? null;
103
125
 
104
126
  let logs;
105
127
  // this block means tagged template is used (syntax like $`text ${someVar}`)
@@ -124,7 +146,7 @@ class Logger {
124
146
  logs = this.#stringifyLogs(strings, ...args);
125
147
  }
126
148
  this.#originalUserLogger.log(logs);
127
- this.#dataStorage.putData(logs);
149
+ this.#dataStorage.putData(logs, context);
128
150
  }
129
151
 
130
152
  /**
@@ -136,12 +158,18 @@ class Logger {
136
158
  #logWrapper(argsArray, level) {
137
159
  if (!argsArray.length) return;
138
160
 
161
+ // entity which is used to define testId
162
+ let context = null;
163
+
164
+ // get context for mocha
165
+ context = global.testTitle ?? null;
166
+
139
167
  const severity = LEVELS[level].severity;
140
168
  if (severity < LEVELS[this.logLevel]?.severity) return;
141
169
 
142
170
  const logs = this.#stringifyLogs(...argsArray);
143
171
  const colorizedLogs = chalk[LEVELS[level].color](logs);
144
- this.#dataStorage.putData(colorizedLogs);
172
+ this.#dataStorage.putData(colorizedLogs, context);
145
173
  try {
146
174
  // level.toLowerCase() represents method name (log, warn, error, etc)
147
175
  this.#originalUserLogger[level.toLowerCase()](colorizedLogs);
@@ -241,6 +269,7 @@ class Logger {
241
269
 
242
270
  Logger.instance = null;
243
271
 
272
+ // module.exports.Logger = Logger;
244
273
  const logger = new Logger();
245
274
 
246
275
  module.exports = logger;
@@ -0,0 +1,187 @@
1
+ const debug = require('debug')('@testomatio/reporter:pipe:html');
2
+ const merge = require('lodash.merge');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const chalk = require('chalk');
6
+ const handlebars = require('handlebars');
7
+
8
+ const { fileSystem, isSameTest } = require('../utils/utils');
9
+ const { HTML_REPORT } = require('../constants');
10
+
11
+ class HtmlPipe {
12
+ constructor(params, store = {}) {
13
+ this.store = store || {};
14
+ this.title = params.title || process.env.TESTOMATIO_TITLE;
15
+ this.apiKey = params.apiKey || process.env.TESTOMATIO;
16
+ this.isHtml = process.env.TESTOMATIO_HTML_REPORT_SAVE;
17
+ this.data = {};
18
+
19
+ debug('HTML Pipe: ', this.apiKey ? 'API KEY' : '*no api key*');
20
+ if (!this.apiKey) {
21
+ return;
22
+ }
23
+
24
+ this.isEnabled = false;
25
+ this.htmlOutputPath = "";
26
+ this.tests = [];
27
+ this.data = {};
28
+
29
+ if (this.isHtml) {
30
+ this.isEnabled = true;
31
+ this.htmlReportDir = process.env.TESTOMATIO_HTML_REPORT_FOLDER || HTML_REPORT.FOLDER;
32
+
33
+ if (process.env.TESTOMATIO_HTML_FILENAME && process.env.TESTOMATIO_HTML_FILENAME.endsWith(".html")) {
34
+ this.htmlReportName = process.env.TESTOMATIO_HTML_FILENAME
35
+ }
36
+
37
+ if (process.env.TESTOMATIO_HTML_FILENAME && !process.env.TESTOMATIO_HTML_FILENAME.endsWith(".html")) {
38
+ console.log(
39
+ chalk.blue(`The name must include the extension ".html". The default report name is used!`)
40
+ );
41
+ this.htmlReportName = HTML_REPORT.REPORT_DEFAULT_NAME;
42
+ }
43
+
44
+ if (!process.env.TESTOMATIO_HTML_FILENAME) {
45
+ this.htmlReportName = HTML_REPORT.REPORT_DEFAULT_NAME;
46
+ }
47
+
48
+ this.templateFolderPath = path.resolve(__dirname, '..', 'template');
49
+ this.templateHtmlPath = path.resolve(this.templateFolderPath, HTML_REPORT.TEMPLATE_NAME);
50
+ this.htmlOutputPath = path.join(this.htmlReportDir, this.htmlReportName);
51
+ // create a new folder for the HTML reports
52
+ fileSystem.createDir(this.htmlReportDir);
53
+
54
+ debug(
55
+ chalk.yellow('HTML Pipe:'),
56
+ `Save HTML report: ${this.isEnabled}`,
57
+ `HTML report folder: ${this.htmlReportDir}, report name: ${this.htmlReportName}`
58
+ );
59
+ }
60
+ }
61
+
62
+ async createRun() {
63
+ // empty
64
+ }
65
+
66
+ updateRun() {
67
+ // empty
68
+ }
69
+
70
+ /**
71
+ * Add test data to the result array for saving. As a result of this function, we get a result object to save.
72
+ * @param {Object} test - object which includes each test entry.
73
+ */
74
+ addTest(test) {
75
+ if (!this.isEnabled) return;
76
+
77
+ const index = this.tests.findIndex(t => isSameTest(t, test));
78
+ // update if they were already added
79
+ if (index >= 0) {
80
+ this.tests[index] = merge(this.tests[index], test);
81
+ return;
82
+ }
83
+
84
+ this.tests.push(test);
85
+ }
86
+
87
+ async finishRun(runParams) {
88
+ if (!this.isEnabled) return;
89
+
90
+ if (this.isHtml) {
91
+ this.data = {
92
+ runId: this.store.runId,
93
+ status: runParams.status,
94
+ parallel: runParams.isParallel,
95
+ runUrl: this.store.runUrl,
96
+ executionTime: testExecutionSumTime(this.tests),
97
+ executionDate: getCurrentDateTimeFormatted(),
98
+ tests: this.tests
99
+ };
100
+
101
+ // GENERATE HTML reports based on the results data
102
+ this.buildReport(this.data);
103
+ }
104
+ }
105
+
106
+ buildReport(data) {
107
+ debug('HTML tests data:', data);
108
+
109
+ if (!this.htmlOutputPath && this.htmlOutputPath !== "") {
110
+ console.log(chalk.yellow(`HTML export path is not set, ignoring...`));
111
+ return;
112
+ }
113
+
114
+ console.log(chalk.yellow(`The test results will be added to the HTML report. It will take some time...`));
115
+ // generate output HTML based on the template
116
+ const html = this.#generateHTMLReport(data);
117
+
118
+ fs.writeFileSync(this.htmlOutputPath, html, 'utf-8');
119
+ }
120
+
121
+ #generateHTMLReport(data) {
122
+ if (!this.templateHtmlPath) {
123
+ console.log(chalk.red(`HTML template not found. Report generation is impossible!`))
124
+ return;
125
+ }
126
+
127
+ const templateSource = fs.readFileSync(this.templateHtmlPath, 'utf8');
128
+ this.#loadReportHelpers();
129
+ try {
130
+ const template = handlebars.compile(templateSource);
131
+
132
+ console.log(chalk.green(`Generated HTML report saved in file: ${this.htmlOutputPath}`));
133
+ return template(data);
134
+ }
135
+ catch (e) {
136
+ console.log('Unknown HTML report generation error: ', e);
137
+ }
138
+ }
139
+
140
+ #loadReportHelpers() {
141
+ handlebars.registerHelper('getTestsByStatus', (tests, status) =>
142
+ tests.filter(test => test.status.toLowerCase() === status.toLowerCase()).length
143
+ );
144
+
145
+ handlebars.registerHelper('json', (obj) => JSON.stringify(obj));
146
+ }
147
+
148
+ toString() {
149
+ return 'HTML Reporter';
150
+ }
151
+ }
152
+
153
+ function testExecutionSumTime(tests) {
154
+ const totalMilliseconds = tests.reduce((sum, test) => {
155
+ if (typeof test.run_time === 'number') {
156
+ return sum + test.run_time;
157
+ }
158
+ return sum;
159
+ }, 0);
160
+
161
+ return formatDuration(totalMilliseconds);
162
+ }
163
+
164
+ function formatDuration(duration) {
165
+ const milliseconds = duration % 1000;
166
+ duration = (duration - milliseconds) / 1000;
167
+ const seconds = duration % 60;
168
+ duration = (duration - seconds) / 60;
169
+ const minutes = duration % 60;
170
+ const hours = (duration - minutes) / 60;
171
+
172
+ return `${hours}h ${minutes}m ${seconds}s ${milliseconds}ms`;
173
+ }
174
+
175
+ function getCurrentDateTimeFormatted() {
176
+ const currentDate = new Date();
177
+ const day = currentDate.getDate().toString().padStart(2, '0');
178
+ const month = (currentDate.getMonth() + 1).toString().padStart(2, '0');
179
+ const year = currentDate.getFullYear();
180
+ const hours = currentDate.getHours().toString().padStart(2, '0');
181
+ const minutes = currentDate.getMinutes().toString().padStart(2, '0');
182
+ const seconds = currentDate.getSeconds().toString().padStart(2, '0');
183
+
184
+ return `(${day}/${month}/${year} ${hours}:${minutes}:${seconds})`;
185
+ }
186
+
187
+ module.exports = HtmlPipe;
package/lib/pipe/index.js CHANGED
@@ -6,6 +6,7 @@ const TestomatioPipe = require('./testomatio');
6
6
  const GitHubPipe = require('./github');
7
7
  const GitLabPipe = require('./gitlab');
8
8
  const CsvPipe = require('./csv');
9
+ const HtmlPipe = require('./html');
9
10
 
10
11
  function PipeFactory(params, opts) {
11
12
  const extraPipes = [];
@@ -43,6 +44,7 @@ function PipeFactory(params, opts) {
43
44
  new GitHubPipe(params, opts),
44
45
  new GitLabPipe(params, opts),
45
46
  new CsvPipe(params, opts),
47
+ new HtmlPipe(params, opts),
46
48
  ...extraPipes,
47
49
  ];
48
50
 
package/lib/reporter.js CHANGED
@@ -1,10 +1,10 @@
1
- const logger = require('./storages/logger');
1
+ const logger = require('./logger');
2
2
  const TestomatClient = require('./client');
3
3
  const TRConstants = require('./constants');
4
+ const TRArtifacts = require('./_ArtifactStorageOld');
4
5
 
5
6
  const log = logger.templateLiteralLog.bind(logger);
6
7
  const step = logger.step.bind(logger);
7
- const reporterFunctions = require('./reporter-functions');
8
8
 
9
9
  module.exports = {
10
10
  logger,
@@ -13,11 +13,6 @@ module.exports = {
13
13
  step,
14
14
  TestomatClient,
15
15
  TRConstants,
16
- };
17
-
18
- module.exports.testomat = {
19
- artifact: reporterFunctions.artifact,
20
- log: reporterFunctions.log,
21
- step: reporterFunctions.step,
22
- meta: reporterFunctions.keyValue,
16
+ TRArtifacts,
17
+ addArtifact: TRArtifacts.artifact,
23
18
  };
@@ -0,0 +1,47 @@
1
+ // TODO: use as example for the unit-tests
2
+
3
+ const result = {
4
+ "runId": "51eb2798",
5
+ "status": "failed",
6
+ "runUrl": "https://beta.testomat.io/projects/codecept-new-mode-exmple/runs/51eb2798/report",
7
+ "executionTime": "0 seconds",
8
+ "executionDate": "(30/07/2023 11:11:11)",
9
+ "tests": [{
10
+ "files": [],
11
+ "steps": "\u001b[32m\u001b[1mOn TodosPage: goto \u001b[22m\u001b[39m\n",
12
+ "status": "passed",
13
+ "stack": "I execute script () => sessionStorage.clear()",
14
+ "example": null,
15
+ "code": null,
16
+ "title": "Create a new todo item @T50e82737",
17
+ "suite_title": "Create Tasks @step:06 @smoke @story:12 @S2f5c1942",
18
+ "test_id": "50e82737",
19
+ "message": "",
20
+ "run_time": 121,
21
+ "artifacts": [],
22
+ "api_key": "tstmt_gRqrhBUaVxTpezGpZjRmlahOeqcRBBbDMA1692050199",
23
+ "create": false
24
+ }, {
25
+ "files": [{
26
+ "path": "/home/codeceptjs-testomat-example/codeceptJS/output/Create_2_@T5b8d1186.failed.png",
27
+ "type": "image/png"
28
+ }],
29
+ "steps": "I am on page \"http://todomvc.com/examples/angularjs/#/\"",
30
+ "status": "failed",
31
+ "stack": "I am on page \"http://todomvc.com/examples/angularjs/#/\"",
32
+ "example": null,
33
+ "code": null,
34
+ "title": "Create a new todo item part 2 @T5b8d1186",
35
+ "suite_title": "@second Create Tasks @step:07 @smoke @story:13 @S2f5c1942",
36
+ "test_id": "5b8d1186",
37
+ "message": "expected expected number of visible is 2, but found 1 \"1\" to equal \"2\"",
38
+ "run_time": 176,
39
+ "artifacts": [null],
40
+ "api_key": "tstmt_gRqrhBUaVxTpezGpZjRmlahOeqcRBBbDMA1692050199",
41
+ "create": false
42
+ }]
43
+ }
44
+
45
+ module.exports = {
46
+ result
47
+ }