Files
backnotprop__plannotator/packages/ui/components/MarkdownDiff.reexport.test.tsx
Michael Ramos 4bbb0f3aff feat(ui): re-export MarkdownDiff through the ui surface (engine 0.8.0 / wrapper 0.4.0)
Adds components/MarkdownDiff.tsx, a theme-bridging shim over
@plannotator/markdown-editor's frozen two-revision diff, mirroring the
MarkdownEditor shim exactly: ThemeProvider mode bridge, plannotator.css
theme import, extensions passthrough (wikiLinks composes), gridEnabled ->
the same design-system card chrome. Hosts import it from
@plannotator/ui/components/MarkdownDiff; AtomicDiffEditor and
@plannotator/atomic-editor stay off the allowlist.

Deps: @plannotator/markdown-editor ^0.4.0, @plannotator/atomic-editor
^0.8.0 (single lockfile copy each), plus @codemirror/merge — the engine's
new required peer — declared directly per the CM6 single-copy discipline.

Tests pin the seam end-to-end: public export surface + types, byte-exact
getMarkdown()/getOriginalMarkdown() incl. CRLF/trailing-space fixtures,
contenteditable="false" frozen contract, change navigation, wiki-link
composition through the shim, and theme/host-class forwarding. The
strict-consumer tsconfig now typechecks the new module.
2026-07-09 23:34:45 -07:00

64 lines
2.5 KiB
TypeScript

/**
* Re-export surface test: hosts import MarkdownDiff (and its handle/prop
* types) from @plannotator/ui's MarkdownDiff module — never from
* @plannotator/markdown-editor's MarkdownDiff or @plannotator/atomic-editor's
* AtomicDiffEditor directly (both are outside the consumer import allowlist).
*
* Runs without DOM: it pins availability and the type surface, not diff
* behavior (the mounted surface is covered by MarkdownDiff.frozen.test.tsx).
*/
import { describe, test, expect } from 'bun:test';
import { EditorView } from '@codemirror/view';
import { MarkdownDiff, type MarkdownDiffHandle, type MarkdownDiffProps } from './MarkdownDiff';
import { wikiLinks } from './MarkdownEditor';
describe('MarkdownDiff module: public re-export surface', () => {
test('MarkdownDiff is exported as a renderable component', () => {
expect(typeof MarkdownDiff).toBe('function');
});
test('the handle type round-trips through the ui surface', () => {
// Compile-time assertion: fails typecheck (not just this test) if the
// re-exported handle drifts from the engine's navigation/byte contract.
const handle: MarkdownDiffHandle = {
goToNextChange: () => true,
goToPreviousChange: () => false,
getMarkdown: () => 'newer',
getOriginalMarkdown: () => 'older',
getChangeCount: () => 1,
getContentDOM: () => null,
};
expect(handle.getMarkdown()).toBe('newer');
expect(handle.getOriginalMarkdown()).toBe('older');
});
test('the props type round-trips, including the extensions seam', () => {
// Compile-time assertions: the shim keeps the packaged prop surface
// (minus mode/cardClassName, which the shim owns) and adds gridEnabled.
// wikiLinks comes from the ui MarkdownEditor surface and must be
// assignable to the diff's extensions seam so consumer extensions compose.
const props: MarkdownDiffProps = {
originalMarkdown: 'older\n',
modifiedMarkdown: 'newer\n',
documentId: 'doc-1',
ariaLabel: 'Document changes',
showToolbar: true,
showOverview: true,
gutter: true,
allowInlineDiffs: true,
highlightChanges: true,
syntaxHighlightDeletions: true,
gridEnabled: true,
mode: 'light',
maxWidth: 720,
className: 'host-outer',
onLinkClick: () => {},
extensions: [
wikiLinks({ suggest: async () => [], resolve: async () => null }),
EditorView.editorAttributes.of({ 'data-host-probe': 'ok' }),
],
};
expect(props.modifiedMarkdown).toBe('newer\n');
});
});