blob: 64805e2048f944da763cd44faffd952f5df5db33 [file]
import '@angular/compiler';
import { Injector, runInInjectionContext } from '@angular/core';
import { HeaderComponent, DOCUMENTATION_URL, BUG_REPORT_URL } from './header.component';
import { GatewayService } from '../gateway/gateway.service';
import { ThemeService } from '../theme/theme.service';
import { assert } from 'chai';
import * as sinon from 'sinon';
describe('HeaderComponent', () => {
let stubConsoleError: sinon.SinonStub;
let openStub: sinon.SinonStub;
beforeEach(() => {
stubConsoleError = sinon.stub(console, 'error');
openStub = sinon.stub(window, 'open');
});
afterEach(() => {
stubConsoleError.restore();
openStub.restore();
});
function createHeaderComponent(mockGateway?: Partial<GatewayService>): HeaderComponent {
const gateway = mockGateway || {
GetUserInfo: async () => ({ email: 'somebody@google.com' }),
};
const injector = Injector.create({
providers: [{ provide: GatewayService, useValue: gateway }, ThemeService],
});
let component!: HeaderComponent;
runInInjectionContext(injector, () => {
component = new HeaderComponent();
});
return component;
}
it('should set userEmail when GetUserInfo succeeds', async () => {
const component = createHeaderComponent();
await component.ngOnInit();
assert.equal(component.userEmail(), 'somebody@google.com');
});
it('should set userEmail to "Unknown user" when GetUserInfo returns no email', async () => {
const component = createHeaderComponent({
GetUserInfo: async () => ({ email: '' }),
});
await component.ngOnInit();
assert.equal(component.userEmail(), 'Unknown user');
});
it('should log an error and set userEmail to an error when GetUserInfo fails', async () => {
const testError = new Error('Network Error');
const component = createHeaderComponent({
GetUserInfo: async () => {
throw testError;
},
});
await component.ngOnInit();
assert.equal(component.userEmail(), 'Error loading user');
assert.isTrue(stubConsoleError.calledOnceWithExactly('Failed to load user info:', testError));
});
it('should redirect to the proxy logout URL on sign out click', () => {
const component = createHeaderComponent();
let redirectedUrl = '';
component.redirect = (url: string) => {
redirectedUrl = url;
};
component.onSignOutClick();
assert.equal(redirectedUrl, `/logout/?redirect=${encodeURIComponent(window.location.origin)}`);
});
it('should open documentation on help click', () => {
const component = createHeaderComponent();
component.onHelpClick();
assert.isTrue(openStub.calledOnceWithExactly(DOCUMENTATION_URL, '_blank'));
});
it('should open buganizer on bug click', () => {
const component = createHeaderComponent();
component.onBugClick();
assert.isTrue(openStub.calledOnceWithExactly(BUG_REPORT_URL, '_blank'));
});
describe('theme toggle', () => {
let localStorageGetStub: sinon.SinonStub;
let localStorageSetStub: sinon.SinonStub;
let initialClasses: string[];
beforeEach(() => {
localStorageGetStub = sinon.stub(localStorage, 'getItem');
localStorageSetStub = sinon.stub(localStorage, 'setItem');
initialClasses = Array.from(document.documentElement.classList);
document.documentElement.className = '';
});
afterEach(() => {
localStorageGetStub.restore();
localStorageSetStub.restore();
document.documentElement.className = initialClasses.join(' ');
});
it('should initialize to light theme by default when no saved theme', async () => {
localStorageGetStub.returns(null);
const component = createHeaderComponent();
await component.ngOnInit();
assert.isFalse(component.isDarkMode());
assert.isFalse(document.documentElement.classList.contains('dark-theme'));
});
it('should initialize to dark theme when saved theme is dark', async () => {
localStorageGetStub.withArgs('theme').returns('dark');
const component = createHeaderComponent();
await component.ngOnInit();
assert.isTrue(component.isDarkMode());
assert.isTrue(document.documentElement.classList.contains('dark-theme'));
});
it('should toggle theme and save to localStorage', async () => {
localStorageGetStub.returns(null);
const component = createHeaderComponent();
await component.ngOnInit(); // isDarkMode = false
assert.isFalse(document.documentElement.classList.contains('dark-theme'));
component.toggleTheme();
assert.isTrue(component.isDarkMode());
assert.isTrue(localStorageSetStub.calledWith('theme', 'dark'));
assert.isTrue(document.documentElement.classList.contains('dark-theme'));
component.toggleTheme();
assert.isFalse(component.isDarkMode());
assert.isTrue(localStorageSetStub.calledWith('theme', 'light'));
assert.isFalse(document.documentElement.classList.contains('dark-theme'));
});
});
});