import { BixiACService } from './ac.service';
import { BixiACGuard } from './ac.guard';
import { TestBed } from '@angular/core/testing';
import { ActivatedRouteSnapshot, Router, Route } from '@angular/router';

describe('# @bixi/ac BixiACGuard', () => {
  let ac: BixiACService;
  let guard: BixiACGuard;
  let mockRouter: any;
  beforeEach(() => {
    mockRouter = jasmine.createSpyObj('Router', [
      'navigateByUrl',
    ]);
    TestBed.configureTestingModule(
      {
        providers: [
          BixiACGuard,
          BixiACService,
          {
            provide: Router, useValue: mockRouter
          }
        ]
      }
    );
    ac = TestBed.inject(BixiACService);
    guard = TestBed.inject(BixiACGuard);
    ac.setPermissions(['per_a', 'per_b']);
    ac.setRoles(['role_a', 'role_b']);
  });

  it('# do nothing', (done) => {
    const snapshot = new ActivatedRouteSnapshot();
    snapshot.data = {};
    guard.canActivate(snapshot).subscribe((res) => {
      expect(res).toBe(true);
      expect(mockRouter.navigateByUrl.calls.count()).toBe(0);
      done();
    })
  });

  // canActivate
  it('# canActivate passed(Permission ac)', (done) => {
    const snapshot = new ActivatedRouteSnapshot();
    snapshot.data = {
      ac: {
        ac: ['per_a'],
      }
    };
    guard.canActivate(snapshot).subscribe((res) => {
      expect(res).toBe(true);
      done();
    })
  });

  it('# canActivate passed(Role ac)', (done) => {
    const snapshot = new ActivatedRouteSnapshot();
    snapshot.data = {
      ac: {
        ac: ['role_a'],
        isRole: true
      }
    };
    guard.canActivate(snapshot).subscribe((res) => {
      expect(res).toBe(true);
      done();
    })
  });

  it('# canActivate rejected(Permission ac)', (done) => {
    const snapshot = new ActivatedRouteSnapshot();
    snapshot.data = {
      ac: {
        ac: ['per_a', 'per_b', 'per_d'],
        redirectTo: 'xxxxx',
      }
    };
    guard.canActivate(snapshot).subscribe((res) => {
      expect(res).toBe(false);
      expect(mockRouter.navigateByUrl.calls.count()).toBe(1);
      expect(mockRouter.navigateByUrl).toHaveBeenCalledWith('xxxxx');
      done();
    })
  });

  it('# canActivate rejected(Role ac)', (done) => {
    const snapshot = new ActivatedRouteSnapshot();
    snapshot.data = {
      ac: {
        ac: ['role_a', 'role_b', 'role_d'],
        redirectTo: 'xxxxx',
        isRole: true
      }
    };
    guard.canActivate(snapshot).subscribe((res) => {
      expect(res).toBe(false);
      expect(mockRouter.navigateByUrl.calls.count()).toBe(1);
      expect(mockRouter.navigateByUrl).toHaveBeenCalledWith('xxxxx');
      done();
    })
  });

  it('# canActivate passed(Permission acAny)', (done) => {
    const snapshot = new ActivatedRouteSnapshot();
    snapshot.data = {
      ac: {
        acAny: ['per_a', 'per_b', 'per_d']
      }
    };
    guard.canActivate(snapshot).subscribe((res) => {
      expect(res).toBe(true);
      done();
    })
  });

  it('# canActivate passed(Permission ace)', (done) => {
    const snapshot = new ActivatedRouteSnapshot();
    snapshot.data = {
      ac: {
        ace: ['per_d']
      }
    };
    guard.canActivate(snapshot).subscribe((res) => {
      expect(res).toBe(true);
      done();
    })
  });

  it('# canActivate passed(Permission aceAny)', (done) => {
    const snapshot = new ActivatedRouteSnapshot();
    snapshot.data = {
      ac: {
        aceAny: ['per_a', 'per_d']
      }
    };
    guard.canActivate(snapshot).subscribe((res) => {
      expect(res).toBe(true);
      done();
    })
  });

  // canActivateChild
  it('# canActivateChild passed', (done) => {
    const snapshot = new ActivatedRouteSnapshot();
    snapshot.data = {
      ac: {
        ac: ['per_a'],
      }
    };
    guard.canActivateChild(snapshot).subscribe((res) => {
      expect(res).toBe(true);
      done();
    })
  });

  // canLoad
  it('# canLoad passed', (done) => {
    const route: Route = {
      data: {
        ac: {
          ac: ['per_a'],
        }
      }
    };
    guard.canLoad(route).subscribe((res) => {
      expect(res).toBe(true);
      done();
    })
  });
});
