I have been writing tests for my angular web application, specifically focusing on a page that includes a firebase UI element. The tests are split into two parts: one to verify that the page loads successfully and another to confirm that the firebaseUI component is loading correctly:
authentication.component.spec.ts
/*eslint-env jasmine*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { AuthenticationComponent } from './authentication.component';
import { FirebaseService } from '../services/firebase.service';
describe('AuthenticationComponent_Logged_Out', () => {
let component: AuthenticationComponent;
let fixture: ComponentFixture<AuthenticationComponent>;
let service;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AuthenticationComponent ],
schemas: [ NO_ERRORS_SCHEMA ]
}).compileComponents();
service = TestBed.inject(FirebaseService);
fixture = TestBed.createComponent(AuthenticationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should render auth ui', () => {
const compiled = fixture.nativeElement;
expect(compiled.querySelector("#firebaseui_auth_container")).toBeTruthy();
});
afterEach(async () => {
service.ui.reset();
});
});
Using the following template file:
<script src="https://www.gstatic.com/firebasejs/ui/4.8.0/firebase-ui-auth.js"></script>
<link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.8.0/firebase-ui-auth.css" />
<div id="authentication-wrapper">
<h1>Please sign in below to access your quotes!</h1>
<div id="firebaseui_auth_container"></div>
<div id="loader">Loading...</div>
</div>
With the accompanying class:
import { Component } from '@angular/core';
import { FirebaseService } from '../services/firebase.service';
@Component({
selector: 'app-authentication',
templateUrl: './authentication.component.html',
styleUrls: ['./authentication.component.css']
})
export class AuthenticationComponent {
constructor (private fbService: FirebaseService) {
sessionStorage.removeItem('displayed_random');
// If user logged in, redirect to feed
if (fbService.currentUser) {
window.location.href = "/feed";
} else {
this.fbService.instantiateUi();
}
}
}
The service responsible for loading the firebase UI is detailed in:
firebase.service.ts
import { Injectable } from '@angular/core';
import firebase from "firebase/app";
import * as firebaseui from "firebaseui";
import { config } from './config';
import 'firebase/database';
import 'firebase/auth';
firebase.initializeApp(config);
@Injectable({
providedIn: 'root'
})
export class FirebaseService {
currentUser: string;
auth = firebase.auth();
ui = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(this.auth);
constructor () {
const username = sessionStorage.getItem('username');
if (username) {
this.currentUser = username;
}
}
signoutUser () {
this.auth.signOut();
this.currentUser = undefined;
if (sessionStorage.getItem('username')) {
sessionStorage.removeItem('username');
}
}
getRef (path) {
return firebase.database().ref(path);
}
instantiateUi () {
this.ui.start("#firebaseui_auth_container", {
callbacks: {
signInSuccessWithAuthResult: (authResult) => {
// Save username in storage
sessionStorage.setItem('username', authResult.user.displayName);
return true;
},
uiShown: () => {
// The widget is rendered, hide the loader.
document.getElementById('loader').style.display = 'none';
}
},
// Will use popup for IDP Providers sign-in flow instead of the default, redirect.
signInFlow: 'popup',
signInSuccessUrl: 'feed',
signInOptions: [
{
provider: firebase.auth.GoogleAuthProvider.PROVIDER_ID,
customParameters: {
prompt: 'select_account' // Forces account selection even when only one account is available.
}
},
firebase.auth.EmailAuthProvider.PROVIDER_ID
]
});
}
}
In a standard development server environment using ng serve
, the UI functions as intended. However, during testing, the UI fails to generate properly, resulting in issues with the firebaseui auth container not being found by the test framework.
https://i.sstatic.net/0oo1c.png
https://i.sstatic.net/6s9wQ.png
I am currently troubleshooting why the test framework is unable to locate the firebaseui auth container. I have attempted multiple injections of the service and ensured the UI is reset after each test run, but so far without success. It seems that the variable compiled
might be undefined for some reason, which is puzzling as this logic has worked seamlessly in my other tests.