Подтвердить что ты не робот

Одна из строк в массиве для соответствия выражению

Проблема:

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

В настоящее время я решаю его с помощью простой конкатенации строк:

protractor.promise.all([text1, text2, text3]).then(function (values) {
    expect(values[0] + values[1] + values[2]).toMatch(/expression/);
});

Очевидно, что это плохо масштабируется и не особенно читаемо.

Вопрос:

Можно ли решить эту проблему с помощью пользовательского набора жасмина или jasmine.any() или пользовательский асимметричный тестер равенства?

4b9b3361

Ответ 1

Вы можете просто использовать map, чтобы получить список boolean, а затем утвердить результат с помощью toContain(true):

var all = protractor.promise.all;
var map = protractor.promise.map;

expect(map(all([text1, text2, text3]), RegExp.prototype.test, /expression/)).toContain(true);

Вы также можете использовать пользовательский соединитель:

expect(all([text1, text2, text3])).toContainPattern(/expression/);

И пользовательский совпад, объявленный в beforeEach:

beforeEach(function() {
  jasmine.addMatchers({
    toContainPattern: function() {
      return {
        compare: function(actual, regex) {
          return {
            pass: actual.some(RegExp.prototype.test, regex), 
            message: "Expected [" + actual + "] to have one or more match with " + regex
          };
        }
      };
    }
  });
});

Ответ 2

Как сказано в комментариях, хотя я изначально использовал map, сокращение позволило бы вам делать то, что вам нужно, и в этой касте, по крайней мере, имеет смысл:

protractor.promise.all([text1, text2, text3]).then(function (values) {
    expect(
        values.reduce(function(p, v) {
            return v.match(/expression/) || p;
        }, false)
    ).toBe(true);
});

Или писать то же самое, но используя функции стрелок ES6:

protractor.promise.all([text1, text2, text3]).then(function(values) {
    exptect(
        values.reduce( (p, v) => v.match(/expression/) || p, false )
    ).toBe(true);
});

Оба делают то же самое, обратный вызов уменьшения по умолчанию будет равен false, пока выражение v.match не будет равно true.
Я предполагаю, что это очевидно для большинства людей, но я думал, что буду предоставлять синтаксисы и некоторые объяснения для будущей ссылки


Возможно, это решение можно было бы оптимизировать немного больше, чтобы остановить сопоставление шаблона после того, как было найдено одно совпадение:

protractor.promise.all([text1, text2, text3]).then(function (values) {
    expect(
        values.reduce(function(p, v) {
            return p || !!v.match(/expression/);
        }, false)
    ).toBe(true);
});

Все, что я сделал, это использовать текущее значение уменьшения как значение по умолчанию (после того, как установлено значение true, нет смысла тестировать любое другое строковое значение). Чтобы v.match оценивал только логическое значение, а не массив, я использовал !!v.match(). Однако эта часть является необязательной. В ES6 то же самое выглядит так:

protractor.promise.all([text1, text2, text3]).then(function(values) {
    exptect(
        values.reduce( (p, v) => p || !!v.match(/expression/), false )
    ).toBe(true);
});

Это может улучшиться с большими наборами данных (учитывая, что вызовы match останавливаются, как только было найдено первое совпадение, в отличие от v.match, вызываемого каждый раз).

Ответ 3

Если это работает,

protractor.promise.all([text1, text2, text3]).then(function (values) {
    expect(values[0] + values[1] + values[2]).toMatch(/expression/);
});

Я думаю, вы можете написать это следующим образом:

protractor.promise.all([text1, text2, text3]).then(function (values) {
    expect(values.join('')).toMatch(/expression/);
});

И это масштабируемо.:)

Ответ 4

Если те [text1, text2, text3] являются текстами из ElementFinder .getText(), тогда вы также можете попробовать с ожидаемыми условиями (вы знаете, что я большой поклонник EC правильно?:)).

describe('test', function () {

    it('test', function () {
        var EC = protractor.ExpectedConditions;
        browser.get('http://www.protractortest.org/testapp/ng1/#/form');

        var textToContain = 'Check'; //Notice, that this is not 'equals', this is 'contains'
        var elementTextToCheck1 = EC.textToBePresentInElement($('#checkboxes h4'), textToContain); // Here it will be true : Checkboxes
        var elementTextToCheck2 = EC.textToBePresentInElement($('#animals h4'), textToContain); //false
        var elementTextToCheck3 = EC.textToBePresentInElement($('#transformedtext h4'), textToContain); //false

        var oneElementShouldContainText = EC.or(elementTextToCheck1, elementTextToCheck2, elementTextToCheck3);

        expect(oneElementShouldContainText()).toBeTruthy(`At least one element should contain "${textToContain}"`);
    })
});

Для простых элементов: http://www.protractortest.org/#/api?view=ExpectedConditions.prototype.textToBePresentInElement

Для textArea входы: http://www.protractortest.org/#/api?view=ExpectedConditions.prototype.textToBePresentInElementValue

Обратите внимание, что unfortunatelly.textToBePresentInElement работает только с одним ElementFinder, ArrayElementFinder не поддерживается. Но в этом случае вы можете сделать что-то с .filter() и утверждать, что возвращенный список пуст.