Skip to content

Commit

Permalink
test(multiple): Update AppRef.tick spy tests to assert CD runs on a c…
Browse files Browse the repository at this point in the history
…omponent instance

Upstream FW changes will result in automatic change detections running
through an internal `ApplicationRef._tick` method rather than the public
one that can be spied on. Instead, tests should instead observe the
expected number of times the component under test was checked.
  • Loading branch information
atscott committed Apr 1, 2024
1 parent da980a8 commit 042b27d
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 27 deletions.
33 changes: 18 additions & 15 deletions src/cdk/overlay/dispatchers/overlay-keyboard-dispatcher.spec.ts
@@ -1,13 +1,12 @@
import {TestBed, inject} from '@angular/core/testing';
import {dispatchKeyboardEvent} from '../../testing/private';
import {ESCAPE} from '@angular/cdk/keycodes';
import {ApplicationRef, Component} from '@angular/core';
import {Component, DoCheck} from '@angular/core';
import {OverlayModule, Overlay} from '../index';
import {OverlayKeyboardDispatcher} from './overlay-keyboard-dispatcher';
import {ComponentPortal} from '@angular/cdk/portal';

describe('OverlayKeyboardDispatcher', () => {
let appRef: ApplicationRef;
let keyboardDispatcher: OverlayKeyboardDispatcher;
let overlay: Overlay;

Expand All @@ -16,14 +15,10 @@ describe('OverlayKeyboardDispatcher', () => {
imports: [OverlayModule, TestComponent],
});

inject(
[ApplicationRef, OverlayKeyboardDispatcher, Overlay],
(ar: ApplicationRef, kbd: OverlayKeyboardDispatcher, o: Overlay) => {
appRef = ar;
keyboardDispatcher = kbd;
overlay = o;
},
)();
inject([OverlayKeyboardDispatcher, Overlay], (kbd: OverlayKeyboardDispatcher, o: Overlay) => {
keyboardDispatcher = kbd;
overlay = o;
})();
});

it('should track overlays in order as they are attached and detached', () => {
Expand Down Expand Up @@ -185,18 +180,21 @@ describe('OverlayKeyboardDispatcher', () => {
});

it('should not run change detection if there are no `keydownEvents` observers', () => {
spyOn(appRef, 'tick');
const instance = overlay.create();
const componentRef = instance.attach(new ComponentPortal(TestComponent));

const initialCheckCount = componentRef.instance.checked;
const overlayRef = overlay.create();
keyboardDispatcher.add(overlayRef);

expect(appRef.tick).toHaveBeenCalledTimes(0);
expect(componentRef.instance.checked).toEqual(initialCheckCount);
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
expect(appRef.tick).toHaveBeenCalledTimes(0);
expect(componentRef.instance.checked).toEqual(initialCheckCount);

overlayRef.keydownEvents().subscribe();
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);

expect(appRef.tick).toHaveBeenCalledTimes(1);
expect(componentRef.instance.checked).toEqual(initialCheckCount + 1);
});
});

Expand All @@ -205,4 +203,9 @@ describe('OverlayKeyboardDispatcher', () => {
standalone: true,
imports: [OverlayModule],
})
class TestComponent {}
class TestComponent implements DoCheck {
checked = 0;
ngDoCheck() {
this.checked++;
}
}
15 changes: 10 additions & 5 deletions src/cdk/scrolling/virtual-scroll-viewport.spec.ts
Expand Up @@ -17,6 +17,7 @@ import {
Directive,
ViewContainerRef,
ApplicationRef,
DoCheck,
} from '@angular/core';
import {
waitForAsync,
Expand Down Expand Up @@ -827,15 +828,14 @@ describe('CdkVirtualScrollViewport', () => {
testComponent.virtualForOf.viewChange.subscribe();
finishInit(fixture);
testComponent.items = Array(10).fill(0);
fixture.detectChanges();
fixture.autoDetectChanges();
flush();

spyOn(appRef, 'tick');

const initialCheckCount = fixture.componentInstance.checked;
viewport.scrollToIndex(5);
triggerScroll(viewport);

expect(appRef.tick).toHaveBeenCalledTimes(1);
expect(fixture.componentInstance.checked).toEqual(initialCheckCount + 1);
}));
});
});
Expand Down Expand Up @@ -1252,7 +1252,7 @@ function triggerScroll(viewport: CdkVirtualScrollViewport, offset?: number) {
standalone: true,
imports: [ScrollingModule],
})
class FixedSizeVirtualScroll {
class FixedSizeVirtualScroll implements DoCheck {
@ViewChild(CdkVirtualScrollViewport, {static: true}) viewport: CdkVirtualScrollViewport;
// Casting virtualForOf as any so we can spy on private methods
@ViewChild(CdkVirtualForOf, {static: true}) virtualForOf: any;
Expand All @@ -1271,6 +1271,11 @@ class FixedSizeVirtualScroll {

scrolledToIndex = 0;
hasMargin = false;
checked = 0;

ngDoCheck() {
this.checked++;
}

get viewportWidth() {
return this.orientation == 'horizontal' ? this.viewportSize : this.viewportCrossSize;
Expand Down
18 changes: 11 additions & 7 deletions src/material/progress-bar/progress-bar.spec.ts
@@ -1,5 +1,5 @@
import {TestBed, ComponentFixture} from '@angular/core/testing';
import {ApplicationRef, Component, DebugElement, Provider, Type} from '@angular/core';
import {Component, DebugElement, Provider, DoCheck, Type} from '@angular/core';
import {By} from '@angular/platform-browser';
import {dispatchFakeEvent} from '@angular/cdk/testing/private';
import {MatProgressBarModule, MAT_PROGRESS_BAR_DEFAULT_OPTIONS} from './index';
Expand Down Expand Up @@ -301,18 +301,17 @@ describe('MDC-based MatProgressBar', () => {
});

it('should not run change detection if there are no `animationEnd` observers', () => {
fixture.detectChanges();
fixture.autoDetectChanges();

const animationEndSpy = jasmine.createSpy();
const appRef = TestBed.inject(ApplicationRef);
spyOn(appRef, 'tick');
const initialCheckCount = fixture.componentInstance.checked;

progressComponent.value = 30;
progressComponent.bufferValue = 60;
// On animation end, output should be emitted.
dispatchFakeEvent(primaryValueBar.nativeElement, 'transitionend', true);

expect(appRef.tick).not.toHaveBeenCalled();
expect(fixture.componentInstance.checked).toEqual(initialCheckCount);

progressComponent.animationEnd.subscribe(animationEndSpy);

Expand All @@ -321,7 +320,7 @@ describe('MDC-based MatProgressBar', () => {
// On animation end, output should be emitted.
dispatchFakeEvent(primaryValueBar.nativeElement, 'transitionend', true);

expect(appRef.tick).toHaveBeenCalled();
expect(fixture.componentInstance.checked).toEqual(initialCheckCount + 1);
expect(animationEndSpy).toHaveBeenCalledWith({value: 40});
});
});
Expand All @@ -340,4 +339,9 @@ class BasicProgressBar {}
standalone: true,
imports: [MatProgressBar],
})
class BufferProgressBar {}
class BufferProgressBar implements DoCheck {
checked = 0;
ngDoCheck() {
this.checked++;
}
}

0 comments on commit 042b27d

Please sign in to comment.