@testomatio/reporter 1.1.1-beta-codecept-logger → 1.1.1-file-upload.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/lib/client.js CHANGED
@@ -27,6 +27,7 @@ class Client {
27
27
  this.pipes = pipesFactory(params, store);
28
28
  this.queue = Promise.resolve();
29
29
  this.totalUploaded = 0;
30
+ this.failedToUpload = 0;
30
31
  this.version = JSON.parse(fs.readFileSync(join(__dirname, '..', 'package.json')).toString()).version;
31
32
  this.executionList = Promise.resolve();
32
33
 
@@ -130,9 +131,12 @@ class Client {
130
131
  steps,
131
132
  code = null,
132
133
  title,
134
+ file,
133
135
  suite_title,
134
136
  suite_id,
135
137
  test_id,
138
+ manuallyAttachedArtifacts,
139
+ meta,
136
140
  } = testData;
137
141
  let { message = '' } = testData;
138
142
 
@@ -146,18 +150,13 @@ class Client {
146
150
  // Attach logs
147
151
  const fullLogs = this.formatLogs({ error: errorFormatted, steps, logs: testData.logs });
148
152
 
149
- // GET ARTIFACTS from storage
150
- // const artifactFiles = artifactStorage.get(test_id);
151
- // if (artifactFiles) files.push(...artifactFiles);
153
+ // add artifacts
154
+ if (manuallyAttachedArtifacts?.length) files.push(...manuallyAttachedArtifacts);
152
155
 
153
- // // GET KEY-VALUEs from storage
154
- // const keyValueStorage = require('./storages/key-value-storage');
155
- // const keyValues = keyValueStorage.get(test_id);
156
-
157
156
  const uploadedFiles = [];
158
157
 
159
- for (const file of files) {
160
- uploadedFiles.push(upload.uploadFileByPath(file, this.uuid));
158
+ for (const f of files) {
159
+ uploadedFiles.push(upload.uploadFileByPath(f, this.uuid));
161
160
  }
162
161
 
163
162
  for (const [idx, buffer] of filesBuffers.entries()) {
@@ -165,11 +164,14 @@ class Client {
165
164
  uploadedFiles.push(upload.uploadFileAsBuffer(buffer, fileName, this.uuid));
166
165
  }
167
166
 
168
- const artifacts = await Promise.all(uploadedFiles);
167
+ const artifacts = (await Promise.all(uploadedFiles)).filter(n => !!n);
169
168
 
170
- // global.testomatioArtifacts = [];
169
+ if (artifacts.length < uploadedFiles.length) {
170
+ const failedUploading = uploadedFiles.length - artifacts.length;
171
+ this.failedToUpload += failedUploading;
172
+ }
171
173
 
172
- this.totalUploaded += uploadedFiles.filter(n => n).length;
174
+ this.totalUploaded += artifacts.length;
173
175
 
174
176
  const data = {
175
177
  files,
@@ -177,6 +179,7 @@ class Client {
177
179
  status,
178
180
  stack: fullLogs,
179
181
  example,
182
+ file,
180
183
  code,
181
184
  title,
182
185
  suite_title,
@@ -185,7 +188,7 @@ class Client {
185
188
  message,
186
189
  run_time: parseFloat(time),
187
190
  artifacts,
188
- // meta: keyValues,
191
+ meta,
189
192
  };
190
193
 
191
194
  debug('Adding test run...', data);
@@ -234,6 +237,16 @@ class Client {
234
237
  process.env.TESTOMATIO_PRIVATE_ARTIFACTS ? 'privately' : chalk.bold('publicly')
235
238
  } uploaded to S3 bucket`,
236
239
  );
240
+
241
+ if (this.failedToUpload > 0) {
242
+ console.log(
243
+ APP_PREFIX,
244
+ chalk.yellow(
245
+ `Some artifacts were not uploaded. ${this.failedToUpload} artifacts could not be uploaded. Run tests with DEBUG="@testomatio/reporter:file-uploader" to see details"`,
246
+ ),
247
+ );
248
+ }
249
+
237
250
  }
238
251
  })
239
252
  .catch(err => console.log(APP_PREFIX, err));
