I initially believed that spying on services in Jasmine using the spyOn method and returning a value when the method is called was straightforward. However, it seems like my assumption may have been too simplistic?
I intend to test the following action in nxjs:
./Auth.state.ts
// ...
@Action(Login)
login(ctx: StateContext<AuthStateModel>, action: Login) {
return this.authService.login(action.payload).pipe(
tap(({ accessToken }: { accessToken: string }) => {
const {exp} = jwt_decode(accessToken);
const expiresAt = dayjs().add(exp, 'second');
ctx.patchState({
token: accessToken,
username: action.payload.username,
expiresAt
});
})
);
}
This action relies on the authService login method:
./auth.service.ts
// ...
login({ username, password }: User): Observable<{ accessToken?: string }> {
return this.http
.post(`${api.BASEURL}${api.API_LOGIN}`, { username, password });
}
Now I am trying to write a test for this scenario:
./Auth.state.spec.ts
describe('Auth', () => {
let store: Store;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NgxsModule.forRoot([AuthState]), HttpClientTestingModule],
providers: [HttpClient, HttpHandler, AuthService]
});
store = TestBed.inject(Store);
});
function setupState(NEW_STATE = null) {
store.reset({
...store.snapshot(),
auth: NEW_STATE
});
}
describe('login', () => {
it('updates the state upon successful login', () => {
// TS2345: Argument of type '"register"' is not assignable to parameter of type 'never'.
spyOn(AuthService, 'login').and.returnValue(false);
// find a possible workaround here: https://github.com/facebook/jest/issues/9675
// Object.defineProperty(AuthService, 'login', { get(){ return false; } });
// still no success...
const expectedState = { token: null, username: 'Some username', expiresAt: null };
setupState();
store.dispatch(new Login({ username: expectedState.username, password: '' }));
const auth = store.selectSnapshot(state => state.auth);
expect(auth).toEqual(expectedState);
});
});
// ...