editor: migrate tests to vitest

This commit is contained in:
Abdullah Atta
2023-03-06 14:29:12 +05:00
committed by Abdullah Atta
parent dfa718f8ea
commit 2f4a7f5410
9 changed files with 2064 additions and 12715 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@
"dependencies": {
"@emotion/react": "^11.10.0",
"@notesnook/theme": "*",
"@remirror/core-utils": "^2.0.10",
"@social-embed/lib": "^0.0.2-next.1",
"@theme-ui/components": "^0.14.7",
"@theme-ui/core": "^0.14.7",
@@ -32,6 +33,7 @@
"@tiptap/starter-kit": "^2.0.0-beta.218",
"detect-indent": "^7.0.0",
"katex": "^0.16.2",
"nanoid": "^4.0.1",
"prism-themes": "^1.9.0",
"prosemirror-codemark": "^0.4.1",
"re-resizable": "^6.9.9",
@@ -45,25 +47,20 @@
"zustand": "^3.7.2"
},
"devDependencies": {
"@happy-dom/global-registrator": "^8.9.0",
"@mdi/js": "^6.9.96",
"@mdi/react": "^1.6.0",
"@swc/core": "^1.3.36",
"@types/katex": "^0.14.0",
"@types/prismjs": "^1.26.0",
"@types/react": "17.0.2",
"@types/react-color": "^3.0.6",
"@types/react-dom": "17.0.2",
"@types/react-modal": "^3.13.1",
"@types/tap": "^15.0.8",
"@types/tinycolor2": "^1.4.3",
"expect": "^29.4.3",
"framer-motion": "^6.5.1",
"isomorphic-fetch": "^3.0.0",
"prosemirror-test-builder": "^1.1.0",
"tap": "^16.3.4",
"tsconfig-paths": "^3.14.2",
"typescript": "^4.8.2",
"vitest": "^0.29.2",
"web-vitals": "^2.1.4",
"zx": "^7.0.8"
},

View File

