11import { existsSync , readFileSync } from 'fs' ;
22import glob from 'glob' ;
3- import fsPath , { resolve , dirname } from 'path' ;
4- import generated from '@codeceptjs/helper' ;
3+ import { resolve , dirname , isAbsolute , join } from 'path' ;
54import { fileURLToPath } from 'url' ;
65import { createRequire } from 'node:module' ;
76import container from './container.js' ;
@@ -12,237 +11,218 @@ import * as output from './output.js';
1211import { emptyFolder } from './utils.js' ;
1312import * as index from './index.js' ;
1413
15- import * as actor0 from './actor.js' ;
16-
17- import pause0 from './pause.js' ;
18-
19- import within0 from './within.js' ;
20-
21- import session0 from './session.js' ;
22-
14+ // Helpers and features
15+ import * as actor from './actor.js' ;
16+ import pause from './pause.js' ;
17+ import within from './within.js' ;
18+ import session from './session.js' ;
2319import data from './data/table.js' ;
24-
2520import Locator from './locator.js' ;
26-
2721import secret from './secret.js' ;
28-
29- // BDD
3022import * as stepDefinitions from './interfaces/bdd.js' ;
3123
24+ // Listeners
3225import listener from './listener/steps.js' ;
33-
34- import listener0 from './listener/artifacts.js' ;
35-
36- import listener01 from './listener/config.js' ;
37-
38- import listener012 from './listener/helpers.js' ;
39-
40- import listener0123 from './listener/retry.js' ;
41-
42- import listener01234 from './listener/timeout.js' ;
43-
44- import listener012345 from './listener/exit.js' ;
26+ import listenerArtifacts from './listener/artifacts.js' ;
27+ import listenerConfig from './listener/config.js' ;
28+ import listenerHelpers from './listener/helpers.js' ;
29+ import listenerRetry from './listener/retry.js' ;
30+ import listenerTimeout from './listener/timeout.js' ;
31+ import listenerExit from './listener/exit.js' ;
4532
4633const __dirname = dirname ( fileURLToPath ( import . meta. url ) ) ;
4734const require = createRequire ( import . meta. url ) ;
4835
4936/**
50- * CodeceptJS runner
37+ * CodeceptJS runner class.
5138 */
5239export default class Codecept {
5340 /**
54- * Create CodeceptJS runner.
55- * Config and options should be passed
56- *
57- * @param {* } config
58- * @param {* } opts
41+ * Initializes CodeceptJS runner with config and options.
42+ * @param {Object } config - Configuration object.
43+ * @param {Object } opts - Options.
5944 */
6045 constructor ( config , opts ) {
6146 this . config = Config . create ( config ) ;
6247 this . opts = opts ;
63- this . testFiles = new Array ( 0 ) ;
64- this . requireModules ( config . require ) ;
48+ this . testFiles = [ ] ;
49+ this . requireModules ( config ? .require ) ;
6550 }
6651
6752 /**
68- * Require modules before codeceptjs running
69- *
70- * @param {string[] } requiringModules
53+ * Requires necessary modules before running CodeceptJS.
54+ * @param {string[] } requiringModules - List of modules to require.
7155 */
7256 requireModules ( requiringModules ) {
73- if ( requiringModules ) {
74- requiringModules . forEach ( ( requiredModule ) => {
75- const isLocalFile = existsSync ( requiredModule ) || existsSync ( `${ requiredModule } .js` ) ;
76- if ( isLocalFile ) {
77- requiredModule = resolve ( requiredModule ) ;
78- }
79- require ( requiredModule ) ;
80- } ) ;
81- }
57+ requiringModules ?. forEach ( ( requiredModule ) => {
58+ const isLocalFile = existsSync ( requiredModule ) || existsSync ( `${ requiredModule } .js` ) ;
59+ const modulePath = isLocalFile ? resolve ( requiredModule ) : requiredModule ;
60+ require ( modulePath ) ;
61+ } ) ;
8262 }
8363
8464 /**
85- * Initialize CodeceptJS at specific directory.
86- * If async initialization is required, pass callback as second parameter.
87- *
88- * @param {string } dir
65+ * Initializes CodeceptJS in a specific directory.
66+ * @param {string } dir - Directory path.
8967 */
9068 init ( dir ) {
9169 this . initGlobals ( dir ) ;
92- // initializing listeners
9370 container . create ( this . config , this . opts ) ;
9471 this . runHooks ( ) ;
9572 }
9673
9774 /**
98- * Creates global variables
99- *
100- * @param {string } dir
75+ * Initializes global variables.
76+ * @param {string } dir - Directory path.
10177 */
10278 initGlobals ( dir ) {
103- // @ts -ignore
10479 global . codecept_dir = dir ;
105- // @ts -ignore
106- global . output_dir = fsPath . resolve ( dir , this . config . output ) ;
80+ global . output_dir = resolve ( dir , this . config . output ) ;
10781
10882 if ( this . config . emptyOutputFolder ) emptyFolder ( global . output_dir ) ;
10983
11084 if ( ! this . config . noGlobals ) {
111- global . Helper = global . codecept_helper = generated ;
112- global . actor = global . codecept_actor = actor0 ;
113- global . pause = pause0 ;
114- global . within = within0 ;
115- global . session = session0 ;
116- global . DataTable = data ;
117- global . locate = locator => new Locator ( locator ) ;
118- global . inject = container . support ;
119- global . share = container . share ;
120- global . secret = secret ;
121- global . codecept_debug = output . debug ;
122- global . codeceptjs = index ; // load all objects
123- global . Given = stepDefinitions . Given ;
124- global . When = stepDefinitions . When ;
125- global . Then = stepDefinitions . Then ;
126- global . DefineParameterType = stepDefinitions . defineParameterType ;
127-
128- // debug mode
129- global . debugMode = false ;
85+ this . initGlobalHelpers ( ) ;
13086 }
13187 }
13288
13389 /**
134- * Executes hooks.
90+ * Initializes global helpers and other CodeceptJS features.
91+ */
92+ initGlobalHelpers ( ) {
93+ global . Helper = global . codecept_helper = index . generated ;
94+ global . actor = global . codecept_actor = actor ;
95+ global . pause = pause ;
96+ global . within = within ;
97+ global . session = session ;
98+ global . DataTable = data ;
99+ global . locate = ( locator ) => new Locator ( locator ) ;
100+ global . inject = container . support ;
101+ global . share = container . share ;
102+ global . secret = secret ;
103+ global . codecept_debug = output . debug ;
104+ global . codeceptjs = index ;
105+
106+ // BDD
107+ global . Given = stepDefinitions . Given ;
108+ global . When = stepDefinitions . When ;
109+ global . Then = stepDefinitions . Then ;
110+ global . DefineParameterType = stepDefinitions . defineParameterType ;
111+ global . debugMode = false ;
112+ }
113+
114+ /**
115+ * Runs all hooks, including custom and default.
135116 */
136117 runHooks ( ) {
137- // default hooks
138- runHook ( listener ) ;
139- runHook ( listener0 ) ;
140- runHook ( listener01 ) ;
141- runHook ( listener012 ) ;
142- runHook ( listener0123 ) ;
143- runHook ( listener01234 ) ;
144- runHook ( listener012345 ) ;
145-
146- // custom hooks (previous iteration of plugins)
147- this . config . hooks . forEach ( hook => runHook ( hook ) ) ;
118+ const listeners = [
119+ listener ,
120+ listenerArtifacts ,
121+ listenerConfig ,
122+ listenerHelpers ,
123+ listenerRetry ,
124+ listenerTimeout ,
125+ listenerExit ,
126+ ] ;
127+
128+ listeners . forEach ( runHook ) ;
129+
130+ // Run custom hooks
131+ this . config . hooks . forEach ( runHook ) ;
148132 }
149133
150134 /**
151- * Executes bootstrap.
152- *
135+ * Executes the bootstrap process.
153136 */
154137 async bootstrap ( ) {
155138 return runHook ( this . config . bootstrap , 'bootstrap' ) ;
156139 }
157140
158141 /**
159- * Executes teardown.
160-
142+ * Executes the teardown process.
161143 */
162144 async teardown ( ) {
163145 return runHook ( this . config . teardown , 'teardown' ) ;
164146 }
165147
166148 /**
167- * Loads tests by pattern or by config.tests
168- *
169- * @param {string } [pattern]
149+ * Loads test files based on the given pattern or config.
150+ * @param {string } [pattern] - Optional pattern for loading tests.
170151 */
171152 loadTests ( pattern ) {
172- const options = {
173- cwd : global . codecept_dir ,
174- } ;
175-
176- let patterns = [ pattern ] ;
177- if ( ! pattern ) {
178- patterns = [ ] ;
179-
180- // If the user wants to test a specific set of test files as an array or string.
181- if ( this . config . tests && ! this . opts . features ) {
182- if ( Array . isArray ( this . config . tests ) ) {
183- patterns . push ( ...this . config . tests ) ;
184- } else {
185- patterns . push ( this . config . tests ) ;
153+ const patterns = this . getTestPatterns ( pattern ) ;
154+ const options = { cwd : global . codecept_dir } ;
155+
156+ patterns . forEach ( ( p ) => {
157+ glob . sync ( p , options ) . forEach ( ( file ) => {
158+ if ( ! file . includes ( 'node_modules' ) ) {
159+ const fullPath = isAbsolute ( file ) ? file : join ( global . codecept_dir , file ) ;
160+ const resolvedFile = resolve ( fullPath ) ;
161+
162+ if ( ! this . testFiles . includes ( resolvedFile ) ) {
163+ this . testFiles . push ( resolvedFile ) ;
164+ }
186165 }
187- }
166+ } ) ;
167+ } ) ;
168+ }
188169
189- if ( this . config . gherkin . features && ! this . opts . tests ) {
190- if ( Array . isArray ( this . config . gherkin . features ) ) {
191- this . config . gherkin . features . forEach ( feature => {
192- patterns . push ( feature ) ;
193- } ) ;
194- } else {
195- patterns . push ( this . config . gherkin . features ) ;
196- }
197- }
170+ /**
171+ * Gets test patterns based on config and options.
172+ * @param {string } [pattern] - Test pattern to match.
173+ * @returns {string[] } - Array of test patterns.
174+ */
175+ getTestPatterns ( pattern ) {
176+ if ( pattern ) return [ pattern ] ;
177+
178+ const patterns = [ ] ;
179+ const { tests, gherkin } = this . config ;
180+
181+ if ( tests && ! this . opts . features ) {
182+ patterns . push ( ...( Array . isArray ( tests ) ? tests : [ tests ] ) ) ;
198183 }
199184
200- for ( pattern of patterns ) {
201- glob . sync ( pattern , options ) . forEach ( ( file ) => {
202- if ( file . includes ( 'node_modules' ) ) return ;
203- if ( ! fsPath . isAbsolute ( file ) ) {
204- file = fsPath . join ( global . codecept_dir , file ) ;
205- }
206- if ( ! this . testFiles . includes ( fsPath . resolve ( file ) ) ) {
207- this . testFiles . push ( fsPath . resolve ( file ) ) ;
208- }
209- } ) ;
185+ if ( gherkin ?. features && ! this . opts . tests ) {
186+ patterns . push ( ...( Array . isArray ( gherkin . features ) ? gherkin . features : [ gherkin . features ] ) ) ;
210187 }
188+
189+ return patterns ;
211190 }
212191
213192 /**
214- * Run a specific test or all loaded tests.
215- *
216- * @param {string } [test]
193+ * Runs tests either specific to a file or all loaded tests.
194+ * @param {string } [test] - Test file to run.
217195 * @returns {Promise<void> }
218196 */
219197 async run ( test ) {
220- return new Promise ( ( resolve , reject ) => {
221- const mocha = container . mocha ( ) ;
222- mocha . files = this . testFiles ;
223- if ( test ) {
224- if ( ! fsPath . isAbsolute ( test ) ) {
225- test = fsPath . join ( global . codecept_dir , test ) ;
226- }
227- mocha . files = mocha . files . filter ( t => fsPath . basename ( t , '.js' ) === test || t === test ) ;
228- }
229- const done = ( ) => {
230- event . emit ( event . all . result , this ) ;
231- event . emit ( event . all . after , this ) ;
232- resolve ( ) ;
233- } ;
198+ const mocha = container . mocha ( ) ;
199+ mocha . files = this . testFiles ;
234200
235- try {
201+ if ( test ) {
202+ const testPath = isAbsolute ( test ) ? test : join ( global . codecept_dir , test ) ;
203+ mocha . files = mocha . files . filter ( ( t ) => resolve ( t ) === resolve ( testPath ) ) ;
204+ }
205+
206+ return new Promise ( ( resolve , reject ) => {
207+ try { x
236208 event . emit ( event . all . before , this ) ;
237- mocha . run ( ( ) => done ( ) ) ;
238- } catch ( e ) {
239- output . output . error ( e . stack ) ;
240- reject ( e ) ;
209+ mocha . run ( ( ) => {
210+ event . emit ( event . all . result , this ) ;
211+ event . emit ( event . all . after , this ) ;
212+ resolve ( ) ;
213+ } ) ;
214+ } catch ( error ) {
215+ output . output . error ( error . stack ) ;
216+ reject ( error ) ;
241217 }
242218 } ) ;
243219 }
244220}
245221
222+ /**
223+ * Retrieves the version from package.json.
224+ * @returns {string } - The version of the package.
225+ */
246226export function version ( ) {
247- return JSON . parse ( readFileSync ( ` ${ __dirname } / ../package.json` , 'utf8' ) ) . version ;
227+ return JSON . parse ( readFileSync ( resolve ( __dirname , ' ../package.json' ) , 'utf8' ) ) . version ;
248228}
0 commit comments