@testomatio/reporter 2.3.7-beta.8-stack-artifacts → 2.3.7-rc.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.
@@ -471,10 +471,14 @@ function transformEnvVarToBoolean(value) {
471
471
  return Boolean(value);
472
472
  }
473
473
  function truncate(s, size = 255) {
474
- if (s.toString().trim().length < size) {
475
- return s.toString();
474
+ if (s === undefined || s === null) {
475
+ return '';
476
+ }
477
+ const str = s.toString();
478
+ if (str.trim().length < size) {
479
+ return str;
476
480
  }
477
- return `${s.toString().substring(0, size)}...`;
481
+ return `${str.substring(0, size)}...`;
478
482
  }
479
483
 
480
484
  module.exports.getPackageVersion = getPackageVersion;
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "2.3.7-beta.8-stack-artifacts",
3
+ "version": "2.3.7-rc.1",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "engines": {
6
6
  "node": ">=18"
7
7
  },
8
- "typings": "typings/index.d.ts",
8
+ "main": "lib/reporter.js",
9
+ "module": "src/reporter.js",
10
+ "types": "types/types.d.ts",
9
11
  "repository": "git@github.com:testomatio/reporter.git",
10
12
  "author": "Michael Bodnarchuk <davert@testomat.io>,Koushik Mohan <koushikmohan1996@gmail.com>",
11
13
  "license": "MIT",
@@ -45,7 +47,8 @@
45
47
  "bin",
46
48
  "lib",
47
49
  "src",
48
- "testcafe"
50
+ "testcafe",
51
+ "types"
49
52
  ],
