I'm following a page object pattern for use with WebDriver JS based automation code. The tutorial called for a page object that looks something like what's below using Object.create() to create an object that extends a simple Page object -- but their example didn't cover having functions that referenced this
from inside the created object. I've tried changing the the object param get
and value
around a couple different ways in the property configuration and haven't noticed a difference so far.
page.js:
"use strict";
function Page() {
}
Page.prototype.open = function(path) {
browser.url('/' + path);
};
Page.prototype.getUrl = function() {
return browser.getUrl();
};
module.exports = new Page();
login.page.js:
"use strict";
var Page = require('./page');
var LoginPage = Object.create(Page, {
email: { value: 'input#email' } ,
password: { value: 'input#password' } ,
loginButton: { value: 'button#login-button' },
errorText: { value: 'span.help-block' },
loginErrorMessage: { value: 'These credentials do not match our records.' },
open: { value: function() {
Page.open('login');
}},
loginAsTestUser: { value: function() {
this.open();
browser.logger.info('Logging in');
this.login('test@dev.com', 'test');
}},
login: { value: function(email, password) {
browser.element(this.email).setValue(email);
browser.element(this.password).setValue(password);
browser.element(this.loginButton).click();
}}
});
module.exports = LoginPage;
test.spec.js
"use strict";
var LoginPage = require('../pages/login.page.js');
var Header = require('../pages/header.page.js');
describe('Navigation bar', function() {
before('open login page', LoginPage.open);
it('should be visible', function() {
browser.isVisibleWithinViewport(Header.navbar).should.be.true;
});
describe('when logged in', function() {
before('login', LoginPage.loginAsTestUser);
it('should have the Add dropdown list displayed', function() {
browser.isVisibleWithinViewport(Header.addDropdownButton).should.be.true;
});
after('logout', Header.logout);
});
});
Here's the error for this.open
:
1) Navigation bar when logged in "before all" hook:
this.open is not a function
running chrome
TypeError: this.open is not a function
at Context.<anonymous> (/code/tests/test/pages/login.page.js:20:18)
at Promise.F (/code/tests/node_modules/core-js/library/modules/_export.js:35:28)
And when this.open();
is replaced with its function to let the code progress, this.login();
errors as well:
1) Navigation bar when logged in "before all" hook:
this.login is not a function
running chrome
TypeError: this.login is not a function
at Context.<anonymous> (/code/tests/test/pages/login.page.js:24:18)
at Promise.F (/code/tests/node_modules/core-js/library/modules/_export.js:35:28)
I guess I could see this
not meaning much in that property config object being passed to Object.create
but I'm not sure how else you'd do this - the documentation for Object.defineProperties doesn't even reference an example that works this way.
Edit: This is different from the proposed duplicate question: How to access the correct `this` inside a callback? - I am talking about referencing variable properties of an object while I'm creating it because the variables build on each other. The proposed duplicate is talking about JavaScript scope issues in general with this
- this particular question is a lot more focused and is more about how to build properties of an object using other properties of that object before that object is fully created.