#angularjs #testing #angularjs-directive #jasmine
#angularjs #тестирование #angularjs-директива #jasmine
Вопрос:
У меня есть директива, которая условно применяет классы CSS к отображаемому HTML на основе вычислений по ширине окна. Директива работает просто отлично… если вы измените размер окна на этой странице, вы можете увидеть, как элементы помещаются в раскрывающийся список переполнения: http://ngofficeuifabric.com/demos/uifBreadcrumb . Код для контроллера директивы находится здесь: https://github.com/ngOfficeUIFabric/ng-officeuifabric/blob/master/src/components/breadcrumb/breadcrumbDirective.ts#L119-L164.
Проблема, с которой мы сталкиваемся, заключается в написании надежных тестов. В рамках тестов мы хотим убедиться, что класс overflow добавляется / удаляется на основе изменения размера окна. Мы пробовали множество способов сделать это, но безуспешно … кажется, событие изменения размера сработает, но мы это сделаем после оценки теста. Мы сделали это, установив значение window.innerWidth
свойства, но оно должно быть доступно только для чтения.
Мы попытались установить значение перед всеми тестами в качестве отправной точки:
beforeAll(() => {
originalWidth = jQuery(document.body).css('width');
jQuery(document.body).css('width', '800px');
jQuery(window).trigger('resize');
});
а затем попробуйте выполнить такой тест:
it('should not have is-overflow class', () => {
expect(element).not.toHaveClass('is-overflow');
});
Это не удается, потому что PhantomJS начинается с width = 400px, поэтому класс добавлен, но в beforeAll()
мы устанавливаем его на 800px … обработчик события изменения размера запускается сразу после выполнения этого теста, и это выдает ошибку. Даже добавление задержек setTimeout()
не помогает (и не желательно).
В других тестах нам нужно несколько раз изменять размер браузера, чтобы убедиться, что все обновляется по желанию.
it('should change breadcrumb count on resize', inject(($window: ng.IWindowService) => {
let startingWidth: string = jQuery(document.body).css('width');
let visibleLinks: JQuery = element.find('.ms-Breadcrumb-list li');
expect(visibleLinks.length).toBe(4);
let overflowLinks: JQuery = element.find('.ms-ContextualMenu li');
expect(overflowLinks.length).toBe(2);
// narrow down window
jQuery(document.body).css('width', '620px'); // must be less than break point
jQuery(window).trigger('resize');
visibleLinks = element.find('.ms-Breadcrumb-list li');
expect(visibleLinks.length).toBe(2);
overflowLinks = element.find('.ms-ContextualMenu li');
expect(overflowLinks.length).toBe(4);
// back to normal
jQuery(document.body).css('width', startingWidth);
jQuery(window).trigger('resize');
visibleLinks = element.find('.ms-Breadcrumb-list li');
expect(visibleLinks.length).toBe(4);
overflowLinks = element.find('.ms-ContextualMenu li');
expect(overflowLinks.length).toBe(2);
}));
Ручное тестирование директивы показывает, что она делает именно то, что мы хотим, но после добавления многочисленных console.log()
операторов становится ясно, что событие изменения размера запускается не сразу, когда мы пытаемся его вызвать … скорее, оно откладывается для запуска после выполнения тестов.
Есть ли надежный способ инициировать событие изменения размера для запуска и завершения из тестов?
Ответ №1:
Я думаю, что изменение размера и прокрутка не входят в периметр модульного теста. было бы легко проверить такие события внутри интеграционного теста (т.е. с помощью транспортира).
Например, мне пришлось разработать функцию прокрутки вверх в одном из моих проектов, и единственным способом ее тестирования были интеграционные тесты.
Комментарии:
1. Да… Я думаю, у вас есть хорошая точка зрения. Вместо этого я собираюсь просто выполнить модульное тестирование функции, которая выполняет часть пересчета, и не пытаться вызвать событие. Триггер события просто вызывает процесс пересчета.