Angular Транспортир - Проверка перенаправления страницы - PullRequest
0 голосов
/ 27 февраля 2020

Я пишу несколько тестов E2E в приложении Angular. У меня проблема в том, что всякий раз, когда я перенаправляю на новый маршрут, я хотел бы убедиться, что отображается правильный компонент. По какой-то причине это всегда приводит к ошибке со следующей ошибкой:

- Failed: script timeout

Я искал во всем Интернете, чтобы найти решение, но все решения, которые я ' я обнаружил, что у меня ничего не вышло.

Пример

  • Ожидание Angular

browser.waitForAngular();

Ссылка

  • Проверьте текущий URL браузера и сравните с ожидаемым URL:
browser.driver.wait(() => {
    browser.driver.getCurrentUrl().then((url) => {
        return /expected-url/.test(url);
    });
}, 10000);

Ссылка


Пример кода

Ниже приведен пример кода, который проверяет функциональность входа в систему.

Страница входа Класс объекта

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 Spe c Файл

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, поэтому не совсем уверен, что это проблема.


На всякий случай вот номер версии важных пакетов:

  • Angular: 8.2.14
  • Angular CLI : 8.2.2
  • Транспортир : 5.4.2
  • Жасмин : 2.8.0

Ответы [ 3 ]

0 голосов
/ 27 февраля 2020

вам нужно использовать обещание с оператором then это решение сработало для меня, если вы знаете время ответа, которое вы можете использовать

browser.driver.sleep(1000)

, но это плохая практика

Примечание: если приложение работает очень медленно, пришло время сообщить о проблеме с производительностью.

0 голосов
/ 02 марта 2020

В моем случае, кроме ожидания определенных объектов Promise, у меня также было что-то еще, что вызывало ошибку. Короче говоря, у меня есть интервал, который отвечает за отображение текущего времени пользователю. Поскольку интервал является асинхронной функцией, Protractor будет предполагать, что Angular все еще выполняет некоторую функцию, и, таким образом, продолжает ждать, пока Angular будет "отзывчивым".

В Angular 2+, чтобы Для такого сценария необходимо запускать функцию setInterval() вне зоны Angular.

Пример

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

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

Приведенный выше код приведет к Транспортир дает таймауты всякий раз, когда компонент с интервалом существует на странице.

Чтобы исправить эту проблему, мы можем использовать 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);
});

Ссылки

0 голосов
/ 27 февраля 2020

Я бы предложил вам использовать структуру операторов async / await. Ваше подозрение, кажется, исправляется, и проблема, с которой вы сталкиваетесь, из-за неправильного обращения с обещаниями.

Вы можете попробовать написать spe c как:

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, когда есть взаимодействие с браузером и сделайте функцию asyn c, если есть какое-либо ожидание.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...