Одна из строк в массиве для соответствия выражению
Проблема:
У меня есть массив из promises, который разрешен для массива строк. Теперь тест должен пройти, если хотя бы одна из строк соответствует регулярному выражению.
В настоящее время я решаю его с помощью простой конкатенации строк:
protractor.promise.all([text1, text2, text3]).then(function (values) {
expect(values[0] + values[1] + values[2]).toMatch(/expression/);
});
Очевидно, что это плохо масштабируется и не особенно читаемо.
Вопрос:
Можно ли решить эту проблему с помощью пользовательского набора жасмина или jasmine.any()
или пользовательский асимметричный тестер равенства?
Ответы
Ответ 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()
и утверждать, что возвращенный список пуст.
Ответ 5
Array.prototype.some()
выглядит так, как вы на самом деле ищете.
protractor.promise.all([text1, text2, text3]).then(function (values) {
expect(values.some(v => v.match(/expression/)).toBe(true);
});
Для получения дополнительной информации https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/some