Backend: - Rename V006 migration to V026 (avoid conflict with existing V006) - Migration adds invalidated_at + partial unique index on household_invite Frontend: - Toast.svelte — new system component (message + dismiss) - SegmentedControl.svelte — new system component (options, value, onchange) - members/+page.server.ts — loads members + active invite - members/[userId]/+server.ts — DELETE/PATCH proxy - members/invites/+server.ts — POST (regenerate) proxy - MemberCard.svelte — tile with avatar, kebab, inline role edit - RemoveDialog.svelte — confirmation dialog (desktop modal + BottomSheet mobile) - InviteCard.svelte + InvitePanel.svelte — invite management UI - MemberGrid.svelte — responsive 4/2-col grid with sorted members - members/+page.svelte — page composing all components with optimistic updates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
31 lines
1.3 KiB
TypeScript
31 lines
1.3 KiB
TypeScript
import { describe, it, expect, vi } from 'vitest';
|
|
import { render, screen } from '@testing-library/svelte';
|
|
import userEvent from '@testing-library/user-event';
|
|
import SegmentedControl from './SegmentedControl.svelte';
|
|
|
|
const options = [
|
|
{ value: 'planner', label: 'Planer' },
|
|
{ value: 'member', label: 'Mitglied' }
|
|
];
|
|
|
|
describe('SegmentedControl', () => {
|
|
it('renders all option labels', () => {
|
|
render(SegmentedControl, { props: { options, value: 'planner', onchange: vi.fn() } });
|
|
expect(screen.getByRole('button', { name: 'Planer' })).toBeInTheDocument();
|
|
expect(screen.getByRole('button', { name: 'Mitglied' })).toBeInTheDocument();
|
|
});
|
|
|
|
it('marks the active option with aria-pressed', () => {
|
|
render(SegmentedControl, { props: { options, value: 'planner', onchange: vi.fn() } });
|
|
expect(screen.getByRole('button', { name: 'Planer' })).toHaveAttribute('aria-pressed', 'true');
|
|
expect(screen.getByRole('button', { name: 'Mitglied' })).toHaveAttribute('aria-pressed', 'false');
|
|
});
|
|
|
|
it('calls onchange with the new value when an option is clicked', async () => {
|
|
const onchange = vi.fn();
|
|
render(SegmentedControl, { props: { options, value: 'planner', onchange } });
|
|
await userEvent.click(screen.getByRole('button', { name: 'Mitglied' }));
|
|
expect(onchange).toHaveBeenCalledWith('member');
|
|
});
|
|
});
|