samedi 11 mai 2019

How to test an angular service that use NGRX

I've the following service:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { auth } from 'firebase/app';
import { AngularFireAuth } from '@angular/fire/auth';
import { Store } from '@ngrx/store';
import * as fromRoot from '../app.reducer';
import * as  Auth from './auth.actions';

@Injectable({
    providedIn: 'root'
})
export class AuthService {

    constructor(public afAuth: AngularFireAuth, public router: Router, private store: Store<fromRoot.State>) {
        this.afAuth.authState.subscribe(user => {
            if (user) {
                this.store.dispatch(new Auth.SetAuthenticated(user));
            } else {
                this.store.dispatch(new Auth.SetUnauthenticated());
                this.router.navigate(['auth/login']);
            }
        });
    }

    async login(email: string, password: string) {
        return await this.afAuth.auth.signInWithEmailAndPassword(
            email,
            password
        );
    }
    async register(email: string, password: string) {
        return await this.afAuth.auth.createUserWithEmailAndPassword(
            email,
            password
        );
    }

    async sendPasswordResetEmail(passwordResetEmail: string) {
        return await this.afAuth.auth.sendPasswordResetEmail(
            passwordResetEmail
        );
    }
    async logout() {
        await this.afAuth.auth.signOut();
    }
    async loginWithGoogle() {
        return await this.afAuth.auth.signInWithPopup(new auth.GoogleAuthProvider());
    }
}

I'm trying to test it in my auth.service.specs.ts:

import { TestBed, inject } from '@angular/core/testing';

import { AuthService } from './auth.service';
import { BehaviorSubject } from 'rxjs';
import { AngularFireAuth } from '@angular/fire/auth';
import { RouterTestingModule } from '@angular/router/testing';
import { TestStore } from '../test/testStore';
import { Store } from '@ngrx/store';
import * as fromRoot from '../app.reducer';
import { User } from 'firebase';

const FirestoreStub = {
    collection: (name: string) => ({
      doc: (_id: string) => ({
        valueChanges: () => new BehaviorSubject({ foo: 'bar' }),
        set: (_d: any) => new Promise((resolve, _reject) => resolve()),
      }),
    }),
  };

  let store: TestStore<fromRoot.State>;

describe('AuthService', () => {
     // An anonymous user
  const authState: User = {
    displayName: null,
    isAnonymous: true,
    uid: '17WvU2Vj58SnTz8v7EqyYYb0WRc2'
  };

  beforeEach(() => TestBed.configureTestingModule({
    imports: [RouterTestingModule],
    providers: [
        { provide: AngularFireAuth, useValue: FirestoreStub },
        { provide: Store, useClass: TestStore }   // use test store instead of ngrx store
      ],
  }));
  beforeEach(inject([Store], (testStore: TestStore<fromRoot.State>) => {
    store = testStore;                            // save store reference for use in tests
    store.setState({auth: {isAuthenticated:false, user:null}}); // set default state
  }));

  it('should be created', () => {
    const service: AuthService = TestBed.get(AuthService);
    expect(service).toBeTruthy();
  });
});

Currently, I cannot even have this should be created working:

HeadlessChrome 74.0.3723 (Windows 10.0.0) AuthService should be created FAILED
        TypeError: Cannot read property 'subscribe' of undefined
            at new AuthService (src/app/auth/auth.service.ts:16:31)
            at node_modules/@angular/core/fesm5/core.js:15518:29
            at _callFactory (node_modules/@angular/core/fesm5/core.js:21279:1)
            at _createProviderInstance (node_modules/@angular/core/fesm5/core.js:21237:1)
            at resolveNgModuleDep (node_modules/@angular/core/fesm5/core.js:21212:1)
            at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (node_modules/@angular/core/fesm5/core.js:21906:1)
            at TestBedViewEngine.push../node_modules/@angular/core/fesm5/testing.js.TestBedViewEngine.get (node_modules/@angular/core/fesm5/testing.js:1815:1)
            at Function.push../node_modules/@angular/core/fesm5/testing.js.TestBedViewEngine.get (node_modules/@angular/core/fesm5/testing.js:1598:1)
            at UserContext.<anonymous> (src/app/auth/auth.service.spec.ts:37:42)
            at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:391:1)

My understanding is that it's because my authState is not observable, but this starts to be quite cumbersome. How should this be done?

Aucun commentaire:

Enregistrer un commentaire