Home > Software design >  Angular NX/Jest testing of a directive and passing different test Users
Angular NX/Jest testing of a directive and passing different test Users

Time:08-19

I'm using Nx with Angular and Jest (with MockUtils library). I've got a test file of a structural directive and I want different tests for different Users (who have different levels of authorization). If a user is an admin they see 4 apps and if they're not, they see 2. I'll try and just add the relevant example code:

const testUser1 = {
    "role": "admin"
}
const testUser2 = {
    "role": "regularJoe"
}

describe('MyStructuralDirective', () => {
    let fixture: Component<TestHostComponent>;
    let component: TestHostComponent
    let authService: AuthService;

    beforeEach(() => {
         TestBed.configureTestingModule({
             imports: [],
             declarations: [
                 MyStructuralDirective,
                 TestHostComponent
             ],
             providers: [
                 MockUtils.mockProvider( AuthService, {
                     user$: new BehaviorSubject<any | null>(null),
                     isAuthorized: jest.fn((someFlag: string) => {
                         const user = authService.user$.value as any;
                         console.log(`USER: ${user.role}`);
                         return user.role === 'admin';
                     })
                 });
             ],
             schemas: [NO_ERRORS_SCHEMA]
         }).compileComponents();
         fixture = TestBed.createComponent(TestHostComponent);
         authService = TestBed.inject(AuthService);
         component = fixture.componentInstance;
     });

     afterEach(() => jest.clearAllMocks());
     
     test('should display two apps for user 1', () => {
         authService.user$.next(testUser1 as any);
         fixture.detectChanges();
         expect(component.numApps).toBe(2);
     });

     test('should display four apps for user 2', () => {
         authService.user$.next(testUser2 as any);
         fixture.detectChanges();
         expect(component.numApps).toBe(4);
     });
    
});

Here's a snippet of the Directive under test:

ngOnInit(): void{
    this.authService.user$.subscribe({
        next: user => {
            if(user) this.authService.isAuthorized(someFlag) ? this.vcr.createEmbeddedView(this.templateRef) : null;
        }
    });
}    

When I run the tests, no apps are coming thru. It's always the same:

 Expected: 2 (or whatever number i have in the assertion)
 Received: 0

Clearly, it's got to be something that I'm not understanding about the Angular Change Detection process. But the console statement in the isAuthorized() method is outputting the correct role, i.e. Admin and then RegularJoe. So, the user is getting updated and the ngOnInit() is being run.

I guess that I'm putting my assertions in the wrong place??? Can anyone shed any light, please?

CodePudding user response:

You have asynchronous code here, and should check it with same test pattern. For example you can use fakeAsync wrapper for your tests:

test('should display two apps for user 1', fakeAsync(() => {
   authService.user$.next(testUser1 as any);
   fixture.detectChanges();

   tick();

   expect(component.numApps).toBe(2);
}));
  • Related