Reputation: 41
Helpme please.
I'm migrating to Jest to run Unit Tests of ANGULAR, but when executing I get an error:
FAIL src/app/modules/dashboard/components/navbar/navbar.component.spec.ts
Test suite failed to runReferenceError: AuthenticationContext is not defined 6 | 7 | declare var AuthenticationContext: adal.AuthenticationContextStatic; > 8 | const createAuthContextFn: adal.AuthenticationContextStatic = AuthenticationContext; | ^ 9 | 10 | @Injectable() 11 | export class AdalService { at Object.<anonymous> (src/app/core/authentication/adal.service.ts:8:63) at Object.<anonymous> (src/app/core/authentication/adal-access.guard.ts:3:1) at Object.<anonymous> (src/app/modules/dashboard/components/navbar/navbar.component.spec.ts:5:1)
Test Suites: 1 failed, 1 total
Adal.service.ts doesn't work for me in angular when I run the tests with Jest.
when I run with Karma it works
This is the TEST:
import { Store } from '@ngrx/store';
import { RouterTestingModule } from '@angular/router/testing';
import { MatMenuModule } from '@angular/material/menu';
import { AdalConfigService } from './../../../../core/authentication/adal-config.service';
import { AdalAccessGuard } from './../../../../core/authentication/adal-access.guard';
import { AdalService } from '@authentication/adal.service';
import { environment } from '@env/environment';
import { APP_CONFIG } from '@app/app.config';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NavbarComponent } from './navbar.component';
describe('NavbarComponent', () => {
let component: NavbarComponent;
let fixture: ComponentFixture<NavbarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [NavbarComponent],
imports: [
RouterTestingModule,
MatMenuModule
],
providers: [
{
provide: Store,
useValue: {
dispatch: jest.fn(),
pipe: jest.fn()
}
},
AdalService,
AdalConfigService,
AdalAccessGuard,
{
provide: APP_CONFIG, useValue: {
apiEndpoint: environment.apiEndPoint,
clientId: environment.azureActiveDirectory.clientId,
tenantId: environment.azureActiveDirectory.tenantId,
resource: environment.azureActiveDirectory.resource,
redirectUri: environment.azureActiveDirectory.redirectUri
}
}]
})
.compileComponents();
}));
beforeEach(() => {
let mockAdalError;
let mockAdal;
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
mockAdalError = false;
mockAdal = {
userName: 'xxx',
profile: {
aud: 'xxx',
}
};
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { AdalService } from '@authentication/adal.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
public name;
public surname;
public email;
constructor( private adalService: AdalService ) { }
ngOnInit() {
this.loadUserInfo(this.adalService.userInfo);
}
onLogout(): void {
this.adalService.logout();
}
loadUserInfo(adalUser: any): void {
if (adalUser) {
this.name = XXX;
this.email = XXX;
} else {
this.name = 'No disponible';
this.email = 'No disponible';
}
}
}
This is SERVICE of ADAL:
import { Injectable } from '@angular/core';
import { Observable, Subscriber } from 'rxjs';
import { retry } from 'rxjs/operators';
import { AdalConfigService } from './adal-config.service';
import { adal } from 'adal-angular';
declare var AuthenticationContext: adal.AuthenticationContextStatic;
const createAuthContextFn: adal.AuthenticationContextStatic = AuthenticationContext;
@Injectable()
export class AdalService {
private context: adal.AuthenticationContext;
constructor(private configService: AdalConfigService) {
this.context = new createAuthContextFn(configService.adalSettings);
}
login() {
this.context.login();
}
logout() {
this.context.logOut();
}
get authContext() {
return this.context;
}
handleWindowCallback() {
this.context.handleWindowCallback();
}
public get userInfo() {
return this.context.getCachedUser();
}
public get accessToken() {
return this.context.getCachedToken(this.configService.adalSettings.clientId);
}
public get isAuthenticated() {
return this.userInfo && this.accessToken;
}
public isCallback(hash: string) {
return this.context.isCallback(hash);
}
public getLoginError() {
return this.context.getLoginError();
}
public getAccessToken(endpoint: string, callbacks: (message: string, token: string) => any) {
return this.context.acquireToken(endpoint, callbacks);
}
public acquireTokenResilient(resource: string): Observable<any> {
return new Observable<any>((subscriber: Subscriber<any>) =>
this.context.acquireToken(resource, (message: string, token: string) => {
token ? subscriber.next(token) : subscriber.error(message);
})
).pipe(retry(3));
}
}
I am using the version: "adal-angular": "^1.0.17",
Upvotes: 2
Views: 357
Reputation: 520
To make your setup run smoothly you have to initialize the AuthenticationContext somewhere globally. I assume this happens in the browser in your code by loading some adal script in your index.html
or in polyfills.ts
.
Jest is not loading these files and therefore it does not initialize AuthenticationContext anywhere.
With your declaration of the variable declare var AuthenticationContext: adal.AuthenticationContextStatic
you tell TypeScript: "I am guaranteeing that I initialize this variable globally somewhere else", but it looks like you are not doing this here in a Jest run.
The solution would be to either import the script which initializes the AuthenticationContext in the test files where it is required, or to do it manually in the files where required:
// 1. Initialize Variable
// not sure if you can initialize it like this, see the adal docs or source code
globalThis.AuthenticationContext = new AuthenticationContext();
// 2. Tell TypeScript compiler about this variable
declare const AuthenticationContext: adal.AuthenticationContextStatic;
You talk about unit tests, but your tests do not really look like unit tests as you do not test them in a isolated manner.
If you would like to test each component by unit, you should not at all instantiate the AuthenticationContext to test your NavBar. All other components and objects which come not from inside the NavBar should be mocked and provided as dummy objects. This would indirectly solve your issue as well.
To understand this better, look at the Angular Testing Guide and the jest documentation.
Cheers and happy coding!
Upvotes: 1