Как издеваться над угловым внешним объектом Javascript
У меня есть приложение angular, единственной целью которого является создание @angular / elements (без index.html, без app.component и т. Д.).
Эти элементы используются в приложении.NET Mvc, которое предоставляет два типа вещей, которые я пытаюсь имитировать в своих модульных тестах:
1 - Внешние библиотеки
Например, JQuery, lodash и т. Д.
2 - Клиентская платформа "foo"
Внутри представления.NET MVC, которое включает мои веб-элементы, приложение MVC создает объект с именем foo. Этот объект не является модулем ES6. Он создается вручную с помощью красивого foo = new Foo({ someOptionsGeneratedFromServerSide});
Оба случая используются внутри моих веб-элементов. Например, компонент будет использовать функцию foo.displayAlert("С сообщением"). Единственное решение, которое я нашел, чтобы заставить мое приложение angular соответствовать этому, - это добавить следующее:
// tslint:disable-next-line: max-line-length no-reference
/// <reference path='path/to/the/definition.d.ts' />
Я знаю, что это не совсем ортодоксально.
Приложение Angular работает нормально, пока я не попробую выполнить модульное тестирование. Примечание: он не может работать в одиночку (ng serve, как и ожидалось, бесполезен).
Пример
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('ng-jest app is running!');
});
Для этого компонента / крючка:
ngOnInit() {
foo.displayAlert('With a message');
}
Произойдет сбой со следующим (вполне ожидаемым) сообщением:
AppComponent › should render title
ReferenceError: foo is not defined
Я попытался явно издеваться над объектом перед тестом:
let foo: any;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
foo = {
displayAlert: Function
};
}));
Пока не повезло. Я делал много попыток насмехаться над этим объектом внутри x.spect.ts, но безрезультатно.
Я попытался создать другое приложение Angular с index.html, которое включает все ресурсы, такие как представление MVC, но это не удалось.
Заключительные примечания
Для сторонних разработчиков, таких как JQuery / lodash, я не хочу добавлять их в свой проект Angular, например:npm i -D lodash
поскольку я не хочу, чтобы они были включены в мой файл vendor.js. Эти библиотеки предоставляются приложением.Net Mvc, и это нормально. Это также относится к объекту foo. Наконец, я попробовал с (Jest) и без (Karma) безголовый браузер для тестов.
Любая помощь могла бы быть полезна!
Изменить 27/03/2020
Пожалуйста спаси меня!
Изменить 28/03/2020
Пробовал jasmine.createSpyObject & spyOn, тоже не повезло:(
1 ответ
Сложная настройка, вы не упростите себе задачу.
Однако, похоже, вам просто нужно подделать foo
в качестве глобальной переменной, поскольку глобальная область видимости - это то место, где ваш компонент ожидает, что переменная будет. Когда вы заявляетеlet foo
внутри модуля ECMAScript вы создаете переменную, привязанную к этому файлу, к которому ваш компонент не может получить доступ.
beforeEach(() => {
window.foo = {
displayAlert: () => {},
};
});
Это, вероятно, заставит вас бороться с TypeScript. Быстрое исправление - это
beforeEach(() => {
(window as any).foo = {
displayAlert: () => {},
};
});