import { Component, ViewChild } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import {
UiButtonComponent,
UiConfirmDialogComponent,
UiEmptyStateComponent,
UiFormFieldComponent,
UiIconButtonComponent,
UiPaginationComponent,
UiStatusBadgeComponent,
UiToastHostComponent,
ToastService,
} from './index';
import { isDesignSystemRouteEnabled } from '../../core/dev-only.guard';
import { devRoutes } from '../../core/dev-routes.prod';
@Component({
standalone: true,
imports: [
UiButtonComponent,
UiConfirmDialogComponent,
UiEmptyStateComponent,
UiFormFieldComponent,
UiIconButtonComponent,
UiPaginationComponent,
UiStatusBadgeComponent,
UiToastHostComponent,
],
template: `
`,
})
class UiTestHostComponent {
@ViewChild(UiConfirmDialogComponent) dialog?: UiConfirmDialogComponent;
page = 2;
emptyActionCount = 0;
}
describe('shared UI components', () => {
it('renders button loading and disabled state', async () => {
await TestBed.configureTestingModule({ imports: [UiTestHostComponent] }).compileComponents();
const fixture = TestBed.createComponent(UiTestHostComponent);
fixture.detectChanges();
const button = (fixture.nativeElement as HTMLElement).querySelector('ui-button button');
expect(button?.hasAttribute('disabled')).toBe(true);
expect(button?.getAttribute('aria-busy')).toBe('true');
});
it('requires accessible labels for icon buttons', async () => {
await TestBed.configureTestingModule({ imports: [UiTestHostComponent] }).compileComponents();
const fixture = TestBed.createComponent(UiTestHostComponent);
fixture.detectChanges();
const button = (fixture.nativeElement as HTMLElement).querySelector('ui-icon-button button');
expect(button?.getAttribute('aria-label')).toBe('Eintrag loeschen');
});
it('shows form field errors and status text', async () => {
await TestBed.configureTestingModule({ imports: [UiTestHostComponent] }).compileComponents();
const fixture = TestBed.createComponent(UiTestHostComponent);
fixture.detectChanges();
const element = fixture.nativeElement as HTMLElement;
expect(element.textContent).toContain('Name ist erforderlich');
expect(element.textContent).toContain('Deaktiviert');
});
it('opens and closes confirm dialog and restores focus', async () => {
await TestBed.configureTestingModule({ imports: [UiTestHostComponent] }).compileComponents();
const fixture = TestBed.createComponent(UiTestHostComponent);
fixture.detectChanges();
const trigger = (fixture.nativeElement as HTMLElement).querySelector(
'#trigger',
);
trigger?.focus();
const promise = fixture.componentInstance.dialog?.open({
title: 'Loeschen',
description: 'Wirklich loeschen?',
confirmLabel: 'Loeschen',
danger: true,
});
fixture.detectChanges();
await fixture.whenStable();
expect((fixture.nativeElement as HTMLElement).querySelector('[role="dialog"]')).not.toBeNull();
fixture.componentInstance.dialog?.close(true);
fixture.detectChanges();
await expect(promise).resolves.toBe(true);
expect(document.activeElement).toBe(trigger);
});
it('shows and closes toasts', async () => {
await TestBed.configureTestingModule({ imports: [UiTestHostComponent] }).compileComponents();
const fixture = TestBed.createComponent(UiTestHostComponent);
const service = TestBed.inject(ToastService);
const id = service.show({ tone: 'success', title: 'Gespeichert' });
fixture.detectChanges();
expect((fixture.nativeElement as HTMLElement).textContent).toContain('Gespeichert');
service.close(id);
fixture.detectChanges();
expect((fixture.nativeElement as HTMLElement).textContent).not.toContain('Gespeichert');
});
it('emits empty state and pagination actions', async () => {
await TestBed.configureTestingModule({ imports: [UiTestHostComponent] }).compileComponents();
const fixture = TestBed.createComponent(UiTestHostComponent);
fixture.detectChanges();
const element = fixture.nativeElement as HTMLElement;
element.querySelector('ui-empty-state button')?.click();
element.querySelectorAll('ui-pagination button')[0]?.click();
expect(fixture.componentInstance.emptyActionCount).toBe(1);
expect(fixture.componentInstance.page).toBe(1);
});
it('keeps the design system route disabled outside development mode', () => {
expect(isDesignSystemRouteEnabled(false)).toBe(false);
expect(devRoutes).toHaveLength(0);
});
});