You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/soma/components/words/words-content.svelte.test.ts

121 lines
3.4 KiB

// @vitest-environment jsdom
import { flushSync, mount, settled, unmount } from 'svelte';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { createActiveDom } from '$adom';
import type { Morfo } from '$uix/morfo';
import { Soma } from '$soma/core/soma.svelte';
import { createSomaRuntime, type SomaRuntimeSources } from '$soma/runtime.svelte';
import { FieldProvider } from '../field';
import WordsContentHarness from './test/words-content-harness.svelte';
function installSomaHarness() {
const dom = createActiveDom();
const logger = {
trace: vi.fn(),
debug: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
fatal: vi.fn()
};
const soma = {
dom,
logger,
langs: {
ts: vi.fn((key: string) => key)
},
runtime: (morfo: Morfo, sources: Omit<SomaRuntimeSources, 'dom' | 'eventEngine'>) =>
createSomaRuntime(morfo, {
dom,
translate: (key) => key,
...sources
})
} as unknown as Soma;
vi.spyOn(Soma, 'require').mockReturnValue(soma);
vi.spyOn(FieldProvider, 'get').mockReturnValue(undefined);
return { dom };
}
function textLeaf(root: HTMLElement): Text {
const leaf = root.querySelector('[data-words-node="text"]')?.firstChild;
if (!(leaf instanceof Text)) throw new Error('Words text leaf not rendered');
return leaf;
}
function mountRenderedSelection(root: HTMLElement, offset: number) {
const leaf = textLeaf(root);
const range = document.createRange();
range.setStart(leaf, offset);
range.collapse(true);
const selection = document.getSelection();
selection?.removeAllRanges();
selection?.addRange(range);
}
describe('Words.Content component', () => {
afterEach(() => {
vi.restoreAllMocks();
document.body.innerHTML = '';
});
it('manages rendered html and restores DOM selection after an edit', async () => {
const { dom } = installSomaHarness();
const target = document.createElement('div');
document.body.append(target);
const component = mount(WordsContentHarness, { target });
await settled();
const content = target.querySelector('[data-testid="words-content"]') as HTMLElement | null;
expect(content).toBeTruthy();
if (!content) throw new Error('Words content did not mount');
expect(textLeaf(content).textContent).toBe('Hello');
mountRenderedSelection(content, 2);
const beforeInput = new InputEvent('beforeinput', {
inputType: 'insertText',
data: 'X',
bubbles: true,
cancelable: true
});
content.dispatchEvent(beforeInput);
flushSync();
await settled();
expect(beforeInput.defaultPrevented).toBe(true);
expect(textLeaf(content).textContent).toBe('HeXllo');
const selection = document.getSelection();
expect(selection?.anchorNode).toBe(textLeaf(content));
expect(selection?.anchorOffset).toBe(3);
await unmount(component);
dom.dispose();
});
it('still manages html when Svelte provides an empty children snippet', async () => {
const { dom } = installSomaHarness();
const target = document.createElement('div');
document.body.append(target);
const component = mount(WordsContentHarness, {
target,
props: { emptyChildren: true }
});
await settled();
const content = target.querySelector('[data-testid="words-content"]') as HTMLElement | null;
expect(content).toBeTruthy();
if (!content) throw new Error('Words content did not mount');
expect(textLeaf(content).textContent).toBe('Hello');
await unmount(component);
dom.dispose();
});
});

Powered by TurnKey Linux.