diff --git a/frontend/src/lib/nav/AppShell.svelte b/frontend/src/lib/nav/AppShell.svelte new file mode 100644 index 0000000..dba02e4 --- /dev/null +++ b/frontend/src/lib/nav/AppShell.svelte @@ -0,0 +1,19 @@ + + +
+ +
+ +
+ {@render children?.()} +
+ +
+
diff --git a/frontend/src/lib/nav/AppShell.test.ts b/frontend/src/lib/nav/AppShell.test.ts new file mode 100644 index 0000000..63e9eb0 --- /dev/null +++ b/frontend/src/lib/nav/AppShell.test.ts @@ -0,0 +1,37 @@ +import { describe, it, expect, vi } from 'vitest'; +import { render, screen } from '@testing-library/svelte'; +import AppShell from './AppShell.svelte'; + +vi.mock('$app/stores', () => { + const { readable } = require('svelte/store'); + return { + page: readable({ url: new URL('http://localhost/planner') }) + }; +}); + +describe('AppShell', () => { + const defaultProps = { appName: 'Mealprep', householdName: 'Familie Müller' }; + + it('renders the DesktopSidebar', () => { + render(AppShell, { props: defaultProps }); + expect(screen.getByTestId('variety-widget-slot')).toBeInTheDocument(); + }); + + it('renders the MobileTabBar nav', () => { + render(AppShell, { props: defaultProps }); + const navs = screen.getAllByLabelText('Hauptnavigation'); + expect(navs.length).toBeGreaterThanOrEqual(2); + }); + + it('renders a main content area', () => { + render(AppShell, { props: defaultProps }); + expect(screen.getByRole('main')).toBeInTheDocument(); + }); + + it('renders all navigation links from all nav variants', () => { + render(AppShell, { props: defaultProps }); + const links = screen.getAllByRole('link'); + // Mobile: 4, Tablet: 4, Desktop: 5 = 13 total + expect(links).toHaveLength(13); + }); +});