156 lines
5.7 KiB
TypeScript
156 lines
5.7 KiB
TypeScript
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
import { cleanup, render } from 'vitest-browser-svelte';
|
|
import { page as browserPage } from 'vitest/browser';
|
|
|
|
const mockPage = { url: new URL('http://localhost/documents') };
|
|
|
|
vi.mock('$app/state', () => ({
|
|
get page() {
|
|
return mockPage;
|
|
}
|
|
}));
|
|
|
|
afterEach(cleanup);
|
|
|
|
async function loadComponent() {
|
|
return (await import('./AppNav.svelte')).default;
|
|
}
|
|
|
|
describe('AppNav', () => {
|
|
it('renders the brand link', async () => {
|
|
mockPage.url = new URL('http://localhost/');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
await expect.element(browserPage.getByRole('link', { name: /familienarchiv/i })).toBeVisible();
|
|
});
|
|
|
|
it('renders all four primary nav links by default', async () => {
|
|
mockPage.url = new URL('http://localhost/');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
await expect.element(browserPage.getByRole('link', { name: /^dokumente$/i })).toBeVisible();
|
|
await expect.element(browserPage.getByRole('link', { name: /^personen$/i })).toBeVisible();
|
|
await expect.element(browserPage.getByRole('link', { name: /^stammbaum$/i })).toBeVisible();
|
|
await expect.element(browserPage.getByRole('link', { name: /^geschichten$/i })).toBeVisible();
|
|
});
|
|
|
|
it('hides the admin link when isAdmin is false', async () => {
|
|
mockPage.url = new URL('http://localhost/');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
await expect
|
|
.element(browserPage.getByRole('link', { name: /^admin$/i }))
|
|
.not.toBeInTheDocument();
|
|
});
|
|
|
|
it('shows the admin link when isAdmin is true', async () => {
|
|
mockPage.url = new URL('http://localhost/');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: true } });
|
|
|
|
await expect.element(browserPage.getByRole('link', { name: /^admin$/i })).toBeVisible();
|
|
});
|
|
|
|
it('shows the open-menu hamburger by default', async () => {
|
|
mockPage.url = new URL('http://localhost/');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
await expect
|
|
.element(browserPage.getByRole('button', { name: /menü öffnen/i }))
|
|
.toHaveAttribute('aria-expanded', 'false');
|
|
});
|
|
|
|
it('opens the mobile nav and switches the hamburger label when clicked', async () => {
|
|
mockPage.url = new URL('http://localhost/');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
await browserPage.getByRole('button', { name: /menü öffnen/i }).click();
|
|
|
|
await expect
|
|
.element(browserPage.getByRole('button', { name: /menü schließen/i }))
|
|
.toHaveAttribute('aria-expanded', 'true');
|
|
});
|
|
|
|
it('marks the documents link as active when pathname starts with /documents', async () => {
|
|
mockPage.url = new URL('http://localhost/documents/abc');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
const link = Array.from(document.querySelectorAll('nav a[href="/documents"]'))[0];
|
|
expect(link?.className).toContain('border-accent');
|
|
});
|
|
|
|
it('marks the persons link as active when pathname starts with /persons', async () => {
|
|
mockPage.url = new URL('http://localhost/persons/123');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
const link = Array.from(document.querySelectorAll('nav a[href="/persons"]'))[0];
|
|
expect(link?.className).toContain('border-accent');
|
|
});
|
|
|
|
it('marks the stammbaum link as active when pathname starts with /stammbaum', async () => {
|
|
mockPage.url = new URL('http://localhost/stammbaum');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
const link = Array.from(document.querySelectorAll('nav a[href="/stammbaum"]'))[0];
|
|
expect(link?.className).toContain('border-accent');
|
|
});
|
|
|
|
it('marks the geschichten link as active when pathname starts with /geschichten', async () => {
|
|
mockPage.url = new URL('http://localhost/geschichten/x');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
const link = Array.from(document.querySelectorAll('nav a[href="/geschichten"]'))[0];
|
|
expect(link?.className).toContain('border-accent');
|
|
});
|
|
|
|
it('marks the admin link as active when pathname starts with /admin and isAdmin is true', async () => {
|
|
mockPage.url = new URL('http://localhost/admin/users');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: true } });
|
|
|
|
const link = Array.from(document.querySelectorAll('nav a[href="/admin"]'))[0];
|
|
expect(link?.className).toContain('border-accent');
|
|
});
|
|
|
|
it('closes the mobile nav when the backdrop is clicked', async () => {
|
|
mockPage.url = new URL('http://localhost/');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
await browserPage.getByRole('button', { name: /menü öffnen/i }).click();
|
|
|
|
// Mobile nav is now open
|
|
const backdrop = document.querySelector('.bg-black\\/20') as HTMLElement;
|
|
expect(backdrop).not.toBeNull();
|
|
backdrop.click();
|
|
|
|
await expect
|
|
.element(browserPage.getByRole('button', { name: /menü öffnen/i }))
|
|
.toHaveAttribute('aria-expanded', 'false');
|
|
});
|
|
|
|
it('closes the mobile nav when Escape is pressed on the overlay', async () => {
|
|
mockPage.url = new URL('http://localhost/');
|
|
const AppNav = await loadComponent();
|
|
render(AppNav, { props: { isAdmin: false } });
|
|
|
|
await browserPage.getByRole('button', { name: /menü öffnen/i }).click();
|
|
|
|
const overlay = document.querySelector('.fixed.inset-0') as HTMLElement;
|
|
overlay.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
|
|
await expect
|
|
.element(browserPage.getByRole('button', { name: /menü öffnen/i }))
|
|
.toHaveAttribute('aria-expanded', 'false');
|
|
});
|
|
});
|