Недавно столкнулся с необходимостью написать кастомный матчер в jasmine. Первым же делом начал гуглить и нашел пример, где все четко и понятно объяснено. Собственно код представлен ниже:
describe('Hello world', function () {
beforeEach(function() {
this.addMatchers({
toBeWithinOf: function(distance, base) {
this.message = function() {
var lower = base - distance,
upper = base + distance;
return "Expected " + this.actual + " to be between " +
lower + " and " + upper + " (inclusive)";
};
return Math.abs(this.actual - base) <= distance;
}
});
});
it('should be within in range', function () {
expect(8).toBeWithinOf(2, 6);
});
});
В этом примере создается матчер, который будет сообщать о том, находиться ли введенное число (this.actual) в некотором интервале. Заметьте, при вызове матчера передается два параметра:base — число от которого будет отсчитываться в обе стороны некая величина — distance, в итоге образуя интервал поиска — [base — distance, base + distance]. В данном случае мы ожидаем, что 8 будет в интервале [4, 8]. Если же заданное пользователем число будет вне интервала, то в тестах мы увидим ошибку, которою формируем с помощью функции this.message.
Всё вроде ничего, но при запуске примера в jasmine 2.0 ничего из этого не работает. Оказывается, немного изменился синтаксис.
Перепробовал кучу способов и облазив не один форум я смог решить данный вопрос. Код решения имеет следующий вид:
describe('Hello world', function () {
beforeEach(function () {
jasmine.addMatchers({
toBeWithinOf: function () {
return {
compare: function (actual, distance, base) {
var lower = base - distance,
upper = base + distance,
result = {
pass: Math.abs(actual - base) <= distance
};
if(!result.pass) {
result.message = "Expected " + actual + " to be between " +
lower + " and " + upper + " (inclusive)";
}
return result;
}
}
}
})
});
it('should be within in range', function () {
expect(8).toBeWithinOf(2, 6);
});
});
Как можно заметить, был изменен способ вызова функции добавления матчеров — (this.addMatchers -> jasmine.addMatchers). Также из самой функции мы вынуждены возвращать объект, в котором должен быть объявлен метод compare, который и принимает все параметры, а не сама функция матчер.
Обратите внимание, что первый параметр(actual) соответствует числу, которое мы хотим проверять, и если нам требуется в сам матчер передавать свои параметры (как в нашем случае — base и distance), то можно указать их там же.
Внутри самой функции compare мы создаем объект, в который сразу же записываем свойство сравнения (pass). И только если это свойство в итоге не отрабатывает, то уже только тогда создается свойство message, в котором можно сформировать текст, который увидит пользователь при ошибке теста.
Ссылку на рабочий пример можно найти здесь — fiddle.
На этом все.
Автор: montanaqw