codeceptjs 4.0.0-beta.18 → 4.0.0-beta.19
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/codecept.js +25 -1
- package/lib/command/init.js +2 -1
- package/lib/utils/loaderCheck.js +124 -0
- package/package.json +10 -1
package/lib/codecept.js
CHANGED
|
@@ -3,8 +3,9 @@ import { globSync } from 'glob'
|
|
|
3
3
|
import shuffle from 'lodash.shuffle'
|
|
4
4
|
import fsPath from 'path'
|
|
5
5
|
import { resolve } from 'path'
|
|
6
|
-
import { fileURLToPath } from 'url'
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from 'url'
|
|
7
7
|
import { dirname } from 'path'
|
|
8
|
+
import { createRequire } from 'module'
|
|
8
9
|
|
|
9
10
|
const __filename = fileURLToPath(import.meta.url)
|
|
10
11
|
const __dirname = dirname(__filename)
|
|
@@ -18,6 +19,7 @@ import ActorFactory from './actor.js'
|
|
|
18
19
|
import output from './output.js'
|
|
19
20
|
import { emptyFolder } from './utils.js'
|
|
20
21
|
import { initCodeceptGlobals } from './globals.js'
|
|
22
|
+
import { validateTypeScriptSetup } from './utils/loaderCheck.js'
|
|
21
23
|
import recorder from './recorder.js'
|
|
22
24
|
|
|
23
25
|
import storeListener from './listener/store.js'
|
|
@@ -66,6 +68,21 @@ class Codecept {
|
|
|
66
68
|
modulePath = `${modulePath}.js`
|
|
67
69
|
}
|
|
68
70
|
}
|
|
71
|
+
} else {
|
|
72
|
+
// For npm packages, resolve from the user's directory
|
|
73
|
+
// This ensures packages like tsx are found in user's node_modules
|
|
74
|
+
const userDir = global.codecept_dir || process.cwd()
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
// Use createRequire to resolve from user's directory
|
|
78
|
+
const userRequire = createRequire(pathToFileURL(resolve(userDir, 'package.json')).href)
|
|
79
|
+
const resolvedPath = userRequire.resolve(requiredModule)
|
|
80
|
+
modulePath = pathToFileURL(resolvedPath).href
|
|
81
|
+
} catch (resolveError) {
|
|
82
|
+
// If resolution fails, try direct import (will check from CodeceptJS node_modules)
|
|
83
|
+
// This is the fallback for globally installed packages
|
|
84
|
+
modulePath = requiredModule
|
|
85
|
+
}
|
|
69
86
|
}
|
|
70
87
|
// Use dynamic import for ESM
|
|
71
88
|
await import(modulePath)
|
|
@@ -246,6 +263,13 @@ class Codecept {
|
|
|
246
263
|
async run(test) {
|
|
247
264
|
await container.started()
|
|
248
265
|
|
|
266
|
+
// Check TypeScript loader configuration before running tests
|
|
267
|
+
const tsValidation = validateTypeScriptSetup(this.testFiles, this.requiringModules || [])
|
|
268
|
+
if (tsValidation.hasError) {
|
|
269
|
+
output.error(tsValidation.message)
|
|
270
|
+
process.exit(1)
|
|
271
|
+
}
|
|
272
|
+
|
|
249
273
|
// Ensure translations are loaded for Gherkin features
|
|
250
274
|
try {
|
|
251
275
|
const { loadTranslations } = await import('./mocha/gherkin.js')
|
package/lib/command/init.js
CHANGED
|
@@ -161,7 +161,7 @@ export default async function (initPath) {
|
|
|
161
161
|
isTypeScript = true
|
|
162
162
|
extension = isTypeScript === true ? 'ts' : 'js'
|
|
163
163
|
packages.push('typescript')
|
|
164
|
-
packages.push('
|
|
164
|
+
packages.push('tsx') // Add tsx for TypeScript support
|
|
165
165
|
packages.push('@types/node')
|
|
166
166
|
}
|
|
167
167
|
|
|
@@ -172,6 +172,7 @@ export default async function (initPath) {
|
|
|
172
172
|
config.tests = result.tests
|
|
173
173
|
if (isTypeScript) {
|
|
174
174
|
config.tests = `${config.tests.replace(/\.js$/, `.${extension}`)}`
|
|
175
|
+
config.require = ['tsx/cjs'] // Add tsx/cjs loader for TypeScript tests
|
|
175
176
|
}
|
|
176
177
|
|
|
177
178
|
// create a directory tests if it is included in tests path
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for checking TypeScript loader availability
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Check if a TypeScript loader is available for test files
|
|
7
|
+
* Note: This checks if loaders are in the require array, not if packages are installed
|
|
8
|
+
* Package installation is checked when actually requiring modules
|
|
9
|
+
* @param {string[]} requiredModules - Array of required modules from config
|
|
10
|
+
* @returns {boolean}
|
|
11
|
+
*/
|
|
12
|
+
export function checkTypeScriptLoader(requiredModules = []) {
|
|
13
|
+
// Check if a loader is configured in the require array
|
|
14
|
+
return (
|
|
15
|
+
requiredModules.includes('tsx/esm') ||
|
|
16
|
+
requiredModules.includes('tsx/cjs') ||
|
|
17
|
+
requiredModules.includes('tsx') ||
|
|
18
|
+
requiredModules.includes('ts-node/esm') ||
|
|
19
|
+
requiredModules.includes('ts-node/register') ||
|
|
20
|
+
requiredModules.includes('ts-node')
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Generate helpful error message if .ts tests found but no loader configured
|
|
26
|
+
* @param {string[]} testFiles - Array of test file paths
|
|
27
|
+
* @returns {string|null} Error message or null if no TypeScript files
|
|
28
|
+
*/
|
|
29
|
+
export function getTypeScriptLoaderError(testFiles) {
|
|
30
|
+
const tsFiles = testFiles.filter(f => f.endsWith('.ts'))
|
|
31
|
+
|
|
32
|
+
if (tsFiles.length === 0) return null
|
|
33
|
+
|
|
34
|
+
return `
|
|
35
|
+
╔═════════════════════════════════════════════════════════════════════════════╗
|
|
36
|
+
║ ║
|
|
37
|
+
║ ⚠️ TypeScript Test Files Detected but No Loader Configured ║
|
|
38
|
+
║ ║
|
|
39
|
+
╚═════════════════════════════════════════════════════════════════════════════╝
|
|
40
|
+
|
|
41
|
+
Found ${tsFiles.length} TypeScript test file(s) but no TypeScript loader is configured.
|
|
42
|
+
|
|
43
|
+
CodeceptJS 4.x uses ES Modules (ESM) and requires a loader to run TypeScript tests.
|
|
44
|
+
|
|
45
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
46
|
+
│ Option 1: tsx (Recommended - Fast, Zero Config) │
|
|
47
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
48
|
+
|
|
49
|
+
Installation:
|
|
50
|
+
npm install --save-dev tsx
|
|
51
|
+
|
|
52
|
+
Configuration:
|
|
53
|
+
Add to your codecept.conf.ts or codecept.conf.js:
|
|
54
|
+
|
|
55
|
+
export const config = {
|
|
56
|
+
tests: './**/*_test.ts',
|
|
57
|
+
require: ['tsx/cjs'], // ← Add this line
|
|
58
|
+
helpers: { /* ... */ }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
Why tsx?
|
|
62
|
+
⚡ Fast: Built on esbuild
|
|
63
|
+
🎯 Zero config: No tsconfig.json required
|
|
64
|
+
✅ Works with Mocha: Uses CommonJS hooks
|
|
65
|
+
✅ Complete: Handles all TypeScript features
|
|
66
|
+
|
|
67
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
68
|
+
│ Option 2: ts-node/esm (Alternative - Established, Requires Config) │
|
|
69
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
70
|
+
|
|
71
|
+
Installation:
|
|
72
|
+
npm install --save-dev ts-node
|
|
73
|
+
|
|
74
|
+
Configuration:
|
|
75
|
+
1. Add to your codecept.conf.ts:
|
|
76
|
+
require: ['ts-node/esm']
|
|
77
|
+
|
|
78
|
+
2. Create tsconfig.json:
|
|
79
|
+
{
|
|
80
|
+
"compilerOptions": {
|
|
81
|
+
"module": "ESNext",
|
|
82
|
+
"target": "ES2022",
|
|
83
|
+
"moduleResolution": "node",
|
|
84
|
+
"esModuleInterop": true
|
|
85
|
+
},
|
|
86
|
+
"ts-node": {
|
|
87
|
+
"esm": true,
|
|
88
|
+
"experimentalSpecifierResolution": "node"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
📚 Documentation: https://codecept.io/typescript
|
|
93
|
+
|
|
94
|
+
Note: TypeScript config files (codecept.conf.ts) and helpers are automatically
|
|
95
|
+
transpiled. Only test files require a loader to be configured.
|
|
96
|
+
`
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Check if user is trying to run TypeScript tests without proper loader
|
|
101
|
+
* @param {string[]} testFiles - Array of test file paths
|
|
102
|
+
* @param {string[]} requiredModules - Array of required modules from config
|
|
103
|
+
* @returns {{hasError: boolean, message: string|null}}
|
|
104
|
+
*/
|
|
105
|
+
export function validateTypeScriptSetup(testFiles, requiredModules = []) {
|
|
106
|
+
const tsFiles = testFiles.filter(f => f.endsWith('.ts'))
|
|
107
|
+
|
|
108
|
+
if (tsFiles.length === 0) {
|
|
109
|
+
// No TypeScript test files, all good
|
|
110
|
+
return { hasError: false, message: null }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Check if a loader is configured in the require array
|
|
114
|
+
const hasLoader = checkTypeScriptLoader(requiredModules)
|
|
115
|
+
|
|
116
|
+
if (hasLoader) {
|
|
117
|
+
// Loader configured, all good (package will be checked when requireModules runs)
|
|
118
|
+
return { hasError: false, message: null }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// No loader configured and TypeScript tests exist
|
|
122
|
+
const message = getTypeScriptLoaderError(testFiles)
|
|
123
|
+
return { hasError: true, message }
|
|
124
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
6
6
|
"keywords": [
|
|
@@ -183,6 +183,7 @@
|
|
|
183
183
|
"ts-node": "10.9.2",
|
|
184
184
|
"tsd": "^0.33.0",
|
|
185
185
|
"tsd-jsdoc": "2.5.0",
|
|
186
|
+
"tsx": "^4.19.2",
|
|
186
187
|
"typedoc": "0.28.13",
|
|
187
188
|
"typedoc-plugin-markdown": "4.9.0",
|
|
188
189
|
"typescript": "5.8.3",
|
|
@@ -191,6 +192,14 @@
|
|
|
191
192
|
"xml2js": "0.6.2",
|
|
192
193
|
"xpath": "0.0.34"
|
|
193
194
|
},
|
|
195
|
+
"peerDependencies": {
|
|
196
|
+
"tsx": "^4.0.0"
|
|
197
|
+
},
|
|
198
|
+
"peerDependenciesMeta": {
|
|
199
|
+
"tsx": {
|
|
200
|
+
"optional": true
|
|
201
|
+
}
|
|
202
|
+
},
|
|
194
203
|
"engines": {
|
|
195
204
|
"node": ">=16.0",
|
|
196
205
|
"npm": ">=5.6.0"
|