foundation: project guide, tooling, design tokens, bilingual shell and routing contracts

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-25 17:06:51 +02:00
parent 1020ac4c68
commit 42e9f01253
89 changed files with 3615 additions and 297 deletions

View File

@@ -1,23 +1,46 @@
import { TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import { App } from './app';
import { routes } from './app.routes';
import { PLACEHOLDER_CONTENT } from './core/content/placeholder-content';
import { SITE_CONTENT } from './core/content/content.token';
describe('App', () => {
beforeEach(async () => {
vi.spyOn(HTMLCanvasElement.prototype, 'getContext').mockReturnValue(null);
await TestBed.configureTestingModule({
imports: [App],
providers: [provideRouter(routes), { provide: SITE_CONTENT, useValue: PLACEHOLDER_CONTENT }],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(App);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
afterEach(() => {
vi.restoreAllMocks();
});
it('should render title', async () => {
it('should create the shell', async () => {
const fixture = TestBed.createComponent(App);
await fixture.whenStable();
expect(fixture.componentInstance).toBeTruthy();
});
it('should render an accessible application shell', async () => {
const fixture = TestBed.createComponent(App);
await fixture.whenStable();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, Portfolio');
const focusable = compiled.querySelectorAll(
'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])',
);
const firstFocusable = focusable.item(0);
expect(firstFocusable).toBeTruthy();
expect(firstFocusable.getAttribute('href')).toBe('#main-content');
expect(firstFocusable.classList.contains('skip-link')).toBe(true);
expect(compiled.querySelector('main#main-content')).toBeTruthy();
expect(compiled.querySelector('nav[aria-label]')).toBeTruthy();
expect(compiled.querySelector('a.language-switch[hreflang]')).toBeTruthy();
expect(compiled.querySelector('footer')).toBeTruthy();
});
});