test(frontend): set up Vitest with jsdom and run tests in the image build
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 43s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 43s
- Add vitest, jsdom and Testing Library as dev dependencies, replace the placeholder test:run script with vitest run. - Add outliner tests for Backspace merging and caret placement on click. - Run the frontend tests in the Dockerfile before the Vite build. - Update docs (README, architecture, FLAW-19). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2b5291dc7b
commit
106a34d260
11 files changed
+1466
-73
No files matched your search
@@ -0,0 +1,64 @@
|
||||
import React from 'react';
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { render, fireEvent } from '@testing-library/react';
|
||||
import { OutlinerBlock, mapRenderedOffsetToRaw } from '../OutlinerBlock';
|
||||
import { DocumentBlock } from '../../../lib/types';
|
||||
|
||||
describe('mapRenderedOffsetToRaw', () => {
|
||||
it('is the identity for plain text', () => {
|
||||
expect(mapRenderedOffsetToRaw('Hallo Welt', 'Hallo Welt', 4)).toBe(4);
|
||||
});
|
||||
it('skips bold markers', () => {
|
||||
expect(mapRenderedOffsetToRaw('Hallo **Welt** du', 'Hallo Welt du', 8)).toBe(10);
|
||||
});
|
||||
it('maps behind closing markers', () => {
|
||||
expect(mapRenderedOffsetToRaw('a **b** c', 'a b c', 4)).toBe(8);
|
||||
});
|
||||
it('maps into a link label', () => {
|
||||
expect(mapRenderedOffsetToRaw('x [Seite](https://a.de) y', 'x Seite y', 4)).toBe(5);
|
||||
});
|
||||
it('handles the empty placeholder', () => {
|
||||
expect(mapRenderedOffsetToRaw('', '', 1)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clicking into an unfocused bullet', () => {
|
||||
afterEach(() => {
|
||||
delete (document as any).caretRangeFromPoint;
|
||||
});
|
||||
|
||||
it('places the caret at the click position instead of the end', () => {
|
||||
const block = { id: 'b1', type: 'bullet', content: 'Hallo **Welt** du', level: 0, position: 1 } as DocumentBlock;
|
||||
const { container } = render(
|
||||
<OutlinerBlock
|
||||
docId="d"
|
||||
block={block}
|
||||
index={0}
|
||||
isLast
|
||||
maxAllowedLevel={1}
|
||||
hasChildren={false}
|
||||
isFocused={false}
|
||||
canEdit
|
||||
onUpdateBlock={() => {}}
|
||||
onCreateBlockBelow={() => {}}
|
||||
onDeleteBlock={() => {}}
|
||||
onIndentBlock={() => {}}
|
||||
onNavigateFocus={() => {}}
|
||||
registerTextareaRef={() => {}}
|
||||
/>
|
||||
);
|
||||
const ta = container.querySelector('textarea') as HTMLTextAreaElement;
|
||||
const strong = container.querySelector('strong') as HTMLElement; // rendered "Welt"
|
||||
// jsdom has no layout: pretend the click hit between "We" and "lt"
|
||||
(document as any).caretRangeFromPoint = () => {
|
||||
const r = document.createRange();
|
||||
r.setStart(strong.firstChild!, 2);
|
||||
return r;
|
||||
};
|
||||
|
||||
fireEvent.click(strong);
|
||||
|
||||
expect(document.activeElement).toBe(ta);
|
||||
expect(ta.selectionStart).toBe(10); // "Hallo **We|lt** du"
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user