В Protractor для проверки результатов тестов чаще всего используются
стандартные матчер-функции Jasmine, такие как toEqual,
toBe, toContain и другие. Однако сложные
проверки, нестандартные сравнения или специфические требования к логике
теста требуют создания кастомных матчеров. Кастомные матчеры позволяют
расширить возможности Jasmine, делая проверки более выразительными и
удобными.
Кастомный матчер создаётся через объект с методом
expect.extend. Каждое определение матчера должно возвращать
объект с двумя обязательными свойствами:
Пример базового кастомного матчера:
beforeEach(() => {
jasmine.addMatchers({
toBeVisible: function() {
return {
compare: async function(actual) {
const isDisplayed = await actual.isDisplayed();
return {
pass: isDisplayed,
message: isDisplayed
? `Ожидалось, что элемент не будет видимым`
: `Ожидалось, что элемент будет видимым`
};
}
};
}
});
});
Здесь создаётся матчер toBeVisible, который проверяет
видимость элемента на странице. Ключевой момент — использование
async/await, так как взаимодействие с элементами через
Protractor всегда асинхронное.
После определения матчера его можно использовать в тестах так же, как стандартные матчеры:
it('должен показать элемент', async () => {
const button = element(by.id('submit'));
await expectAsync(button).toBeVisible();
});
Обратите внимание на использование expectAsync, которое
является обязательным при проверках промисов или
ElementFinder в Protractor.
Матчеры могут принимать параметры для более гибкой проверки. Например, проверка текста элемента с учётом регистра:
beforeEach(() => {
jasmine.addMatchers({
toHaveTextIgnoringCase: function() {
return {
compare: async function(actual, expected) {
const text = await actual.getText();
const pass = text.toLowerCase() === expected.toLowerCase();
return {
pass: pass,
message: pass
? `Текст совпадает с ${expected} (игнорируется регистр)`
: `Ожидалось: ${expected}, но получено: ${text}`
};
}
};
}
});
});
Применение:
it('проверка текста элемента без учёта регистра', async () => {
const label = element(by.css('.label'));
await expectAsync(label).toHaveTextIgnoringCase('Привет Мир');
});
Кастомные матчеры особенно полезны для:
Пример проверки массива элементов:
beforeEach(() => {
jasmine.addMatchers({
allElementsHaveText: function() {
return {
compare: async function(elements, expectedText) {
const texts = await Promise.all(elements.map(el => el.getText()));
const pass = texts.every(t => t === expectedText);
return {
pass: pass,
message: pass
? `Все элементы содержат текст "${expectedText}"`
: `Не все элементы содержат текст "${expectedText}": ${texts.join(', ')}`
};
}
};
}
});
});
Применение:
it('все элементы списка должны содержать одинаковый текст', async () => {
const items = element.all(by.css('.item'));
await expectAsync(items).allElementsHaveText('Готово');
});
Ясные сообщения об ошибках Сообщения должны максимально точно отражать, что проверялось и что не прошло. Это ускоряет отладку тестов.
Поддержка асинхронности Все операции с элементами и данными в Protractor возвращают промисы, поэтому матчеры должны быть асинхронными.
Повторное использование Если матчер используется
в нескольких тестах, стоит вынести его в отдельный файл и подключать
через beforeAll или onPrepare в конфиге
Protractor.
Минимизация побочных эффектов Кастомный матчер должен только проверять состояние, но не изменять DOM или данные страницы.
Для глобального подключения кастомных матчеров можно использовать
файл onPrepare:
// protractor.conf.js
onPrepare: async () => {
require('./customMatchers');
}
В customMatchers.js определяется весь набор кастомных
проверок, что упрощает поддержку и повторное использование в проектах с
большим количеством тестов.
Кастомные матчеры в Protractor позволяют писать более выразительные и надежные тесты, упрощают чтение кода и обеспечивают гибкость проверки сложных условий. Они являются неотъемлемой частью масштабируемого тестирования веб-приложений на JavaScript.