@testomatio/reporter 2.0.0-beta-esm → 2.0.0-beta.1-xml

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 (123) hide show
  1. package/lib/adapter/codecept.d.ts +2 -0
  2. package/lib/adapter/codecept.js +31 -26
  3. package/lib/adapter/cucumber/current.d.ts +14 -0
  4. package/lib/adapter/cucumber/legacy.d.ts +0 -0
  5. package/lib/adapter/cucumber.d.ts +2 -0
  6. package/lib/adapter/cypress-plugin/index.d.ts +2 -0
  7. package/lib/adapter/cypress-plugin/index.js +10 -10
  8. package/lib/adapter/jasmine.d.ts +11 -0
  9. package/lib/adapter/jest.d.ts +13 -0
  10. package/lib/adapter/mocha.d.ts +2 -0
  11. package/lib/adapter/mocha.js +4 -4
  12. package/lib/adapter/nightwatch.d.ts +4 -0
  13. package/lib/adapter/nightwatch.js +80 -0
  14. package/lib/adapter/playwright.d.ts +14 -0
  15. package/lib/adapter/playwright.js +58 -33
  16. package/lib/adapter/vitest.d.ts +35 -0
  17. package/lib/adapter/vitest.js +6 -6
  18. package/lib/adapter/webdriver.d.ts +24 -0
  19. package/lib/adapter/webdriver.js +51 -14
  20. package/lib/bin/cli.d.ts +2 -0
  21. package/lib/bin/cli.js +250 -0
  22. package/lib/bin/reportXml.d.ts +2 -0
  23. package/lib/bin/reportXml.js +15 -11
  24. package/lib/bin/startTest.d.ts +2 -0
  25. package/lib/bin/startTest.js +12 -7
  26. package/lib/bin/uploadArtifacts.d.ts +2 -0
  27. package/lib/bin/uploadArtifacts.js +82 -0
  28. package/lib/client.d.ts +76 -0
  29. package/lib/client.js +128 -53
  30. package/lib/config.d.ts +1 -0
  31. package/lib/config.js +2 -2
  32. package/lib/constants.d.ts +25 -0
  33. package/lib/constants.js +5 -1
  34. package/lib/data-storage.d.ts +34 -0
  35. package/lib/data-storage.js +19 -9
  36. package/lib/junit-adapter/adapter.d.ts +9 -0
  37. package/lib/junit-adapter/csharp.d.ts +5 -0
  38. package/lib/junit-adapter/csharp.js +11 -1
  39. package/lib/junit-adapter/index.d.ts +3 -0
  40. package/lib/junit-adapter/java.d.ts +5 -0
  41. package/lib/junit-adapter/javascript.d.ts +4 -0
  42. package/lib/junit-adapter/python.d.ts +5 -0
  43. package/lib/junit-adapter/ruby.d.ts +4 -0
  44. package/lib/output.d.ts +11 -0
  45. package/lib/package.json +3 -1
  46. package/lib/pipe/bitbucket.d.ts +23 -0
  47. package/lib/pipe/bitbucket.js +19 -9
  48. package/lib/pipe/csv.d.ts +47 -0
  49. package/lib/pipe/csv.js +2 -2
  50. package/lib/pipe/debug.d.ts +29 -0
  51. package/lib/pipe/debug.js +108 -0
  52. package/lib/pipe/github.d.ts +30 -0
  53. package/lib/pipe/github.js +37 -5
  54. package/lib/pipe/gitlab.d.ts +23 -0
  55. package/lib/pipe/gitlab.js +2 -3
  56. package/lib/pipe/html.d.ts +35 -0
  57. package/lib/pipe/html.js +9 -4
  58. package/lib/pipe/index.d.ts +1 -0
  59. package/lib/pipe/index.js +20 -10
  60. package/lib/pipe/testomatio.d.ts +70 -0
  61. package/lib/pipe/testomatio.js +54 -39
  62. package/lib/reporter-functions.d.ts +34 -0
  63. package/lib/reporter-functions.js +17 -7
  64. package/lib/reporter.d.ts +232 -0
  65. package/lib/reporter.js +19 -33
  66. package/lib/services/artifacts.d.ts +33 -0
  67. package/lib/services/index.d.ts +9 -0
  68. package/lib/services/key-values.d.ts +27 -0
  69. package/lib/services/key-values.js +1 -1
  70. package/lib/services/logger.d.ts +64 -0
  71. package/lib/services/logger.js +1 -2
  72. package/lib/template/testomatio.hbs +651 -1366
  73. package/lib/uploader.d.ts +60 -0
  74. package/lib/uploader.js +312 -0
  75. package/lib/utils/pipe_utils.d.ts +41 -0
  76. package/lib/utils/pipe_utils.js +3 -5
  77. package/lib/utils/utils.d.ts +47 -0
  78. package/lib/utils/utils.js +99 -12
  79. package/lib/xmlReader.d.ts +92 -0
  80. package/lib/xmlReader.js +64 -25
  81. package/package.json +19 -13
  82. package/src/adapter/codecept.js +30 -26
  83. package/src/adapter/cypress-plugin/index.js +5 -5
  84. package/src/adapter/mocha.cjs +1 -1
  85. package/src/adapter/mocha.js +4 -4
  86. package/src/adapter/nightwatch.js +88 -0
  87. package/src/adapter/playwright.js +59 -31
  88. package/src/adapter/vitest.js +6 -6
  89. package/src/adapter/webdriver.js +42 -12
  90. package/src/bin/cli.js +303 -0
  91. package/src/bin/reportXml.js +19 -9
  92. package/src/bin/startTest.js +9 -4
  93. package/src/bin/uploadArtifacts.js +91 -0
  94. package/src/client.js +137 -57
  95. package/src/config.js +2 -2
  96. package/src/constants.js +5 -1
  97. package/src/data-storage.js +2 -2
  98. package/src/junit-adapter/csharp.js +13 -1
  99. package/src/pipe/bitbucket.js +2 -2
  100. package/src/pipe/csv.js +3 -3
  101. package/src/pipe/debug.js +104 -0
  102. package/src/pipe/github.js +3 -5
  103. package/src/pipe/gitlab.js +6 -7
  104. package/src/pipe/html.js +14 -7
  105. package/src/pipe/index.js +5 -7
  106. package/src/pipe/testomatio.js +75 -76
  107. package/src/reporter-functions.js +18 -7
  108. package/src/reporter.cjs_decprecated +21 -0
  109. package/src/reporter.js +20 -11
  110. package/src/services/key-values.js +1 -1
  111. package/src/services/logger.js +5 -4
  112. package/src/template/testomatio.hbs +651 -1366
  113. package/src/uploader.js +371 -0
  114. package/src/utils/pipe_utils.js +4 -12
  115. package/src/utils/utils.js +64 -15
  116. package/src/xmlReader.js +76 -26
  117. package/lib/adapter/jasmine/jasmine.js +0 -63
  118. package/lib/adapter/mocha/mocha.js +0 -125
  119. package/lib/fileUploader.js +0 -245
  120. package/lib/utils/chalk.js +0 -10
  121. package/src/fileUploader.js +0 -307
  122. package/src/reporter.cjs +0 -22
  123. package/src/utils/chalk.js +0 -13
