11aba5dbd0
Signed-off-by: Gato <cedric@goutailler-olivier.fr>
144 lines
5.0 KiB
TypeScript
144 lines
5.0 KiB
TypeScript
import { signal } from '@angular/core';
|
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
import { provideRouter } from '@angular/router';
|
|
import { of, throwError } from 'rxjs';
|
|
import { vi } from 'vitest';
|
|
import { KeycloakService } from '../auth/keycloak.service';
|
|
import { ProjectContextService } from '../projects/project-context.service';
|
|
import { ProjectEntity } from '../projects/projects.store';
|
|
import { VersionApiService } from '../version/version-api.service';
|
|
import { Menu } from './menu';
|
|
|
|
describe('Menu', () => {
|
|
let component: Menu;
|
|
let fixture: ComponentFixture<Menu>;
|
|
|
|
const isAuthenticated = signal(false);
|
|
const username = signal<string | undefined>(undefined);
|
|
const projectId = signal<number | null>(null);
|
|
const project = signal<ProjectEntity | null>(null);
|
|
|
|
const keycloakMock = { isAuthenticated, username, logout: vi.fn(), login: vi.fn() };
|
|
const projectContextMock = { projectId, project };
|
|
const versionApiMock = { getVersion: vi.fn() };
|
|
|
|
beforeEach(async () => {
|
|
isAuthenticated.set(false);
|
|
projectId.set(null);
|
|
project.set(null);
|
|
keycloakMock.logout = vi.fn();
|
|
keycloakMock.login = vi.fn();
|
|
versionApiMock.getVersion = vi.fn();
|
|
|
|
await TestBed.configureTestingModule({
|
|
imports: [Menu],
|
|
providers: [
|
|
provideRouter([]),
|
|
{ provide: KeycloakService, useValue: keycloakMock },
|
|
{ provide: ProjectContextService, useValue: projectContextMock },
|
|
{ provide: VersionApiService, useValue: versionApiMock },
|
|
],
|
|
}).compileComponents();
|
|
|
|
fixture = TestBed.createComponent(Menu);
|
|
component = fixture.componentInstance;
|
|
await fixture.whenStable();
|
|
});
|
|
|
|
it('should create', () => {
|
|
expect(component).toBeTruthy();
|
|
});
|
|
|
|
describe('projectMenuItems', () => {
|
|
it('returns empty array when no project is selected', () => {
|
|
expect((component as any).projectMenuItems()).toEqual([]);
|
|
});
|
|
|
|
it('returns dashboard, issues, milestones and statuts items when a project is selected', () => {
|
|
projectId.set(5);
|
|
const items = (component as any).projectMenuItems();
|
|
expect(items.length).toBe(4);
|
|
expect(items[0].path).toBe('/projects/5/dashboard');
|
|
expect(items[1].path).toBe('/projects/5/issues');
|
|
expect(items[2].path).toBe('/projects/5/milestones');
|
|
expect(items[3].path).toBe('/projects/5/statuses');
|
|
});
|
|
});
|
|
|
|
it('logout calls keycloak.logout()', () => {
|
|
(component as any).logout();
|
|
expect(keycloakMock.logout).toHaveBeenCalled();
|
|
});
|
|
|
|
it('shows Projets link when authenticated', async () => {
|
|
isAuthenticated.set(true);
|
|
fixture.detectChanges();
|
|
await fixture.whenStable();
|
|
const links = fixture.nativeElement.querySelectorAll('a.sidebar-link');
|
|
const hrefs = Array.from(links).map((l: any) => l.getAttribute('href') ?? '');
|
|
expect(hrefs.some((h) => h === '/projects')).toBe(true);
|
|
});
|
|
|
|
describe('info button', () => {
|
|
it('toggleInfo opens the popover and fetches API version', () => {
|
|
versionApiMock.getVersion.mockReturnValue(of({ version: '1.2.3' }));
|
|
|
|
(component as any).toggleInfo();
|
|
|
|
expect((component as any).showInfo()).toBe(true);
|
|
expect((component as any).apiVersion()).toBe('1.2.3');
|
|
});
|
|
|
|
it('toggleInfo closes the popover when already open', () => {
|
|
versionApiMock.getVersion.mockReturnValue(of({ version: '1.2.3' }));
|
|
(component as any).toggleInfo();
|
|
(component as any).toggleInfo();
|
|
|
|
expect((component as any).showInfo()).toBe(false);
|
|
});
|
|
|
|
it('does not call getVersion again when popover is reopened', () => {
|
|
versionApiMock.getVersion.mockReturnValue(of({ version: '1.2.3' }));
|
|
(component as any).toggleInfo();
|
|
(component as any).toggleInfo();
|
|
(component as any).toggleInfo();
|
|
|
|
expect(versionApiMock.getVersion).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('sets apiVersion to — on API error', () => {
|
|
versionApiMock.getVersion.mockReturnValue(throwError(() => new Error('network')));
|
|
|
|
(component as any).toggleInfo();
|
|
|
|
expect((component as any).apiVersion()).toBe('—');
|
|
});
|
|
|
|
it('closeInfo hides the popover', () => {
|
|
versionApiMock.getVersion.mockReturnValue(of({ version: '1.2.3' }));
|
|
(component as any).toggleInfo();
|
|
(component as any).closeInfo();
|
|
|
|
expect((component as any).showInfo()).toBe(false);
|
|
});
|
|
|
|
it('versionMismatch is false when versions match', () => {
|
|
versionApiMock.getVersion.mockReturnValue(of({ version: (component as any).version }));
|
|
(component as any).toggleInfo();
|
|
|
|
expect((component as any).versionMismatch()).toBe(false);
|
|
});
|
|
|
|
it('versionMismatch is true when versions differ', () => {
|
|
versionApiMock.getVersion.mockReturnValue(of({ version: '99.99.99' }));
|
|
(component as any).toggleInfo();
|
|
|
|
expect((component as any).versionMismatch()).toBe(true);
|
|
});
|
|
|
|
it('versionMismatch is false before API responds', () => {
|
|
expect((component as any).versionMismatch()).toBe(false);
|
|
});
|
|
});
|
|
});
|