@@ -251,9 +264,9 @@ class Client {
251
264
  logs = logs?.trim();
252
265
 
253
266
  let testLogs = '';
254
- if (steps) testLogs += `${chalk.bold.blue('################[ Steps ]################')}\n${steps}`;
255
- if (logs) testLogs += `\n\n${chalk.bold.gray('################[ Logs ]################')}\n${logs}`;
256
- if (error) testLogs += `\n\n${chalk.bold.red('################[ Failure ]################')}\n${error}`;
267
+ if (steps) testLogs += `${chalk.bold.blue('################[ Steps ]################')}\n${steps}\n\n`;
268
+ if (logs) testLogs += `${chalk.bold.gray('################[ Logs ]################')}\n${logs}\n\n`;
269
+ if (error) testLogs += `${chalk.bold.red('################[ Failure ]################')}\n${error}`;
257
270
  return testLogs;
258
271
  }
259
272
 
@@ -296,6 +309,7 @@ class Client {
296
309
 
297
310
  function isNotInternalFrame(frame) {
298
311
  return (
312
+ frame.getFileName() &&
299
313
  frame.getFileName().includes(sep) &&
300
314
  !frame.getFileName().includes('node_modules') &&
301
315
  !frame.getFileName().includes('internal')
package/lib/config.js CHANGED
@@ -8,6 +8,10 @@ const debug = require('debug')('@testomatio/reporter:config');
8
8
  const dotenv = require('dotenv');
9
9
  const envFileVars = dotenv.config({ path: '.env' }).parsed; */
10
10
 
11
+ const TESTOMATIO = process.env.TESTOMATIO || process.env.TESTOMATIO_API_KEY || process.env.TESTOMATIO_TOKEN || '';
12
+ if (TESTOMATIO === 'undefined') console.error('TESTOMATIO is "undefined". Something went wrong. Contact dev team.');
13
+ process.env.TESTOMATIO = TESTOMATIO;
14
+
11
15
  // select only TESTOMATIO related variables (only to print them in debug)
12
16
  const testomatioEnvVars =
13
17
  Object.keys(process.env)
@@ -22,3 +26,4 @@ debug('TESTOMATIO variables:', testomatioEnvVars);
22
26
  const config = process.env;
23
27
 
24
28
  module.exports = config;
29
+ module.exports.TESTOMATIO = TESTOMATIO;
@@ -3,25 +3,38 @@ 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 } = require('../utils/utils');
6
+ const { TESTOMAT_TMP_STORAGE_DIR } = require('./constants');
7
+ const { fileSystem, jestHelpers } = require('./utils/utils');
8
8
 
9
9
  class DataStorage {
10
+ static #instance;
11
+
12
+ context;
13
+
14
+ /**
15
+ *
16
+ * @returns {DataStorage}
17
+ */
18
+ static getInstance() {
19
+ if (!this.#instance) {
20
+ this.#instance = new DataStorage();
21
+ }
22
+ return this.#instance;
23
+ }
24
+
25
+ setContext(context) {
26
+ this.context = context;
27
+ }
28
+
10
29
  /**
11
- * Creates data storage instance for specific data type.
12
- * Stores data to global variable or to file depending on what is applicable for current test runner
30
+ * Creates data storage instance as singleton
31
+ * Stores data to global variable or to file depending on what is applicable for current test runner (adapter)
13
32
  * Recommend to use composition while using this class (instead of inheritance).
14
33
  * ! Also the class which will use data storage should be singleton (to avoid data loss).
15
- * But the data storage itself is not singleton. It will have an instance per data type.
16
- * @param {'log' | 'artifact' | 'keyvalue'} dataType – type of data to store
17
34
  */
18
- constructor(dataType) {
19
- this.dataType = dataType || 'data';
20
-
35
+ constructor() {
21
36
  // some frameworks use global variable to store data, some use file storage
22
37
  this.isFileStorage = true;
23
-
24
- this.dataDirPath = path.join(TESTOMAT_TMP_STORAGE_DIR, this.dataType);
25
38
  }
26
39
 
27
40
  #stringToFilename(str) {
@@ -37,23 +50,28 @@ class DataStorage {
37
50
  /**
38
51
  * Puts any data to storage (file or global variable).
39
52
  * If file: stores data as text, if global variable – stores as array of data.
53
+ * @param {'log' | 'artifact' | 'keyvalue'} dataType
40
54
  * @param {*} data anything you want to store (string, object, array, etc)
41
55
  * @param {*} context could be testId or any context (test name, suite name, including their IDs etc)
42
56
  * suite name + test name is used by default
43
57
  * @returns
44
58
  */
45
- putData(data, context = null) {
46
- fileSystem.createDir(this.dataDirPath);
59
+ putData(dataType, data, context = null) {
60
+ if (!dataType || !data) return;
61
+
62
+ context = context || this.context || global.testomatioTestTitle || jestHelpers.getIdOfCurrentlyRunningTest();
47
63
  if (!context) {
48
- debug(`No context provided for "${this.dataType}" data:`, data);
64
+ debug(`No context provided for "${dataType}" data:`, data);
49
65
  return;
50
66
  }
51
67
  context = this.#stringToFilename(context);
52
68
 
53
69
  if (this.isFileStorage) {
54
- this.#putDataToFile(data, context);
70
+ const dataDirPath = path.join(TESTOMAT_TMP_STORAGE_DIR, dataType);
71
+ fileSystem.createDir(dataDirPath);
72
+ this.#putDataToFile(dataType, data, context);
55
73
  } else {
56
- this.#putDataToGlobalVar(data, context);
74
+ this.#putDataToGlobalVar(dataType, data, context);
57
75
  }
58
76
  }
59
77
 
@@ -61,12 +79,16 @@ class DataStorage {
61
79
  * Returns data, stored for specific test/context (or data which was stored without test id specified).
62
80
  * This method will get data from global variable and/or from from file (previosly saved with put method).
63
81
  *
82
+ * @param {'log' | 'artifact' | 'keyvalue'} dataType
64
83
  * @param {string} context
65
- * @returns {any []} of data (any type), null (if no data found for test) or string (if data type is log)
84
+ * @returns {any []} array of data (any type), null (if no data found for context) or string (if data type is log)
66
85
  */
67
- getData(context) {
86
+ getData(dataType, context) {
87
+ // TODO: think if it could be useful
88
+ // context = context || this.context || global.testomatioTestTitle || jestHelpers.getIdOfCurrentlyRunningTest();
89
+
68
90
  if (!context) {
69
- debug(`No context passed`, context);
91
+ debug(`Trying to get "${dataType}" data without context`);
70
92
  return null;
71
93
  }
72
94
 
@@ -76,36 +98,37 @@ class DataStorage {
76
98
  let testDataFromGlobalVar = [];
77
99
 
78
100
  if (global?.testomatioDataStore) {
79
- testDataFromGlobalVar = this.#getDataFromGlobalVar(context);
101
+ testDataFromGlobalVar = this.#getDataFromGlobalVar(dataType, context);
80
102
  if (testDataFromGlobalVar) {
81
103
  if (testDataFromGlobalVar.length) return testDataFromGlobalVar;
82
104
  }
83
105
  // don't return nothing if no data in global variable
84
106
  }
85
107
 
86
- testDataFromFile = this.#getDataFromFile(context);
108
+ testDataFromFile = this.#getDataFromFile(dataType, context);
87
109
 
88
110
  if (testDataFromFile.length) {
89
111
  return testDataFromFile;
90
112
  }
91
- debug(`No "${this.dataType}" data for test id ${context} in both file and global variable`);
113
+ debug(`No "${dataType}" data for context "${context}" in both file and global variable`);
92
114
 
93
- // in case no data found for test
115
+ // in case no data found for context
94
116
  return null;
95
117
  }
96
118
 
97
119
  /**
120
+ * @param {'log' | 'artifact' | 'keyvalue'} dataType
98
121
  * @param {string} context
99
122
  * @returns aray of data (any type)
100
123
  */
101
- #getDataFromGlobalVar(context) {
124
+ #getDataFromGlobalVar(dataType, context) {
102
125
  try {
103
- if (global?.testomatioDataStore[this.dataType]) {
104
- const testData = global.testomatioDataStore[this.dataType][context];
105
- if (testData) debug(`"${this.dataType}" data for test id ${context}:`, testData.join(', '));
126
+ if (global?.testomatioDataStore[dataType]) {
127
+ const testData = global.testomatioDataStore[dataType][context];
128
+ if (testData) debug(`"${dataType}" data for constext "${context}":`, testData.join(', '));
106
129
  return testData || [];
107
130
  }
108
- // debug(`No ${this.dataType} data for test context ${context} in <global> storage`);
131
+ // debug(`No ${this.dataType} data for context ${context} in <global> storage`);
109
132
  return [];
110
133
  } catch (e) {
111
134
  // there could be no data, ignore
@@ -113,20 +136,21 @@ class DataStorage {
113
136
  }
114
137
 
115
138
  /**
116
- *
139
+ * @param {'log' | 'artifact' | 'keyvalue'} dataType
117
140
  * @param {*} context
118
141
  * @returns array of data (any type)
119
142
  */
120
- #getDataFromFile(context) {
143
+ #getDataFromFile(dataType, context) {
144
+ const dataDirPath = path.join(TESTOMAT_TMP_STORAGE_DIR, dataType);
121
145
  try {
122
- const filepath = join(this.dataDirPath, `${this.dataType}_${context}`);
146
+ const filepath = join(dataDirPath, `${dataType}_${context}`);
123
147
  if (fs.existsSync(filepath)) {
124
148
  const testDataAsText = fs.readFileSync(filepath, 'utf-8');
125
- if (testDataAsText) debug(`"${this.dataType}" data for test id ${context}:`, testDataAsText);
149
+ if (testDataAsText) debug(`"${dataType}" data for context "${context}":`, testDataAsText);
126
150
  const testDataArr = testDataAsText?.split(os.EOL) || [];
127
151
  return testDataArr;
128
152
  }
129
- // debug(`No ${this.dataType} data for test ${context} in <file> storage`);
153
+ // debug(`No ${this.dataType} data for ${context} in <file> storage`);
130
154
  return [];
131
155
  } catch (e) {
132
156
  // there could be no data, ignore
@@ -136,24 +160,33 @@ class DataStorage {
136
160
 
137
161
  /**
138
162
  * Puts data to global variable. Unlike the file storage, stores data in array (file storage just append as string).
163
+ * @param {'log' | 'artifact' | 'keyvalue'} dataType
139
164
  * @param {*} data
140
165
  * @param {*} context
141
166
  */
142
- #putDataToGlobalVar(data, context) {
167
+ #putDataToGlobalVar(dataType, data, context) {
143
168
  debug('Saving data to global variable for ', context, ':', data);
144
169
  if (!global.testomatioDataStore) global.testomatioDataStore = {};
145
- if (!global.testomatioDataStore?.[this.dataType]) global.testomatioDataStore[this.dataType] = {};
170
+ if (!global.testomatioDataStore?.[dataType]) global.testomatioDataStore[dataType] = {};
146
171
 
147
- if (!global.testomatioDataStore?.[this.dataType][context]) global.testomatioDataStore[this.dataType][context] = [];
148
- global.testomatioDataStore[this.dataType][context].push(data);
172
+ if (!global.testomatioDataStore?.[dataType][context]) global.testomatioDataStore[dataType][context] = [];
173
+ global.testomatioDataStore[dataType][context].push(data);
149
174
  }
150
175
 
151
- #putDataToFile(data, context) {
176
+ /**
177
+ * Puts data to file. Unlike the global variable storage, stores data as string
178
+ * @param {'log' | 'artifact' | 'keyvalue'} dataType
179
+ * @param {*} data
180
+ * @param {string} context
181
+ * @returns
182
+ */
183
+ #putDataToFile(dataType, data, context) {
184
+ const dataDirPath = path.join(TESTOMAT_TMP_STORAGE_DIR, dataType);
152
185
  if (typeof data !== 'string') data = JSON.stringify(data);
153
- const filename = `${this.dataType}_${context}`;
154
- const filepath = join(this.dataDirPath, filename);
155
- if (!fs.existsSync(this.dataDirPath)) fileSystem.createDir(this.dataDirPath);
156
- debug('Saving data to file for', context, 'to', filepath, ':\n', data, '\n');
186
+ const filename = `${dataType}_${context}`;
187
+ const filepath = join(dataDirPath, filename);
188
+ if (!fs.existsSync(dataDirPath)) fileSystem.createDir(dataDirPath);
189
+ debug(`Saving data to file for context "${context}" to ${filepath}. Data: ${JSON.stringify(data)}`);
157
190
 
158
191
  // append new line if file already exists (in this case its definitely includes some data)
159
192
  if (fs.existsSync(filepath)) {
@@ -164,7 +197,7 @@ class DataStorage {
164
197
  }
165
198
  }
166
199
 
167
- module.exports = DataStorage;
200
+ module.exports.dataStorage = DataStorage.getInstance();
168
201
 
169
202
  // TODO: consider using fs promises instead of writeSync/appendFileSync to
170
203
  // prevent blocking and improve performance (probably queue usage will be required)
@@ -11,7 +11,6 @@ const readFile = util.promisify(fs.readFile);
11
11
  const stat = util.promisify(fs.stat);
12
12
  const chalk = require('chalk');
13
13
  const { randomUUID } = require('crypto');
14
- const memoize = require('lodash.memoize');
15
14
 
16
15
  const { APP_PREFIX } = require('./constants');
17
16
 
@@ -146,8 +145,13 @@ const uploadUsingS3 = async (filePath, runId) => {
146
145
  params
147
146
  });
148
147
 
149
- return await getS3LocationLink(out);
150
- }
148
+
149
+ const link = await getS3LocationLink(out);
150
+
151
+ debug(`Succesfully uploaded ${filePath} => ${S3_BUCKET}/${Key} | URL: ${link}`);
152
+
153
+ return link;
154
+ }
151
155
  catch (e) {
152
156
  debug('S3 file uploading error: ', e);
153
157
 
@@ -279,8 +283,6 @@ const getS3LocationLink = async (out) => {
279
283
 
280
284
  let s3Location = response?.Location;
281
285
 
282
- debug('Uploaded response.Location', s3Location);
283
-
284
286
  if (!s3Location) {
285
287
  // TODO: out: a fallback case - remove after deeper testing
286
288
  s3Location = out?.singleUploadResult?.Location;
@@ -295,8 +297,8 @@ const getS3LocationLink = async (out) => {
295
297
  };
296
298
 
297
299
  module.exports = {
298
- uploadFileByPath: memoize(uploadFileByPath),
299
- uploadFileAsBuffer: memoize(uploadFileAsBuffer),
300
+ uploadFileByPath,
301
+ uploadFileAsBuffer,
300
302
  isArtifactsEnabled,
301
303
  resetConfig,
302
304
  };
@@ -6,8 +6,7 @@ const RubyAdapter = require('./ruby');
6
6
  const CSharpAdapter = require('./csharp');
7
7
 
8
8
  function AdapterFactory(lang, opts) {
9
- if (!lang) return new Adapter(opts);
10
-
9
+
11
10
  if (lang === 'java') {
12
11
  return new JavaAdapter(opts);
13
12
  }
@@ -23,6 +22,8 @@ function AdapterFactory(lang, opts) {
23
22
  if (lang === 'c#' || lang === 'csharp') {
24
23
  return new CSharpAdapter(opts);
25
24
  }
25
+
26
+ return new Adapter(opts);
26
27
  }
27
28
 
28
29
  module.exports = AdapterFactory;
@@ -5,6 +5,7 @@ const JsonCycle = require('json-cycle');
5
5
  const { APP_PREFIX, STATUS } = require('../constants');
6
6
  const { isValidUrl, foundedTestLog } = require('../utils/utils');
7
7
  const { parseFilterParams, generateFilterRequestParams, setS3Credentials, } = require('../utils/pipe_utils');
8
+ const { TESTOMATIO } = require('../config');
8
9
 
9
10
  if (process.env.TESTOMATIO_RUN) {
10
11
  process.env.runId = process.env.TESTOMATIO_RUN;
@@ -20,7 +21,7 @@ class TestomatioPipe {
20
21
  constructor(params, store) {
21
22
  this.isEnabled = false;
22
23
  this.url = params.testomatioUrl || process.env.TESTOMATIO_URL || 'https://app.testomat.io';
23
- this.apiKey = params.apiKey || process.env.TESTOMATIO;
24
+ this.apiKey = params.apiKey || TESTOMATIO;
24
25
  debug('Testomatio Pipe: ', this.apiKey ? 'API KEY' : '*no api key*');
25
26
  if (!this.apiKey) {
26
27
  return;
@@ -175,13 +176,14 @@ class TestomatioPipe {
175
176
  * @returns
176
177
  */
177
178
  addTest(data) {
178
- debug('Adding test...');
179
179
  if (!this.isEnabled) return;
180
180
  if (!this.runId) return;
181
181
  data.api_key = this.apiKey;
182
182
  data.create = this.createNewTests;
183
183
  const json = JsonCycle.stringify(data);
184
184
 
185
+ debug('Adding test', json);
186
+
185
187
  return this.axios.post(`/api/reporter/${this.runId}/testrun`, json, {
186
188
  maxContentLength: Infinity,
187
189
  maxBodyLength: Infinity,
@@ -1,6 +1,9 @@
1
- const { logger } = require('./storages/logger');
2
- const { artifactStorage } = require('./storages/artifact-storage');
3
- const { keyValueStorage } = require('./storages/key-value-storage');
1
+ const { services } = require('./services');
2
+ const { initPlaywrightForStorage } = require('./adapter/playwright');
3
+
4
+ if (process.env.PLAYWRIGHT_TEST_BASE_URL) {
5
+ initPlaywrightForStorage();
6
+ }
4
7
 
5
8
  /**
6
9
  * Stores path to file as artifact and uploads it to the S3 storage
@@ -8,7 +11,7 @@ const { keyValueStorage } = require('./storages/key-value-storage');
8
11
  */
9
12
  function saveArtifact(data, context = null) {
10
13
  if (!data) return;
11
- artifactStorage.put(data, context);
14
+ services.artifacts.put(data, context);
12
15
  }
13
16
 
14
17
  /**
@@ -16,7 +19,7 @@ function saveArtifact(data, context = null) {
16
19
  * @param {...any} args
17
20
  */
18
21
  function logMessage(...args) {
19
- logger.log(...args);
22
+ services.logger.templateLiteralLog(...args);
20
23
  }
21
24
 
22
25
  /**
@@ -24,7 +27,7 @@ function logMessage(...args) {
24
27
  * @param {*} message
25
28
  */
26
29
  function addStep(message) {
27
- logger.step(message);
30
+ services.logger.step(message);
28
31
  }
29
32
 
30
33
  /**
@@ -32,17 +35,7 @@ function addStep(message) {
32
35
  * @param {*} keyValue
33
36
  */
34
37
  function setKeyValue(keyValue) {
35
- keyValueStorage.put(keyValue);
36
- }
37
-
38
- /**
39
- *
40
- * @param {string} context – test id or test title or suite title + test title
41
- */
42
- function _setContext(context) {
43
- logger.setContext(context);
44
- keyValueStorage.setContext(context);
45
- artifactStorage.setContext(context);
38
+ services.keyValues.put(keyValue);
46
39
  }
47
40
 
48
41
  module.exports = {
@@ -50,5 +43,4 @@ module.exports = {
50
43
  log: logMessage,
51
44
  step: addStep,
52
45
  keyValue: setKeyValue,
53
- _setContext,
54
46
  };
package/lib/reporter.js CHANGED
@@ -1,24 +1,19 @@
1
- const { logger } = require('./storages/logger');
2
1
  const TestomatClient = require('./client');
3
2
  const TRConstants = require('./constants');
4
3
 
5
- const log = logger.templateLiteralLog.bind(logger);
6
- const step = logger.step.bind(logger);
7
4
  const reporterFunctions = require('./reporter-functions');
8
5
 
9
6
  module.exports = {
10
- logger,
11
- testomatioLogger: logger,
12
- log,
13
- step,
14
- TestomatClient,
15
- TRConstants,
16
- };
7
+ // TODO: deprecate in future; use log or testomat.log
8
+ logger: reporterFunctions.log,
9
+ testomatioLogger: reporterFunctions.log,
17
10
 
18
- module.exports.testomat = {
19
11
  artifact: reporterFunctions.artifact,
20
12
  log: reporterFunctions.log,
21
- step: reporterFunctions.step,
22
13
  meta: reporterFunctions.keyValue,
23
- _setContext: reporterFunctions._setContext,
14
+ step: reporterFunctions.step,
15
+
16
+ TestomatClient,
17
+ TRConstants,
24
18
  };
19
+
@@ -1,5 +1,5 @@
1
- const debug = require('debug')('@testomatio/reporter:artifact-storage');
2
- const DataStorage = require('./data-storage');
1
+ const debug = require('debug')('@testomatio/reporter:services-artifacts');
2
+ const { dataStorage } = require('../data-storage');
3
3
 
4
4
  /**
5
5
  * Artifact storage is supposed to store file paths
@@ -7,18 +7,6 @@ const DataStorage = require('./data-storage');
7
7
  class ArtifactStorage {
8
8
  static #instance;
9
9
 
10
- #context;
11
-
12
- // there is autocompletion for the class methods if implemented singleton this way
13
- constructor() {
14
- this.dataStorage = new DataStorage('artifact');
15
-
16
- // singleton
17
- if (!ArtifactStorage.#instance) {
18
- ArtifactStorage.#instance = this;
19
- }
20
- }
21
-
22
10
  /**
23
11
  * Singleton
24
12
  * @returns {ArtifactStorage}
@@ -30,39 +18,28 @@ class ArtifactStorage {
30
18
  return this.#instance;
31
19
  }
32
20
 
33
- /**
34
- * @param {string} context - suite title + test title
35
- */
36
- setContext(context) {
37
- this.#context = context;
38
- }
39
-
40
21
  /**
41
22
  * Stores path to file as artifact and uploads it to the S3 storage
42
23
  * @param {string | {path: string, type: string, name: string}} data - path to file or object with path, type and name
43
24
  * @param {*} context testId or test title
44
25
  */
45
26
  put(data, context = null) {
46
- context = context || this.#context;
47
27
  if (!data) return;
48
28
  debug('Save artifact:', data);
49
- this.dataStorage.putData(data, context);
29
+ dataStorage.putData('artifact', data, context);
50
30
  }
51
31
 
52
32
  /**
53
33
  * Returns list of artifacts to upload
54
34
  * @param {*} context testId or test context from test runner
55
- * @returns {string | {path: string, type: string, name: string}[]}
35
+ * @returns {(string | {path: string, type: string, name: string})[]}
56
36
  */
57
37
  get(context) {
58
- if (!context) return null;
59
-
60
- // array of any data
61
- let artifacts = this.dataStorage.getData(context);
62
- if (!artifacts || !artifacts.length) return null;
38
+ let artifacts = dataStorage.getData('artifact', context);
39
+ if (!artifacts || !artifacts.length) return [];
63
40
 
64
41
  artifacts = artifacts.map(artifactData => {
65
- // artifact could be an object ({type, path, name} props) or string
42
+ // artifact could be an object ({type, path, name} props) or string (just path)
66
43
  let artifact;
67
44
  try {
68
45
  artifact = JSON.parse(artifactData);
@@ -72,7 +49,8 @@ class ArtifactStorage {
72
49
  return artifact;
73
50
  });
74
51
  artifacts = artifacts.filter(artifact => !!artifact);
75
- return artifacts.length ? artifacts : null;
52
+ debug(`Artifacts for test ${context}:`, artifacts);
53
+ return artifacts.length ? artifacts : [];
76
54
  }
77
55
  }
78
56
 
@@ -0,0 +1,13 @@
1
+ const { logger } = require('./logger');
2
+ const { artifactStorage } = require('./artifacts');
3
+ const { keyValueStorage } = require('./key-values');
4
+ const { dataStorage } = require('../data-storage');
5
+
6
+ module.exports.services = {
7
+ logger,
8
+ artifacts: artifactStorage,
9
+ keyValues: keyValueStorage,
10
+ setContext: context => {
11
+ dataStorage.setContext(context);
12
+ },
13
+ };