@testomatio/reporter 1.3.5-beta → 1.4.0-beta-wdio-bdd

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.
Files changed (46) hide show
  1. package/README.md +60 -57
  2. package/lib/adapter/codecept.js +96 -35
  3. package/lib/adapter/cucumber/current.js +18 -11
  4. package/lib/adapter/cucumber/legacy.js +6 -5
  5. package/lib/adapter/cucumber.js +2 -2
  6. package/lib/adapter/cypress-plugin/index.js +52 -25
  7. package/lib/adapter/jasmine.js +1 -1
  8. package/lib/adapter/jest.js +49 -16
  9. package/lib/adapter/mocha.js +103 -51
  10. package/lib/adapter/playwright.js +95 -33
  11. package/lib/adapter/webdriver.js +46 -1
  12. package/lib/bin/reportXml.js +22 -16
  13. package/lib/bin/startTest.js +27 -6
  14. package/lib/client.js +179 -53
  15. package/lib/config.js +34 -0
  16. package/lib/constants.js +32 -7
  17. package/lib/data-storage.js +203 -0
  18. package/lib/fileUploader.js +135 -54
  19. package/lib/junit-adapter/adapter.js +0 -2
  20. package/lib/junit-adapter/csharp.js +3 -4
  21. package/lib/junit-adapter/index.js +3 -3
  22. package/lib/junit-adapter/java.js +35 -17
  23. package/lib/junit-adapter/javascript.js +1 -2
  24. package/lib/junit-adapter/python.js +12 -14
  25. package/lib/junit-adapter/ruby.js +1 -2
  26. package/lib/pipe/csv.js +5 -3
  27. package/lib/pipe/github.js +9 -19
  28. package/lib/pipe/gitlab.js +22 -26
  29. package/lib/pipe/html.js +354 -0
  30. package/lib/pipe/index.js +3 -1
  31. package/lib/pipe/testomatio.js +257 -53
  32. package/lib/reporter-functions.js +46 -0
  33. package/lib/reporter.js +11 -9
  34. package/lib/services/artifacts.js +57 -0
  35. package/lib/services/index.js +13 -0
  36. package/lib/services/key-values.js +58 -0
  37. package/lib/services/logger.js +311 -0
  38. package/lib/template/testomatio.hbs +1236 -0
  39. package/lib/utils/pipe_utils.js +129 -0
  40. package/lib/{util.js → utils/utils.js} +145 -15
  41. package/lib/xmlReader.js +211 -122
  42. package/package.json +17 -9
  43. package/lib/_ArtifactStorageOld.js +0 -142
  44. package/lib/artifactStorage.js +0 -25
  45. package/lib/dataStorage.js +0 -244
  46. package/lib/logger.js +0 -301