@@ -15,21 +15,32 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
28
38
  Object.defineProperty(exports, "__esModule", { value: true });
29
- // eslint-disable-next-line
30
39
  const reporter_1 = __importStar(require("@wdio/reporter"));
31
40
  const client_js_1 = __importDefault(require("../client.js"));
32
41
  const utils_js_1 = require("../utils/utils.js");
42
+ const index_js_1 = require("../services/index.js");
43
+ const constants_js_1 = require("../constants.js");
33
44
  class WebdriverReporter extends reporter_1.default {
34
45
  constructor(options) {
35
46
  super(options);
@@ -51,18 +62,30 @@ class WebdriverReporter extends reporter_1.default {
51
62
  this._isSynchronising = true;
52
63
  await Promise.all(this._addTestPromises);
53
64
  this._isSynchronising = false;
54
- // NOTE: new functionality; may break everything
65
+ // NOTE: new functionality; may break everything
55
66
  // also this may require additional status mapping
56
67
  await this.client.updateRunStatus(runData.failures ? 'failed' : 'passed');
57
68
  }
69
+ onRunnerStart() {
70
+ // clear dir with artifacts/logs
71
+ //
72
+ utils_js_1.fileSystem.clearDir(constants_js_1.TESTOMAT_TMP_STORAGE_DIR);
73
+ }
74
+ onTestStart(test) {
75
+ index_js_1.services.setContext(test.fullTitle);
76
+ }
58
77
  onTestEnd(test) {
78
+ test.suite = test.parent;
79
+ const logs = getTestLogs(test.fullTitle);
80
+ // TODO: FIX: artifacts for some reason leads to empty report on Testomat.io
81
+ // const artifacts = services.artifacts.get(test.fullTitle);
82
+ // const keyValues = services.keyValues.get(test.fullTitle);
83
+ test.logs = logs;
84
+ // test.artifacts = artifacts;
85
+ // test.meta = keyValues;
59
86
  this._addTestPromises.push(this.addTest(test));
60
87
  }
61
88
  // wdio-cucumber does not trigger onTestEnd hook, thus, using this one
62
- /**
63
- *
64
- * @returns
65
- */
66
89
  onSuiteEnd(scerario) {
67
90
  if (scerario.type === 'scenario') {
68
91
  this._addTestPromises.push(this.addBddScenario(scerario));
@@ -78,7 +101,10 @@ class WebdriverReporter extends reporter_1.default {
78
101
  .filter(el => el.endpoint === screenshotEndpoint && el.result && el.result.value)
79
102
  .map(el => Buffer.from(el.result.value, 'base64'));
80
103
  await this.client.addTestRun(state, {
104
+ manuallyAttachedArtifacts: test.artifacts,
81
105
  error,
106
+ logs: test.logs,
107
+ meta: test.meta,
82
108
  title,
83
109
  test_id: testId,
84
110
  time: duration,
@@ -86,7 +112,7 @@ class WebdriverReporter extends reporter_1.default {
86
112
  });
87
113
  }
88
114
  /**
89
- * @param {import('../../types').WebdriverIOScenario} scenario
115
+ * @param {import('../../types/types.js').WebdriverIOScenario} scenario
90
116
  */
91
117
  addBddScenario(scenario) {
92
118
  if (!this.client)
@@ -114,4 +140,15 @@ class WebdriverReporter extends reporter_1.default {
114
140
  });
115
141
  }
116
142
  }
143
+ /**
144
+ *
145
+ * @param {*} fullTestTitle
146
+ * @returns string
147
+ */
148
+ function getTestLogs(fullTestTitle) {
149
+ const logsArr = index_js_1.services.logger.getLogs(fullTestTitle);
150
+ // remove duplicates (for some reason, logs are duplicated several times)
151
+ const logs = logsArr ? Array.from(new Set(logsArr)).join('\n').trim() : '';
152
+ return logs;
153
+ }
117
154
  module.exports = WebdriverReporter;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/lib/bin/cli.js ADDED
@@ -0,0 +1,250 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const cross_spawn_1 = require("cross-spawn");
9
+ const glob_1 = require("glob");
10
+ const debug_1 = __importDefault(require("debug"));
11
+ const client_js_1 = __importDefault(require("../client.js"));
12
+ const xmlReader_js_1 = __importDefault(require("../xmlReader.js"));
13
+ const constants_js_1 = require("../constants.js");
14
+ const utils_js_1 = require("../utils/utils.js");
15
+ const config_js_1 = require("../config.js");
16
+ const utils_js_2 = require("../utils/utils.js");
17
+ const picocolors_1 = __importDefault(require("picocolors"));
18
+ const filesize_1 = require("filesize");
19
+ const dotenv_1 = __importDefault(require("dotenv"));
20
+ const debug = (0, debug_1.default)('@testomatio/reporter:xml-cli');
21
+ const version = (0, utils_js_1.getPackageVersion)();
22
+ console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io Reporter v${version}`)));
23
+ const program = new commander_1.Command();
24
+ program
25
+ .version(version)
26
+ .option('--env-file <envfile>', 'Load environment variables from env file')
27
+ .hook('preAction', thisCommand => {
28
+ const opts = thisCommand.opts();
29
+ if (opts.envFile) {
30
+ dotenv_1.default.config({ path: opts.envFile });
31
+ }
32
+ else {
33
+ dotenv_1.default.config();
34
+ }
35
+ });
36
+ program
37
+ .command('start')
38
+ .description('Start a new run and return its ID')
39
+ .action(async () => {
40
+ console.log('Starting a new Run on Testomat.io...');
41
+ const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
42
+ const client = new client_js_1.default({ apiKey });
43
+ client.createRun().then(() => {
44
+ console.log(process.env.runId);
45
+ process.exit(0);
46
+ });
47
+ });
48
+ program
49
+ .command('finish')
50
+ .description('Finish Run by its ID')
51
+ .action(async () => {
52
+ process.env.TESTOMATIO_RUN ||= (0, utils_js_2.readLatestRunId)();
53
+ if (!process.env.TESTOMATIO_RUN) {
54
+ console.log('TESTOMATIO_RUN environment variable must be set or restored from a previous run.');
55
+ return process.exit(1);
56
+ }
57
+ console.log('Finishing Run on Testomat.io...');
58
+ const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
59
+ const client = new client_js_1.default({ apiKey });
60
+ // @ts-ignore
61
+ client.updateRunStatus(constants_js_1.STATUS.FINISHED).then(() => {
62
+ console.log(picocolors_1.default.yellow(`Run ${process.env.TESTOMATIO_RUN} was finished`));
63
+ process.exit(0);
64
+ });
65
+ });
66
+ program
67
+ .command('run')
68
+ .description('Run tests with the specified command')
69
+ .argument('<command>', 'Test runner command')
70
+ .option('--filter <filter>', 'Additional execution filter')
71
+ .action(async (command, opts) => {
72
+ const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
73
+ const title = process.env.TESTOMATIO_TITLE;
74
+ if (!command || !command.split) {
75
+ console.log(constants_js_1.APP_PREFIX, `No command provided. Use -c option to launch a test runner.`);
76
+ return process.exit(255);
77
+ }
78
+ const client = new client_js_1.default({ apiKey, title, parallel: true });
79
+ if (opts.filter) {
80
+ const [pipe, ...optsArray] = opts.filter.split(':');
81
+ const pipeOptions = optsArray.join(':');
82
+ try {
83
+ const tests = await client.prepareRun({ pipe, pipeOptions });
84
+ if (tests && tests.length > 0) {
85
+ command += ` --grep (${tests.join('|')})`;
86
+ }
87
+ }
88
+ catch (err) {
89
+ console.log(constants_js_1.APP_PREFIX, err);
90
+ }
91
+ }
92
+ console.log(constants_js_1.APP_PREFIX, `🚀 Running`, picocolors_1.default.green(command));
93
+ const runTests = () => {
94
+ const testCmds = command.split(' ');
95
+ const cmd = (0, cross_spawn_1.spawn)(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
96
+ cmd.on('close', code => {
97
+ const emoji = code === 0 ? '🟢' : '🔴';
98
+ console.log(constants_js_1.APP_PREFIX, emoji, `Runner exited with ${picocolors_1.default.bold(code)}`);
99
+ if (apiKey) {
100
+ const status = code === 0 ? 'passed' : 'failed';
101
+ client.updateRunStatus(status, true);
102
+ }
103
+ process.exit(code);
104
+ });
105
+ };
106
+ if (apiKey) {
107
+ client.createRun().then(runTests);
108
+ }
109
+ else {
110
+ runTests();
111
+ }
112
+ });
113
+ // program
114
+ // .command('xml')
115
+ // .description('Parse XML reports and upload to Testomat.io')
116
+ // .argument('<pattern>', 'XML file pattern')
117
+ // .option('-d, --dir <dir>', 'Project directory')
118
+ // .option('--java-tests [java-path]', 'Load Java tests from path, by default: src/test/java')
119
+ // .option('--lang <lang>', 'Language used (python, ruby, java)')
120
+ // .option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
121
+ // .action(async (pattern, opts) => {
122
+ // if (!pattern.endsWith('.xml')) {
123
+ // pattern += '.xml';
124
+ // }
125
+ // let { javaTests, lang } = opts;
126
+ // if (javaTests === true) javaTests = 'src/test/java';
127
+ // lang = lang?.toLowerCase();
128
+ // const runReader = new XmlReader({ javaTests, lang });
129
+ // const files = glob.sync(pattern, { cwd: opts.dir || process.cwd() });
130
+ // if (!files.length) {
131
+ // console.log(APP_PREFIX, `Report can't be created. No XML files found 😥`);
132
+ // process.exit(1);
133
+ // }
134
+ program
135
+ .command('xml')
136
+ .description('Parse XML reports and upload to Testomat.io')
137
+ .argument('<pattern>', 'XML file pattern')
138
+ .option('-d, --dir <dir>', 'Project directory')
139
+ .option('--java-tests [java-path]', 'Load Java tests from path, by default: src/test/java')
140
+ .option('--lang <lang>', 'Language used (python, ruby, java)')
141
+ .option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
142
+ .action(async (pattern, opts) => {
143
+ if (!pattern.endsWith('.xml')) {
144
+ pattern += '.xml';
145
+ }
146
+ let { javaTests, lang } = opts;
147
+ if (javaTests === true)
148
+ javaTests = 'src/test/java';
149
+ lang = lang?.toLowerCase();
150
+ const runReader = new xmlReader_js_1.default({ javaTests, lang });
151
+ const files = glob_1.glob.sync(pattern, { cwd: opts.dir || process.cwd() });
152
+ if (!files.length) {
153
+ console.log(constants_js_1.APP_PREFIX, `Report can't be created. No XML files found 😥`);
154
+ process.exit(1);
155
+ }
156
+ for (const file of files) {
157
+ console.log(constants_js_1.APP_PREFIX, `Parsed ${file}`);
158
+ runReader.parse(file);
159
+ }
160
+ let timeoutTimer;
161
+ if (opts.timelimit) {
162
+ timeoutTimer = setTimeout(() => {
163
+ console.log(`⚠️ Reached timeout of ${opts.timelimit}s. Exiting... (Exit code is 0 to not fail the pipeline)`);
164
+ process.exit(0);
165
+ }, parseInt(opts.timelimit, 10) * 1000);
166
+ }
167
+ try {
168
+ await runReader.createRun();
169
+ await runReader.uploadData();
170
+ }
171
+ catch (err) {
172
+ console.log(constants_js_1.APP_PREFIX, 'Error updating status, skipping...', err);
173
+ }
174
+ if (timeoutTimer)
175
+ clearTimeout(timeoutTimer);
176
+ });
177
+ program
178
+ .command('upload-artifacts')
179
+ .description('Upload artifacts to Testomat.io')
180
+ .option('--force', 'Re-upload artifacts even if they were uploaded before')
181
+ .action(async (opts) => {
182
+ const apiKey = config_js_1.config.TESTOMATIO;
183
+ process.env.TESTOMATIO_DISABLE_ARTIFACTS = '';
184
+ const runId = process.env.TESTOMATIO_RUN || process.env.runId || (0, utils_js_2.readLatestRunId)();
185
+ if (!runId) {
186
+ console.log('TESTOMATIO_RUN environment variable must be set or restored from a previous run.');
187
+ return process.exit(1);
188
+ }
189
+ const client = new client_js_1.default({
190
+ apiKey,
191
+ runId,
192
+ isBatchEnabled: false,
193
+ });
194
+ let testruns = client.uploader.readUploadedFiles(runId);
195
+ const numTotalArtifacts = testruns.length;
196
+ debug('Found testruns:', testruns);
197
+ if (!opts.force)
198
+ testruns = testruns.filter(tr => !tr.uploaded);
199
+ if (!testruns.length) {
200
+ console.log(constants_js_1.APP_PREFIX, '🗄️ Total artifacts:', numTotalArtifacts);
201
+ if (numTotalArtifacts) {
202
+ console.log(constants_js_1.APP_PREFIX, 'No new artifacts to upload');
203
+ console.log(constants_js_1.APP_PREFIX, 'To re-upload artifacts run this command with --force flag');
204
+ }
205
+ process.exit(0);
206
+ }
207
+ const testrunsByRid = testruns.reduce((acc, { rid, file }) => {
208
+ if (!acc[rid]) {
209
+ acc[rid] = [];
210
+ }
211
+ if (!acc[rid].includes(file))
212
+ acc[rid].push(file);
213
+ return acc;
214
+ }, {});
215
+ await client.createRun();
216
+ client.uploader.checkEnabled();
217
+ client.uploader.disableLogStorage();
218
+ for (const rid in testrunsByRid) {
219
+ const files = testrunsByRid[rid];
220
+ await client.addTestRun(undefined, { rid, files });
221
+ }
222
+ console.log(constants_js_1.APP_PREFIX, '🗄️', client.uploader.successfulUploads.length, 'artifacts 🟢uploaded');
223
+ if (client.uploader.successfulUploads.length) {
224
+ debug('\n', constants_js_1.APP_PREFIX, `🗄️ ${client.uploader.successfulUploads.length} artifacts uploaded to S3 bucket`);
225
+ const uploadedArtifacts = client.uploader.successfulUploads.map(file => ({
226
+ relativePath: file.path.replace(process.cwd(), ''),
227
+ link: file.link,
228
+ sizePretty: (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
229
+ }));
230
+ uploadedArtifacts.forEach(upload => {
231
+ debug(`🟢Uploaded artifact`, `${upload.relativePath},`, 'size:', `${upload.sizePretty},`, 'link:', `${upload.link}`);
232
+ });
233
+ }
234
+ const filesizeStrMaxLength = 7;
235
+ if (client.uploader.failedUploads.length) {
236
+ console.log('\n', constants_js_1.APP_PREFIX, '🗄️', client.uploader.failedUploads.length, `artifacts 🔴${picocolors_1.default.bold('failed')} to upload`);
237
+ const failedUploads = client.uploader.failedUploads.map(({ path, size }) => ({
238
+ relativePath: path.replace(process.cwd(), ''),
239
+ sizePretty: (0, filesize_1.filesize)(size, { round: 0 }).toString(),
240
+ }));
241
+ const pathPadding = Math.max(...failedUploads.map(upload => upload.relativePath.length)) + 1;
242
+ failedUploads.forEach(upload => {
243
+ console.log(` ${picocolors_1.default.gray('|')} 🔴 ${upload.relativePath.padEnd(pathPadding)} ${picocolors_1.default.gray(`| ${upload.sizePretty.padStart(filesizeStrMaxLength)} |`)}`);
244
+ });
245
+ }
246
+ });
247
+ program.parse(process.argv);
248
+ if (!process.argv.slice(2).length) {
249
+ program.outputHelp();
250
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -4,16 +4,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- const commander_1 = __importDefault(require("commander"));
7
+ const commander_1 = require("commander");
8
8
  const picocolors_1 = __importDefault(require("picocolors"));
9
- const glob_1 = __importDefault(require("glob"));
9
+ const glob_1 = require("glob");
10
10
  const debug_1 = __importDefault(require("debug"));
11
11
  const constants_js_1 = require("../constants.js");
12
12
  const xmlReader_js_1 = __importDefault(require("../xmlReader.js"));
13
- const package_json_1 = require("../../package.json");
13
+ const utils_js_1 = require("../utils/utils.js");
14
+ const dotenv_1 = __importDefault(require("dotenv"));
15
+ const path_1 = __importDefault(require("path"));
16
+ const version = (0, utils_js_1.getPackageVersion)();
14
17
  const debug = (0, debug_1.default)('@testomatio/reporter:xml-cli');
15
- console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io XML Reporter v${package_json_1.version}`)));
16
- commander_1.default
18
+ console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io XML Reporter v${version}`)));
19
+ const program = new commander_1.Command();
20
+ program
17
21
  .arguments('<pattern>')
18
22
  .option('-d, --dir <dir>', 'Project directory')
19
23
  .option('--java-tests [java-path]', 'Load Java tests from path, by default: src/test/java')
@@ -28,13 +32,13 @@ commander_1.default
28
32
  if (opts.envFile) {
29
33
  console.log(constants_js_1.APP_PREFIX, 'Loading env file:', opts.envFile);
30
34
  debug('Loading env file: %s', opts.envFile);
31
- require('dotenv').config({ path: opts.envFile }); // eslint-disable-line
35
+ dotenv_1.default.config({ path: opts.envFile });
32
36
  }
33
- if (javaTests === true)
34
- javaTests = 'src/test/java';
35
37
  lang = lang?.toLowerCase();
38
+ if (javaTests === true || (lang === 'java' && !javaTests))
39
+ javaTests = 'src/test/java';
36
40
  const runReader = new xmlReader_js_1.default({ javaTests, lang });
37
- const files = glob_1.default.sync(pattern, { cwd: opts.dir || process.cwd() });
41
+ const files = glob_1.glob.sync(pattern, { cwd: opts.dir || process.cwd() });
38
42
  if (!files.length) {
39
43
  console.log(constants_js_1.APP_PREFIX, `Report can't be created. No XML files found 😥`);
40
44
  process.exitCode = 1;
@@ -62,6 +66,6 @@ commander_1.default
62
66
  clearTimeout(timeoutTimer);
63
67
  });
64
68
  if (process.argv.length < 3) {
65
- commander_1.default.outputHelp();
69
+ program.outputHelp();
66
70
  }
67
- commander_1.default.parse(process.argv);
71
+ program.parse(process.argv);
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -5,14 +5,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const cross_spawn_1 = require("cross-spawn");
8
- const commander_1 = __importDefault(require("commander"));
8
+ const commander_1 = require("commander");
9
9
  const picocolors_1 = __importDefault(require("picocolors"));
10
10
  const client_js_1 = __importDefault(require("../client.js"));
11
11
  const constants_js_1 = require("../constants.js");
12
- const package_json_1 = require("../../package.json");
12
+ const utils_js_1 = require("../utils/utils.js");
13
13
  const config_js_1 = require("../config.js");
14
- console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io Reporter v${package_json_1.version}`)));
15
- commander_1.default
14
+ const dotenv_1 = __importDefault(require("dotenv"));
15
+ const version = (0, utils_js_1.getPackageVersion)();
16
+ console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io Reporter v${version}`)));
17
+ const program = new commander_1.Command();
18
+ program
16
19
  .option('-c, --command <cmd>', 'Test runner command')
