Skip to content

Commit 783e473

Browse files
VorobeykoDavertMik
authored andcommitted
fix(pageObject): Not work when PageObject as class (#1896)
* fix(pageObject): Not work when PageObject as class * fix * fix * fix * fix * fix by comment * fix
1 parent 96b2868 commit 783e473

8 files changed

Lines changed: 148 additions & 2 deletions

File tree

lib/container.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,12 +292,41 @@ function loadSupportObject(modulePath, supportObjectName) {
292292
modulePath = path.join(global.codecept_dir, modulePath);
293293
}
294294
try {
295-
return require(modulePath);
295+
const obj = require(modulePath);
296+
if (typeof obj !== 'function'
297+
&& Object.getPrototypeOf(obj) !== Object.prototype
298+
&& !Array.isArray(obj)
299+
) {
300+
return getObjectMethods(obj);
301+
}
302+
303+
return obj;
296304
} catch (err) {
297305
throw new Error(`Could not include object ${supportObjectName} from module '${modulePath}'\n${err.message}`);
298306
}
299307
}
300308

309+
/**
310+
* Method collect own property and prototype
311+
*/
312+
function getObjectMethods(obj) {
313+
const methodsSet = new Set();
314+
let protoObj = Reflect.getPrototypeOf(obj);
315+
do {
316+
if (protoObj.constructor.prototype !== Object.prototype) {
317+
const keys = Reflect.ownKeys(protoObj);
318+
keys.forEach(k => methodsSet.add(k));
319+
}
320+
}
321+
while (protoObj = Reflect.getPrototypeOf(protoObj));
322+
Reflect.ownKeys(obj).forEach(k => methodsSet.add(k));
323+
const methods = {};
324+
for (const key of methodsSet.keys()) {
325+
if (key !== 'constructor') methods[key] = obj[key];
326+
}
327+
return methods;
328+
}
329+
301330
function loadTranslation(translation) {
302331
if (!translation) {
303332
return new Translation({
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
exports.config = {
2+
tests: './*_test.js',
3+
output: './output',
4+
helpers: {
5+
CustomHelper: {
6+
require: './customHelper.js',
7+
},
8+
},
9+
include: {
10+
classpage: './pages/classpage.js',
11+
classnestedpage: './pages/classnestedpage.js',
12+
},
13+
bootstrap: null,
14+
mocha: {},
15+
name: 'pageobject-as-class',
16+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// const Helper = require('../../lib/helper');
2+
3+
class CustomHelper extends Helper {
4+
printMessage(s) {
5+
// this.debug('Print message from CustomHelper');
6+
console.log(s);
7+
}
8+
}
9+
10+
module.exports = CustomHelper;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Feature('PageObject');
2+
3+
Scenario('@ClassPageObject', async (I, classpage) => {
4+
await classpage.type('Class Page Type');
5+
await classpage.purgeDomains();
6+
});
7+
8+
9+
Scenario('@NestedClassPageObject', (I, classnestedpage) => {
10+
classnestedpage.type('Nested Class Page Type');
11+
classnestedpage.purgeDomains();
12+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const { I } = inject();
2+
3+
class Base {
4+
async type(s) {
5+
await I.printMessage(s);
6+
}
7+
}
8+
9+
class PageObject extends Base {
10+
constructor() {
11+
super();
12+
this.method1 = () => { console.log(123); };
13+
}
14+
15+
purgeDomains() {
16+
I.printMessage('purgeDomains');
17+
}
18+
}
19+
20+
module.exports = new PageObject();
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const { I } = inject();
2+
3+
class PageObject {
4+
constructor() {
5+
this.method1 = () => { console.log(123); };
6+
}
7+
8+
async type(s) {
9+
await I.printMessage(s);
10+
}
11+
12+
purgeDomains() {
13+
I.printMessage('purgeDomains');
14+
}
15+
}
16+
17+
module.exports = new PageObject();

test/runner/pageobject_test.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const assert = require('assert');
2+
const path = require('path');
3+
const exec = require('child_process').exec;
4+
5+
const runner = path.join(__dirname, '/../../bin/codecept.js');
6+
const codecept_dir = path.join(__dirname, '/../data/sandbox/configs/pageObjects');
7+
const codecept_run = `${runner} run`;
8+
const config_run_config = (config, grep) => `${codecept_run} --config ${codecept_dir}/${config} ${grep ? `--grep "${grep}"` : ''}`;
9+
const config_run_override = config => `${codecept_run} --override '${JSON.stringify(config)}'`;
10+
11+
describe('CodeceptJS Interface', () => {
12+
before(() => {
13+
process.chdir(codecept_dir);
14+
});
15+
16+
it('should inject page objects by class', (done) => {
17+
exec(`${config_run_config('codecept.conf.js', '@ClassPageObject')} --debug`, (err, stdout) => {
18+
stdout.should.not.include('classpage.type is not a function');
19+
stdout.should.include('classpage: type');
20+
stdout.should.include('I print message "Class Page Type"');
21+
stdout.should.include('classpage: purgeDomains');
22+
stdout.should.include('I print message "purgeDomains"');
23+
stdout.should.include('Class Page Type');
24+
stdout.should.include('OK | 1 passed');
25+
assert(!err);
26+
done();
27+
});
28+
});
29+
30+
it('should inject page objects by class which nested base clas', (done) => {
31+
exec(`${config_run_config('codecept.conf.js', '@NestedClassPageObject')} --debug`, (err, stdout) => {
32+
stdout.should.not.include('classnestedpage.type is not a function');
33+
stdout.should.include('classnestedpage: type');
34+
stdout.should.include('I print message "Nested Class Page Type"');
35+
stdout.should.include('classnestedpage: purgeDomains');
36+
stdout.should.include('I print message "purgeDomains"');
37+
stdout.should.include('Nested Class Page Type');
38+
stdout.should.include('OK | 1 passed');
39+
assert(!err);
40+
done();
41+
});
42+
});
43+
});

test/runner/run_multiple_test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ describe('CodeceptJS Multiple Runner', function () {
176176
const _codecept_run = `run-multiple --config ${codecept_dir}`;
177177
it('should be executed from async function in config', (done) => {
178178
exec(`${runner} ${_codecept_run}/codecept.async.bootstrapall.multiple.code.js default`, (err, stdout, stderr) => {
179-
console.log(stdout);
180179
stdout.should.include('CodeceptJS'); // feature
181180
stdout.should.include('Results: inside Promise\n"event.multiple.before" is called');
182181
stdout.should.include('"teardownAll" is called.');

0 commit comments

Comments
 (0)