Использование Protractor с циклами для заполнения формы получения данных из таблицы Cucumber.js

(я видел это обсуждение SO, но не знал, как применить его к мой случай, поэтому я задаю новый вопрос. Надеюсь, это не дубликат)

Я тестирую форму, написанную на Angular, используя Protractor с Cucumber.js.

Итак, что я хотел бы сделать, это сказать Protractor, чтобы он щелкнул заголовок поля (который является ссылкой), затем, когда это поле появится, введите в него некоторый текст, а затем перейдите к заголовку следующего поля, и так далее.

Вот мой шаг в Cucumber:

When I fill the form with the following data
    | field            | content           |
    | First Name       | John              |
    | Last Name        | Doe               |
    | Address          | Some test address |
# and so forth

Вот нерешительная попытка определения шага:

this.When(/^I fill the form with the following data$/, function (table, callback) {
    data = table.hashes();
    # that gives me an array of objects such as this one:
    # [ { field: 'First Name', content: 'John' },...]

    for (var i = 0; i < data.length; i++){
        var el = element(by.cssContainingText('#my-form a', data[i].field));
          el.click().then(function(){
                var fieldEl = el.element(by.xpath("../.."))
                    .element(by.css('textarea'));
                fieldEl.sendKeys(data[i].content);
            });
        }
    };
    callback();
});

Но это, конечно, не работает, потому что еще до того, как Protractor успеет кликнуть по названию поля и ввести в поле необходимые данные, вызывается callback-функция, и Cucumber переходит к следующему шагу.

Итак, мой вопрос: как я могу, используя Protractor с Cucumber.js, написать шаг для вставки данных, определенных в таблице Cucumber, в поля формы? Возможно ли это с помощью цикла for?


person azangru    schedule 26.04.2015    source источник
comment
Я пробовал то же самое, но не смог вывести на консоль 'data[i].content', есть идеи, почему? Это работает на вашей стороне?   -  person Gaurav Lad    schedule 11.03.2016


Ответы (1)


Ваш цикл ставит обещания в очередь, поэтому цикл завершается до того, как произойдет какое-либо «щелкание» или отправка ключей. Вам нужно вызвать callback после того, как все промисы будут разрешены.

Я вижу два решения (я думаю). Вы можете отслеживать промисы в массиве, а затем использовать protractor.promise.all (см. http://spin.atomicobject.com/2014/12/17/asynchronous-testing-protractor-angular/), чтобы дождаться завершения массива промисов. Сначала сохраните обещание в массиве var promises = []:

var p = el.click().then(function(){ ... });
promises.push(p)

Затем вне цикла:

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

Или вы можете положиться на ControlFlow, чтобы сохранить порядок обещаний в цикле и вызвать обратный вызов в последней итерации цикла:

var p = fieldEl.sendKeys(data[i].content);
if (i === data.length - 1) { // beware: you want to check "i" inside the loop and not in a promise created in the loop.
     p.then(callback);
}

Несмотря на весь текст об обратном, я не могу обещать, что ни один из них не сработает. Надеюсь, они хотя бы укажут вам правильное направление.

person P.T.    schedule 26.04.2015
comment
Спасибо! Я попробовал первый способ, который вы предложили, и он в основном работает. Я вижу в браузере, что Protractor открывает правильные поля и вставляет в них правильные данные, но затем выключает Selenium и не выполняет шаг, не объясняя причины. Пока не знаю, как решить эту проблему, но, похоже, это другой вопрос. Просто хотел указать, что API Протрактора называется promise (как вы правильно написали в первый раз), а не promises. Транспортир будет жаловаться, что он не может вызвать метод «все» из неопределенного, если вы попытаетесь вызвать protractor.promises.all. - person azangru; 26.04.2015
comment
Любопытная вещь: Транспортир/Огурец сначала проваливает шаг (что видно в консоли), а потом продолжает кликать по ссылкам и заполнять поля формы. - person azangru; 26.04.2015
comment
из любопытства, зачем использовать protractor.promise.all, а не только Promise.all есть ли что-то особенное, что версия транспортира добавляет к смеси›? - person Chuck van der Linden; 26.08.2016
comment
Это сработало в моем случае. Использование циклов внутри синхронной функции сложно, и это помогло мне завершить мой код. - person Harisha K P; 11.02.2020