@testomatio/reporter 2.3.7 β†’ 2.3.8-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.
package/README.md CHANGED
@@ -13,7 +13,7 @@ Testomat.io Reporter (this npm package) supports:
13
13
  - πŸ”Ž [Stack traces](./docs/stacktrace.md) and error messages
14
14
  - πŸ™ [GitHub](./docs/pipes/github.md), [GitLab](./docs/pipes/gitlab.md) & [Bitbucket](./docs/pipes/bitbucket.md) integration
15
15
  - πŸš… Realtime reports
16
- - πŸ—ƒοΈ Other test frameworks supported via [JUNit XML](./docs/junit.md)
16
+ - πŸ—ƒοΈ Other test frameworks supported via [JUnit XML](./docs/junit.md) with [XML import configuration](./docs/xml-imports.md)
17
17
  - πŸšΆβ€β™€οΈ Steps _(work in progress)_
18
18
  - πŸ“„ [Logger](./docs/logger.md) _(work in progress, supports Jest for now)_
19
19
  - ☁️ Custom properties and metadata _(work in progress)_
package/lib/bin/cli.js CHANGED
@@ -37,12 +37,17 @@ program
37
37
  program
38
38
  .command('start')
39
39
  .description('Start a new run and return its ID')
40
- .action(async () => {
40
+ .option('--kind <type>', 'Specify run type: automated, manual, or mixed')
41
+ .action(async (opts) => {
41
42
  (0, utils_js_1.cleanLatestRunId)();
42
43
  console.log('Starting a new Run on Testomat.io...');
43
44
  const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
44
45
  const client = new client_js_1.default({ apiKey });
45
- client.createRun().then(() => {
46
+ const createRunParams = {};
47
+ if (opts.kind) {
48
+ createRunParams.kind = opts.kind;
49
+ }
50
+ client.createRun(createRunParams).then(() => {
46
51
  console.log(process.env.runId);
47
52
  process.exit(0);
48
53
  });
@@ -70,6 +75,7 @@ program
70
75
  .description('Run tests with the specified command')
71
76
  .argument('<command>', 'Test runner command')
72
77
  .option('--filter <filter>', 'Additional execution filter')
78
+ .option('--kind <type>', 'Specify run type: automated, manual, or mixed')
73
79
  .action(async (command, opts) => {
74
80
  const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
75
81
  const title = process.env.TESTOMATIO_TITLE;
@@ -108,8 +114,12 @@ program
108
114
  process.exit(code);
109
115
  });
110
116
  };
117
+ const createRunParams = {};
118
+ if (opts.kind) {
119
+ createRunParams.kind = opts.kind;
120
+ }
111
121
  if (apiKey) {
112
- await client.createRun().then(runTests);
122
+ await client.createRun(createRunParams).then(runTests);
113
123
  }
114
124
  else {
115
125
  await runTests();
File without changes
File without changes
File without changes
package/lib/client.d.ts CHANGED
@@ -44,7 +44,7 @@ export class Client {
44
44
  *
45
45
  * @returns {Promise<any>} - resolves to Run id which should be used to update / add test
46
46
  */
47
- createRun(params: any): Promise<any>;
47
+ createRun(params?: {}): Promise<any>;
48
48
  /**
49
49
  * Updates test status and its data
50
50
  *
package/lib/client.js CHANGED
@@ -131,7 +131,7 @@ class Client {
131
131
  *
132
132
  * @returns {Promise<any>} - resolves to Run id which should be used to update / add test
133
133
  */
134
- async createRun(params) {
134
+ async createRun(params = {}) {
135
135
  if (!this.pipes || !this.pipes.length)
136
136
  this.pipes = await (0, index_js_1.pipesFactory)(params || this.paramsForPipesFactory || {}, this.pipeStore);
137
137
  debug('Creating run...');
@@ -139,7 +139,7 @@ class Client {
139
139
  if (!this.pipes?.filter(p => p.isEnabled).length)
140
140
  return Promise.resolve();
141
141
  this.queue = this.queue
142
- .then(() => Promise.all(this.pipes.map(p => p.createRun())))
142
+ .then(() => Promise.all(this.pipes.map(p => p.createRun(params))))
143
143
  .catch(err => console.log(constants_js_1.APP_PREFIX, err))
144
144
  .then(() => {
145
145
  const runId = this.pipeStore?.runId;
@@ -47,11 +47,12 @@ declare class TestomatioPipe implements Pipe {
47
47
  prepareRun(opts: any): Promise<string[]>;
48
48
  /**
49
49
  * Creates a new run on Testomat.io
50
- * @param {{isBatchEnabled?: boolean}} params
50
+ * @param {{isBatchEnabled?: boolean, kind?: string}} params
51
51
  * @returns Promise<void>
52
52
  */
53
53
  createRun(params?: {
54
54
  isBatchEnabled?: boolean;
55
+ kind?: string;
55
56
  }): Promise<void>;
56
57
  runUrl: string;
57
58
  runPublicUrl: any;
@@ -148,7 +148,7 @@ class TestomatioPipe {
148
148
  }
149
149
  /**
150
150
  * Creates a new run on Testomat.io
151
- * @param {{isBatchEnabled?: boolean}} params
151
+ * @param {{isBatchEnabled?: boolean, kind?: string}} params
152
152
  * @returns Promise<void>
153
153
  */
154
154
  async createRun(params = {}) {
@@ -184,6 +184,7 @@ class TestomatioPipe {
184
184
  label: this.label,
185
185
  shared_run: this.sharedRun,
186
186
  shared_run_timeout: this.sharedRunTimeout,
187
+ kind: params.kind,
187
188
  }).filter(([, value]) => !!value));
188
189
  debug(' >>>>>> Run params', JSON.stringify(runParams, null, 2));
189
190
  if (this.runId) {
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "2.3.7",
3
+ "version": "2.3.8-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 πŸ˜₯`);
@@ -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
  }