Skip to content

Commit 8e2fc37

Browse files
committed
fix: codepcept-js code and types
1 parent a7e5a76 commit 8e2fc37

File tree

2 files changed

+197
-567
lines changed

2 files changed

+197
-567
lines changed

lib/codecept.js

Lines changed: 132 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { existsSync, readFileSync } from 'fs';
22
import glob from 'glob';
3-
import fsPath, { resolve, dirname } from 'path';
4-
import generated from '@codeceptjs/helper';
3+
import { resolve, dirname, isAbsolute, join } from 'path';
54
import { fileURLToPath } from 'url';
65
import { createRequire } from 'node:module';
76
import container from './container.js';
@@ -12,237 +11,218 @@ import * as output from './output.js';
1211
import { emptyFolder } from './utils.js';
1312
import * 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';
2319
import data from './data/table.js';
24-
2520
import Locator from './locator.js';
26-
2721
import secret from './secret.js';
28-
29-
// BDD
3022
import * as stepDefinitions from './interfaces/bdd.js';
3123

24+
// Listeners
3225
import 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

4633
const __dirname = dirname(fileURLToPath(import.meta.url));
4734
const require = createRequire(import.meta.url);
4835

4936
/**
50-
* CodeceptJS runner
37+
* CodeceptJS runner class.
5138
*/
5239
export 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+
*/
246226
export 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

Comments
 (0)