I'm working on some QE tests using node.js, selenium-webdriver, mocha, and chai.
I'm creating UI tests and ran into a problem with my tests failing.
This is the error I am getting:
Uncaught TypeError: Cannot read property 'isElementPresent' of undefined
at test/admin/users/add_user/org_admin_adds_new_users_positive.js:65:29
at node_modules/selenium-webdriver/lib/webdriver/webdriver.js:720:12
I don't understand what I am doing wrong. All the methods I created in my page objects work correctly. I can even see firefox run the tests and adding the organizations correctly so I know I am properly using selenium-webdriver (well most of it).
The logic of my tests are: 1) adding a organization through a modal window 2) verify that we have correctly added an organization by testing to see if an element that was on the previous screen is now visible.
I run my tests headlessly and I have some issues with the server we are using so I thought by introducing the wait method would fix my issues and fragile tests.
Here is the link to the method I am trying to use: http://selenium.googlecode.com/git/docs/api/javascript/class_webdriver_WebDriver.html#wait
I'm basically tweaking the this answer to a SO Q for my own purpose: Selenium WebDriver wait till element is displayed
turning it to this:
this.driver.wait(function() {
return this.driver.isElementPresent(By.css('div.AppBar'));
}, 10000);
Here is my entire test code:
var driver = require('selenium-webdriver');
var chai = require('chai');
var expect = chai.expect;
var adminVar = require('_/variables/admin_variables');
var AdminLogin = require('_/pageObject/admin/login/index');
var Common = require('_/pageObject/admin/login/common/index');
var HamburgerMenu = require('_/pageObject/admin/login/common/hamburgerMenu/index');
var Users = require('_/pageObject/admin/login/users/index');
var AddUserModal = require('_/pageObject/admin/login/users/addUserModal/index');
var userVar = require('_/variables/users_variables.json');
chai.use(require('chai-as-promised'));
describe('Admin Tests - Org Admin User', function() {
this.timeout(500000);
before(function() {
this.driver = new driver.Builder().withCapabilities(driver.Capabilities.firefox()).build();
this.driver.get(adminVar.local.adminSignin);
var adminLogin = new AdminLogin(this.driver);
adminLogin.fillEmail();
adminLogin.fillPassword();
adminLogin.signin();
return this.driver.manage().timeouts().implicitlyWait(2500);
});
after(function() {
return this.driver.quit();
});
describe('would like to click Users panel', function() {
before(function() {
var com = new Common(this.driver);
com.clickHamburger();
var hamburgMenu = new HamburgerMenu(this.driver);
hamburgMenu.clickUser();
});
describe('add a new user', function() {
beforeEach(function() {
var users = new Users(this.driver);
this.driver.sleep(500);
users.addNewUser();
return this.driver.manage().timeouts().implicitlyWait(3500);
});
afterEach(function() {
return this.driver.manage().timeouts().implicitlyWait(3500);
});
it('correctly add user: name - Model Employee && email - memployee@test.com', function() {
var userModal = new AddUserModal(this.driver);
this.driver.manage().timeouts().pageLoadTimeout(10000);
userModal.addUser(userVar.goodUser1.name, userVar.goodUser1.email);
var users = new Users(this.driver);
this.driver.wait(function() {
return this.driver.isElementPresent(By.css('div.AppBar ul.AppBar-breadcrumbs'));
}, 10000);
return expect(users.toggleFilter.isDisplayed()).to.eventually.equal(true);
});
it('correctly add user: name - £∆ΩΩ¥ ßœ†∑®§ && email - unicode1@test.com', function() {
var userModal = new AddUserModal(this.driver);
this.driver.manage().timeouts().pageLoadTimeout(10000);
userModal.addUser(userVar.badUser3.name, userVar.badUser3.email);
var users = new Users(this.driver);
this.driver.wait(function() {
return this.driver.isElementPresent(By.css('div.AppBar ul.AppBar-breadcrumbs'));
}, 10000);
return expect(users.toggleFilter.isDisplayed()).to.eventually.equal(true);
});
});
});
});
Here are the relevant page objects I am using for this code:
class Organizations {
constructor(driver) {
this.driver = driver;
this.driver.manage().timeouts().implicitlyWait(2000);
var name;
this.pageHeader = this.driver.findElement({
css: 'div.AppBar ul.AppBar-breadcrumbs > li > span'
});
this.toggleFilter = this.driver.findElement({
css: 'div.AppBar button.AppBar-filter'
});
this.inputFilter = this.driver.findElement({
css: 'div.OrganizationListFilters-byText input[type="text"]'
});
this.addButton = this.driver.findElement({
css: '#app > div > div > div > div > div.Page-wrapper > div:nth-child(2) > div.Material-button--primary > div > button'
});
}
clearSearch() {
this.inputFilter.clear();
}
inputSearch(name) {
this.inputFilter.clear();
this.inputFilter.sendKeys(name);
return this.driver.manage().timeouts().implicitlyWait(1000);
}
toggleSearch() {
this.toggleFilter.click();
return this.driver.manage().timeouts().implicitlyWait(4500);
}
addNewOrgButton() {
this.driver.manage().timeouts().implicitlyWait(7500);
this.addButton.click();
return this.driver.manage().timeouts().implicitlyWait(2500);
}
menuButtonAfterAction() {
this.driver.manage().timeouts().implicitlyWait(1500);
this.driver.findElement({
css: 'td.RowMenu button.RowMenu-button'
}).click();
return this.driver.manage().timeouts().implicitlyWait(2500);
}
}
module.exports = Organizations;
and the adding an organization modal
class AddOrgModal {
constructor(driver) {
this.driver = driver;
this.driver.manage().timeouts().implicitlyWait(2000);
var name, subdomain, type, id;
this.modalTitle = this.driver.findElement({
css: 'div.AddOrganizationDialog h3'
});
this.nameInput = this.driver.findElement({
css: 'div.AddOrganizationDialog input[name="name"]'
});
this.domainInput = this.driver.findElement({
css: 'div.AddOrganizationDialog input[name="domain"]'
});
this.typeInput = this.driver.findElement({
css: 'div.AddOrganizationDialog input[name="type"]'
});
this.idInput = this.driver.findElement({
css: 'div.AddOrganizationDialog input[name="externalID"]'
});
this.enableExperience = this.driver.findElement({
css: 'div.AddOrganizationDialog input[name="hasExperience"]'
});
this.subdomainInput = this.driver.findElement({
css: 'div.AddOrganizationDialog input[name="subdomain"]'
});
this.cancelButton = this.driver.findElement({
css: 'div.AddOrganizationDialog button.AddOrganizationDialog-cancel'
});
this.submitButton = this.driver.findElement({
css: 'div.AddOrganizationDialog button.AddOrganizationDialog-submit'
});
}
getHeaderText() {
return this.driver.modalTitle.getText();
}
cancelModal() {
this.cancelButton.click();
}
newOrg(name, subdomain, type, id) {
this.driver.manage().timeouts().implicitlyWait(3000);
this.nameInput.clear();
this.nameInput.sendKeys(name);
this.typeInput.clear();
this.typeInput.sendKeys(type);
this.idInput.clear();
this.idInput.sendKeys(id);
this.enableExperience.click();
this.subdomainInput.clear();
this.subdomainInput.sendKeys(subdomain);
this.submitButton.click();
return this.driver.manage().timeouts().implicitlyWait(5000);
}
}
module.exports = AddOrgModal;
As I stated above I believe I am using and referencing selenium-webdriver correctly, the docs are kinda confusing because they don't provide actual examples and I'm still somewhat new using testing frameworks.
Is there something I am missing?
tl:dr version:
I believe I'm referencing selenium-webdriver correctly for this function:
this.driver.wait(function() {
return this.driver.isElementPresent(By.css('div.AppBar'));
}, 10000);
but I still get the error
Uncaught TypeError: Cannot read property 'isElementPresent' of undefined
at test/admin/users/add_user/org_admin_adds_new_users_positive.js:65:29
at node_modules/selenium-webdriver/lib/webdriver/webdriver.js:720:12