未捕获的TypeError:无法读取未定义

时间:2016-03-02 17:34:43

标签: javascript node.js selenium-webdriver

我正在使用node.js,selenium-webdriver,mocha和chai进行一些QE测试。

我正在创建UI测试并遇到问题,我的测试失败了。

这是我得到的错误:

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

我不明白我做错了什么。我在页面对象中创建的所有方法都能正常工作。我甚至可以看到firefox运行测试并正确添加组织所以我知道我正在使用selenium-webdriver(大部分都是这样)。

我的测试逻辑是:1)通过模态窗口添加组织2)通过测试验证我们是否已正确添加组织,以查看上一个屏幕上的元素现在是否可见。

我无头地运行我的测试,我对使用的服务器有一些问题所以我想通过介绍等待方法将解决我的问题和脆弱的测试。

以下是我尝试使用的方法的链接: http://selenium.googlecode.com/git/docs/api/javascript/class_webdriver_WebDriver.html#wait

我基本上是为了自己的目的将这个答案调整为SO Q: Selenium WebDriver wait till element is displayed

转向它:

this.driver.wait(function() {
  return this.driver.isElementPresent(By.css('div.AppBar'));
}, 10000);

这是我的整个测试代码:

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);
      });
    });

  });

});

以下是我为此代码使用的相关页面对象:

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;

并添加组织模式

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;

正如我上面所说的,我相信我正在使用和正确引用selenium-webdriver,文档有点令人困惑,因为它们没有提供实际的例子,而且我使用测试框架仍然有点新。

我有什么遗失的吗?

tl:dr版本:

我相信我正在为此功能正确引用selenium-webdriver:

this.driver.wait(function() {
  return this.driver.isElementPresent(By.css('div.AppBar'));
}, 10000);

但我仍然收到错误

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

2 个答案:

答案 0 :(得分:0)

尝试,返回this.isElementPresent(By.css('div.AppBar'));

答案 1 :(得分:0)

我可能错了,因为我没有使用Node.js对Selenium进行编码,但我猜想.isElementPresent方法只对Element实例而不是驱动程序实例本身有意义。

换句话说,我猜这会更有意义:

this.driver.findElement(By.css('div.AppBar')).isElementPresent()

如果我错了,请原谅。问题的性质使我不得不猜测。