package/lib/logger.js DELETED
@@ -1,301 +0,0 @@
1
- const chalk = require('chalk');
2
- const debug = require('debug')('@testomatio/reporter:logger');
3
- const _ = require('lodash');
4
- const { DataStorage } = require('./dataStorage');
5
-
6
- const LOG_METHODS = ['assert', 'debug', 'error', 'info', 'log', 'trace', 'warn'];
7
- const LEVELS = {
8
- ALL: { severity: 1, color: '' },
9
- VERBOSE: { severity: 3, color: 'grey' },
10
- TRACE: { severity: 5, color: 'grey' },
11
- DEBUG: { severity: 7, color: 'cyan' },
12
- INFO: { severity: 9, color: 'black' },
13
- LOG: { severity: 11, color: 'black' },
14
- WARN: { severity: 13, color: 'yellow' },
15
- ERROR: { severity: 15, color: 'red' },
16
- };
17
-
18
- /**
19
- * Logger allows to:
20
- * 1. Intercept logs from user logger (console.log, etc) and store them.
21
- * 2. Output logs to console (actually, logger functionality).
22
- * 3. Varied syntax.
23
- */
24
- class Logger {
25
- // _originalUserLogger used to output logs to console by the user logger
26
- // _loggerToIntercept intercepted and reassigned immediately when added
27
-
28
- constructor() {
29
- // set default logger to be used in log, warn, error, etc methods
30
- this._originalUserLogger = { ...console };
31
-
32
- this.dataStorage = new DataStorage('log');
33
- this.logLevel = process?.env?.LOG_LEVEL?.toUpperCase() || 'ALL';
34
-
35
- // commented because prefer to use "intercept" method
36
- // if (params?.logger) this._loggerToIntercept = params.logger;
37
-
38
- // intercept console by default
39
- this.intercept(console);
40
-
41
- // singleton
42
- if (!Logger.instance) {
43
- Logger.instance = this;
44
- }
45
-
46
- this._helpers = {
47
- parseLastArgToGetTestId: (...args) => {
48
- try {
49
- return this.dataStorage._tryToRetrieveTestId(args.at(-1));
50
- } catch (e) {
51
- // node 14 support
52
- return this.dataStorage._tryToRetrieveTestId(args[args.length - 1]);
53
- }
54
- },
55
- };
56
- }
57
-
58
- /**
59
- * Allows you to define a step inside a test. Step name is attached to the report and
60
- * helps to understand the test flow.
61
- * @param {*} strings
62
- * @param {...any} values
63
- */
64
- step(strings, ...values) {
65
- let logs = '';
66
- for (let i = 0; i < strings.length; i++) {
67
- logs += strings[i];
68
- if (i < values.length) {
69
- logs += values[i];
70
- }
71
- }
72
- logs = chalk.blue(`> ${logs}`);
73
- this.dataStorage.putData(logs);
74
- }
75
-
76
- /**
77
- *
78
- * @param {*} context testId or test context from test runner
79
- * @returns
80
- */
81
- getLogs(context) {
82
- const logs = this.dataStorage.getData(context);
83
- return logs || '';
84
- }
85
-
86
- _stringifyLogs(...args) {
87
- const logs = [];
88
- // stringify everything except strings
89
- for (const arg of args) {
90
- // ignore empty strings
91
- if (arg === '') continue;
92
- if (typeof arg === 'string') {
93
- logs.push(arg);
94
- } else if (Array.isArray(arg)) {
95
- logs.push(arg.join(' '));
96
- } else {
97
- try {
98
- // eslint-disable-next-line no-unused-expressions
99
- this.prettyObjects ? logs.push(JSON.stringify(arg, null, 2)) : logs.push(JSON.stringify(arg));
100
- } catch (e) {
101
- debug('Error while stringify object', e);
102
- logs.push(arg);
103
- }
104
- }
105
- }
106
- return logs.join(' ');
107
- }
108
-
109
- /**
110
- * Tagget template literal. Allows to use different syntaxes:
111
- * 1. Tagget template: $`text ${someVar}`
112
- * 2. Standard: $(`text ${someVar}`)
113
- * 3. Standard with multiple arguments: $('text', someVar)
114
- */
115
- _log(strings, ...args) {
116
- // entity which is used to define testId
117
- let context = null;
118
- // last argument could contain testId
119
- const testId = this._helpers.parseLastArgToGetTestId(...args);
120
- if (testId) {
121
- // last arg is test id, do not log it
122
- context = args.pop();
123
- }
124
-
125
- // filter empty strings
126
- strings = strings.filter(item => item !== '');
127
-
128
- let logs;
129
- // this block means tagged template is used (syntax like $`text ${someVar}`)
130
- if (Array.isArray(strings) && strings.length === args.length + 1) {
131
- logs = strings.reduce(
132
- (result, current, index) =>
133
- result +
134
- current +
135
- // strings are splitted by args when use tagged template, thus we add arg after each string
136
- // it looks like: `string1 arg1 string2 arg2 string3`
137
- (args[index] !== undefined // eslint-disable-line no-nested-ternary
138
- ? typeof args[index] === 'string'
139
- ? args[index] // add arg as it is
140
- : this._stringifyLogs(args[index]) // stringify arg
141
- : ' '), // add space if no arg after string
142
- // initial accumulator value
143
- '',
144
- );
145
- } else {
146
- // this block means arguments syntax is used (syntax like $('text', someVar))
147
- // in this case strings represents just a first argument
148
- logs = this._stringifyLogs(strings, ...args);
149
- }
150
- this._originalUserLogger.log(logs);
151
- this.dataStorage.putData(logs, context);
152
- }
153
-
154
- /**
155
- * This function is a wrapper for all logging methods (not to repeat the same code)
156
- * @param {*} argsArray
157
- * @param {*} level
158
- * @returns
159
- */
160
- _logWrapper(argsArray, level) {
161
- if (!argsArray.length) return;
162
-
163
- // entity which is used to define testId
164
- let context = null;
165
- // last argument could contain testId
166
- const testId = this._helpers.parseLastArgToGetTestId(...argsArray);
167
- if (testId) {
168
- // last arg is test id, do not log it
169
- context = argsArray.pop();
170
- }
171
-
172
- const severity = LEVELS[level].severity;
173
- if (severity < LEVELS[this.logLevel]?.severity) return;
174
-
175
- const logs = this._stringifyLogs(...argsArray);
176
- const colorizedLogs = chalk[LEVELS[level].color](logs);
177
- this.dataStorage.putData(colorizedLogs, context);
178
- try {
179
- // level.toLowerCase() represents method name (log, warn, error, etc)
180
- this._originalUserLogger[level.toLowerCase()](colorizedLogs);
181
- } catch (e) {
182
- // method could be unexisting, ignore error
183
- }
184
- }
185
-
186
- assert(...args) {
187
- // sometimes user invokes logger without any arguments passed
188
- if (!args.length) return;
189
-
190
- const level = 'ERROR';
191
- const severity = LEVELS[level].severity;
192
- if (severity < LEVELS[this.logLevel]?.severity) return;
193
-
194
- const logs = this._stringifyLogs(...args);
195
- this.dataStorage.putData(logs);
196
- try {
197
- this._originalUserLogger.log(`Assertion result: `, ...args);
198
- } catch (e) {
199
- // method could be unexisting, ignore error
200
- }
201
- }
202
-
203
- debug(...args) {
204
- this._logWrapper(args, 'DEBUG');
205
- }
206
-
207
- error(...args) {
208
- this._logWrapper(args, 'ERROR');
209
- }
210
-
211
- info(...args) {
212
- this._logWrapper(args, 'INFO');
213
- }
214
-
215
- log(...args) {
216
- this._logWrapper(args, 'LOG');
217
- }
218
-
219
- trace(...args) {
220
- this._logWrapper(args, 'TRACE');
221
- }
222
-
223
- warn(...args) {
224
- this._logWrapper(args, 'WARN');
225
- }
226
-
227
- /**
228
- * Intercepts user logger messages.
229
- * When call this method, Logger start to control the user logger,
230
- * but almost nothing is changed for user regarding the console output (like log level set by user)
231
- * (until multiple loggers are intercepted,
232
- * in this case only the last intercepted logger will be used as user console output).
233
- * @param {*} userLogger
234
- */
235
- intercept(userLogger) {
236
- if (!userLogger) return;
237
-
238
- /* prevent multiple console interceptions (cause infinite loop)
239
- actual only for "console", because its used as default output and is intercepted by default */
240
- const isUserLoggerConsole = userLogger.toString?.().toLowerCase() === '[object console]';
241
- if (isUserLoggerConsole && process.env.TESTOMATIO_LOGGER_CONSOLE_INTERCEPTED) {
242
- debug(`Try to intercept console, but it is already intercepted`);
243
- return;
244
- }
245
- // prevent other loggers multiple interceptions
246
- if (_.isEqual(userLogger, this._originalUserLogger)) {
247
- debug(`Try to intercept user logger, but it is already intercepted`);
248
- return;
249
- }
250
-
251
- process.env.TESTOMATIO_LOGGER_CONSOLE_INTERCEPTED = 'true';
252
- debug(isUserLoggerConsole ? 'console intercepted' : 'User logger intercepted');
253
-
254
- /* logs could be intercepted for playwright only if console provides output, thus adding this exception.
255
- it means default _originalUserLogger (console by default) will be used to provide output
256
- (for other frameworks user logger will be passed for output) */
257
- if (this.dataStorage.runningEnvironment !== 'playwright') {
258
- // save original user logger to use it for logging (last intercepted will be used for console output)
259
- //! TODO: temporary don't oeverride user logger to prevent recursion; console will be used for output
260
- // this._originalUserLogger = { ...userLogger };
261
- }
262
- this._loggerToIntercept = userLogger;
263
-
264
- /*
265
- override user logger (any, e.g. console) methods to intercept log messages
266
- this._loggerToIntercept = this; could be used, but decided to override only output methods
267
- */
268
- for (const method of LOG_METHODS) {
269
- /*
270
- decided to comment next code line because its better to create method even if it does not exist in user logger;
271
- on method invocation, we will store the data anyway and catch block will prevent potential errors
272
- */
273
- // if (!this._loggerToIntercept[method]) continue;
274
- this._loggerToIntercept[method] = (...args) => this[method](...args);
275
- }
276
- }
277
-
278
- /**
279
- * Allows to configure logger. Make sure you do it before the logger usage in your code.
280
- *
281
- * @param {Object} [config={}] - The configuration object.
282
- * @param {string} [config.logLevel] - The desired log level. Valid values are 'DEBUG', 'INFO', 'WARN', and 'ERROR'.
283
- * @param {boolean} [config.prettyObjects] - Specifies whether to enable pretty printing of objects.
284
- * @returns {void}
285
- */
286
- configure(config = {}) {
287
- if (!config) return;
288
- if (config.prettyObjects) this.prettyObjects = config.prettyObjects;
289
- if (config.logLevel) this.logLevel = config.logLevel.toUpperCase();
290
- }
291
- }
292
-
293
- Logger.instance = null;
294
-
295
- // module.exports.Logger = Logger;
296
- const logger = new Logger();
297
-
298
- module.exports = logger;
299
-
300
- // TODO: parse passed arguments as {level: 'str', message: 'str'} because some loggers use such syntax;
301
- // upd: did not face such loggers, but still could be useful