Angular2 + e2e测试 - 不能使用by.id.

时间:2017-06-02 15:55:19

标签: javascript angular protractor e2e-testing

我是Angular2的新手,并且没有开发出要测试的Angular组件。但是,我应该编写一些UI(e2e)测试,但我甚至无法在输入字段中输入文本。

我的问题是  element(by.id('username')).sendKeys('test') 不管用。 (与Button元素相同,等等)

我确信这只是一件小事,但我无法弄清楚它是什么。

我有以下配置:

  • Proctractor :5.1.2
  • Chrome驱动程序:58.0.3029.110
  • 操作系统:Windows NT 6.1.7601 SP1 x86_64

规范文件:

import { LoginPage } from './login.po';

describe('login tests', function() {
  let page: LoginPage;

  beforeEach(() => {
    page = new LoginPage();
  });

  it('Demo', () => {
    page.navigateTo();
    page.getUsernameInput().sendKeys('test');
  });
});

页面对象文件:

import { browser, element, by } from 'protractor';

export class LoginPage {
  navigateTo() {
    return browser.get('/login');
  }

  getParagraphText() {
    return element(by.class('app-root h1')).getText();
  }

  getUsernameInput() {
    return element(by.id('username'));
  }
}

HTML模板:

....
<div>
  <input
    id="username" 
    name="username" 
    ngModel 
    type="text" 
    placeholder="{{something}}" 
    autocomplete="off" 
    class="input-text" 
    required>
</div>
...

Proctractor配置

var SpecReporter = require('jasmine-spec-reporter');

exports.config = {
    allScriptsTimeout: 120000,
    getPageTimeout: 120000,
    specs: [
      './e2e/**/*.e2e-spec.ts'
    ],
    capabilities: {
      'browserName': 'chrome'
    },
    directConnect: true,
    seleniumAddress: 'http://localhost:4444/wd/hub',
    baseUrl: 'http://localhost:8001',
    framework: 'jasmine',
    jasmineNodeOpts: {
      showColors: true,
      defaultTimeoutInterval: 30000,
      print: function() {}
    },
    useAllAngular2AppRoots: true,
    beforeLaunch: function() {
      require('ts-node').register({
        project: 'e2e'
      });
    },
    onPrepare: function() {
      jasmine.getEnv().addReporter(new SpecReporter());
    }
};

非常感谢任何帮助。

修改 在我的案例中没有一个解决方案。我最终使用browser.driver.findElement(by.id('username'));代替element(by.id('username'));这是不满意的,因为我仍然不明白为什么这不起作用。如果有人能给我一个提示或解释,我会感激不尽。

2 个答案:

答案 0 :(得分:2)

我认为你的问题是时机。

如果您这样做会发生什么:

it('Demo', () => {
    // wait for page to change to /login
    return page.navigateTo().then(() => {
        // then look for user input and write 'test' 
        return page.getUsernameInput().sendKeys('test');
    });    
});

编辑:

我觉得browser.driver.findElement(by.id('username'))有效,因为element(by.id('username'))应该是等效的,这听起来很奇怪。

我使用辅助类来进行大量的浏览器交互,也许值得一试。

我用来查找元素和发送击键的片段:

public static async getElement(locator: By | Function, waitMs?: number): Promise<ElementFinder | any> {

    await BrowserHelper.waitForVisibilityOf(locator, waitMs | 1000);

    return element(locator);
}

public static sendKeys(locator: By | Function, keys: string, clear?: boolean, waitMs?: number): Promise<void> {
    return BrowserHelper.getElement(locator, waitMs).then((element: ElementFinder) => {
        if (!clear) {
            return element;
        }

        return element.clear().then(() => element);
    }).then((element: ElementFinder) => {
        return element.sendKeys(keys)
    });
}

public static async waitForVisibilityOf(locator: By | Function, waitMs?: number): Promise<any> {
    await browser.wait(EC.presenceOf(element(locator)), waitMs || 5000).then(() => {
        // visible
    }, (error) => {
        console.error('timeout at waitForVisibilityOf', locator, error);
    });
}

答案 1 :(得分:0)

我认为这是由于您的getUsernameInput()方法在这种情况下不返回定位器。根据Protractor文档,

  

element()函数返回一个ElementFinder对象。 ElementFinder知道如何使用您作为参数传入的定位器来定位DOM元素,但它实际上还没有这样做。在调用操作方法之前,它不会联系浏览器。

您可以尝试修改此代码

   getUsernameInput() {
      element(by.id('username')).sendKeys('text');
    }
   }

然后使用

  it('Demo', () => {
      page.navigateTo();
      page.getUsernameInput();
  });
});

此外,我不确定您的getText()是否会返回文字,因为getText()会返回您必须解决的承诺。这已经解释为here