@testomatio/reporter 1.1.0-beta → 1.2.0-beta
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/lib/_ArtifactStorageOld.js +5 -4
- package/lib/logger.js +98 -18
- package/lib/reporter.js +2 -0
- package/package.json +1 -1
|
@@ -7,9 +7,8 @@ const { TESTOMAT_ARTIFACT_SUFFIX } = require('./constants');
|
|
|
7
7
|
const { specificTestInfo } = require('./util');
|
|
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;
|
|
@@ -21,7 +20,7 @@ class ArtifactStorage {
|
|
|
21
20
|
// so the solution is make it opposite to isMemory (which will be retrieved from global)
|
|
22
21
|
this.isFile = true;
|
|
23
22
|
this.isMemory = false;
|
|
24
|
-
this.tmpDirFullpath = this.createTestomatTmpDir(
|
|
23
|
+
this.tmpDirFullpath = this.createTestomatTmpDir(ArtifactStorage._tmpPrefix);
|
|
25
24
|
debug('SAVE to tmp folder mode enabled!');
|
|
26
25
|
}
|
|
27
26
|
}
|
|
@@ -113,7 +112,7 @@ class ArtifactStorage {
|
|
|
113
112
|
|
|
114
113
|
// no need to use multiple dirs; we can implement it later if required
|
|
115
114
|
static tmpTestomatDirNames() {
|
|
116
|
-
const subname =
|
|
115
|
+
const subname = ArtifactStorage._tmpPrefix || "tsmt_reporter";
|
|
117
116
|
|
|
118
117
|
return fs.readdirSync(os.tmpdir(), { withFileTypes: true })
|
|
119
118
|
.filter((item) => item.isDirectory())
|
|
@@ -138,4 +137,6 @@ class ArtifactStorage {
|
|
|
138
137
|
}
|
|
139
138
|
}
|
|
140
139
|
|
|
140
|
+
ArtifactStorage._tmpPrefix = "tsmt_reporter";
|
|
141
|
+
|
|
141
142
|
module.exports = ArtifactStorage;
|
package/lib/logger.js
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
1
2
|
const debug = require('debug')('@testomatio/reporter:logger');
|
|
2
3
|
const { DataStorage } = require('./dataStorage');
|
|
3
4
|
|
|
4
5
|
const LOG_METHODS = ['assert', 'debug', 'error', 'info', 'log', 'trace', 'warn'];
|
|
6
|
+
const LEVELS = {
|
|
7
|
+
ALL: { severity: 1, color: '' },
|
|
8
|
+
VERBOSE: { severity: 3, color: 'grey' },
|
|
9
|
+
TRACE: { severity: 5, color: 'grey' },
|
|
10
|
+
DEBUG: { severity: 7, color: 'cyan' },
|
|
11
|
+
INFO: { severity: 9, color: 'black' },
|
|
12
|
+
LOG: { severity: 11, color: 'black' },
|
|
13
|
+
WARN: { severity: 13, color: 'yellow' },
|
|
14
|
+
ERROR: { severity: 15, color: 'red' },
|
|
15
|
+
};
|
|
5
16
|
|
|
6
17
|
/**
|
|
7
18
|
* Logger allows to:
|
|
@@ -14,7 +25,11 @@ class Logger {
|
|
|
14
25
|
// _loggerToIntercept intercepted and reassigned immediately when added
|
|
15
26
|
|
|
16
27
|
constructor(params = {}) {
|
|
28
|
+
// set default logger to be used in log, warn, error, etc methods
|
|
29
|
+
this._originalUserLogger = { ...console };
|
|
30
|
+
|
|
17
31
|
this.dataStorage = new DataStorage('log', params);
|
|
32
|
+
this.logLevel = process?.env?.LOG_LEVEL?.toUpperCase() || 'ALL';
|
|
18
33
|
|
|
19
34
|
// commented because prefer to use "intercept" method
|
|
20
35
|
// if (params?.logger) this._loggerToIntercept = params.logger;
|
|
@@ -65,22 +80,38 @@ class Logger {
|
|
|
65
80
|
// it looks like: `string1 arg1 string2 arg2 string3`
|
|
66
81
|
(args[index] !== undefined // eslint-disable-line no-nested-ternary
|
|
67
82
|
? typeof args[index] === 'string'
|
|
68
|
-
? // add arg as it is
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
this._strinfifyLogs(args[index])
|
|
72
|
-
: // add space if no arg after string
|
|
73
|
-
' '),
|
|
83
|
+
? args[index] // add arg as it is
|
|
84
|
+
: this._strinfifyLogs(args[index]) // stringify arg
|
|
85
|
+
: ' '), // add space if no arg after string
|
|
74
86
|
// initial accumulator value
|
|
75
87
|
'',
|
|
76
88
|
);
|
|
77
89
|
} else {
|
|
78
90
|
// this block means arguments syntax is used (syntax like $('text', someVar))
|
|
91
|
+
// in this case strings represents just a first argument
|
|
79
92
|
logs = this._strinfifyLogs(strings, ...args);
|
|
80
93
|
}
|
|
81
94
|
this.dataStorage.putData(logs);
|
|
82
95
|
}
|
|
83
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Allows you to define a step inside a test. Step name is attached to the report and
|
|
99
|
+
* helps to understand the test flow.
|
|
100
|
+
* @param {*} strings
|
|
101
|
+
* @param {...any} values
|
|
102
|
+
*/
|
|
103
|
+
step(strings, ...values) {
|
|
104
|
+
let logs = '';
|
|
105
|
+
for (let i = 0; i < strings.length; i++) {
|
|
106
|
+
logs += strings[i];
|
|
107
|
+
if (i < values.length) {
|
|
108
|
+
logs += values[i];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
logs = chalk.blue(`> ${logs}`);
|
|
112
|
+
this.dataStorage.putData(logs);
|
|
113
|
+
}
|
|
114
|
+
|
|
84
115
|
/**
|
|
85
116
|
*
|
|
86
117
|
* @param {*} context testId or test context from test runner
|
|
@@ -97,13 +128,23 @@ class Logger {
|
|
|
97
128
|
if (typeof arg === 'string') {
|
|
98
129
|
logs.push(arg);
|
|
99
130
|
} else {
|
|
100
|
-
|
|
131
|
+
try {
|
|
132
|
+
// eslint-disable-next-line no-unused-expressions
|
|
133
|
+
this.prettyObjects ? logs.push(JSON.stringify(arg, null, 2)) : logs.push(JSON.stringify(arg));
|
|
134
|
+
} catch (e) {
|
|
135
|
+
debug('Error while stringify object', e);
|
|
136
|
+
logs.push(arg);
|
|
137
|
+
}
|
|
101
138
|
}
|
|
102
139
|
}
|
|
103
140
|
return logs.join(' ');
|
|
104
141
|
}
|
|
105
142
|
|
|
106
143
|
assert(...args) {
|
|
144
|
+
const level = 'ERROR';
|
|
145
|
+
const severity = LEVELS[level].severity;
|
|
146
|
+
if (severity < LEVELS[this.logLevel]?.severity) return;
|
|
147
|
+
|
|
107
148
|
const logs = this._strinfifyLogs(...args);
|
|
108
149
|
this.dataStorage.putData(logs);
|
|
109
150
|
try {
|
|
@@ -114,8 +155,14 @@ class Logger {
|
|
|
114
155
|
}
|
|
115
156
|
|
|
116
157
|
debug(...args) {
|
|
158
|
+
const level = 'DEBUG';
|
|
159
|
+
const severity = LEVELS[level].severity;
|
|
160
|
+
if (severity < LEVELS[this.logLevel]?.severity) return;
|
|
161
|
+
|
|
162
|
+
if (this.logLevel === 'error' || this.logLevel === 'warn') return;
|
|
117
163
|
const logs = this._strinfifyLogs(...args);
|
|
118
|
-
|
|
164
|
+
const colorizedLogs = chalk[LEVELS[level].color](logs);
|
|
165
|
+
this.dataStorage.putData(colorizedLogs);
|
|
119
166
|
try {
|
|
120
167
|
this._originalUserLogger.debug(...args);
|
|
121
168
|
} catch (e) {
|
|
@@ -124,8 +171,13 @@ class Logger {
|
|
|
124
171
|
}
|
|
125
172
|
|
|
126
173
|
error(...args) {
|
|
174
|
+
const level = 'ERROR';
|
|
175
|
+
const severity = LEVELS[level].severity;
|
|
176
|
+
if (severity < LEVELS[this.logLevel]?.severity) return;
|
|
177
|
+
|
|
127
178
|
const logs = this._strinfifyLogs(...args);
|
|
128
|
-
|
|
179
|
+
const colorizedLogs = chalk[LEVELS[level].color](logs);
|
|
180
|
+
this.dataStorage.putData(colorizedLogs);
|
|
129
181
|
try {
|
|
130
182
|
this._originalUserLogger.error(...args);
|
|
131
183
|
} catch (e) {
|
|
@@ -134,6 +186,10 @@ class Logger {
|
|
|
134
186
|
}
|
|
135
187
|
|
|
136
188
|
info(...args) {
|
|
189
|
+
const level = 'INFO';
|
|
190
|
+
const severity = LEVELS[level].severity;
|
|
191
|
+
if (severity < LEVELS[this.logLevel]?.severity) return;
|
|
192
|
+
|
|
137
193
|
const logs = this._strinfifyLogs(...args);
|
|
138
194
|
this.dataStorage.putData(logs);
|
|
139
195
|
try {
|
|
@@ -144,6 +200,10 @@ class Logger {
|
|
|
144
200
|
}
|
|
145
201
|
|
|
146
202
|
log(...args) {
|
|
203
|
+
const level = 'INFO';
|
|
204
|
+
const severity = LEVELS[level].severity;
|
|
205
|
+
if (severity < LEVELS[this.logLevel]?.severity) return;
|
|
206
|
+
|
|
147
207
|
const logs = this._strinfifyLogs(...args);
|
|
148
208
|
this.dataStorage.putData(logs);
|
|
149
209
|
try {
|
|
@@ -154,8 +214,13 @@ class Logger {
|
|
|
154
214
|
}
|
|
155
215
|
|
|
156
216
|
trace(...args) {
|
|
217
|
+
const level = 'TRACE';
|
|
218
|
+
const severity = LEVELS[level].severity;
|
|
219
|
+
if (severity < LEVELS[this.logLevel]?.severity) return;
|
|
220
|
+
|
|
157
221
|
const logs = this._strinfifyLogs(...args);
|
|
158
|
-
|
|
222
|
+
const colorizedLogs = chalk[LEVELS[level].color](logs);
|
|
223
|
+
this.dataStorage.putData(colorizedLogs);
|
|
159
224
|
try {
|
|
160
225
|
this._originalUserLogger.trace(...args);
|
|
161
226
|
} catch (e) {
|
|
@@ -164,8 +229,13 @@ class Logger {
|
|
|
164
229
|
}
|
|
165
230
|
|
|
166
231
|
warn(...args) {
|
|
232
|
+
const level = 'WARN';
|
|
233
|
+
const severity = LEVELS[level].severity;
|
|
234
|
+
if (severity < LEVELS[this.logLevel]?.severity) return;
|
|
235
|
+
|
|
167
236
|
const logs = this._strinfifyLogs(...args);
|
|
168
|
-
|
|
237
|
+
const colorizedLogs = chalk[LEVELS[level].color](logs);
|
|
238
|
+
this.dataStorage.putData(colorizedLogs);
|
|
169
239
|
try {
|
|
170
240
|
this._originalUserLogger.warn(...args);
|
|
171
241
|
} catch (e) {
|
|
@@ -202,6 +272,20 @@ class Logger {
|
|
|
202
272
|
this._loggerToIntercept[method] = (...args) => this[method](...args);
|
|
203
273
|
}
|
|
204
274
|
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Allows to configure logger. Make sure you do it before the logger usage in your code.
|
|
278
|
+
*
|
|
279
|
+
* @param {Object} [config={}] - The configuration object.
|
|
280
|
+
* @param {string} [config.logLevel] - The desired log level. Valid values are 'DEBUG', 'INFO', 'WARN', and 'ERROR'.
|
|
281
|
+
* @param {boolean} [config.prettyObjects] - Specifies whether to enable pretty printing of objects.
|
|
282
|
+
* @returns {void}
|
|
283
|
+
*/
|
|
284
|
+
configure(config = {}) {
|
|
285
|
+
if (!config) return;
|
|
286
|
+
if (config.prettyObjects) this.prettyObjects = config.prettyObjects;
|
|
287
|
+
if (config.logLevel) this.logLevel = config.logLevel.toUpperCase();
|
|
288
|
+
}
|
|
205
289
|
}
|
|
206
290
|
|
|
207
291
|
Logger.instance = null;
|
|
@@ -210,12 +294,8 @@ Logger.instance = null;
|
|
|
210
294
|
module.exports = new Logger();
|
|
211
295
|
|
|
212
296
|
// TODO: consider using fs promises instead of writeSync/appendFileSync to prevent blocking and improve performance
|
|
213
|
-
// TODO:
|
|
214
|
-
//
|
|
215
|
-
|
|
216
|
-
// TODO: parse passed arguments as {level: 'str', message: 'str'} because some loggers use such syntax
|
|
217
|
-
// TODO: add setLevel method - allows skip messages with the lower level
|
|
297
|
+
// TODO: parse passed arguments as {level: 'str', message: 'str'} because some loggers use such syntax;
|
|
298
|
+
// upd: did not face such loggers, but still could be useful
|
|
299
|
+
|
|
218
300
|
// TODO: in case of unset _originalUserLogger, logger.{method} will not provide console output,
|
|
219
301
|
// need to add some logger by default
|
|
220
|
-
|
|
221
|
-
// TODO step method (blue color)
|
package/lib/reporter.js
CHANGED
|
@@ -4,10 +4,12 @@ const TRConstants = require('./constants');
|
|
|
4
4
|
const TRArtifacts = require('./_ArtifactStorageOld');
|
|
5
5
|
|
|
6
6
|
const log = logger._log.bind(logger);
|
|
7
|
+
const step = logger.step.bind(logger);
|
|
7
8
|
|
|
8
9
|
module.exports = {
|
|
9
10
|
logger,
|
|
10
11
|
log,
|
|
12
|
+
step,
|
|
11
13
|
TestomatClient,
|
|
12
14
|
TRConstants,
|
|
13
15
|
TRArtifacts,
|