50
53
  "scripts": {
51
54
  "clear-exportdir": "rm -rf export/",
@@ -57,7 +60,8 @@
57
60
  "test": "mocha 'tests/unit/**/*_test.js'",
58
61
  "test:playwright": "mocha tests/adapter/playwright.test.js",
59
62
  "test:codecept": "mocha tests/adapter/codecept.test.js tests/adapter/codecept_comprehensive.test.js tests/adapter/codecept_steps_sections.test.js",
60
- "test:frameworks": "npm run test:playwright && npm run test:codecept",
63
+ "test:vitest": "mocha tests/adapter/vitest.test.js",
64
+ "test:frameworks": "npm run test:playwright && npm run test:codecept && npm run test:vitest",
61
65
  "test:all": "npm run test && npm run test:frameworks",
62
66
  "test:adapters": "mocha tests/adapter/*.test.js",
63
67
  "test:codecept:bug948": "mocha tests/adapter/codecept_aftersuite_failure.test.js",
package/src/bin/cli.js CHANGED
@@ -158,7 +158,7 @@ program
158
158
  .option('--lang <lang>', 'Language used (python, ruby, java)')
159
159
  .option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
160
160
  .action(async (pattern, opts) => {
161
- if (!pattern.endsWith('.xml')) {
161
+ if (!pattern.endsWith('.xml') && !pattern.includes('*')) {
162
162
  pattern += '.xml';
163
163
  }
164
164
  let { javaTests, lang } = opts;
@@ -23,7 +23,7 @@ program
23
23
  .option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
24
24
  .option('--env-file <envfile>', 'Load environment variables from env file')
25
25
  .action(async (pattern, opts) => {
26
- if (!pattern.endsWith('.xml')) {
26
+ if (!pattern.endsWith('.xml') && !pattern.includes('*')) {
27
27
  pattern += '.xml';
28
28
  }
29
29
  let { javaTests, lang } = opts;
@@ -34,7 +34,10 @@ program
34
34
  }
35
35
  lang = lang?.toLowerCase();
36
36
  if (javaTests === true || (lang === 'java' && !javaTests)) javaTests = 'src/test/java';
37
- const runReader = new XmlReader({ javaTests, lang });
37
+ const runReader = new XmlReader({
38
+ javaTests,
39
+ lang,
40
+ });
38
41
  const files = glob.sync(pattern, { cwd: opts.dir || process.cwd() });
39
42
  if (!files.length) {
40
43
  console.log(APP_PREFIX, `Report can't be created. No XML files found 😥`);
@@ -18,7 +18,7 @@ const newArgs = ['run'];
18
18
  let i = 0;
19
19
  while (i < args.length) {
20
20
  const arg = args[i];
21
-
21
+
22
22
  if (arg === '-c' || arg === '--command') {
23
23
  // Map -c/--command to positional argument for run command
24
24
  i++;
@@ -33,7 +33,7 @@ while (i < args.length) {
33
33
  // Map --launch to start command
34
34
  newArgs[0] = 'start';
35
35
  } else if (arg === '--finish') {
36
- // Map --finish to finish command
36
+ // Map --finish to finish command
37
37
  newArgs[0] = 'finish';
38
38
  } else {
39
39
  // Pass through other arguments
@@ -45,9 +45,9 @@ while (i < args.length) {
45
45
  // Execute the main CLI with mapped arguments
46
46
 
47
47
  const child = spawn(process.execPath, [cliPath, ...newArgs], {
48
- stdio: 'inherit'
48
+ stdio: 'inherit',
49
49
  });
50
50
 
51
- child.on('exit', (code) => {
51
+ child.on('exit', code => {
52
52
  process.exit(code);
53
- });
53
+ });
package/src/client.js CHANGED
@@ -170,12 +170,12 @@ class Client {
170
170
  title,
171
171
  suite_title,
172
172
  } = testData;
173
- const steps = originalSteps;
173
+ let steps = originalSteps;
174
174
 
175
175
  const uploadedFiles = [];
176
176
  const stackArtifactsEnabled = transformEnvVarToBoolean(process.env.TESTOMATIO_STACK_ARTIFACTS);
177
177
 
178
-
178
+
179
179
  const {
180
180
  time = 0,
181
181
  example = null,
@@ -210,18 +210,18 @@ class Client {
210
210
 
211
211
  let fullLogs = this.formatLogs({ error: errorFormatted, steps, logs: testData.logs });
212
212
 
213
- if (stackArtifactsEnabled) {
214
- const timestamp = +new Date;
213
+ if (stackArtifactsEnabled && fullLogs?.trim()?.length > 0) {
215
214
  uploadedFiles.push(
216
215
  this.uploader.uploadFileAsBuffer(
217
216
  Buffer.from(stripColors(fullLogs), 'utf8'),
218
- [this.runId, rid, `logs_${timestamp}.log`]
217
+ [this.runId, rid, `logs_${+new Date}.log`]
219
218
  )
220
219
  );
221
220
  fullLogs = '';
221
+ steps = null;
222
222
  }
223
223
 
224
-
224
+
225
225
  if (!this.pipes || !this.pipes.length)
226
226
  this.pipes = await pipesFactory(this.paramsForPipesFactory || {}, this.pipeStore);
227
227
 
@@ -336,7 +336,7 @@ class Client {
336
336
  const uploadedArtifacts = this.uploader.successfulUploads.map(file => ({
337
337
  relativePath: file.path.replace(process.cwd(), ''),
338
338
  link: file.link,
339
- sizePretty: prettyBytes(file.size, { round: 0 }).toString(),
339
+ sizePretty: file.size == null ? 'unknown' : prettyBytes(file.size, { round: 0 }).toString(),
340
340
  }));
341
341
 
342
342
  uploadedArtifacts.forEach(upload => {
@@ -358,7 +358,7 @@ class Client {
358
358
  );
359
359
  const failedUploads = this.uploader.failedUploads.map(file => ({
360
360
  relativePath: file.path.replace(process.cwd(), ''),
361
- sizePretty: prettyBytes(file.size, { round: 0 }).toString(),
361
+ sizePretty: file.size == null ? 'unknown' : prettyBytes(file.size, { round: 0 }).toString(),
362
362
  }));
363
363
 
364
364
  const pathPadding = Math.max(...failedUploads.map(upload => upload.relativePath.length)) + 1;
@@ -3,18 +3,50 @@ import Adapter from './adapter.js';
3
3
 
4
4
  class CSharpAdapter extends Adapter {
5
5
  formatTest(t) {
6
- const title = t.title.replace(/\(.*?\)/, '').trim();
7
- const example = t.title.match(/\((.*?)\)/);
8
- if (example) t.example = { ...example[1].split(',') };
6
+ // Extract example from title if not already present
7
+ if (!t.example) {
8
+ const exampleMatch = t.title.match(/\((.*?)\)/);
9
+ if (exampleMatch) {
10
+ // Extract parameters as object with numeric keys for API
11
+ const params = exampleMatch[1].split(',').map(param => param.trim());
12
+ t.example = {};
13
+ params.forEach((param, index) => {
14
+ t.example[index] = param;
15
+ });
16
+ }
17
+ }
18
+
19
+ // Remove parameters from title to avoid duplicates in Test Suite
20
+ // The example field will be used for grouping on import
21
+ t.title = t.title.replace(/\(.*?\)/, '').trim();
22
+
9
23
  const suite = t.suite_title.split('.');
10
24
  t.suite_title = suite.pop();
11
25
  t.file = namespaceToFileName(t.file);
12
- t.title = title.trim();
13
26
  return t;
14
27
  }
15
28
 
16
29
  getFilePath(t) {
17
- const fileName = namespaceToFileName(t.file);
30
+ if (!t.file) return null;
31
+
32
+ // Normalize path separators for cross-platform compatibility
33
+ let filePath = t.file.replace(/\\/g, '/');
34
+
35
+ // If file already has .cs extension, use it directly
36
+ if (filePath.endsWith('.cs')) {
37
+ // Make relative path if it's absolute
38
+ if (path.isAbsolute(filePath)) {
39
+ // Try to find project-relative path
40
+ const cwd = process.cwd().replace(/\\/g, '/');
41
+ if (filePath.startsWith(cwd)) {
42
+ filePath = path.relative(cwd, filePath).replace(/\\/g, '/');
43
+ }
44
+ }
45
+ return filePath;
46
+ }
47
+
48
+ // Convert namespace path to file path
49
+ const fileName = namespaceToFileName(filePath);
18
50
  return fileName;
19
51
  }
20
52
  }
@@ -22,7 +54,14 @@ class CSharpAdapter extends Adapter {
22
54
  export default CSharpAdapter;
23
55
 
24
56
  function namespaceToFileName(fileName) {
57
+ if (!fileName) return '';
58
+
59
+ // If already a .cs file path, clean it up
60
+ if (fileName.endsWith('.cs')) {
61
+ return fileName.replace(/\\/g, '/');
62
+ }
63
+
25
64
  const fileParts = fileName.split('.');
26
65
  fileParts[fileParts.length - 1] = fileParts[fileParts.length - 1]?.replace(/\$.*/, '');
27
- return `${fileParts.join(path.sep)}.cs`;
66
+ return `${fileParts.join('/')}.cs`;
28
67
  }