I have an Angular 9 (9.1.44) application, it utilises Azure B2C via the @azure/msal-angular (^1.0.0) and msal (^1.3.4) NPM packages to get authentication tokens to be used to access a backend service.
The app works fine, and the unit test all pass. However the default protractor e2e test that the angular scaffolding created with the project fails. I have modified the CSS selector in the page object to match my actual page content, but otherwise this it the exact same code as generated by ng new
.
When I run the e2e test it fails with this error (stack trace removed for brevity):
× should display app name the in navigation header
- Failed: Error while waiting for Protractor to sync with the page: "both angularJS testability and angular testability are undefined.
This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping.
See http://git.io/v4gXM for details"
I Think this is due to some combination of the MsalGuard
in the routing for the home page causing the browser to redirect to the B2C authentication page before the Angular page is rendered and possibly the HttpInterceptor
that will add the B2C token to outgoing calls. But since the browser is closed after the tests fail I cant look at the browser's console logs to check. The home page does not call an external API, but is subject to the Msal route guard.
I think I should be mocking the whole Msal stuff in the e2e tests so I can inject a bearer token and check with mocked API endpoints; I want a UI integration test, not a system integration test here. The problem is I can find no documentation on how to e2e test Angular apps using @azure/msal.
e2e test code:
import { AppPage } from './app.po';
import { browser, logging } from 'protractor';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display app name the in navigation header', () => {
page.navigateTo();
expect(page.getTitleText()).toEqual('ASA Admin');
});
afterEach(async () => {
// Assert that there are no errors emitted from the browser
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
expect(logs).not.toContain(jasmine.objectContaining({
level: logging.Level.SEVERE,
} as logging.Entry));
});
});
e2e page object code
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo(): Promise<unknown> {
return browser.get(`browser.baseUrl`) as Promise<unknown>;
}
getTitleText(): Promise<string> {
return element(by.css('.nav-heading')).getText() as Promise<string>;
}
}
interceptor code:
import {MsalInterceptor} from '@azure/msal-angular';
import {Injectable} from '@angular/core';
@Injectable()
export class AuthenticationInterceptor extends MsalInterceptor {}
I have tried temporarily removing the canActivate: [MsalGuard]
from the home page route but this still raises the same error.
Help!
I have looked at Protractor : Make test case wait till authentication is done, Failed: Error while waiting for Protractor to sync with the page” while executing Protractor tests and Protractor: Error while waiting for Protractor to sync with the page: "both angularJS testability and angular testability are undefined but non of the suggested actions have helped.