角度量角器-验证页面重定向

时间:2020-02-27 10:52:42

标签: angular protractor angular-e2e

我正在Angular应用程序中编写一些E2E测试。我遇到的一个问题是,每当我重定向到新路由时,我都想验证是否显示了正确的组件。由于某些原因,这总是会导致失败并出现以下错误:

- Failed: script timeout

我一直在网上搜索以寻求解决方案,但是我发现的所有解决方案都不适用于我。

示例

  • 等待Angular

browser.waitForAngular();

Reference

  • 检查浏览器的当前URL并与预期URL进行比较:
browser.driver.wait(() => {
    browser.driver.getCurrentUrl().then((url) => {
        return /expected-url/.test(url);
    });
}, 10000);

Reference


代码示例

以下是测试登录功能的代码示例。

登录页面对象类

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

export class LoginPage {
    private credentials: { username: string, password: string } = {
        username: 'admin',
        password: 'admin'
    };

    navigateTo() {
        return browser.get(browser.baseUrl) as Promise<any>;
    }

    getLoginComponent() {
        return element(by.css('ra-login'));
    }

    getUsernameTextbox() {
        return element(by.css('ra-login [data-test-id="username"]'));
    }

    getPasswordTextbox() {
        return element(by.css('ra-login [data-test-id="password"]'));
    }

    getLoginButton() {
        return element(by.css('ra-login [data-test-id="login-btn"]'));
    }

    getSecurePage() {
        return element(by.css('ra-secure-content'));
    }

    login(credentials: { username: string, password: string } = this.credentials) {
        this.getUsernameTextbox().sendKeys(credentials.username);
        this.getPasswordTextbox().sendKeys(credentials.password);
        this.getLoginButton().click();
    }

    getErrorMessage() {
        return element(by.css('ra-login [data-test-id="login-error"]'));
    }
}

登录E2E规范文件

describe('Login Functionality', () => {
    let loginPage: LoginPage;

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

    // Test runs successfully
    it('should display login', () => {
        loginPage.navigateTo();
        expect(loginPage.getLoginComponent().isPresent()).toBeTruthy();
    });

    // Test runs successfully
    it('should have the login button disabled', () => {
        loginPage.navigateTo();
        expect(loginPage.getLoginButton().isEnabled()).toBe(false);
    });

    // Test runs fails
    it('should redirect to a secure page', () => {
        loginPage.navigateTo();
        loginPage.login();

        expect(loginPage.getSecurePage().isPresent()).toBeTruthy();
    });

    afterEach(async () => {
        // Assert that there are no errors emitted from the browser
        const logs = await browser.manage().logs().get(logging.Type.BROWSER);
        expect(logs).not.toContain(jasmine.objectContaining({
            level: logging.Level.SEVERE,
        } as logging.Entry));
    });
});

使用以上代码,测试'should redirect to a secure page'失败。此测试试图验证成功登录后是否显示“安全内容”组件。此组件是包装器组件,用于托管仅在用户登录后才能显示的页面。

页面重定向始终成功,并且正在显示正确的页面。我怀疑测试是否以某种方式试图在实际重定向之前使元素存在?

我是E2E的新手,所以我不确定这是否是问题所在。


以防万一,这是重要软件包的版本号:

  • 角度:8.2.14
  • Angular CLI :8.2.2
  • 量角器:5.4.2
  • 茉莉花:2.8.0

3 个答案:

答案 0 :(得分:0)

我建议您使用异步/等待语句结构。您的怀疑似乎已经纠正,并且您面临的问题是由于诺言处理不当。

您可以尝试将规范写为:

it('should redirect to a secure page', async() => {
        await loginPage.navigateTo();
        await loginPage.login();

        expect(await(await loginPage.getSecurePage()).isPresent()).toBeTruthy();
    });

还将导航和登录功能更改为:

async navigateTo() {
        return await browser.get(browser.baseUrl);
    }

只要有浏览器交互,就可以添加await;如果有任何await语句,则可以使函数异步。

引用:[1]:https://hackernoon.com/should-i-use-promises-or-async-await-126ab5c98789

答案 1 :(得分:0)

u必须与操作符then一起使用promise这个解决方案对我有用 如果您知道响应时间,可以使用

browser.driver.sleep(1000)

但这是一个坏习惯

注意:如果应用程序非常慢,则是时候报告性能问题了。

答案 2 :(得分:0)

就我而言,除了等待某些Promise对象外,我还有其他原因导致错误。长话短说,我有一个间隔,负责向用户显示当前时间。由于间隔是异步函数,因此量角器将假定Angular仍在运行某些函数,因此将继续等待Angular进行“响应”。

在Angular 2+中,为了适应这种情况,setInterval()函数需要在Angular区域之外运行。

示例

ngOnInit() {
    this.now = new Date();

    setInterval(() => {
        this.now = new Date();
    }, 1000);
}

以上代码将导致Protractor在页面上存在具有间隔的组件时给出超时。

要解决此问题,我们可以使用NgZone

示例

import { NgZone } from '@angular/core';

constructor(private ngZone: NgZone) { }

ngOnInit() {
    this.now = new Date();

    // running setInterval() function outside angular
    // this sets the asynchronous call to not run within the angular zone
    this.ngZone.runOutsideAngular(() => {
        setInterval(() => {
            // update the date within angular, so that change detection is triggered
            this.ngZone.runTask(() => {
                this.now = new Date();
            });
        }, 1000);
    });
}

参考


在测试中,我还添加了一个实用程序功能,该功能有助于等待元素在屏幕上显示。

import { ElementFinder, ExpectedConditions, browser } from 'protractor';

const until = ExpectedConditions;

export const waitForElement = (elementToFind: ElementFinder, timeout = 10000) => {
    return browser.wait(until.presenceOf(elementToFind), timeout, 'Element not found');
};

然后将哪些用于这样的测试中:

it('should redirect to a secure page', async () => {
    loginPage.navigateTo();
    loginPage.login();

    const secureContent = loginPage.getSecureContentComponent();
    waitForElement(secureContent);

    expect(secureContent.isPresent()).toBe(true);
});

参考