fix(quick-260921-jt4): Notiz-Aufgabenkaestchen bedient sich selbst

- NoteCheckbox traegt jetzt ein echtes onChange und gibt sein eigenes
  DOM-Element an onToggle weiter; readOnly entfaellt (D-01) — war bisher
  nur da, um Reacts Warnung ueber ein gesteuertes Feld ohne onChange zu
  unterdruecken
- Index-Ermittlung bleibt wortgleich (alle Kaestchen im Behaelter
  einsammeln, indexOf auf dem ausloesenden Element), wandert aber vom
  Behaelter-onClick in handleCheckboxToggle, das den Behaelter ueber ein
  ref statt event.currentTarget findet
- previewOptions als useMemo mit leerer Abhaengigkeitsliste, Rueckruf
  ueber ein ref erreicht — identitaetsstabil wie die alte Modulkonstante,
  T-JT4-03: rehypePlugins: [[rehypeSanitize]] unveraendert erhalten
- Tests: echte Tastaturbetaetigung (Leertaste auf fokussiertem
  Kaestchen) UND echter Klick loesen onToggle/PATCH aus; neue Tests
  belegen readOnly/disabled entfallen

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
This commit is contained in:
2026-09-21 14:47:45 +02:00
parent 0c89c13bb2
commit b601141bcf
4 changed files with 164 additions and 34 deletions
@@ -1,5 +1,6 @@
import { render } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import userEvent from '@testing-library/user-event';
import { describe, expect, it, vi } from 'vitest';
import MDEditor from '@uiw/react-md-editor';
import rehypeSanitize from 'rehype-sanitize';
import { NoteCheckbox, isTaskLine, toggleTaskLine } from './note-task-list';
@@ -75,6 +76,45 @@ describe('note-task-list', () => {
});
});
describe('NoteCheckbox — bedient sich selbst (quick-260921-jt4, D-01)', () => {
it('ist nicht mehr readOnly und traegt kein disabled', () => {
const { container } = render(<NoteCheckbox checked={true} />);
const box = container.querySelector('input[type="checkbox"]') as HTMLInputElement;
expect(box.readOnly).toBe(false);
expect(box.disabled).toBe(false);
});
it('ruft onToggle mit dem eigenen DOM-Element auf, wenn eine echte Tastaturbetaetigung (Leertaste) das fokussierte Kaestchen ausloest', async () => {
const onToggle = vi.fn();
const user = userEvent.setup({ delay: null });
const { container } = render(
<NoteCheckbox checked={false} onToggle={onToggle} />,
);
const box = container.querySelector('input[type="checkbox"]') as HTMLInputElement;
box.focus();
await user.keyboard(' ');
expect(onToggle).toHaveBeenCalledOnce();
expect(onToggle).toHaveBeenCalledWith(box);
});
it('ruft onToggle auch bei einem echten Mausklick auf', async () => {
const onToggle = vi.fn();
const user = userEvent.setup({ delay: null });
const { container } = render(
<NoteCheckbox checked={false} onToggle={onToggle} />,
);
const box = container.querySelector('input[type="checkbox"]') as HTMLInputElement;
await user.click(box);
expect(onToggle).toHaveBeenCalledOnce();
expect(onToggle).toHaveBeenCalledWith(box);
});
});
describe('echte Vorschau (MDEditor.Markdown + rehypeSanitize + components-Override)', () => {
it('rendert genau die Aufgabenzeilen als anklickbare Kaestchen', () => {
const SRC =