testomatio-reporter-cli 2.20.0 → 2.22.0

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.
@@ -0,0 +1,151 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import pc from 'picocolors';
4
+
5
+ const LAUNCHER_PREFIXES = ['npx', 'npm', 'yarn', 'pnpm', 'bun', 'node', 'bunx'];
6
+
7
+ const PLACEHOLDER_PHRASE_RE = /^<?-*(?:run|your|test)\s+(?:[\w-]+\s+)?(?:tests?|command|runner)>?$/i;
8
+
9
+ const RUNNERS = [
10
+ {
11
+ name: 'Playwright',
12
+ configs: ['playwright.config.js', 'playwright.config.ts', 'playwright.config.mjs', 'playwright.config.cjs'],
13
+ dependencies: ['@playwright/test'],
14
+ command: 'npx playwright test',
15
+ },
16
+ {
17
+ name: 'CodeceptJS',
18
+ configs: ['codecept.conf.js', 'codecept.conf.ts'],
19
+ dependencies: ['codeceptjs'],
20
+ command: 'npx codeceptjs run',
21
+ },
22
+ {
23
+ name: 'WebdriverIO',
24
+ configs: ['wdio.conf.js', 'wdio.conf.ts'],
25
+ dependencies: ['@wdio/cli'],
26
+ dependencyPrefix: '@wdio/',
27
+ command: 'npx wdio run ./wdio.conf.js',
28
+ },
29
+ {
30
+ name: 'Cypress',
31
+ configs: ['cypress.config.js', 'cypress.config.ts'],
32
+ dependencies: ['cypress'],
33
+ command: 'npx cypress run',
34
+ },
35
+ {
36
+ name: 'Jest',
37
+ configs: ['jest.config.js', 'jest.config.ts', 'jest.config.mjs', 'jest.config.cjs', 'jest.config.json'],
38
+ dependencies: ['jest'],
39
+ command: 'npx jest',
40
+ },
41
+ {
42
+ name: 'Vitest',
43
+ configs: ['vitest.config.js', 'vitest.config.ts', 'vitest.config.mjs'],
44
+ dependencies: ['vitest'],
45
+ command: 'npx vitest run',
46
+ },
47
+ {
48
+ name: 'Mocha',
49
+ configs: ['.mocharc.js', '.mocharc.cjs', '.mocharc.json', '.mocharc.yml', '.mocharc.yaml'],
50
+ dependencies: ['mocha'],
51
+ command: 'npx mocha',
52
+ },
53
+ {
54
+ name: 'Cucumber',
55
+ configs: ['cucumber.js', 'cucumber.cjs'],
56
+ dependencies: ['@cucumber/cucumber'],
57
+ command: 'npx cucumber-js',
58
+ },
59
+ ];
60
+
61
+ /**
62
+ * @param {string} command
63
+ * @returns {boolean}
64
+ */
65
+ function isPlaceholderCommand(command) {
66
+ const cmd = (command || '').trim();
67
+ if (!cmd) return false;
68
+
69
+ if (cmd.includes('<') || cmd.includes('>')) return true;
70
+
71
+ const firstToken = cmd.split(/\s+/)[0].toLowerCase();
72
+ if (LAUNCHER_PREFIXES.includes(firstToken)) return false;
73
+
74
+ return PLACEHOLDER_PHRASE_RE.test(cmd);
75
+ }
76
+
77
+ /**
78
+ * @param {string} cwd
79
+ * @returns {Record<string, string>}
80
+ */
81
+ function readPackageDependencies(cwd) {
82
+ try {
83
+ const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
84
+ return { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
85
+ } catch {
86
+ return {};
87
+ }
88
+ }
89
+
90
+ /**
91
+ * @param {string} [cwd]
92
+ * @returns {{ name: string, command: string } | null}
93
+ */
94
+ function detectRunner(cwd = process.cwd()) {
95
+ const dependencies = readPackageDependencies(cwd);
96
+
97
+ for (const runner of RUNNERS) {
98
+ const config = runner.configs.find(file => fs.existsSync(path.join(cwd, file)));
99
+
100
+ const hasDependency = runner.dependencies?.some(dep => dependencies[dep])
101
+ || (runner.dependencyPrefix && Object.keys(dependencies).some(dep => dep.startsWith(runner.dependencyPrefix)));
102
+
103
+ if (!config && !hasDependency) continue;
104
+
105
+ let command = runner.command;
106
+ if (runner.name === 'WebdriverIO') {
107
+ command = `npx wdio run ./${config || 'wdio.conf.js'}`;
108
+ }
109
+
110
+ return { name: runner.name, command };
111
+ }
112
+
113
+ return null;
114
+ }
115
+
116
+ /**
117
+ * @param {string} [cwd]
118
+ * @returns {string}
119
+ */
120
+ function runnerHint(cwd = process.cwd()) {
121
+ const runner = detectRunner(cwd);
122
+ if (runner) {
123
+ return `💡 Looks like this project uses ${runner.name}. Try: ${pc.green(runner.command)}`;
124
+ }
125
+ return `💡 Replace the placeholder with your test runner command, e.g. ${pc.green('npx playwright test')}`;
126
+ }
127
+
128
+ /**
129
+ * @param {string} command
130
+ * @returns {string[]}
131
+ */
132
+ function buildFilterWarning(command) {
133
+ return [
134
+ '⚠️ The runner exited with a non-zero code while a Testomat.io filter was applied.',
135
+ 'Your command was modified to run only tests matching Testomat IDs:',
136
+ ` ${pc.bold(command)}`,
137
+ 'This usually means no local tests matched the filter:',
138
+ ' - tests are not annotated with the matching @Txxxxxx IDs in their titles',
139
+ ' - the filter selected tests from another repository or branch',
140
+ ' - the test runner does not support the appended --grep / --testNamePattern option',
141
+ '💡 Hint: run the printed command without the appended filter option to see all your tests,',
142
+ 'then annotate them with Testomat IDs.',
143
+ ];
144
+ }
145
+
146
+ export {
147
+ isPlaceholderCommand,
148
+ detectRunner,
149
+ runnerHint,
150
+ buildFilterWarning,
151
+ };