refactor(geschichte): extract delete handler to [id]/+page.svelte, pass via ondelete prop
Moves the confirm-then-delete flow out of StoryReader and JourneyReader into the single [id]/+page.svelte owner. Both reader components gain an optional ondelete prop — the delete button calls ondelete?.() so the handler is opt-in and never duplicated. Tests verify the prop is called on click. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { describe, it, expect, vi, afterEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page } from 'vitest/browser';
|
||||
import { page, userEvent } from 'vitest/browser';
|
||||
import { createConfirmService, CONFIRM_KEY } from '$lib/shared/services/confirm.svelte.js';
|
||||
import type { components } from '$lib/generated/api';
|
||||
|
||||
@@ -75,8 +75,11 @@ describe('JourneyReader', () => {
|
||||
props: { geschichte: baseGeschichte({ body: ' ' }), canBlogWrite: false }
|
||||
});
|
||||
|
||||
expect(document.body.textContent?.trim().replace(/\s+/g, ' ')).not.toContain(' ');
|
||||
// Whitespace-only body must NOT produce a visible intro paragraph.
|
||||
// The only rendered content should be the empty-state message.
|
||||
await expect.element(page.getByTestId('journey-empty-state')).toBeVisible();
|
||||
const paragraphs = document.querySelectorAll('p:not([data-testid])');
|
||||
expect(paragraphs.length).toBe(0);
|
||||
});
|
||||
|
||||
it('renders empty-state message when items array is empty', async () => {
|
||||
@@ -148,6 +151,22 @@ describe('JourneyReader', () => {
|
||||
await expect.element(page.getByText('Diese Lesereise ist noch leer.')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('clicking delete button calls ondelete prop', async () => {
|
||||
const ondelete = vi.fn().mockResolvedValue(undefined);
|
||||
render(JourneyReader, {
|
||||
context: ctx(),
|
||||
props: {
|
||||
geschichte: baseGeschichte({ items: [docItem('i1', 'Brief', 0)] }),
|
||||
canBlogWrite: true,
|
||||
ondelete
|
||||
}
|
||||
});
|
||||
|
||||
await userEvent.click(page.getByRole('button', { name: /löschen/i }));
|
||||
|
||||
expect(ondelete).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('XSS: Journey body is rendered as plaintext — injected payload does not execute', async () => {
|
||||
// JourneyReader uses Svelte text interpolation, NOT {@html}.
|
||||
render(JourneyReader, {
|
||||
|
||||
Reference in New Issue
Block a user