feat(recipes): display form error from \$page.form in RecipeForm
- Import page store and render role="alert" error banner - Add mock for \$app/stores and \$app/forms in RecipeForm tests - Add tests: error banner shown when form.error set, hidden when null Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
type Category = { id: string; name: string; tagType?: string };
|
type Category = { id: string; name: string; tagType?: string };
|
||||||
|
|
||||||
type EditRecipe = {
|
type EditRecipe = {
|
||||||
@@ -45,6 +47,11 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form method="POST" {action}>
|
<form method="POST" {action}>
|
||||||
|
<!-- Error banner -->
|
||||||
|
{#if $page.form?.error}
|
||||||
|
<div role="alert">{$page.form.error}</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<!-- Basic info -->
|
<!-- Basic info -->
|
||||||
<label for="name">Name</label>
|
<label for="name">Name</label>
|
||||||
<input id="name" name="name" type="text" bind:value={name} required />
|
<input id="name" name="name" type="text" bind:value={name} required />
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
import { render, screen } from '@testing-library/svelte';
|
import { render, screen } from '@testing-library/svelte';
|
||||||
import { userEvent } from '@testing-library/user-event';
|
import { userEvent } from '@testing-library/user-event';
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
import RecipeForm from './RecipeForm.svelte';
|
import RecipeForm from './RecipeForm.svelte';
|
||||||
|
|
||||||
|
vi.mock('$app/stores', () => ({
|
||||||
|
page: writable({ form: null, url: new URL('http://localhost/recipes/new') })
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('$app/forms', () => ({
|
||||||
|
enhance: () => ({ destroy: () => {} })
|
||||||
|
}));
|
||||||
|
|
||||||
const mockCategories = [
|
const mockCategories = [
|
||||||
{ id: 'c1', name: 'Pasta', tagType: 'category' },
|
{ id: 'c1', name: 'Pasta', tagType: 'category' },
|
||||||
{ id: 'c2', name: 'Fleisch', tagType: 'category' }
|
{ id: 'c2', name: 'Fleisch', tagType: 'category' }
|
||||||
@@ -140,4 +149,17 @@ describe('RecipeForm', () => {
|
|||||||
const cancelLink = screen.getByRole('link', { name: /abbrechen/i });
|
const cancelLink = screen.getByRole('link', { name: /abbrechen/i });
|
||||||
expect(cancelLink).toHaveAttribute('href', '/recipes');
|
expect(cancelLink).toHaveAttribute('href', '/recipes');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('displays form error message when $page.form.error is set', async () => {
|
||||||
|
const { page } = await import('$app/stores');
|
||||||
|
(page as ReturnType<typeof writable>).set({ form: { error: 'Name ist erforderlich' }, url: new URL('http://localhost/recipes/new') });
|
||||||
|
render(RecipeForm, { props: emptyProps });
|
||||||
|
expect(screen.getByRole('alert')).toHaveTextContent('Name ist erforderlich');
|
||||||
|
(page as ReturnType<typeof writable>).set({ form: null, url: new URL('http://localhost/recipes/new') });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not display error banner when form has no error', () => {
|
||||||
|
render(RecipeForm, { props: emptyProps });
|
||||||
|
expect(screen.queryByRole('alert')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user