Testing your editor
prosekit/core/test provides a small layer for unit-testing extensions and editors without spinning up a browser.
createTestEditor
Section titled “createTestEditor”createTestEditor(options) is a drop-in alternative to createEditor that returns a TestEditor. It exposes the same API as Editor, plus helpers for setting the document and selection from a builder syntax.
import { union function union<const E extends readonly Extension[]>(...exts: E): Union<E> (+1 overload)Merges multiple extensions into one. You can pass multiple extensions as
arguments or a single array containing multiple extensions.@throwsIf no extensions are provided.@example```ts
function defineFancyNodes() {
return union(
defineFancyParagraph(),
defineFancyHeading(),
)
}
```@example```ts
function defineFancyNodes() {
return union([
defineFancyParagraph(),
defineFancyHeading(),
])
}
``` } from 'prosekit/core'
import { createTestEditor function createTestEditor<E extends Extension>(options: EditorOptions<E>): TestEditor<E> } from 'prosekit/core/test'
import { defineDoc function defineDoc(): DocExtension } from 'prosekit/extensions/doc'
import { defineParagraph function defineParagraph(): ParagraphExtensionDefines a paragraph node.
The paragraph node spec has the highest priority, because it should be the
default block node for most cases. } from 'prosekit/extensions/paragraph'
import { defineText function defineText(): TextExtension } from 'prosekit/extensions/text'
const editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> = createTestEditor createTestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>(options: EditorOptions<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>): TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> ({
extension EditorOptions<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>.extension: Union<readonly [DocExtension, TextExtension, ParagraphExtension]>The extension to use when creating the editor. : union union<readonly [DocExtension, TextExtension, ParagraphExtension]>(exts_0: DocExtension, exts_1: TextExtension, exts_2: ParagraphExtension): Union<readonly [DocExtension, TextExtension, ParagraphExtension]> (+1 overload)Merges multiple extensions into one. You can pass multiple extensions as
arguments or a single array containing multiple extensions.@throwsIf no extensions are provided.@example```ts
function defineFancyNodes() {
return union(
defineFancyParagraph(),
defineFancyHeading(),
)
}
```@example```ts
function defineFancyNodes() {
return union([
defineFancyParagraph(),
defineFancyHeading(),
])
}
``` (defineDoc function defineDoc(): DocExtension (), defineText function defineText(): TextExtension (), defineParagraph function defineParagraph(): ParagraphExtensionDefines a paragraph node.
The paragraph node spec has the highest priority, because it should be the
default block node for most cases. ()),
})You don't call editor.mount(...). The test editor manages a detached view internally.
Using the builder syntax
Section titled “Using the builder syntax”editor.nodes.<name>(...) and editor.marks.<name>(...) are typed factories generated from your schema. Use them to build a document and hand it to editor.set(...).
import { union function union<const E extends readonly Extension[]>(...exts: E): Union<E> (+1 overload)Merges multiple extensions into one. You can pass multiple extensions as
arguments or a single array containing multiple extensions.@throwsIf no extensions are provided.@example```ts
function defineFancyNodes() {
return union(
defineFancyParagraph(),
defineFancyHeading(),
)
}
```@example```ts
function defineFancyNodes() {
return union([
defineFancyParagraph(),
defineFancyHeading(),
])
}
``` } from 'prosekit/core'
import { createTestEditor function createTestEditor<E extends Extension>(options: EditorOptions<E>): TestEditor<E> } from 'prosekit/core/test'
import { defineBold function defineBold(): BoldExtension } from 'prosekit/extensions/bold'
import { defineDoc function defineDoc(): DocExtension } from 'prosekit/extensions/doc'
import { defineParagraph function defineParagraph(): ParagraphExtensionDefines a paragraph node.
The paragraph node spec has the highest priority, because it should be the
default block node for most cases. } from 'prosekit/extensions/paragraph'
import { defineText function defineText(): TextExtension } from 'prosekit/extensions/text'
const editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> = createTestEditor createTestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>(options: EditorOptions<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>): TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> ({
extension EditorOptions<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>.extension: Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>The extension to use when creating the editor. : union union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>(exts_0: DocExtension, exts_1: TextExtension, exts_2: ParagraphExtension, exts_3: BoldExtension): Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]> (+1 overload)Merges multiple extensions into one. You can pass multiple extensions as
arguments or a single array containing multiple extensions.@throwsIf no extensions are provided.@example```ts
function defineFancyNodes() {
return union(
defineFancyParagraph(),
defineFancyHeading(),
)
}
```@example```ts
function defineFancyNodes() {
return union([
defineFancyParagraph(),
defineFancyHeading(),
])
}
``` (
defineDoc function defineDoc(): DocExtension (),
defineText function defineText(): TextExtension (),
defineParagraph function defineParagraph(): ParagraphExtensionDefines a paragraph node.
The paragraph node spec has the highest priority, because it should be the
default block node for most cases. (),
defineBold function defineBold(): BoldExtension (),
),
})
const n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
= editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> .nodes Editor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>.nodes: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
All
{@link
NodeAction
}
s defined by the editor.
const m const m: ToMarkAction<SimplifyDeeper<{
bold: {
readonly [x: string]: any;
};
}>>
= editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> .marks Editor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>.marks: ToMarkAction<SimplifyDeeper<{
bold: {
readonly [x: string]: any;
};
}>>
All
{@link
MarkAction
}
s defined by the editor.
const doc const doc: Node = n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
.doc doc: NodeAction
(attrs: {
readonly [x: string]: any;
} | null, ...children: NodeChild[]) => Node (+1 overload)
Creates a node with attributes and any number of children. (
n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
.paragraph paragraph: NodeAction
(...children: NodeChild[]) => Node (+1 overload)
Creates a node with any number of children. ('Hello, ', m const m: ToMarkAction<SimplifyDeeper<{
bold: {
readonly [x: string]: any;
};
}>>
.bold bold: MarkAction
(...children: NodeChild[]) => Node[] (+1 overload)
Applies a mark with any number of children. ('world'), '!'),
)
editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> .set TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>.set(doc: Node): voidSet the editor state to the given document. You can use special tokens
`<a>` and `<b>` to set the anchor and head positions of the selection.@example```ts
const editor = createTestEditor({ extension })
const n = editor.nodes
const doc = n.doc(n.paragraph('<a>Hello<b> world!'))
editor.set(doc) // "Hello" is selected.
``` (doc const doc: Node )Selection markers
Section titled “Selection markers”The set helper recognizes two special tokens in text content:
<a>marks the start of the selection.<b>marks the end of the selection.
import { union function union<const E extends readonly Extension[]>(...exts: E): Union<E> (+1 overload)Merges multiple extensions into one. You can pass multiple extensions as
arguments or a single array containing multiple extensions.@throwsIf no extensions are provided.@example```ts
function defineFancyNodes() {
return union(
defineFancyParagraph(),
defineFancyHeading(),
)
}
```@example```ts
function defineFancyNodes() {
return union([
defineFancyParagraph(),
defineFancyHeading(),
])
}
``` } from 'prosekit/core'
import { createTestEditor function createTestEditor<E extends Extension>(options: EditorOptions<E>): TestEditor<E> } from 'prosekit/core/test'
import { defineDoc function defineDoc(): DocExtension } from 'prosekit/extensions/doc'
import { defineParagraph function defineParagraph(): ParagraphExtensionDefines a paragraph node.
The paragraph node spec has the highest priority, because it should be the
default block node for most cases. } from 'prosekit/extensions/paragraph'
import { defineText function defineText(): TextExtension } from 'prosekit/extensions/text'
const editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> = createTestEditor createTestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>(options: EditorOptions<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>): TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> ({
extension EditorOptions<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>.extension: Union<readonly [DocExtension, TextExtension, ParagraphExtension]>The extension to use when creating the editor. : union union<readonly [DocExtension, TextExtension, ParagraphExtension]>(exts_0: DocExtension, exts_1: TextExtension, exts_2: ParagraphExtension): Union<readonly [DocExtension, TextExtension, ParagraphExtension]> (+1 overload)Merges multiple extensions into one. You can pass multiple extensions as
arguments or a single array containing multiple extensions.@throwsIf no extensions are provided.@example```ts
function defineFancyNodes() {
return union(
defineFancyParagraph(),
defineFancyHeading(),
)
}
```@example```ts
function defineFancyNodes() {
return union([
defineFancyParagraph(),
defineFancyHeading(),
])
}
``` (defineDoc function defineDoc(): DocExtension (), defineText function defineText(): TextExtension (), defineParagraph function defineParagraph(): ParagraphExtensionDefines a paragraph node.
The paragraph node spec has the highest priority, because it should be the
default block node for most cases. ()),
})
const n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
= editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> .nodes Editor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>.nodes: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
All
{@link
NodeAction
}
s defined by the editor.
const doc const doc: Node = n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
.doc doc: NodeAction
(attrs: {
readonly [x: string]: any;
} | null, ...children: NodeChild[]) => Node (+1 overload)
Creates a node with attributes and any number of children. (n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
.paragraph paragraph: NodeAction
(...children: NodeChild[]) => Node (+1 overload)
Creates a node with any number of children. ('<a>Hello<b> world!'))
editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> .set TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>.set(doc: Node): voidSet the editor state to the given document. You can use special tokens
`<a>` and `<b>` to set the anchor and head positions of the selection.@example```ts
const editor = createTestEditor({ extension })
const n = editor.nodes
const doc = n.doc(n.paragraph('<a>Hello<b> world!'))
editor.set(doc) // "Hello" is selected.
``` (doc const doc: Node )
// "Hello" is now selected.Reading a selection back with extractSelection
Section titled “Reading a selection back with extractSelection”extractSelection(doc) reads the <a>/<b> tokens out of a tagged document and returns the matching Selection. Use it in tests to assert against an expected tagged document instead of hand-counting positions.
import { union function union<const E extends readonly Extension[]>(...exts: E): Union<E> (+1 overload)Merges multiple extensions into one. You can pass multiple extensions as
arguments or a single array containing multiple extensions.@throwsIf no extensions are provided.@example```ts
function defineFancyNodes() {
return union(
defineFancyParagraph(),
defineFancyHeading(),
)
}
```@example```ts
function defineFancyNodes() {
return union([
defineFancyParagraph(),
defineFancyHeading(),
])
}
``` } from 'prosekit/core'
import { createTestEditor function createTestEditor<E extends Extension>(options: EditorOptions<E>): TestEditor<E> , extractSelection function extractSelection(doc: Node): Selection | undefinedExtracts a
{@link
Selection
}
from a tagged ProseMirror document built with
the test node builders. The position of the `<a>` token becomes the anchor,
and the optional `<b>` token becomes the head. Returns a `TextSelection` when
`<a>` resolves inside inline content, a `NodeSelection` when `<a>` resolves
inside a block parent, or `undefined` when the document contains no tags.@exampleExtracting a `TextSelection`:
```ts
const editor = createTestEditor({ extension })
const n = editor.nodes
const doc = n.doc(n.paragraph('<a>Hello<b> world!'))
const selection = extractSelection(doc) // TextSelection covering "Hello"
```@exampleExtracting a `NodeSelection`:
```ts
const editor = createTestEditor({ extension })
const n = editor.nodes
const doc = n.doc('<a>', n.paragraph('foo'))
const selection = extractSelection(doc) // NodeSelection on the paragraph
```@exampleA document without tags returns `undefined`:
```ts
const editor = createTestEditor({ extension })
const n = editor.nodes
const doc = n.doc(n.paragraph('Hello world!'))
const selection = extractSelection(doc) // undefined
``` } from 'prosekit/core/test'
import { defineDoc function defineDoc(): DocExtension } from 'prosekit/extensions/doc'
import { defineParagraph function defineParagraph(): ParagraphExtensionDefines a paragraph node.
The paragraph node spec has the highest priority, because it should be the
default block node for most cases. } from 'prosekit/extensions/paragraph'
import { defineText function defineText(): TextExtension } from 'prosekit/extensions/text'
import { expect const expect: ExpectStatic , it const it: TestAPIDefines a test case with a given name and test function. The test function can optionally be configured with test options.@paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example```ts
// Define a simple test
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
```@example```ts
// Define a test with options
it('subtracts two numbers', { retry: 3 }, () => {
expect(subtract(5, 2)).toBe(3);
});
``` } from 'vitest'
const editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> = createTestEditor createTestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>(options: EditorOptions<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>): TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> ({
extension EditorOptions<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>.extension: Union<readonly [DocExtension, TextExtension, ParagraphExtension]>The extension to use when creating the editor. : union union<readonly [DocExtension, TextExtension, ParagraphExtension]>(exts_0: DocExtension, exts_1: TextExtension, exts_2: ParagraphExtension): Union<readonly [DocExtension, TextExtension, ParagraphExtension]> (+1 overload)Merges multiple extensions into one. You can pass multiple extensions as
arguments or a single array containing multiple extensions.@throwsIf no extensions are provided.@example```ts
function defineFancyNodes() {
return union(
defineFancyParagraph(),
defineFancyHeading(),
)
}
```@example```ts
function defineFancyNodes() {
return union([
defineFancyParagraph(),
defineFancyHeading(),
])
}
``` (defineDoc function defineDoc(): DocExtension (), defineText function defineText(): TextExtension (), defineParagraph function defineParagraph(): ParagraphExtensionDefines a paragraph node.
The paragraph node spec has the highest priority, because it should be the
default block node for most cases. ()),
})
const n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
= editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> .nodes Editor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>.nodes: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
All
{@link
NodeAction
}
s defined by the editor.
it it<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)Defines a test case with a given name and test function. The test function can optionally be configured with test options.@paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example```ts
// Define a simple test
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
```@example```ts
// Define a test with options
it('subtracts two numbers', { retry: 3 }, () => {
expect(subtract(5, 2)).toBe(3);
});
``` ('preserves the selection that <a> and <b> describe', () => {
const doc const doc: Node = n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
.doc doc: NodeAction
(attrs: {
readonly [x: string]: any;
} | null, ...children: NodeChild[]) => Node (+1 overload)
Creates a node with attributes and any number of children. (n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
.paragraph paragraph: NodeAction
(...children: NodeChild[]) => Node (+1 overload)
Creates a node with any number of children. ('<a>Hello<b> world!'))
editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> .set TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>.set(doc: Node): voidSet the editor state to the given document. You can use special tokens
`<a>` and `<b>` to set the anchor and head positions of the selection.@example```ts
const editor = createTestEditor({ extension })
const n = editor.nodes
const doc = n.doc(n.paragraph('<a>Hello<b> world!'))
editor.set(doc) // "Hello" is selected.
``` (doc const doc: Node )
expect expect<any>(actual: any, message?: string): Assertion<any> (+1 overload) (editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>> .state Editor<Union<readonly [DocExtension, TextExtension, ParagraphExtension]>>.state: EditorStateThe editor's current state. .selection EditorState.selection: SelectionThe selection. .toJSON Selection.toJSON(): anyConvert the selection to a JSON representation. When implementing
this for a custom selection class, make sure to give the object a
`type` property whose value matches the ID under which you
[registered](https://prosemirror.net/docs/ref/#state.Selection^jsonID) your class. ()).toEqual JestAssertion<any>.toEqual: <any>(expected: any) => voidUsed when you want to check that two objects have the same value.
This matcher recursively checks the equality of all fields, rather than checking for object identity.@exampleexpect(user).toEqual({ name: 'Alice', age: 30 }); (
extractSelection function extractSelection(doc: Node): Selection | undefinedExtracts a
{@link
Selection
}
from a tagged ProseMirror document built with
the test node builders. The position of the `<a>` token becomes the anchor,
and the optional `<b>` token becomes the head. Returns a `TextSelection` when
`<a>` resolves inside inline content, a `NodeSelection` when `<a>` resolves
inside a block parent, or `undefined` when the document contains no tags.@exampleExtracting a `TextSelection`:
```ts
const editor = createTestEditor({ extension })
const n = editor.nodes
const doc = n.doc(n.paragraph('<a>Hello<b> world!'))
const selection = extractSelection(doc) // TextSelection covering "Hello"
```@exampleExtracting a `NodeSelection`:
```ts
const editor = createTestEditor({ extension })
const n = editor.nodes
const doc = n.doc('<a>', n.paragraph('foo'))
const selection = extractSelection(doc) // NodeSelection on the paragraph
```@exampleA document without tags returns `undefined`:
```ts
const editor = createTestEditor({ extension })
const n = editor.nodes
const doc = n.doc(n.paragraph('Hello world!'))
const selection = extractSelection(doc) // undefined
``` (doc const doc: Node )?.toJSON Selection.toJSON(): anyConvert the selection to a JSON representation. When implementing
this for a custom selection class, make sure to give the object a
`type` property whose value matches the ID under which you
[registered](https://prosemirror.net/docs/ref/#state.Selection^jsonID) your class. (),
)
})A complete unit test
Section titled “A complete unit test”import { union function union<const E extends readonly Extension[]>(...exts: E): Union<E> (+1 overload)Merges multiple extensions into one. You can pass multiple extensions as
arguments or a single array containing multiple extensions.@throwsIf no extensions are provided.@example```ts
function defineFancyNodes() {
return union(
defineFancyParagraph(),
defineFancyHeading(),
)
}
```@example```ts
function defineFancyNodes() {
return union([
defineFancyParagraph(),
defineFancyHeading(),
])
}
``` } from 'prosekit/core'
import { createTestEditor function createTestEditor<E extends Extension>(options: EditorOptions<E>): TestEditor<E> } from 'prosekit/core/test'
import { defineBold function defineBold(): BoldExtension } from 'prosekit/extensions/bold'
import { defineDoc function defineDoc(): DocExtension } from 'prosekit/extensions/doc'
import { defineParagraph function defineParagraph(): ParagraphExtensionDefines a paragraph node.
The paragraph node spec has the highest priority, because it should be the
default block node for most cases. } from 'prosekit/extensions/paragraph'
import { defineText function defineText(): TextExtension } from 'prosekit/extensions/text'
import { describe const describe: SuiteAPICreates a suite of tests, allowing for grouping and hierarchical organization of tests.
Suites can contain both tests and other suites, enabling complex test structures.@paramname - The name of the suite, used for identification and reporting.@paramfn - A function that defines the tests and suites within this suite.@example```ts
// Define a suite with two tests
describe('Math operations', () => {
test('should add two numbers', () => {
expect(add(1, 2)).toBe(3);
});
test('should subtract two numbers', () => {
expect(subtract(5, 2)).toBe(3);
});
});
```@example```ts
// Define nested suites
describe('String operations', () => {
describe('Trimming', () => {
test('should trim whitespace from start and end', () => {
expect(' hello '.trim()).toBe('hello');
});
});
describe('Concatenation', () => {
test('should concatenate two strings', () => {
expect('hello' + ' ' + 'world').toBe('hello world');
});
});
});
``` , expect const expect: ExpectStatic , it const it: TestAPIDefines a test case with a given name and test function. The test function can optionally be configured with test options.@paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example```ts
// Define a simple test
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
```@example```ts
// Define a test with options
it('subtracts two numbers', { retry: 3 }, () => {
expect(subtract(5, 2)).toBe(3);
});
``` } from 'vitest'
describe describe<object>(name: string | Function, fn?: SuiteFactory<object> | undefined, options?: number): SuiteCollector<object> (+1 overload)Creates a suite of tests, allowing for grouping and hierarchical organization of tests.
Suites can contain both tests and other suites, enabling complex test structures.@paramname - The name of the suite, used for identification and reporting.@paramfn - A function that defines the tests and suites within this suite.@example```ts
// Define a suite with two tests
describe('Math operations', () => {
test('should add two numbers', () => {
expect(add(1, 2)).toBe(3);
});
test('should subtract two numbers', () => {
expect(subtract(5, 2)).toBe(3);
});
});
```@example```ts
// Define nested suites
describe('String operations', () => {
describe('Trimming', () => {
test('should trim whitespace from start and end', () => {
expect(' hello '.trim()).toBe('hello');
});
});
describe('Concatenation', () => {
test('should concatenate two strings', () => {
expect('hello' + ' ' + 'world').toBe('hello world');
});
});
});
``` ('toggleBold', () => {
it it<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)Defines a test case with a given name and test function. The test function can optionally be configured with test options.@paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example```ts
// Define a simple test
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
```@example```ts
// Define a test with options
it('subtracts two numbers', { retry: 3 }, () => {
expect(subtract(5, 2)).toBe(3);
});
``` ('wraps the selection in a bold mark', () => {
const editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> = createTestEditor createTestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>(options: EditorOptions<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>): TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> ({
extension EditorOptions<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>.extension: Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>The extension to use when creating the editor. : union union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>(exts_0: DocExtension, exts_1: TextExtension, exts_2: ParagraphExtension, exts_3: BoldExtension): Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]> (+1 overload)Merges multiple extensions into one. You can pass multiple extensions as
arguments or a single array containing multiple extensions.@throwsIf no extensions are provided.@example```ts
function defineFancyNodes() {
return union(
defineFancyParagraph(),
defineFancyHeading(),
)
}
```@example```ts
function defineFancyNodes() {
return union([
defineFancyParagraph(),
defineFancyHeading(),
])
}
``` (
defineDoc function defineDoc(): DocExtension (),
defineText function defineText(): TextExtension (),
defineParagraph function defineParagraph(): ParagraphExtensionDefines a paragraph node.
The paragraph node spec has the highest priority, because it should be the
default block node for most cases. (),
defineBold function defineBold(): BoldExtension (),
),
})
const n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
= editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> .nodes Editor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>.nodes: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
All
{@link
NodeAction
}
s defined by the editor.
editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> .set TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>.set(doc: Node): voidSet the editor state to the given document. You can use special tokens
`<a>` and `<b>` to set the anchor and head positions of the selection.@example```ts
const editor = createTestEditor({ extension })
const n = editor.nodes
const doc = n.doc(n.paragraph('<a>Hello<b> world!'))
editor.set(doc) // "Hello" is selected.
``` (n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
.doc doc: NodeAction
(attrs: {
readonly [x: string]: any;
} | null, ...children: NodeChild[]) => Node (+1 overload)
Creates a node with attributes and any number of children. (n const n: ToNodeAction<SimplifyDeeper<{
doc: {
readonly [x: string]: any;
};
paragraph: {
readonly [x: string]: any;
};
text: {
readonly [x: string]: any;
};
}>>
.paragraph paragraph: NodeAction
(...children: NodeChild[]) => Node (+1 overload)
Creates a node with any number of children. ('<a>hi<b>')))
expect expect<boolean>(actual: boolean, message?: string): Assertion<boolean> (+1 overload) (editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> .commands Editor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>.commands: ToCommandAction<{
toggleBold: [];
setParagraph: [];
}>
All
{@link
CommandAction
}
s defined by the editor. .toggleBold toggleBold: CommandAction<[]> .canExec CommandAction<[]>.canExec(): booleanCheck if the current command can be executed. Return `true` if the command
can be executed, otherwise `false`. ()).toBe JestAssertion<boolean>.toBe: <boolean>(expected: boolean) => voidChecks that a value is what you expect. It calls `Object.is` to compare values.
Don't use `toBe` with floating-point numbers.@exampleexpect(result).toBe(42);
expect(status).toBe(true); (true)
editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> .commands Editor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>.commands: ToCommandAction<{
toggleBold: [];
setParagraph: [];
}>
All
{@link
CommandAction
}
s defined by the editor. .toggleBold toggleBold: CommandAction
() => boolean
Execute the current command. Return `true` if the command was successfully
executed, otherwise `false`. ()
expect expect<boolean>(actual: boolean, message?: string): Assertion<boolean> (+1 overload) (editor const editor: TestEditor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>> .marks Editor<Union<readonly [DocExtension, TextExtension, ParagraphExtension, BoldExtension]>>.marks: ToMarkAction<SimplifyDeeper<{
bold: {
readonly [x: string]: any;
};
}>>
All
{@link
MarkAction
}
s defined by the editor. .bold bold: MarkAction<{
readonly [x: string]: any;
}>
.isActive MarkAction<{ readonly [x: string]: any; }>.isActive: (attrs?: {
readonly [x: string]: any;
} | undefined) => boolean
Checks if the mark is active in the current editor selection. If the
optional `attrs` parameter is provided, it will check if the mark is active
with the given attributes. ()).toBe JestAssertion<boolean>.toBe: <boolean>(expected: boolean) => voidChecks that a value is what you expect. It calls `Object.is` to compare values.
Don't use `toBe` with floating-point numbers.@exampleexpect(result).toBe(42);
expect(status).toBe(true); (true)
})
})