简体   繁体   English

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

[英]Angular2+ e2e testing - Cannot use by.id

I'm new to Angular2 and haven't developed the Angular components to be tested. 我是Angular2的新手,还没有开发要测试的Angular组件。 However, I'm supposed to write some some UI (e2e) tests but I'm not even able to input text in an input field. 但是,我应该编写一些UI(e2e)测试,但是我什至无法在输入字段中输入文本。

My problem is that element(by.id('username')).sendKeys('test') is not working. 我的问题是element(by.id('username')).sendKeys('test')无法正常工作。 (Same with Button elements and so on) (与Button元素相同,依此类推)

I'm sure that it is only a small thing but I'm not able to find out what it is. 我确定这只是一件小事,但我无法找出它是什么。

I have the following configuration: 我有以下配置:

  • Proctractor : 5.1.2 量角器 :5.1.2
  • chrome driver : 58.0.3029.110 chrome驱动程序 :58.0.3029.110
  • OS : Windows NT 6.1.7601 SP1 x86_64 作业系统 :Windows NT 6.1.7601 SP1 x86_64

Spec file: 规格文件:

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

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

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

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

Page Object file: 页面对象文件:

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

The HTML template: HTML模板:

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

Proctractor config 量角器配置

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

Any help is highly appreciated. 非常感谢您的帮助。

EDIT: None of the solutions worked in my case. 编辑:在我的情况下没有解决方案。 I ended up using browser.driver.findElement(by.id('username')); 我最终使用了browser.driver.findElement(by.id('username')); instead of element(by.id('username')); 而不是element(by.id('username')); This is unsatisfying because I still don't understand why this doesn't work. 这是不令人满意的,因为我仍然不明白为什么这不起作用。 I'd be thankful if someone could give me a hint or explanation. 如果有人可以给我提示或解释,我将不胜感激。

I think your problem is timing. 我认为您的问题是时机。

What happens if you do: 如果您这样做会发生什么:

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

Edit: 编辑:

Sounds odd to me that browser.driver.findElement(by.id('username')) works since element(by.id('username')) should be equivalent. 由于element(by.id('username'))应该等效,所以browser.driver.findElement(by.id('username'))起作用对我来说听起来很奇怪。

I use a helper class for a lot of the browser interactions, perhaps worth a shot. 我在许多浏览器交互中都使用了一个辅助类,也许值得一试。

Snippets I use for finding element and sending keystrokes: 我用于查找元素和发送击键的代码片段:

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

I believe this is due to your getUsernameInput() method returning not the locator in this case. 我相信这是由于在这种情况下,您的getUsernameInput()方法未返回定位符。 As per Protractor documentation, 根据量角器文档,

The element() function returns an ElementFinder object. element()函数返回一个ElementFinder对象。 The ElementFinder knows how to locate the DOM element using the locator you passed in as a parameter, but it has not actually done so yet. ElementFinder知道如何使用您作为参数传入的定位器来定位DOM元素,但实际上尚未这样做。 It will not contact the browser until an action method has been called. 在调用动作方法之前,它不会与浏览器联系。

You can try this modified code 您可以尝试此修改后的代码

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

and then using 然后使用

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

Also, I'm not sure your getText() would return the text, because getText() returns a Promise, which you would have to resolve. 另外,我不确定您的getText()是否会返回文本,因为getText()返回的Promise必须解决。 This has been explained here . 这已经在这里解释

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM