如何从 Jasmine 测试中触发 ResizeObserver?
How can I trigger ResizeObserver from a Jasmine test?
我有以下组件利用 ResizeObserver
(通过 https://www.npmjs.com/package/@juggle/resize-observer)
export class ResizeTestComponent implements OnInit {
constructor(public hostRef: ElementRef) {}
ngOnInit() {
const resizeObserver = new ResizeObserver(() => this.resized());
resizeObserver.observe(this.hostRef.nativeElement);
}
resized() {
console.log('resized');
}
}
如果我手动更改 window 宽度,组件宽度会更改,并且 resized
会按预期通过 resized
函数输出到控制台。
我想编写一个 Jasmine 测试来检查 resized
函数是否在调整元素大小时被调用。
如何触发 resizeObserver
?
我已尝试发送 resize
事件,但未调用 resized
函数:
it('resized function is called when element is resized', async(() => {
const fixture = TestBed.createComponent(ResizeTestComponent);
fixture.detectChanges();
const resizedSpy = spyOn(fixture.componentInstance, 'resized');
window.dispatchEvent(new Event('resize'));
expect(resizedSpy).toHaveBeenCalled();
}));
我认为问题在于您需要实际调整元素的大小,而不是简单地触发 resize
事件。
也就是说,您实际上必须更改宽度、高度或两者。
所以试试下面的方法。
it('resized function is called when element is resized', async(() => {
const fixture = TestBed.createComponent(ResizeTestComponent);
fixture.detectChanges();
const resizedSpy = spyOn(fixture.componentInstance, 'resized');
// this or some fixed values e.g. 800, 600.
window.resizeTo(
window.screen.availWidth / 2,
window.screen.availHeight / 2
);
expect(resizedSpy).toHaveBeenCalled();
}));
测试这个有点棘手,所以需要模拟组件的实际大小调整。此外 ResizeObserver
在 Angular 的控制之外运行,因此它在测试中表现得很奇怪。当您直接测试组件时,您的组件将 ResizeObserver
注册到 HTML 中根本不存在的组件元素。因此,您需要使用包装器组件来执行此测试。
这是我关于如何测试它的建议。
describe('HostTestComponent', () => {
@Component({
selector: 'test-host',
template: `<resize-test></resize-test>`,
styles: [':host { width: 300px }'],
})
class HostComponent {}
let fixture: ComponentFixture<HostComponent>;
beforeAll(() => {
TestBed.initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
});
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [ResizeTestComponent, HostComponent],
}).compileComponents();
fixture = TestBed.createComponent(HostComponent);
}));
it('resized function is called when element is resized', async(() => {
const resizeTestComponentDebugElement = fixture.debugElement.query(
By.directive(ResizeTestComponent)
);
const resizedSpy = spyOn(
resizeTestComponentDebugElement.componentInstance,
'resized'
);
resizedSpy.and.callThrough();
fixture.detectChanges();
setTimeout(() => { // process first resize when component is first drawn
fixture.whenStable().then(() => {
fixture.debugElement.nativeElement.style.width = '200px';
fixture.detectChanges();
setTimeout(() => { // process resize due to width change.
fixture.whenStable().then(() => {
expect(resizedSpy).toHaveBeenCalledTimes(2);
});
}, 0);
});
}, 0);
}));
});
如您所见,我创建了包装器组件,然后更改了触发组件调整大小的包装器组件的宽度。同样在这种情况下,实际上有两个调整大小事件第一次发生在组件的初始绘制上,第二次发生在实际调整大小时。这是因为在绘制组件之前调用了 ngOnInit
。
这里还有一个 link to a fork of you StackBlitz 你可以看到它在工作。
我有以下组件利用 ResizeObserver
(通过 https://www.npmjs.com/package/@juggle/resize-observer)
export class ResizeTestComponent implements OnInit {
constructor(public hostRef: ElementRef) {}
ngOnInit() {
const resizeObserver = new ResizeObserver(() => this.resized());
resizeObserver.observe(this.hostRef.nativeElement);
}
resized() {
console.log('resized');
}
}
如果我手动更改 window 宽度,组件宽度会更改,并且 resized
会按预期通过 resized
函数输出到控制台。
我想编写一个 Jasmine 测试来检查 resized
函数是否在调整元素大小时被调用。
如何触发 resizeObserver
?
我已尝试发送 resize
事件,但未调用 resized
函数:
it('resized function is called when element is resized', async(() => {
const fixture = TestBed.createComponent(ResizeTestComponent);
fixture.detectChanges();
const resizedSpy = spyOn(fixture.componentInstance, 'resized');
window.dispatchEvent(new Event('resize'));
expect(resizedSpy).toHaveBeenCalled();
}));
我认为问题在于您需要实际调整元素的大小,而不是简单地触发 resize
事件。
也就是说,您实际上必须更改宽度、高度或两者。
所以试试下面的方法。
it('resized function is called when element is resized', async(() => {
const fixture = TestBed.createComponent(ResizeTestComponent);
fixture.detectChanges();
const resizedSpy = spyOn(fixture.componentInstance, 'resized');
// this or some fixed values e.g. 800, 600.
window.resizeTo(
window.screen.availWidth / 2,
window.screen.availHeight / 2
);
expect(resizedSpy).toHaveBeenCalled();
}));
测试这个有点棘手,所以需要模拟组件的实际大小调整。此外 ResizeObserver
在 Angular 的控制之外运行,因此它在测试中表现得很奇怪。当您直接测试组件时,您的组件将 ResizeObserver
注册到 HTML 中根本不存在的组件元素。因此,您需要使用包装器组件来执行此测试。
这是我关于如何测试它的建议。
describe('HostTestComponent', () => {
@Component({
selector: 'test-host',
template: `<resize-test></resize-test>`,
styles: [':host { width: 300px }'],
})
class HostComponent {}
let fixture: ComponentFixture<HostComponent>;
beforeAll(() => {
TestBed.initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
});
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [ResizeTestComponent, HostComponent],
}).compileComponents();
fixture = TestBed.createComponent(HostComponent);
}));
it('resized function is called when element is resized', async(() => {
const resizeTestComponentDebugElement = fixture.debugElement.query(
By.directive(ResizeTestComponent)
);
const resizedSpy = spyOn(
resizeTestComponentDebugElement.componentInstance,
'resized'
);
resizedSpy.and.callThrough();
fixture.detectChanges();
setTimeout(() => { // process first resize when component is first drawn
fixture.whenStable().then(() => {
fixture.debugElement.nativeElement.style.width = '200px';
fixture.detectChanges();
setTimeout(() => { // process resize due to width change.
fixture.whenStable().then(() => {
expect(resizedSpy).toHaveBeenCalledTimes(2);
});
}, 0);
});
}, 0);
}));
});
如您所见,我创建了包装器组件,然后更改了触发组件调整大小的包装器组件的宽度。同样在这种情况下,实际上有两个调整大小事件第一次发生在组件的初始绘制上,第二次发生在实际调整大小时。这是因为在绘制组件之前调用了 ngOnInit
。
这里还有一个 link to a fork of you StackBlitz 你可以看到它在工作。