@testomatio/reporter 1.0.17 → 1.1.0-beta-2
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/adapter/codecept.js +2 -2
- package/lib/adapter/cucumber/current.js +3 -3
- package/lib/adapter/cucumber/legacy.js +2 -2
- package/lib/adapter/jest.js +2 -16
- package/lib/adapter/mocha.js +15 -43
- package/lib/adapter/playwright.js +33 -21
- package/lib/client.js +18 -21
- package/lib/constants.js +4 -6
- package/lib/reporter-functions.js +43 -0
- package/lib/reporter.js +9 -4
- package/lib/storages/artifact-storage.js +70 -0
- package/lib/{dataStorage.js → storages/data-storage.js} +122 -47
- package/lib/storages/key-value-storage.js +58 -0
- package/lib/{logger.js → storages/logger.js} +4 -33
- package/lib/utils/utils.js +14 -0
- package/package.json +1 -1
- package/Changelog.md +0 -355
- package/lib/_ArtifactStorageOld.js +0 -142
- package/lib/artifactStorage.js +0 -25
package/lib/adapter/codecept.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const debug = require('debug')('@testomatio/reporter:adapter:codeceptjs');
|
|
2
2
|
const chalk = require('chalk');
|
|
3
3
|
const TestomatClient = require('../client');
|
|
4
|
-
const { STATUS, APP_PREFIX,
|
|
4
|
+
const { STATUS, APP_PREFIX, TESTOMAT_TMP_STORAGE_DIR } = require('../constants');
|
|
5
5
|
const upload = require('../fileUploader');
|
|
6
6
|
const { parseTest: getIdFromTestTitle, fileSystem } = require('../utils/utils');
|
|
7
7
|
|
|
@@ -56,7 +56,7 @@ function CodeceptReporter(config) {
|
|
|
56
56
|
// Listening to events
|
|
57
57
|
event.dispatcher.on(event.all.before, () => {
|
|
58
58
|
// clear tmp dir
|
|
59
|
-
fileSystem.clearDir(
|
|
59
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
60
60
|
|
|
61
61
|
recorder.add('Creating new run', () => client.createRun());
|
|
62
62
|
videos = [];
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
const { Formatter, formatterHelpers } = require('@cucumber/cucumber');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const fs = require('fs');
|
|
5
|
-
const { STATUS,
|
|
5
|
+
const { STATUS, TESTOMAT_TMP_STORAGE_DIR } = require('../../constants');
|
|
6
6
|
const TestomatClient = require('../../client');
|
|
7
|
-
const logger = require('../../logger');
|
|
7
|
+
const logger = require('../../storages/logger');
|
|
8
8
|
const { parseTest, fileSystem } = require('../../utils/utils');
|
|
9
9
|
|
|
10
10
|
const { GherkinDocumentParser, PickleParser } = formatterHelpers;
|
|
@@ -37,7 +37,7 @@ class CucumberReporter extends Formatter {
|
|
|
37
37
|
|
|
38
38
|
parseEnvelope(envelope) {
|
|
39
39
|
if (envelope.testRunStarted) {
|
|
40
|
-
fileSystem.clearDir(
|
|
40
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
41
41
|
}
|
|
42
42
|
if (envelope.testCaseStarted && this.client) {
|
|
43
43
|
this.client.createRun();
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const { Formatter } = require('cucumber');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const { parseTest, fileSystem } = require('../../utils/utils');
|
|
5
|
-
const { STATUS,
|
|
5
|
+
const { STATUS, TESTOMAT_TMP_STORAGE_DIR } = require('../../constants');
|
|
6
6
|
const TestomatClient = require('../../client');
|
|
7
7
|
|
|
8
8
|
const createTestomatFormatter = apiKey => {
|
|
@@ -97,7 +97,7 @@ const createTestomatFormatter = apiKey => {
|
|
|
97
97
|
|
|
98
98
|
options.eventBroadcaster.on('gherkin-document', addDocument);
|
|
99
99
|
options.eventBroadcaster.on('test-run-started', () => {
|
|
100
|
-
fileSystem.clearDir(
|
|
100
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
101
101
|
this?.client?.createRun();
|
|
102
102
|
});
|
|
103
103
|
options.eventBroadcaster.on('test-case-finished', this.onTestCaseFinished.bind(this));
|
package/lib/adapter/jest.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const TestomatClient = require('../client');
|
|
2
|
-
const { STATUS,
|
|
2
|
+
const { STATUS, TESTOMAT_TMP_STORAGE_DIR } = require('../constants');
|
|
3
3
|
const { parseTest, ansiRegExp, fileSystem } = require('../utils/utils');
|
|
4
4
|
|
|
5
5
|
class JestReporter {
|
|
@@ -11,20 +11,9 @@ class JestReporter {
|
|
|
11
11
|
this.client.createRun();
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
static getIdOfCurrentlyRunningTest() {
|
|
15
|
-
if (!process.env.JEST_WORKER_ID) return null;
|
|
16
|
-
try {
|
|
17
|
-
// @ts-expect-error "expect" could only be defined inside Jest environement (forbidden to import it outside)
|
|
18
|
-
// eslint-disable-next-line no-undef
|
|
19
|
-
if (expect && expect?.getState()?.currentTestName) return parseTest(expect?.getState()?.currentTestName);
|
|
20
|
-
} catch (e) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
14
|
onRunStart() {
|
|
26
15
|
// clear tmp dir
|
|
27
|
-
fileSystem.clearDir(
|
|
16
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
28
17
|
}
|
|
29
18
|
|
|
30
19
|
onTestResult(test, testResult) {
|
|
@@ -72,9 +61,6 @@ class JestReporter {
|
|
|
72
61
|
const { numFailedTests } = results;
|
|
73
62
|
const status = numFailedTests === 0 ? STATUS.PASSED : STATUS.FAILED;
|
|
74
63
|
this.client.updateRunStatus(status);
|
|
75
|
-
|
|
76
|
-
// clear tmp dir
|
|
77
|
-
fileSystem.clearDir(TESTOMAT_TMP_STORAGE.mainDir);
|
|
78
64
|
}
|
|
79
65
|
}
|
|
80
66
|
|
package/lib/adapter/mocha.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
|
2
2
|
const Mocha = require('mocha');
|
|
3
|
-
const debug = require('debug')('@testomatio/reporter:adapter:mocha');
|
|
4
3
|
const chalk = require('chalk');
|
|
5
4
|
const TestomatClient = require('../client');
|
|
6
|
-
const { STATUS,
|
|
7
|
-
const { parseTest,
|
|
8
|
-
const ArtifactStorage = require('../_ArtifactStorageOld');
|
|
5
|
+
const { STATUS, TESTOMAT_TMP_STORAGE_DIR } = require('../constants');
|
|
6
|
+
const { parseTest, fileSystem } = require('../utils/utils');
|
|
9
7
|
|
|
10
8
|
const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING } =
|
|
11
9
|
Mocha.Runner.constants;
|
|
@@ -15,7 +13,7 @@ function MochaReporter(runner, opts) {
|
|
|
15
13
|
let passes = 0;
|
|
16
14
|
let failures = 0;
|
|
17
15
|
let skipped = 0;
|
|
18
|
-
let artifactStore;
|
|
16
|
+
// let artifactStore;
|
|
19
17
|
|
|
20
18
|
const apiKey = opts?.reporterOptions?.apiKey || process.env.TESTOMATIO;
|
|
21
19
|
|
|
@@ -24,13 +22,7 @@ function MochaReporter(runner, opts) {
|
|
|
24
22
|
runner.on(EVENT_RUN_BEGIN, () => {
|
|
25
23
|
client.createRun();
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
toFile: true,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
artifactStore = runner._workerReporter !== undefined ? new ArtifactStorage(params) : new ArtifactStorage();
|
|
32
|
-
|
|
33
|
-
fileSystem.clearDir(TESTOMAT_TMP_STORAGE.mainDir);
|
|
25
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
34
26
|
});
|
|
35
27
|
|
|
36
28
|
runner.on(EVENT_TEST_PASS, async test => {
|
|
@@ -38,20 +30,11 @@ function MochaReporter(runner, opts) {
|
|
|
38
30
|
console.log(chalk.bold.green('✔'), test.fullTitle());
|
|
39
31
|
const testId = parseTest(test.title);
|
|
40
32
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
client.addTestRun(
|
|
47
|
-
STATUS.PASSED,
|
|
48
|
-
{
|
|
49
|
-
test_id: testId,
|
|
50
|
-
title: test.title,
|
|
51
|
-
time: test.duration,
|
|
52
|
-
},
|
|
53
|
-
content,
|
|
54
|
-
);
|
|
33
|
+
client.addTestRun(STATUS.PASSED, {
|
|
34
|
+
test_id: testId,
|
|
35
|
+
title: test.title,
|
|
36
|
+
time: test.duration,
|
|
37
|
+
});
|
|
55
38
|
});
|
|
56
39
|
|
|
57
40
|
runner.on(EVENT_TEST_PENDING, test => {
|
|
@@ -70,29 +53,18 @@ function MochaReporter(runner, opts) {
|
|
|
70
53
|
console.log(chalk.bold.red('✖'), test.fullTitle(), chalk.gray(err.message));
|
|
71
54
|
const testId = parseTest(test.title);
|
|
72
55
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
STATUS.FAILED,
|
|
80
|
-
{
|
|
81
|
-
error: err,
|
|
82
|
-
test_id: testId,
|
|
83
|
-
title: test.title,
|
|
84
|
-
time: test.duration,
|
|
85
|
-
},
|
|
86
|
-
content,
|
|
87
|
-
);
|
|
56
|
+
client.addTestRun(STATUS.FAILED, {
|
|
57
|
+
error: err,
|
|
58
|
+
test_id: testId,
|
|
59
|
+
title: test.title,
|
|
60
|
+
time: test.duration,
|
|
61
|
+
});
|
|
88
62
|
});
|
|
89
63
|
|
|
90
64
|
runner.on(EVENT_RUN_END, () => {
|
|
91
65
|
const status = failures === 0 ? STATUS.PASSED : STATUS.FAILED;
|
|
92
66
|
console.log(chalk.bold(status), `${passes} passed, ${failures} failed, ${skipped} skipped`);
|
|
93
67
|
client.updateRunStatus(status);
|
|
94
|
-
|
|
95
|
-
artifactStore.cleanup();
|
|
96
68
|
});
|
|
97
69
|
}
|
|
98
70
|
|
|
@@ -3,7 +3,7 @@ const crypto = require('crypto');
|
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
|
-
const { APP_PREFIX, STATUS: Status,
|
|
6
|
+
const { APP_PREFIX, STATUS: Status, TESTOMAT_TMP_STORAGE_DIR } = require('../constants');
|
|
7
7
|
const TestomatioClient = require('../client');
|
|
8
8
|
const { isArtifactsEnabled } = require('../fileUploader');
|
|
9
9
|
const { parseTest, fileSystem } = require('../utils/utils');
|
|
@@ -19,15 +19,17 @@ class PlaywrightReporter {
|
|
|
19
19
|
|
|
20
20
|
onBegin(_config, suite) {
|
|
21
21
|
// clean data storage
|
|
22
|
-
fileSystem.clearDir(
|
|
22
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
23
23
|
if (!this.client) return;
|
|
24
24
|
this.suite = suite;
|
|
25
25
|
this.client.createRun();
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
/*
|
|
29
|
+
onTestBegin(test) {
|
|
30
|
+
// does not work; value is not to the storage context
|
|
31
|
+
global.testTitle = test.title;
|
|
32
|
+
} */
|
|
31
33
|
|
|
32
34
|
onTestEnd(test, result) {
|
|
33
35
|
if (!this.client) return;
|
|
@@ -44,23 +46,33 @@ class PlaywrightReporter {
|
|
|
44
46
|
appendStep(step, steps);
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
let logs = '';
|
|
50
|
+
if (result.stderr.length || result.stdout.length) {
|
|
51
|
+
logs = `\n\n${chalk.bold('Logs:')}\n${chalk.red(result.stderr.join(''))}\n${result.stdout.join('')}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const reportTestPromise = this.client
|
|
55
|
+
.addTestRun(checkStatus(result.status), {
|
|
56
|
+
error,
|
|
57
|
+
test_id: testId,
|
|
58
|
+
suite_title,
|
|
59
|
+
title,
|
|
60
|
+
steps: steps.join('\n'),
|
|
61
|
+
time: duration,
|
|
62
|
+
stack: logs,
|
|
63
|
+
})
|
|
64
|
+
.then(pipes => {
|
|
65
|
+
testId = pipes?.filter(p => p.pipe.includes('Testomatio'))[0]?.result?.data?.test_id;
|
|
66
|
+
|
|
67
|
+
this.uploads.push({
|
|
68
|
+
testId,
|
|
69
|
+
title,
|
|
70
|
+
suite_title,
|
|
71
|
+
files: result.attachments.filter(a => a.body || a.path),
|
|
72
|
+
});
|
|
73
|
+
// remove empty uploads
|
|
74
|
+
this.uploads = this.uploads.filter(upload => upload.files.length);
|
|
62
75
|
});
|
|
63
|
-
});
|
|
64
76
|
|
|
65
77
|
reportTestPromises.push(reportTestPromise);
|
|
66
78
|
}
|
package/lib/client.js
CHANGED
|
@@ -8,6 +8,7 @@ const { randomUUID } = require('crypto');
|
|
|
8
8
|
const upload = require('./fileUploader');
|
|
9
9
|
const { APP_PREFIX } = require('./constants');
|
|
10
10
|
const pipesFactory = require('./pipe');
|
|
11
|
+
const artifactStorage = require('./storages/artifact-storage');
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @typedef {import('../types').TestData} TestData
|
|
@@ -96,9 +97,6 @@ class Client {
|
|
|
96
97
|
// all pipes disabled, skipping
|
|
97
98
|
if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
|
|
98
99
|
|
|
99
|
-
global.testomatioArtifacts = [];
|
|
100
|
-
if (!global.testomatioDataStore) global.testomatioDataStore = {};
|
|
101
|
-
|
|
102
100
|
this.queue = this.queue
|
|
103
101
|
.then(() => Promise.all(this.pipes.map(p => p.createRun())))
|
|
104
102
|
.catch(err => console.log(APP_PREFIX, err))
|
|
@@ -112,11 +110,9 @@ class Client {
|
|
|
112
110
|
*
|
|
113
111
|
* @param {string|undefined} status
|
|
114
112
|
* @param {TestData} [testData]
|
|
115
|
-
* @param {string[]} [storeArtifacts]
|
|
116
113
|
* @returns {Promise<PipeResult[]>}
|
|
117
114
|
*/
|
|
118
|
-
async addTestRun(status, testData
|
|
119
|
-
debug('Adding test run for test', testData?.test_id || 'unknown test');
|
|
115
|
+
async addTestRun(status, testData) {
|
|
120
116
|
// all pipes disabled, skipping
|
|
121
117
|
if (!this.pipes?.filter(p => p.isEnabled).length) return [];
|
|
122
118
|
|
|
@@ -155,23 +151,21 @@ class Client {
|
|
|
155
151
|
|
|
156
152
|
stack += testData.stack || '';
|
|
157
153
|
|
|
154
|
+
// ATTACH LOGS from storage
|
|
158
155
|
// in some cases (e.g. using cucumber) logger instance becomes empty object, if import at the top of the file
|
|
159
|
-
const logger = require('./logger');
|
|
156
|
+
const logger = require('./storages/logger');
|
|
160
157
|
const testLogs = logger.getLogs(test_id);
|
|
161
158
|
// debug(`Test logs for ${test_id}:\n`, testLogs);
|
|
162
159
|
if (stack) stack += '\n\n';
|
|
163
160
|
stack += testLogs ? `${chalk.bold('Logs:')}\n${testLogs}` : '';
|
|
164
161
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
162
|
+
// GET ARTIFACTS from storage
|
|
163
|
+
const artifactFiles = artifactStorage.get(test_id);
|
|
164
|
+
if (artifactFiles) files.push(...artifactFiles);
|
|
169
165
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
global.testomatioArtifacts = [];
|
|
174
|
-
}
|
|
166
|
+
// GET KEY-VALUEs from storage
|
|
167
|
+
const keyValueStorage = require('./storages/key-value-storage');
|
|
168
|
+
const keyValues = keyValueStorage.get(test_id);
|
|
175
169
|
|
|
176
170
|
for (const file of files) {
|
|
177
171
|
uploadedFiles.push(upload.uploadFileByPath(file, this.uuid));
|
|
@@ -184,7 +178,7 @@ class Client {
|
|
|
184
178
|
|
|
185
179
|
const artifacts = await Promise.all(uploadedFiles);
|
|
186
180
|
|
|
187
|
-
global.testomatioArtifacts = [];
|
|
181
|
+
// global.testomatioArtifacts = [];
|
|
188
182
|
|
|
189
183
|
this.totalUploaded += uploadedFiles.filter(n => n).length;
|
|
190
184
|
|
|
@@ -202,6 +196,7 @@ class Client {
|
|
|
202
196
|
message,
|
|
203
197
|
run_time: parseFloat(time),
|
|
204
198
|
artifacts,
|
|
199
|
+
meta: keyValues,
|
|
205
200
|
};
|
|
206
201
|
|
|
207
202
|
this.queue = this.queue.then(() =>
|
|
@@ -237,14 +232,16 @@ class Client {
|
|
|
237
232
|
this.queue = this.queue
|
|
238
233
|
.then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
|
|
239
234
|
.then(() => {
|
|
240
|
-
debug('TOTAL
|
|
235
|
+
debug('TOTAL artifacts', this.totalUploaded);
|
|
236
|
+
if (this.totalUploaded && !upload.isArtifactsEnabled())
|
|
237
|
+
debug(`${this.totalUploaded} artifacts are not uploaded, because artifacts uploading is not enabled`);
|
|
241
238
|
|
|
242
|
-
if (
|
|
239
|
+
if (this.totalUploaded && upload.isArtifactsEnabled()) {
|
|
243
240
|
console.log(
|
|
244
241
|
APP_PREFIX,
|
|
245
|
-
`🗄️
|
|
242
|
+
`🗄️ ${this.totalUploaded} artifacts ${
|
|
246
243
|
process.env.TESTOMATIO_PRIVATE_ARTIFACTS ? 'privately' : chalk.bold('publicly')
|
|
247
|
-
} uploaded to S3 bucket
|
|
244
|
+
} uploaded to S3 bucket`,
|
|
248
245
|
);
|
|
249
246
|
}
|
|
250
247
|
})
|
package/lib/constants.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const path = require('path');
|
|
2
4
|
|
|
3
5
|
const APP_PREFIX = chalk.gray('[TESTOMATIO]');
|
|
4
|
-
const TESTOMAT_ARTIFACT_SUFFIX = "testomatio_artifact_";
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
mainDir: "testomatio_tmp",
|
|
8
|
-
}
|
|
7
|
+
const TESTOMAT_TMP_STORAGE_DIR = path.join(os.tmpdir(), 'testomatio_tmp');
|
|
9
8
|
|
|
10
9
|
const CSV_HEADERS = [
|
|
11
10
|
{ id: 'suite_title', title: 'Suite_title' },
|
|
@@ -24,8 +23,7 @@ const STATUS = {
|
|
|
24
23
|
|
|
25
24
|
module.exports = {
|
|
26
25
|
APP_PREFIX,
|
|
27
|
-
|
|
28
|
-
TESTOMAT_TMP_STORAGE,
|
|
26
|
+
TESTOMAT_TMP_STORAGE_DIR,
|
|
29
27
|
CSV_HEADERS,
|
|
30
28
|
STATUS,
|
|
31
29
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const logger = require('./storages/logger');
|
|
2
|
+
const artifactStorage = require('./storages/artifact-storage');
|
|
3
|
+
const keyValueStorage = require('./storages/key-value-storage');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Stores path to file as artifact and uploads it to the S3 storage
|
|
7
|
+
* @param {string | {path: string, type: string, name: string}} data - path to file or object with path, type and name
|
|
8
|
+
*/
|
|
9
|
+
function saveArtifact(data, context = null) {
|
|
10
|
+
if (!data) return;
|
|
11
|
+
artifactStorage.put(data, context);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Attach log message(s) to the test report
|
|
16
|
+
* @param {...any} args
|
|
17
|
+
*/
|
|
18
|
+
function logMessage(...args) {
|
|
19
|
+
logger.log(...args);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Similar to "log" function but marks message in report as a step
|
|
24
|
+
* @param {*} message
|
|
25
|
+
*/
|
|
26
|
+
function addStep(message) {
|
|
27
|
+
logger.step(message);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Add key-value pair(s) to the test report
|
|
32
|
+
* @param {*} keyValue
|
|
33
|
+
*/
|
|
34
|
+
function setKeyValue(keyValue) {
|
|
35
|
+
keyValueStorage.put(keyValue);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
artifact: saveArtifact,
|
|
40
|
+
log: logMessage,
|
|
41
|
+
step: addStep,
|
|
42
|
+
keyValue: setKeyValue,
|
|
43
|
+
};
|
package/lib/reporter.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const logger = require('./logger');
|
|
1
|
+
const logger = require('./storages/logger');
|
|
2
2
|
const TestomatClient = require('./client');
|
|
3
3
|
const TRConstants = require('./constants');
|
|
4
|
-
const TRArtifacts = require('./_ArtifactStorageOld');
|
|
5
4
|
|
|
6
5
|
const log = logger.templateLiteralLog.bind(logger);
|
|
7
6
|
const step = logger.step.bind(logger);
|
|
7
|
+
const reporterFunctions = require('./reporter-functions');
|
|
8
8
|
|
|
9
9
|
module.exports = {
|
|
10
10
|
logger,
|
|
@@ -13,6 +13,11 @@ module.exports = {
|
|
|
13
13
|
step,
|
|
14
14
|
TestomatClient,
|
|
15
15
|
TRConstants,
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
module.exports.testomat = {
|
|
19
|
+
artifact: reporterFunctions.artifact,
|
|
20
|
+
log: reporterFunctions.log,
|
|
21
|
+
step: reporterFunctions.step,
|
|
22
|
+
meta: reporterFunctions.keyValue,
|
|
18
23
|
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const debug = require('debug')('@testomatio/reporter:artifact-storage');
|
|
2
|
+
const DataStorage = require('./data-storage');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Artifact storage is supposed to store file paths
|
|
6
|
+
*/
|
|
7
|
+
class ArtifactStorage {
|
|
8
|
+
|
|
9
|
+
// there is autocompletion for the class methods if implemented singleton this way
|
|
10
|
+
constructor() {
|
|
11
|
+
this.dataStorage = new DataStorage('artifact');
|
|
12
|
+
|
|
13
|
+
// singleton
|
|
14
|
+
if (!ArtifactStorage.instance) {
|
|
15
|
+
ArtifactStorage.instance = this;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// singleton
|
|
20
|
+
static getInstance() {
|
|
21
|
+
if (!ArtifactStorage.instance) {
|
|
22
|
+
ArtifactStorage.instance = new ArtifactStorage();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return ArtifactStorage.instance;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Stores path to file as artifact and uploads it to the S3 storage
|
|
30
|
+
* @param {string | {path: string, type: string, name: string}} data - path to file or object with path, type and name
|
|
31
|
+
* @param {*} context testId or test title
|
|
32
|
+
*/
|
|
33
|
+
put(data, context = null) {
|
|
34
|
+
if (!data) return;
|
|
35
|
+
debug('Save artifact:', data);
|
|
36
|
+
this.dataStorage.putData(data, context);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Returns list of artifacts to upload
|
|
41
|
+
* @param {*} context testId or test context from test runner
|
|
42
|
+
* @returns {string | {path: string, type: string, name: string}[]}
|
|
43
|
+
*/
|
|
44
|
+
get(context) {
|
|
45
|
+
if (!context) return null;
|
|
46
|
+
|
|
47
|
+
// array of any data
|
|
48
|
+
let artifacts = this.dataStorage.getData(context);
|
|
49
|
+
if (!artifacts || !artifacts.length) return null;
|
|
50
|
+
|
|
51
|
+
artifacts = artifacts.map(artifactData => {
|
|
52
|
+
// artifact could be an object ({type, path, name} props) or string
|
|
53
|
+
let artifact;
|
|
54
|
+
try {
|
|
55
|
+
artifact = JSON.parse(artifactData);
|
|
56
|
+
} catch (e) {
|
|
57
|
+
artifact = artifactData;
|
|
58
|
+
}
|
|
59
|
+
return artifact;
|
|
60
|
+
});
|
|
61
|
+
artifacts = artifacts.filter(artifact => !!artifact);
|
|
62
|
+
return artifacts.length ? artifacts : null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
ArtifactStorage.instance = null;
|
|
67
|
+
|
|
68
|
+
// const artifactStorage = ArtifactStorage.getInstance();
|
|
69
|
+
const artifactStorage = new ArtifactStorage();
|
|
70
|
+
module.exports = artifactStorage;
|