@@ -21,6 +21,7 @@ import { Editor, Extension } from "@tiptap/core";
import { isInTable } from "@tiptap/pm/tables";
import { LIST_ITEM_NODE_TYPES, LIST_NODE_TYPES } from "../../utils/node-types";
import { isListActive } from "../../utils/prosemirror";
import { CodeBlock } from "../code-block";
export const KeyMap = Extension.create({
name: "key-map",
@@ -28,7 +29,13 @@ export const KeyMap = Extension.create({
addKeyboardShortcuts() {
return {
Tab: ({ editor }) => {
if (isListActive(editor) || isInTable(editor.state)) return false;
if (
isListActive(editor) ||
isInTable(editor.state) ||
editor.isActive(CodeBlock.name)
)
return false;
return editor.commands.insertContent("\t");
},
"Shift-Tab": ({ editor }) => {
@@ -37,9 +44,9 @@ export const KeyMap = Extension.create({
},
Backspace: ({ editor }) => {
return joinUpWithLastListItem(editor);
}
},
};
}
},
});
/**

View File

@@ -1,22 +1,17 @@
/* IMPORTANT
* This snapshot file is auto-generated, but designed for humans.
* It should be checked into source control and tracked carefully.
* Re-generate by setting TAP_SNAPSHOT=1 and running tests.
* Make sure to inspect the output below. Do not ignore changes!
*/
'use strict'
exports[`src/extensions/key-map/tests/key-map.test.ts TAP join up with last list item in a flat list > must match snapshot 1`] = `
Array [
Object {
"attrs": Null Object {
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`join up with last list item in a flat list 1`] = `
[
{
"attrs": {
"listType": "",
},
"content": Array [
Object {
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"content": [
{
"text": "Hello",
"type": "text",
},
@@ -26,11 +21,11 @@ Array [
],
"type": "listItem",
},
Object {
"content": Array [
Object {
"content": Array [
Object {
{
"content": [
{
"content": [
{
"text": "World",
"type": "text",
},
@@ -44,20 +39,20 @@ Array [
"type": "bulletList",
},
]
`
`;
exports[`src/extensions/key-map/tests/key-map.test.ts TAP join up with last list item in a nested list > must match snapshot 1`] = `
Array [
Object {
"attrs": Null Object {
exports[`join up with last list item in a nested list 1`] = `
[
{
"attrs": {
"listType": "",
},
"content": Array [
Object {
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"content": [
{
"text": "Hello",
"type": "text",
},
@@ -67,27 +62,27 @@ Array [
],
"type": "listItem",
},
Object {
"content": Array [
Object {
"content": Array [
Object {
{
"content": [
{
"content": [
{
"text": "World",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"attrs": Null Object {
{
"attrs": {
"listType": "",
},
"content": Array [
Object {
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"content": [
{
"text": "Hello",
"type": "text",
},
@@ -97,27 +92,27 @@ Array [
],
"type": "listItem",
},
Object {
"content": Array [
Object {
"content": Array [
Object {
{
"content": [
{
"content": [
{
"text": "World",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"attrs": Null Object {
{
"attrs": {
"listType": "",
},
"content": Array [
Object {
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"content": [
{
"text": "Hello",
"type": "text",
},
@@ -133,11 +128,11 @@ Array [
],
"type": "listItem",
},
Object {
"content": Array [
Object {
"content": Array [
Object {
{
"content": [
{
"content": [
{
"text": "A very nested world",
"type": "text",
},
@@ -157,20 +152,20 @@ Array [
"type": "bulletList",
},
]
`
`;
exports[`src/extensions/key-map/tests/key-map.test.ts TAP join up with last list item in a nested list > must match snapshot 2`] = `
Array [
Object {
"attrs": Null Object {
exports[`join up with last list item in a nested list 2`] = `
[
{
"attrs": {
"listType": "",
},
"content": Array [
Object {
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"content": [
{
"text": "Hello",
"type": "text",
},
@@ -180,27 +175,27 @@ Array [
],
"type": "listItem",
},
Object {
"content": Array [
Object {
"content": Array [
Object {
{
"content": [
{
"content": [
{
"text": "World",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"attrs": Null Object {
{
"attrs": {
"listType": "",
},
"content": Array [
Object {
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"content": [
{
"text": "Hello",
"type": "text",
},
@@ -210,27 +205,27 @@ Array [
],
"type": "listItem",
},
Object {
"content": Array [
Object {
"content": Array [
Object {
{
"content": [
{
"content": [
{
"text": "World",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"attrs": Null Object {
{
"attrs": {
"listType": "",
},
"content": Array [
Object {
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"content": [
{
"text": "Hello",
"type": "text",
},
@@ -246,11 +241,11 @@ Array [
],
"type": "listItem",
},
Object {
"content": Array [
Object {
"content": Array [
Object {
{
"content": [
{
"content": [
{
"text": "A very nested world",
"type": "text",
},
@@ -270,4 +265,4 @@ Array [
"type": "bulletList",
},
]
`
`;

View File

@@ -18,13 +18,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { createEditor, h } from "@/test-utils";
import tap from "tap";
import expect from "expect";
import { test, expect } from "vitest";
import BulletList from "../../bullet-list";
import { ListItem } from "../../list-item";
import { joinUpWithLastListItem } from "../key-map";
tap.test(`join up with last list item in a flat list`, async (t) => {
test(`join up with last list item in a flat list`, async () => {
const { editor } = createEditor({
initialContent: h("div", [
h("ul", [h("li", ["Hello"]), h("li", ["World"])]),
@@ -40,10 +39,10 @@ tap.test(`join up with last list item in a flat list`, async (t) => {
joinUpWithLastListItem(editor);
expect(editor.state.selection.$from.parent.textContent).toBe("World");
t.matchSnapshot(editor.state.doc.content.toJSON());
expect(editor.state.doc.content.toJSON()).toMatchSnapshot();
});
tap.test(`join up with last list item in a nested list`, async (t) => {
test(`join up with last list item in a nested list`, async () => {
const { editor } = createEditor({
initialContent: h("div", [
h("ul", [
@@ -71,10 +70,10 @@ tap.test(`join up with last list item in a nested list`, async (t) => {
expect(editor.state.selection.$from.parent.textContent).toBe(
"A very nested world"
);
t.matchSnapshot(editor.state.doc.content.toJSON());
expect(editor.state.doc.content.toJSON()).toMatchSnapshot();
});
tap.test(`join up with last list item in a nested list`, async (t) => {
test(`join up with last list item in a nested list`, async () => {
const { editor } = createEditor({
initialContent: h("div", [
h("ul", [
@@ -102,5 +101,5 @@ tap.test(`join up with last list item in a nested list`, async (t) => {
expect(editor.state.selection.$from.parent.textContent).toBe(
"A very nested world"
);
t.matchSnapshot(editor.state.doc.content.toJSON());
expect(editor.state.doc.content.toJSON()).toMatchSnapshot();
});

View File

@@ -1,25 +1,20 @@
/* IMPORTANT
* This snapshot file is auto-generated, but designed for humans.
* It should be checked into source control and tracked carefully.
* Re-generate by setting TAP_SNAPSHOT=1 and running tests.
* Make sure to inspect the output below. Do not ignore changes!
*/
'use strict'
exports[`src/extensions/task-list/tests/task-list.test.ts TAP delete checked items in a nested task list > must match snapshot 1`] = `
Array [
Object {
"attrs": Null Object {
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`delete checked items in a nested task list 1`] = `
[
{
"attrs": {
"title": null,
},
"content": Array [
Object {
"attrs": Null Object {
"content": [
{
"attrs": {
"checked": false,
},
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"text": "Task item 2",
"type": "text",
},
@@ -29,95 +24,95 @@ Array [
],
"type": "taskItem",
},
Object {
"attrs": Null Object {
{
"attrs": {
"checked": false,
},
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"text": "Task item 3",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 4",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 5",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 6",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 7",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 8",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 9",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 10",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 11",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 12",
"type": "text",
},
@@ -131,23 +126,23 @@ Array [
"type": "taskList",
},
]
`
`;
exports[`src/extensions/task-list/tests/task-list.test.ts TAP delete checked items in a task list > must match snapshot 1`] = `
Array [
Object {
"attrs": Null Object {
exports[`delete checked items in a task list 1`] = `
[
{
"attrs": {
"title": null,
},
"content": Array [
Object {
"attrs": Null Object {
"content": [
{
"attrs": {
"checked": false,
},
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"text": "Task item 2",
"type": "text",
},
@@ -161,23 +156,23 @@ Array [
"type": "taskList",
},
]
`
`;
exports[`src/extensions/task-list/tests/task-list.test.ts TAP sort checked items to the bottom of the task list > must match snapshot 1`] = `
Array [
Object {
"attrs": Null Object {
exports[`sort checked items to the bottom of the task list 1`] = `
[
{
"attrs": {
"title": null,
},
"content": Array [
Object {
"attrs": Null Object {
"content": [
{
"attrs": {
"checked": false,
},
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"text": "Task item 2",
"type": "text",
},
@@ -187,95 +182,95 @@ Array [
],
"type": "taskItem",
},
Object {
"attrs": Null Object {
{
"attrs": {
"checked": false,
},
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"text": "Task item 3",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 4",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 5",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 6",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 7",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 8",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 9",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 10",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 11",
"type": "text",
},
],
"type": "paragraph",
},
Object {
"content": Array [
Object {
{
"content": [
{
"text": "Task item 12",
"type": "text",
},
@@ -285,14 +280,14 @@ Array [
],
"type": "taskItem",
},
Object {
"attrs": Null Object {
{
"attrs": {
"checked": true,
},
"content": Array [
Object {
"content": Array [
Object {
"content": [
{
"content": [
{
"text": "Task item 1",
"type": "text",
},
@@ -306,4 +301,4 @@ Array [
"type": "taskList",
},
]
`
`;

View File

@@ -18,8 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { createEditor, h, ul, li } from "@/test-utils";
import tap from "tap";
import expect from "expect";
import { test, expect } from "vitest";
import { TaskListNode } from "../index";
import { TaskItemNode } from "../../task-item";
import { p, eq } from "prosemirror-test-builder";
@@ -72,7 +71,7 @@ const NESTED_TASK_LIST = taskList(
)
).outerHTML;
tap.test(`count items in a task list`, async () => {
test(`count items in a task list`, async () => {
const {
builder: { taskItem, taskList }
} = createEditor({
@@ -97,7 +96,7 @@ tap.test(`count items in a task list`, async () => {
expect(total).toBe(4);
});
tap.test(`delete checked items in a task list`, async (t) => {
test(`delete checked items in a task list`, async () => {
const { editor } = createEditor({
initialContent: taskList(
taskItem("Task item 1", { checked: true }),
@@ -111,10 +110,10 @@ tap.test(`delete checked items in a task list`, async (t) => {
editor.commands.command(({ tr }) => !!deleteCheckedItems(tr, 0));
t.matchSnapshot(editor.state.doc.content.toJSON());
expect(editor.state.doc.content.toJSON()).toMatchSnapshot();
});
tap.test(`delete checked items in a nested task list`, async (t) => {
test(`delete checked items in a nested task list`, async () => {
const { editor } = createEditor({
initialContent: NESTED_TASK_LIST,
extensions: {
@@ -127,40 +126,37 @@ tap.test(`delete checked items in a nested task list`, async (t) => {
tr = deleteCheckedItems(tr, 0) || tr;
editor.view.dispatch(tr);
t.matchSnapshot(editor.state.doc.content.toJSON());
expect(editor.state.doc.content.toJSON()).toMatchSnapshot();
});
tap.test(
`delete checked items in a task list with no checked items should do nothing`,
async () => {
const { editor } = createEditor({
initialContent: taskList(
taskItem("Task item 1", { checked: false }),
taskItem("Task item 2"),
taskItem(
"Task item 3",
{ checked: false },
taskList(
taskItem("Task item 4", { checked: false }),
taskItem("Task item 5"),
taskItem("Task item 6", { checked: false })
)
test(`delete checked items in a task list with no checked items should do nothing`, async () => {
const { editor } = createEditor({
initialContent: taskList(
taskItem("Task item 1", { checked: false }),
taskItem("Task item 2"),
taskItem(
"Task item 3",
{ checked: false },
taskList(
taskItem("Task item 4", { checked: false }),
taskItem("Task item 5"),
taskItem("Task item 6", { checked: false })
)
).outerHTML,
extensions: {
taskItem: TaskItemNode,
taskList: TaskListNode
}
});
)
).outerHTML,
extensions: {
taskItem: TaskItemNode,
taskList: TaskListNode
}
});
const beforeDoc = editor.state.doc.copy(editor.state.doc.content);
editor.commands.command(({ tr }) => !!deleteCheckedItems(tr, 0));
const beforeDoc = editor.state.doc.copy(editor.state.doc.content);
editor.commands.command(({ tr }) => !!deleteCheckedItems(tr, 0));
expect(eq(editor.state.doc, beforeDoc)).toBe(true);
}
);
expect(eq(editor.state.doc, beforeDoc)).toBe(true);
});
tap.test(`sort checked items to the bottom of the task list`, async (t) => {
test(`sort checked items to the bottom of the task list`, async () => {
const { editor } = createEditor({
initialContent: NESTED_TASK_LIST,
extensions: {
@@ -171,24 +167,21 @@ tap.test(`sort checked items to the bottom of the task list`, async (t) => {
editor.commands.command(({ tr }) => !!sortList(tr, 0));
t.matchSnapshot(editor.state.doc.content.toJSON());
expect(editor.state.doc.content.toJSON()).toMatchSnapshot();
});
tap.test(
`sorting a task list with no checked items should do nothing`,
async () => {
const { editor } = createEditor({
initialContent: taskList(taskItem("Task item 1"), taskItem("Task item 2"))
.outerHTML,
extensions: {
taskItem: TaskItemNode,
taskList: TaskListNode
}
});
test(`sorting a task list with no checked items should do nothing`, async () => {
const { editor } = createEditor({
initialContent: taskList(taskItem("Task item 1"), taskItem("Task item 2"))
.outerHTML,
extensions: {
taskItem: TaskItemNode,
taskList: TaskListNode
}
});
const beforeDoc = editor.state.doc.copy(editor.state.doc.content);
editor.commands.command(({ tr }) => !!sortList(tr, 0));
const beforeDoc = editor.state.doc.copy(editor.state.doc.content);
editor.commands.command(({ tr }) => !!sortList(tr, 0));
expect(eq(editor.state.doc, beforeDoc)).toBe(true);
}
);
expect(eq(editor.state.doc, beforeDoc)).toBe(true);
});

View File

@@ -17,7 +17,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import "./tests.setup";
import { Editor, AnyExtension, Extensions } from "@tiptap/core";
import StarterKit from "@tiptap/starter-kit";
import { builders, NodeBuilder } from "prosemirror-test-builder";
@@ -28,6 +27,7 @@ type Builder<TNodes extends string> = {
} & Record<TNodes, NodeBuilder>;
type EditorOptions<TNodes extends string> = {
element?: HTMLElement;
extensions: Record<TNodes, AnyExtension>;
initialContent?: string;
};
@@ -35,13 +35,18 @@ type EditorOptions<TNodes extends string> = {
export function createEditor<TNodes extends string>(
options: EditorOptions<TNodes>
) {
const { extensions, initialContent } = options;
const { extensions, initialContent, element } = options;
const editor = new Editor({
element,
content: initialContent,
parseOptions: { preserveWhitespace: "full" },
extensions: [
StarterKit.configure({
bulletList: false,
listItem: false,
orderedList: false
orderedList: false,
codeBlock: false,
code: false
}),
...(Object.values(extensions) as Extensions)
]
@@ -49,14 +54,6 @@ export function createEditor<TNodes extends string>(
const builder = builders(editor.schema) as unknown as Builder<TNodes>;
if (initialContent) {
editor.commands.setContent(initialContent, true, {
preserveWhitespace: "full"
});
return { editor, builder };
}
return { editor, builder };
}

View File

@@ -17,6 +17,16 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { GlobalRegistrator } from "@happy-dom/global-registrator";
import { defineConfig } from "vitest/config";
GlobalRegistrator.register();
export default defineConfig({
test: {
alias: {
"@/": "./"
},
environment: "happy-dom",
typecheck: {
tsconfig: "./tsconfig.tests.json"
}
}
});