Тайм-аут Cucumber JS не будет работать

Используя protractor-cucumber-framework, я пытаюсь нажать кнопку сто раз за один шаг «Когда». Однако это приведет к тайм-ауту со значением тайм-аута по умолчанию 5000 мс. Я бы предпочел не менять это значение по умолчанию, используя:

var config = function() {
    this.setDefaultTimeout(60*1000);
};

module.exports = config;

Это работает, но я бы предпочел установить тайм-аут для этого единственного шага следующим образом:

this.When(/^I click on the "([^"]*)" button$/, {timeout: 60*1000}, function(text, callback)
{
    // Click the button 100 times
    var button = element(by.partialButtonText('Widget'));
    for(j = 0; j < i; j++) {
        button.click();
    }
    callback();
});

Согласно ознакомлению cucumber-js, это должно работать, но по-прежнему приводит к:

Error: Step timed out after 5000 milliseconds
    at Timer.listOnTimeout (timer.js:92:15)

Любые идеи о том, почему это не работает?

РЕДАКТИРОВАТЬ: это действительно сработало. Тем не менее, я использовал его в неправильном шаге. Позвонить click() сто раз не так уж и много времени. Время ожидания истекает на шаге после него:

this.Then(/^a new widget is created$/, {timeout: 60 * 1000}, function(callback) {
    // Check if 100 widgets are created
});

Теперь кто-нибудь может объяснить, почему необходим длительный тайм-аут на этапе после всех вызовов click? Есть ли более элегантный способ заставить огурец ждать, пока не закончатся нажатия кнопок?


person Jusser    schedule 28.03.2016    source источник
comment
Документация, на которую вы ссылаетесь, показывает функцию Given, а не When. Я не эксперт по огурцам, но за те небольшие копания, которые я проделал, я не смог найти ничего, что указывало бы на то, что When примет тайм-аут так, как вы пытаетесь его использовать.   -  person CodingGorilla    schedule 28.03.2016
comment
Я отредактировал свой вопрос. Это работает, но не так, как я ожидал. Я думаю, что для ответа на мой вопрос нужен кто-то с большим опытом работы с огурцами, поскольку я все еще не понимаю, почему это работает именно так.   -  person Jusser    schedule 28.03.2016


Ответы (1)


Причина, по которой тайм-аут не работает, как ожидалось, заключается в том, что ваш callback() запускается раньше, даже до завершения первого click(). Это связано с тем, что click() являются асинхронными и добавляются к controlFlow транспортира (они ставятся в очередь для запуска один за другим), а callback() - нет. Есть несколько вариантов избежать этого.

Опция 1

Вы должны убедиться, что callback() запускается только после того, как все обещания, возвращенные click(), будут выполнены.

Вы можете собрать все возвращенные обещания и вызвать callback(), как только все они будут разрешены. Вот что вы хотели бы сделать, если бы не знали о controlFlow:

this.When(/^I click on the "([^"]*)" button$/, {timeout: 60*1000}, function(text, callback)
{
    // Click the button 100 times
    var button = element(by.partialButtonText('Widget'));
    var promises = [];

    for (var i = 0; i < 101; i++) {
        promises.push(button.click());
    }

    protractor.promise.all(promises).then(callback);
});

Вариант №2

Но все может стать намного проще, если вы просто поместите свой callback() в очередь controlFlow следующим образом:

this.When(/^I click on the "([^"]*)" button$/, {timeout: 60*1000}, function(text, callback)
{
    // Click the button 100 times
    var button = element(by.partialButtonText('Widget'));
    for(var i = 0; i < 101; i++) {
        button.click();
    }

    browser.controlFlow().execute(callback);
});

Как видите, при работе с Protractor следует использовать его controlFlow, чтобы избежать написания асинхронного (выглядящего) кода.

person The Victor    schedule 08.04.2016