17
20
  .option('--launch', 'Start a new run and return its ID')
18
21
  .option('--finish', 'Finish Run by its ID')
@@ -22,7 +25,7 @@ commander_1.default
22
25
  const { launch, finish, filter } = opts;
23
26
  let { command } = opts;
24
27
  if (opts.envFile)
25
- require('dotenv').config(opts.envFile); // eslint-disable-line
28
+ dotenv_1.default.config({ path: opts.envFile });
26
29
  const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
27
30
  const title = process.env.TESTOMATIO_TITLE;
28
31
  if (launch) {
@@ -35,6 +38,8 @@ commander_1.default
35
38
  return;
36
39
  }
37
40
  if (finish) {
41
+ // TODO: add error in case of TESTOMATIO environment variable is not set
42
+ // because command is fine in console, but actually (on testomat.io) run is not finished
38
43
  if (!process.env.TESTOMATIO_RUN) {
39
44
  console.log('TESTOMATIO_RUN environment variable must be set.');
40
45
  return process.exit(1);
@@ -96,6 +101,6 @@ commander_1.default
96
101
  });
97
102
  });
98
103
  if (process.argv.length <= 2) {
99
- commander_1.default.outputHelp();
104
+ program.outputHelp();
100
105
  }
101
- commander_1.default.parse(process.argv);
106
+ program.parse(process.argv);
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const picocolors_1 = __importDefault(require("picocolors"));
9
+ const debug_1 = __importDefault(require("debug"));
10
+ const client_js_1 = __importDefault(require("../client.js"));
11
+ const constants_js_1 = require("../constants.js");
12
+ const utils_js_1 = require("../utils/utils.js");
13
+ const config_js_1 = require("../config.js");
14
+ const utils_js_2 = require("../utils/utils.js");
15
+ const dotenv_1 = __importDefault(require("dotenv"));
16
+ const debug = (0, debug_1.default)('@testomatio/reporter:upload-cli');
17
+ const version = (0, utils_js_1.getPackageVersion)();
18
+ console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io Reporter v${version}`)));
19
+ const program = new commander_1.Command();
20
+ program
21
+ .option('--env-file <envfile>', 'Load environment variables from env file')
22
+ .option('--force', 'Re-upload artifacts even if they were uploaded before')
23
+ .action(async (opts) => {
24
+ if (opts.envFile) {
25
+ dotenv_1.default.config({ path: opts.envFile });
26
+ }
27
+ else {
28
+ dotenv_1.default.config();
29
+ }
30
+ const apiKey = config_js_1.config.TESTOMATIO;
31
+ process.env.TESTOMATIO_DISABLE_ARTIFACTS = '';
32
+ const runId = process.env.TESTOMATIO_RUN || process.env.runId || (0, utils_js_2.readLatestRunId)();
33
+ if (!runId) {
34
+ console.log('TESTOMATIO_RUN environment variable must be set or restored from a previous run.');
35
+ return process.exit(1);
36
+ }
37
+ const client = new client_js_1.default({
38
+ apiKey,
39
+ runId,
40
+ isBatchEnabled: false,
41
+ });
42
+ let testruns = client.uploader.readUploadedFiles(process.env.TESTOMATIO_RUN);
43
+ const numTotalArtifacts = testruns.length;
44
+ debug('Found testruns:', testruns);
45
+ if (!opts.force)
46
+ testruns = testruns.filter(tr => !tr.uploaded);
47
+ if (!testruns.length) {
48
+ console.log(constants_js_1.APP_PREFIX, 'Total artifacts:', numTotalArtifacts);
49
+ if (numTotalArtifacts) {
50
+ console.log(constants_js_1.APP_PREFIX, 'No new artifacts to upload');
51
+ console.log(constants_js_1.APP_PREFIX, 'To re-upload artifacts run this command with --force flag');
52
+ }
53
+ process.exit(0);
54
+ }
55
+ const testrunsByRid = testruns.reduce((acc, { rid, file }) => {
56
+ if (!acc[rid]) {
57
+ acc[rid] = [];
58
+ }
59
+ if (!acc[rid].includes(file))
60
+ acc[rid].push(file);
61
+ return acc;
62
+ }, {});
63
+ // we need to obtain S3 credentials
64
+ await client.createRun();
65
+ client.uploader.checkEnabled();
66
+ client.uploader.disableLogStorage();
67
+ for (const rid in testrunsByRid) {
68
+ const files = testrunsByRid[rid];
69
+ await client.addTestRun(undefined, {
70
+ rid,
71
+ files,
72
+ });
73
+ }
74
+ console.log(constants_js_1.APP_PREFIX, client.uploader.successfulUploads.length, 'artifacts uploaded');
75
+ if (client.uploader.failedUploads.length) {
76
+ console.log(constants_js_1.APP_PREFIX, client.uploader.failedUploads.length, 'artifacts failed to upload');
77
+ }
78
+ });
79
+ if (process.argv.length <= 1) {
80
+ program.outputHelp();
81
+ }
82
+ program.parse(process.argv);
@@ -0,0 +1,76 @@
1
+ export default Client;
2
+ export type TestData = import("../types/types.js").TestData;
3
+ export type PipeResult = import("../types/types.js").PipeResult;
4
+ /**
5
+ * @typedef {import('../types/types.js').TestData} TestData
6
+ * @typedef {import('../types/types.js').PipeResult} PipeResult
7
+ */
8
+ export class Client {
9
+ /**
10
+ * Create a Testomat client instance
11
+ * @returns
12
+ */
13
+ constructor(params?: {});
14
+ paramsForPipesFactory: {};
15
+ pipeStore: {};
16
+ runId: `${string}-${string}-${string}-${string}-${string}`;
17
+ queue: Promise<void>;
18
+ version: any;
19
+ executionList: Promise<void>;
20
+ uploader: S3Uploader;
21
+ /**
22
+ * Asynchronously prepares the execution list for running tests through various pipes.
23
+ * Each pipe in the client is checked for enablement,
24
+ * and if all pipes are disabled, the function returns a resolved Promise.
25
+ * Otherwise, it executes the `prepareRun` method for each enabled pipe and collects the results.
26
+ * The results are then filtered to remove any undefined values.
27
+ * If no valid results are found, the function returns undefined.
28
+ * Otherwise, it returns the first non-empty array from the filtered results.
29
+ *
30
+ * @param {Object} params - The options for preparing the test execution list.
31
+ * @param {string} params.pipe - Name of the executed pipe.
32
+ * @param {string} params.pipeOptions - Filter option.
33
+ * @returns {Promise<any>} - A Promise that resolves to an
34
+ * array containing the prepared execution list,
35
+ * or resolves to undefined if no valid results are found or if all pipes are disabled.
36
+ */
37
+ prepareRun(params: {
38
+ pipe: string;
39
+ pipeOptions: string;
40
+ }): Promise<any>;
41
+ pipes: any[];
42
+ /**
43
+ * Used to create a new Test run
44
+ *
45
+ * @returns {Promise<any>} - resolves to Run id which should be used to update / add test
46
+ */
47
+ createRun(params: any): Promise<any>;
48
+ /**
49
+ * Updates test status and its data
50
+ *
51
+ * @param {string|undefined} status
52
+ * @param {TestData} [testData]
53
+ * @returns {Promise<PipeResult[]>}
54
+ */
55
+ addTestRun(status: string | undefined, testData?: TestData): Promise<PipeResult[]>;
56
+ /**
57
+ *
58
+ * Updates the status of the current test run and finishes the run.
59
+ * @param {'passed' | 'failed' | 'skipped' | 'finished'} status - The status of the current test run.
60
+ * Must be one of "passed", "failed", or "finished"
61
+ * @param {boolean} [isParallel] - Whether the current test run was executed in parallel with other tests.
62
+ * @returns {Promise<any>} - A Promise that resolves when finishes the run.
63
+ */
64
+ updateRunStatus(status: "passed" | "failed" | "skipped" | "finished", isParallel?: boolean): Promise<any>;
65
+ /**
66
+ * Returns the formatted stack including the stack trace, steps, and logs.
67
+ * @returns {string}
68
+ */
69
+ formatLogs({ error, steps, logs }: {
70
+ error: any;
71
+ steps: any;
72
+ logs: any;
73
+ }): string;
74
+ formatError(error: any, message: any): string;
75
+ }
76
+ import { S3Uploader } from './uploader.js';