@testomatio/reporter 1.3.6-beta → 1.4.1-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.
- package/README.md +4 -4
- package/lib/adapter/codecept.js +11 -9
- package/lib/adapter/cucumber/current.js +4 -4
- package/lib/adapter/cucumber/legacy.js +3 -3
- package/lib/adapter/cypress-plugin/index.js +1 -1
- package/lib/adapter/jasmine.js +1 -1
- package/lib/adapter/jest.js +12 -17
- package/lib/adapter/mocha.js +22 -50
- package/lib/adapter/playwright.js +34 -22
- package/lib/adapter/webdriver.js +1 -1
- package/lib/bin/reportXml.js +1 -0
- package/lib/bin/startTest.js +25 -4
- package/lib/client.js +93 -27
- package/lib/constants.js +4 -6
- package/lib/fileUploader.js +106 -38
- package/lib/junit-adapter/java.js +27 -9
- package/lib/pipe/csv.js +4 -1
- package/lib/pipe/github.js +5 -16
- package/lib/pipe/gitlab.js +5 -16
- package/lib/pipe/testomatio.js +136 -34
- package/lib/reporter-functions.js +43 -0
- package/lib/reporter.js +11 -5
- package/lib/storages/artifact-storage.js +70 -0
- package/lib/storages/data-storage.js +307 -0
- package/lib/storages/key-value-storage.js +58 -0
- package/lib/{logger.js → storages/logger.js} +103 -114
- package/lib/utils/pipe_utils.js +135 -0
- package/lib/{util.js → utils/utils.js} +129 -12
- package/lib/xmlReader.js +132 -44
- package/package.json +9 -7
- package/lib/_ArtifactStorageOld.js +0 -142
- package/lib/artifactStorage.js +0 -25
- package/lib/dataStorage.js +0 -244
package/lib/dataStorage.js
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
const debug = require('debug')('@testomatio/reporter:storage');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const os = require('os');
|
|
5
|
-
const { join } = require('path');
|
|
6
|
-
const JestReporter = require('./adapter/jest');
|
|
7
|
-
const { TESTOMAT_TMP_STORAGE } = require('./constants');
|
|
8
|
-
const { fileSystem } = require('./util');
|
|
9
|
-
const getTestIdFromTestTitle = require('./util').parseTest;
|
|
10
|
-
|
|
11
|
-
class DataStorage {
|
|
12
|
-
/**
|
|
13
|
-
* Creates data storage instance for specific data type.
|
|
14
|
-
* Stores data to global variable or to file depending on what is applicable for current test runner.
|
|
15
|
-
* dataType: 'log' | 'artifact' | ...
|
|
16
|
-
* @param {*} dataType storage type (like 'log', 'artifact'); could be any string, used only to define file path
|
|
17
|
-
*/
|
|
18
|
-
constructor(dataType) {
|
|
19
|
-
// if (!dataType) throw new Error('Data type is required when creating data storage');
|
|
20
|
-
this.dataType = dataType || 'data';
|
|
21
|
-
this.dataDirName = this.dataType;
|
|
22
|
-
|
|
23
|
-
this._refreshStorageType();
|
|
24
|
-
|
|
25
|
-
// dir is created in any case (not to recheck its existence every time)
|
|
26
|
-
this.dataDirPath = path.join(TESTOMAT_TMP_STORAGE.mainDir, this.dataDirName);
|
|
27
|
-
fileSystem.createDir(this.dataDirPath);
|
|
28
|
-
|
|
29
|
-
debug(`Data storage mode: ${this.isFileStorage ? 'file' : 'memory'}`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Try to define the running environment. Not 100% reliable and used as additional check
|
|
34
|
-
* @returns jest | mocha | ...
|
|
35
|
-
*/
|
|
36
|
-
getRunningEnviroment() {
|
|
37
|
-
// jest
|
|
38
|
-
if (process.env.JEST_WORKER_ID) return 'jest';
|
|
39
|
-
|
|
40
|
-
// mocha
|
|
41
|
-
try {
|
|
42
|
-
// @ts-expect-error mocha is defined only in mocha environment
|
|
43
|
-
if (typeof mocha !== 'undefined') return 'mocha';
|
|
44
|
-
} catch (e) {
|
|
45
|
-
// ignore
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// codeceptjs
|
|
49
|
-
// @ts-expect-error codeceptjs is defined only in codeceptjs environment
|
|
50
|
-
if (global.codeceptjs) return 'codeceptjs';
|
|
51
|
-
|
|
52
|
-
// others
|
|
53
|
-
// 'cucumber:current', 'cucumber:legacy'
|
|
54
|
-
if (global.testomatioRunningEnvironment) return global.testomatioRunningEnvironment;
|
|
55
|
-
|
|
56
|
-
if (process.env.PLAYWRIGHT_TEST_BASE_URL) return 'playwright';
|
|
57
|
-
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Puts any data to storage (file or global variable)
|
|
63
|
-
* @param {*} data anything you want to store
|
|
64
|
-
* @param {*} context could be testId or any context (test, suite, etc) which is used to define testId
|
|
65
|
-
* @returns
|
|
66
|
-
*/
|
|
67
|
-
putData(data, context = null) {
|
|
68
|
-
this._refreshStorageType();
|
|
69
|
-
|
|
70
|
-
let testId = this._tryToRetrieveTestId(context) || null;
|
|
71
|
-
|
|
72
|
-
if (this.runningEnvironment === 'codeceptjs') testId = testId ?? global.testomatioDataStore?.currentlyRunningTestId;
|
|
73
|
-
if (this.runningEnvironment === 'jest') testId = testId ?? JestReporter.getIdOfCurrentlyRunningTest();
|
|
74
|
-
// logs in playwright are gathered by pw framwork itself
|
|
75
|
-
if (this.runningEnvironment === 'playwright' && this.dataType === 'log') return;
|
|
76
|
-
|
|
77
|
-
// get id from global store
|
|
78
|
-
if (global.testomatioDataStore && global.testomatioDataStore.currentlyRunningTestId)
|
|
79
|
-
testId = testId ?? global.testomatioDataStore?.currentlyRunningTestId;
|
|
80
|
-
|
|
81
|
-
// if testId is not provided, data is be saved to `{dataType}_other` file;
|
|
82
|
-
if (!testId) {
|
|
83
|
-
debug(`No test id provided for ${this.dataType} data: ${data}`);
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (this.isFileStorage) {
|
|
88
|
-
this._putDataToFile(data, testId);
|
|
89
|
-
} else {
|
|
90
|
-
this._putDataToGlobalVar(data, testId);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Returns data, stored for specific testId (or data which was stored without test id specified).
|
|
96
|
-
* This method will get data from global variable. But if it is not available, it will try to get data from file.
|
|
97
|
-
* Thus, good approach is to remove file storage folder before each test run (and after, for sure).
|
|
98
|
-
*
|
|
99
|
-
* Defining the execution environment is not guaranteed! Is used only as additional check.
|
|
100
|
-
* @param {*} context could be testId or any context (test, suite, etc) which is used to define testId
|
|
101
|
-
* @returns
|
|
102
|
-
*/
|
|
103
|
-
getData(context) {
|
|
104
|
-
this._refreshStorageType();
|
|
105
|
-
|
|
106
|
-
let testId = null;
|
|
107
|
-
if (typeof context === 'string') {
|
|
108
|
-
testId = context;
|
|
109
|
-
} else {
|
|
110
|
-
// TODO: derive testId from context
|
|
111
|
-
// testId = context...
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (!testId) {
|
|
115
|
-
debug(`Cannot get test id from passed context:\n}`, context);
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
let testData = null;
|
|
120
|
-
|
|
121
|
-
if (global?.testomatioDataStore) {
|
|
122
|
-
testData = this._getDataFromGlobalVar(testId);
|
|
123
|
-
if (testData) return testData;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (this.isFileStorage || !testData) {
|
|
127
|
-
testData = this._getDataFromFile(testId);
|
|
128
|
-
if (testData) return testData;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
debug(`No ${this.dataType} data for test id ${testId} in both file and global variable`);
|
|
132
|
-
return testData;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* This method is named as "try" because it does not guarantee that test id could be retrieved.
|
|
137
|
-
* Context could be anything (test, suite, string, etc) which is used to define testId.
|
|
138
|
-
* Or it could represent any other entity (which does not contain test id).
|
|
139
|
-
* @param {*} context
|
|
140
|
-
*/
|
|
141
|
-
_tryToRetrieveTestId(context) {
|
|
142
|
-
if (!context) return null;
|
|
143
|
-
this._refreshStorageType();
|
|
144
|
-
|
|
145
|
-
if (this.runningEnvironment === 'playwright' || context?.title) {
|
|
146
|
-
// context is testInfo
|
|
147
|
-
const testId = getTestIdFromTestTitle(context.title);
|
|
148
|
-
if (testId) return testId;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (typeof context === 'string') {
|
|
152
|
-
const testId = getTestIdFromTestTitle(context);
|
|
153
|
-
if (testId) return testId;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Refreshes storage type (file or global variable) depending on current environment
|
|
161
|
-
* This method should be run on each attempt to put or get data from/to storage
|
|
162
|
-
* Because storage instance is created before the test runner is started. And storage type could be changed
|
|
163
|
-
*/
|
|
164
|
-
_refreshStorageType() {
|
|
165
|
-
this.isFileStorage = !global.testomatioDataStore;
|
|
166
|
-
/*
|
|
167
|
-
FYI:
|
|
168
|
-
If this storage instance is used within test runner, it works fine.
|
|
169
|
-
But if, for example, we create storage instance inside the testomatio client (to get stored data),
|
|
170
|
-
the environment could differs (not already a test runner environment).
|
|
171
|
-
Thus, checking environment is only reasonable when you put data to starage
|
|
172
|
-
(to define where to put data - to global variable or to file)
|
|
173
|
-
and potentially useless when getting data from storage
|
|
174
|
-
*/
|
|
175
|
-
this.runningEnvironment = this.getRunningEnviroment();
|
|
176
|
-
|
|
177
|
-
// some test frameworks do not persist global variables, thus file storage is used for them
|
|
178
|
-
if (this.runningEnvironment === 'jest') this.isFileStorage = true;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
_getDataFromGlobalVar(testId) {
|
|
182
|
-
try {
|
|
183
|
-
if (global?.testomatioDataStore[this.dataDirName]) {
|
|
184
|
-
const testData = global.testomatioDataStore[this.dataDirName][testId];
|
|
185
|
-
debug(`Data for test id ${testId}:\n${testData}`);
|
|
186
|
-
return testData;
|
|
187
|
-
}
|
|
188
|
-
debug(`No ${this.dataType} data for test id ${testId} in <global> storage`);
|
|
189
|
-
return null;
|
|
190
|
-
} catch (e) {
|
|
191
|
-
// there could be no data, ignore
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
_getDataFromFile(testId) {
|
|
196
|
-
try {
|
|
197
|
-
const filepath = join(this.dataDirPath, `${this.dataType}_${testId}`);
|
|
198
|
-
if (fs.existsSync(filepath)) {
|
|
199
|
-
const testData = fs.readFileSync(filepath, 'utf-8');
|
|
200
|
-
debug(`Data for test id ${testId}:\n${testData}`);
|
|
201
|
-
return testData;
|
|
202
|
-
}
|
|
203
|
-
debug(`No ${this.dataType} data for test id ${testId} in <file> storage`);
|
|
204
|
-
return null;
|
|
205
|
-
} catch (e) {
|
|
206
|
-
// there could be no data, ignore
|
|
207
|
-
}
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
_putDataToGlobalVar(data, testId) {
|
|
212
|
-
debug('Saving data to global variable for test', testId, ':\n', data, '\n');
|
|
213
|
-
if (!global.testomatioDataStore[this.dataDirName]) global.testomatioDataStore[this.dataDirName] = {};
|
|
214
|
-
global.testomatioDataStore[this.dataDirName][testId] // eslint-disable-line no-unused-expressions
|
|
215
|
-
? (global.testomatioDataStore[this.dataDirName][testId] += `\n${data}`)
|
|
216
|
-
: (global.testomatioDataStore[this.dataDirName][testId] = data);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
_putDataToFile(data, testId) {
|
|
220
|
-
if (typeof data !== 'string') data = JSON.stringify(data);
|
|
221
|
-
const filename = `${this.dataType}_${testId}`;
|
|
222
|
-
const filepath = join(this.dataDirPath, filename);
|
|
223
|
-
debug('Saving data to file for test', testId, 'to', filepath, ':\n', data, '\n');
|
|
224
|
-
|
|
225
|
-
// TODO: handle multiple invocations of JSON.stringify.
|
|
226
|
-
// UPD: not actual because decided not to use it - it created extra wrapping quotes "" and // (escaped slashes)
|
|
227
|
-
fs.appendFileSync(filepath, data + os.EOL, 'utf-8');
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
module.exports.DataStorage = DataStorage;
|
|
232
|
-
|
|
233
|
-
// TODO: consider using fs promises instead of writeSync/appendFileSync to
|
|
234
|
-
// prevent blocking and improve performance (probably queue usage will be required)
|
|
235
|
-
|
|
236
|
-
// TODO: rewrite client - everything regarding storing artifacts
|
|
237
|
-
// TODO: try to define adapter inside client
|
|
238
|
-
// TODO: use .env
|
|
239
|
-
// TODO: ability to intercept multiple loggers (upd: no need)
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
/* Cypress
|
|
243
|
-
Parallelization is only available if using Cypress Dashboard??
|
|
244
|
-
*/
|