Angular-Protractor-Headless Chromium: при использовании APP_INITIALIZE Angular не может быть найден на странице

Мы создаем гибридное приложение Ionic и внедрили автоматизированные тесты E2E, которые выполняются системой CI. Все эти тесты работали правильно, пока мы не внедрили APP_INITIALIZE в наш «app.module», чтобы получить язык браузера перед инициализацией.

Это грязный код нашей реализации APP_INITIALIZE:

-app.module.ts

export function configurateLocaleData(dynamicRegisterLocaleService: DynamicRegisterLocaleService): () => Promise<any> {
    return () => dynamicRegisterLocaleService.configurateLocaleData();
}

...

providers: [

...


        {
            provide: APP_INITIALIZER, 
            useFactory: configurateLocaleData,
            deps: [ DynamicRegisterLocaleService ],
            multi: true
        }
...

-динамический-регистр-locale.service.ts

import {Injectable} from "@angular/core";
import {HttpClient} from "@angular/common/http";
import {AppConfig} from "../app.constants";
import {DateLocaleService} from "./dateLocale.service";
import {registerLocaleData} from "@angular/common";

@Injectable()
export class DynamicRegisterLocaleService {

    constructor(private httpClient: HttpClient) {
    }

    public configurateLocaleData(): Promise<any> {
        let currentLang = DateLocaleService.getLanguage();
        return this.httpClient.get("../assets/locales/" + currentLang + ".js", {responseType: "text"}).toPromise()
        .then(data => {
            const startPos = data.indexOf(AppConfig.EXPORT_DEFAULT);
            let localeText = "return " + data.substring(startPos + AppConfig.EXPORT_DEFAULT.length);
            registerLocaleData((new Function(localeText))());
        });
    }
}

Вот некоторые из тестов транспортира-огурца, которые мы проводим, и его конфигурация:

-огурец.conf.js

exports.config = {
    allScriptsTimeout: 70000,
    framework: 'custom',
    frameworkPath: require.resolve('protractor-cucumber-framework'),

    directConnect: true,
    restartBrowserBetweenTests: true,
    capabilities: {
        'browserName': 'chrome',
        'chromeOptions': {
            'args': ['--disable-web-security', '--headless', '--disable-gpu', '--no-sandbox'],
            'perfLoggingPrefs': {
                'enableNetwork': true,
                'enablePage': false
            }
        },
        loggingPrefs: {
            performance: 'ALL',
            browser: 'ALL'
        }  
    },

    specs: [
        '../e2e/cucumber/features/*.feature'
    ],

    cucumberOpts: {
        require: ['../e2e/cucumber/steps/*.steps.js'],
        strict: true
    },
};

-огурец.steps.js

var TestsCfg = require("./../tests.constants.js");
var SupportFunctions = require("./../support/support-functions.js");

var {defineSupportCode, After} = require("cucumber");
var chai = require("chai").use(require("chai-as-promised"));
var expect = chai.expect;

defineSupportCode(function({setDefaultTimeout, When, Then, Given, And}) {
    setDefaultTimeout(TestsCfg.CUCUMBER_STEPS_MAX_TIMEOUT_MS);

    After(function() {
        return browser.manage().logs().get('browser').then(function(browserLogs) {
            console.log("Console logs for this scenario: ");
            browserLogs.forEach(function(log){
                console.log(log.message);
            });
        });
    });

    When("I navigate to App", function() {
        return browser.get(TestsCfg.APP_TEST_URL);
    });

    Then("the title should be {string}", function(title) {
        return expect(browser.getTitle()).to.eventually.eql(title);
    });

    Given("I should be able to login as {string}", function(username) {
        var usernameInput = element.all(by.css(".login-input .text-input")).get(0).getWebElement();
        var passwordInput = element.all(by.css(".login-input .text-input")).get(1).getWebElement();
        var loginButton = element(by.id("loginButton"));

        return browser.wait(SupportFunctions.isElementVisible(loginButton)).then(function() {
            usernameInput.click();
            usernameInput.sendKeys(username);
            passwordInput.click();
            passwordInput.sendKeys(pass);

            return loginButton.click();
        });
    });

    Then("the dashboard should be shown for house {string}", function(house) {
        var headerSpan = element(by.css(".header-text"));

        return browser.wait(SupportFunctions.isElementVisible(headerSpan)).then(function() {
            return expect(headerSpan.getText()).to.eventually.eql(house);
        });
    });

Тестов больше, но все они работают одинаково. Переходим по нужному URL, авторизуемся и затем запускаем конкретный тест. Поскольку это приложение Ionic, все они имеют ExpectedConditions, поэтому они ждут, пока все не загрузится должным образом.

Проблема в том, что все эти тесты правильно работают локально, и до реализации APP_INITIALIZE они также работали в нашей системе CI. Как только APP_INITIALIZE был реализован, эти ошибки начали появляться для каждого отдельного теста:

введите здесь описание изображения

Наш CI — это Bitbucket Pipelines, на котором запущен образ Docker weboaks/node-karma-protractor-chrome:debian-node8, который включает версию Chromium 64.0.3282.119. Мы используем chromedriver 2.37, последнюю версию, совместимую с Chromium 64.

И это факты, которые мы получили из наших тестов:

  • Мы знаем, что это связано с APP_INITIALIZE, потому что если мы удалим эту реализацию, все будет работать правильно.
  • Мы также знаем, что он отлично работает при запуске Protractor-Cucumber без флага "--headless".
  • Это также работает при использовании Chromium v66, даже без головы. Но это не работает на Chromium 64.0.3282.119.

Кто-нибудь знает, является ли это ошибкой Angular, Protractor или Chromium?

Спасибо!


person luron    schedule 05.06.2018    source источник


Ответы (1)


Protractor имеет метод, отключающий это ожидание. browser.waitForAngularEnabled(false); Я поместил его в свой config файл в onPrepare вроде

  onPrepare: async () => {
    await browser.waitForAngularEnabled(false);
  },

вы также можете попытаться поместить это непосредственно в свой тест в начале.

person Oleksii    schedule 05.06.2018
comment
Уже пробовал, как в конфигурационном файле, так и на первом шаге каждого сценария, но не повезло, как будто он не ждет Angular, не будет элементов, которые транспортир может найти. - person luron; 05.06.2018
comment
не могли бы вы проверить этот пост github.com/angular/protractor/issues/ . Я не уверен. - person Oleksii; 05.06.2018