Aam-Digital/ndb-core

View on GitHub
src/app/core/demo-data/demo-data-initializer.service.spec.ts

Summary

Maintainability
A
50 mins
Test Coverage
import { fakeAsync, TestBed, tick } from "@angular/core/testing";

import { DemoDataInitializerService } from "./demo-data-initializer.service";
import { DemoDataService } from "./demo-data.service";
import { DemoUserGeneratorService } from "../user/demo-user-generator.service";
import { MatDialog } from "@angular/material/dialog";
import { DemoDataGeneratingProgressDialogComponent } from "./demo-data-generating-progress-dialog.component";
import { LoginStateSubject, SessionType } from "../session/session-type";
import { environment } from "../../../environments/environment";
import { SessionInfo, SessionSubject } from "../session/auth/session-info";
import { LocalAuthService } from "../session/auth/local/local-auth.service";
import { SessionManagerService } from "../session/session-service/session-manager.service";
import { PouchDatabase } from "../database/pouch-database";
import { Database } from "../database/database";
import { LoginState } from "../session/session-states/login-state.enum";

describe("DemoDataInitializerService", () => {
  const normalUser: SessionInfo = {
    name: DemoUserGeneratorService.DEFAULT_USERNAME,
    id: DemoUserGeneratorService.DEFAULT_USERNAME,
    entityId: "User:demo",
    roles: ["user_app"],
  };
  const adminUser: SessionInfo = {
    name: DemoUserGeneratorService.ADMIN_USERNAME,
    id: DemoUserGeneratorService.ADMIN_USERNAME,
    entityId: "User:demo-admin",
    roles: ["user_app", "admin_app"],
  };
  let service: DemoDataInitializerService;
  let mockDemoDataService: jasmine.SpyObj<DemoDataService>;
  let mockLocalAuth: jasmine.SpyObj<LocalAuthService>;
  let sessionManager: jasmine.SpyObj<SessionManagerService>;
  let mockDialog: jasmine.SpyObj<MatDialog>;
  let demoUserDBName: string;
  let adminDBName: string;

  beforeEach(() => {
    environment.session_type = SessionType.mock;
    demoUserDBName = `${DemoUserGeneratorService.DEFAULT_USERNAME}-${environment.DB_NAME}`;
    adminDBName = `${DemoUserGeneratorService.ADMIN_USERNAME}-${environment.DB_NAME}`;
    mockDemoDataService = jasmine.createSpyObj(["publishDemoData"]);
    mockDemoDataService.publishDemoData.and.resolveTo();
    mockDialog = jasmine.createSpyObj(["open"]);
    mockDialog.open.and.returnValue({ close: () => {} } as any);
    mockLocalAuth = jasmine.createSpyObj(["saveUser"]);
    sessionManager = jasmine.createSpyObj(["offlineLogin"]);

    TestBed.configureTestingModule({
      providers: [
        DemoDataInitializerService,
        LoginStateSubject,
        SessionSubject,
        { provide: MatDialog, useValue: mockDialog },
        { provide: Database, useClass: PouchDatabase },
        { provide: DemoDataService, useValue: mockDemoDataService },
        { provide: LocalAuthService, useValue: mockLocalAuth },
        { provide: SessionManagerService, useValue: sessionManager },
      ],
    });
    service = TestBed.inject(DemoDataInitializerService);
  });

  afterEach(async () => {
    localStorage.clear();
    const tmpDB = new PouchDatabase();
    await tmpDB.initInMemoryDB(demoUserDBName).destroy();
    await tmpDB.initInMemoryDB(adminDBName).destroy();
  });

  it("should be created", () => {
    expect(service).toBeTruthy();
  });

  it("should save the default users", () => {
    service.run();

    expect(mockLocalAuth.saveUser).toHaveBeenCalledWith(normalUser);
    expect(mockLocalAuth.saveUser).toHaveBeenCalledWith(adminUser);
  });

  it("it should publish the demo data after logging in the default user", fakeAsync(() => {
    service.run();

    expect(sessionManager.offlineLogin).toHaveBeenCalledWith(normalUser);
    expect(mockDemoDataService.publishDemoData).not.toHaveBeenCalled();

    tick();

    expect(mockDemoDataService.publishDemoData).toHaveBeenCalled();
  }));

  it("should show a dialog while generating demo data", fakeAsync(() => {
    const closeSpy = jasmine.createSpy();
    mockDialog.open.and.returnValue({ close: closeSpy } as any);
    service.run();

    expect(mockDialog.open).toHaveBeenCalledWith(
      DemoDataGeneratingProgressDialogComponent,
    );
    expect(closeSpy).not.toHaveBeenCalled();

    tick();

    expect(closeSpy).toHaveBeenCalled();
  }));

  it("should sync with existing demo data when another user logs in", fakeAsync(() => {
    service.run();
    const database = TestBed.inject(Database) as PouchDatabase;
    database.initInMemoryDB(demoUserDBName);
    const defaultUserDB = database.getPouchDB();

    const userDoc = { _id: "userDoc" };
    database.put(userDoc);
    tick();

    TestBed.inject(SessionSubject).next({
      name: adminUser.name,
      id: adminUser.id,
      roles: [],
    });
    database.initInMemoryDB(adminDBName);
    TestBed.inject(LoginStateSubject).next(LoginState.LOGGED_IN);
    tick();

    expectAsync(database.get(userDoc._id)).toBeResolved();
    tick();

    const adminDoc1 = { _id: "adminDoc1" };
    const adminDoc2 = { _id: "adminDoc2" };
    database.put(adminDoc1);
    database.put(adminDoc2);
    tick();

    expect(database.getPouchDB().name).toBe(adminDBName);
    expectAsync(database.get(adminDoc1._id)).toBeResolved();
    expectAsync(database.get(adminDoc2._id)).toBeResolved();
    expectAsync(defaultUserDB.get(adminDoc1._id)).toBeResolved();
    expectAsync(defaultUserDB.get(adminDoc2._id)).toBeResolved();
    expectAsync(defaultUserDB.get(userDoc._id)).toBeResolved();
    tick();
  }));

  it("should stop syncing after logout", fakeAsync(() => {
    service.run();
    tick();

    const database = TestBed.inject(Database) as PouchDatabase;
    TestBed.inject(SessionSubject).next({
      name: adminUser.name,
      id: adminUser.id,
      roles: [],
    });
    database.initInMemoryDB(adminDBName);
    TestBed.inject(LoginStateSubject).next(LoginState.LOGGED_IN);
    const adminUserDB = database.getPouchDB();
    tick();

    const syncedDoc = { _id: "syncedDoc" };
    adminUserDB.put(syncedDoc);
    tick();

    TestBed.inject(LoginStateSubject).next(LoginState.LOGGED_OUT);

    const unsyncedDoc = { _id: "unsyncedDoc" };
    adminUserDB.put(unsyncedDoc);
    tick();

    database.initInMemoryDB(demoUserDBName);
    const defaultUserDB = database.getPouchDB();
    expectAsync(defaultUserDB.get(syncedDoc._id)).toBeResolved();
    expectAsync(defaultUserDB.get(unsyncedDoc._id)).toBeRejected();
    tick();
  }));
});