I was trying to figure it out by myself for last two days but I have no clue what I’m doing wrong. It has to be related somehow to asynchronus operations (probably selectors from ngrx) in my component, especially that part here:
combineLatest([
this._store$.pipe(select(selectUserPreferences)),
this._store$.pipe(select(selectGlobalsFiltered([GlobalPreferencesKeys.flightCallsignType])))
]).pipe(
takeUntil(this.componentDestroyed$),
map(([userPrefs, globals]) => {
if (userPrefs?.userPreferences[GlobalPreferencesKeys.flightCallsignType] !== undefined) {
return userPrefs.userPreferences[GlobalPreferencesKeys.flightCallsignType];
} else if (globals[GlobalPreferencesKeys.flightCallsignType]) {
return globals[GlobalPreferencesKeys.flightCallsignType];
}
return undefined;
}),
filter(res => !!res),
distinctUntilChanged()
).subscribe((flightCallsignType) => {
this.flightCallsignType = flightCallsignType;
this._changeDetectorRef.detectChanges();
});
And in my spec file I create component with createComponentFactory
where I put all of imports, declarations, providers etc. Store is mocked with provideMockStore
where I pass to the config object initialState and selector (with their initial values). So far so good I guess. When I’m running test separately it looks ok, when I’m doing it at once the second one (should display the empty state message when there are no flights) is failing because that: userPrefs = { userPreferences: undefined }
even thoug I set it in beforeEach block like that:
beforeEach(() => {
spectator = null as any;
spectator = createComponent();
mockStore = spectator.inject(MockStore);
mockStore.resetSelectors();
mockStore.overrideSelector(selectAllAlarms, []);
mockStore.overrideSelector(selectIsFisInterfaceDisabled, false);
mockStore.overrideSelector(selectGlobalsFiltered([GlobalPreferencesKeys.flightCallsignType]), {
[GlobalPreferencesKeys.flightCallsignType]: 'EXTERNAL'
});
mockStore.overrideSelector(selectUserPreferences, { userPreferences: {} });
mockStore.overrideSelector(selectStandFlights({ internalStand: '101', dgss: ['DGS101'] }), [flight1]);
mockStore.refreshState();
mockAlarmsService = spectator.inject(AlarmsService) as jest.Mocked<AlarmsService>;
mockOverlayService = spectator.inject(OverlayService) as jest.Mocked<OverlayService>;
mockDeviceDetectorService = spectator.inject(DeviceDetectorService) as jest.Mocked<DeviceDetectorService>;
});
afterEach(() => {
spectator.fixture.destroy();
});
it('should create', () => {
expect(spectator.component).toBeTruthy();
});
it('should display the empty state message when there are no flights', () => {
jest.spyOn(StandFlightsSelectors, 'selectStandFlights').mockReturnValue(
createSelector(
(state: any) => state,
() => []
)
);
spectator.component.id = '101';
spectator.component.standDgss = ['DGS101'];
spectator.component.ngOnInit();
const emptyMessage = spectator.query('[data-cy="stand-flights-empty"]');
expect(emptyMessage).toBeTruthy();
});
it('should display flight rows when flights are present', () => {
jest.spyOn(StandFlightsSelectors, 'selectStandFlights').mockReturnValue(
createSelector(
(state: any) => state,
() => [flight1, flight2]
)
);
spectator.component.id = '101';
spectator.component.standDgss = ['DGS101'];
spectator.component.ngOnInit();
const emptyMessage = spectator.query('[data-cy="stand-flights-empty"]');
const flightsRowsNumber = spectator.queryAll('tr')?.length || 0;
expect(emptyMessage).toBeFalsy();
expect(flightsRowsNumber).toBe(2);
});
it('should display only external callsign', () => {
jest.spyOn(StandFlightsSelectors, 'selectStandFlights').mockReturnValue(
createSelector(
(state: any) => state,
() => [flight1, flight2]
)
);
mockStore.overrideSelector(selectUserPreferences, {
userPreferences: { [GlobalPreferencesKeys.flightCallsignType]: FlightCallsignType.EXTERNAL }
});
mockStore.overrideSelector(selectGlobalsFiltered([GlobalPreferencesKeys.flightCallsignType]), {
[GlobalPreferencesKeys.flightCallsignType]: 'CALCULATED'
});
mockStore.refreshState();
spectator.component.id = '101';
spectator.component.standDgss = ['DGS101'];
spectator.component.ngOnInit();
spectator.detectChanges();
const flightRows = spectator.queryAll('tr');
// 1st row of flight plan without the external call sign field specified
const firstFlightRow = flightRows[0];
const cellsOfFlightWithoutExternalCallsign = firstFlightRow.querySelectorAll('td');
expect(cellsOfFlightWithoutExternalCallsign[2]).toHaveText('');
// 2nd row of flight plan with the external call sign field specified
const secondFlightRow = flightRows[1];
const cellsOfFlightWithExternalCallsign = secondFlightRow.querySelectorAll('td');
expect(cellsOfFlightWithExternalCallsign[2]).toHaveText('AA1766');
});
I have tried with mockStore.resetSelectors()
in afterEach. I have tried with fakeAsync
and tick()
. I really can’t understand what’s going on. Maybe someone can help me with that?