mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
editor: set up integration tests
This commit is contained in:
committed by
Abdullah Atta
parent
912e97dc3c
commit
16ffec1f1e
@@ -21,4 +21,7 @@ packages/editor/styles/
|
|||||||
packages/editor/languages/
|
packages/editor/languages/
|
||||||
|
|
||||||
# editor mobile
|
# editor mobile
|
||||||
packages/editor-mobile/build.bundle
|
packages/editor-mobile/build.bundle
|
||||||
|
|
||||||
|
# snapshots
|
||||||
|
tap-snapshots
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,4 +6,5 @@ dist
|
|||||||
nx-cloud.env
|
nx-cloud.env
|
||||||
.idea
|
.idea
|
||||||
.eslintcache
|
.eslintcache
|
||||||
.env.local
|
.env.local
|
||||||
|
.nyc_output
|
||||||
12869
packages/editor/package-lock.json
generated
12869
packages/editor/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -28,8 +28,8 @@
|
|||||||
"@tiptap/extension-text-align": "^2.0.0-beta.218",
|
"@tiptap/extension-text-align": "^2.0.0-beta.218",
|
||||||
"@tiptap/extension-text-style": "^2.0.0-beta.218",
|
"@tiptap/extension-text-style": "^2.0.0-beta.218",
|
||||||
"@tiptap/extension-underline": "^2.0.0-beta.218",
|
"@tiptap/extension-underline": "^2.0.0-beta.218",
|
||||||
"@tiptap/starter-kit": "^2.0.0-beta.218",
|
|
||||||
"@tiptap/pm": "^2.0.0-beta.218",
|
"@tiptap/pm": "^2.0.0-beta.218",
|
||||||
|
"@tiptap/starter-kit": "^2.0.0-beta.218",
|
||||||
"detect-indent": "^7.0.0",
|
"detect-indent": "^7.0.0",
|
||||||
"katex": "^0.16.2",
|
"katex": "^0.16.2",
|
||||||
"prism-themes": "^1.9.0",
|
"prism-themes": "^1.9.0",
|
||||||
@@ -45,17 +45,24 @@
|
|||||||
"zustand": "^3.7.2"
|
"zustand": "^3.7.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@happy-dom/global-registrator": "^8.9.0",
|
||||||
"@mdi/js": "^6.9.96",
|
"@mdi/js": "^6.9.96",
|
||||||
"@mdi/react": "^1.6.0",
|
"@mdi/react": "^1.6.0",
|
||||||
|
"@swc/core": "^1.3.36",
|
||||||
"@types/katex": "^0.14.0",
|
"@types/katex": "^0.14.0",
|
||||||
"@types/prismjs": "^1.26.0",
|
"@types/prismjs": "^1.26.0",
|
||||||
"@types/react": "17.0.2",
|
"@types/react": "17.0.2",
|
||||||
"@types/react-color": "^3.0.6",
|
"@types/react-color": "^3.0.6",
|
||||||
"@types/react-dom": "17.0.2",
|
"@types/react-dom": "17.0.2",
|
||||||
"@types/react-modal": "^3.13.1",
|
"@types/react-modal": "^3.13.1",
|
||||||
|
"@types/tap": "^15.0.8",
|
||||||
"@types/tinycolor2": "^1.4.3",
|
"@types/tinycolor2": "^1.4.3",
|
||||||
|
"expect": "^29.4.3",
|
||||||
"framer-motion": "^6.5.1",
|
"framer-motion": "^6.5.1",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
|
"prosemirror-test-builder": "^1.1.0",
|
||||||
|
"tap": "^16.3.4",
|
||||||
|
"tsconfig-paths": "^3.14.2",
|
||||||
"typescript": "^4.8.2",
|
"typescript": "^4.8.2",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
"zx": "^7.0.8"
|
"zx": "^7.0.8"
|
||||||
@@ -67,6 +74,7 @@
|
|||||||
"react-dom": ">=17.0.0"
|
"react-dom": ">=17.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"test": "TS_NODE_PROJECT=tsconfig.tests.json tap --ts --no-check-coverage --test-env=NODE_ENV=test src/**/*.test.ts",
|
||||||
"prebuild": "zx ./scripts/build.mjs",
|
"prebuild": "zx ./scripts/build.mjs",
|
||||||
"prewatch": "zx ./scripts/build.mjs",
|
"prewatch": "zx ./scripts/build.mjs",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
|||||||
@@ -103,8 +103,9 @@ export class ReactNodeView<P extends ReactNodeViewProps> implements NodeView {
|
|||||||
private renderReactComponent(
|
private renderReactComponent(
|
||||||
component: () => React.ReactElement<unknown> | null
|
component: () => React.ReactElement<unknown> | null
|
||||||
) {
|
) {
|
||||||
|
if (process.env.NODE_ENV === "test") return;
|
||||||
if (!this.domRef || !component || !this.portalProviderAPI) {
|
if (!this.domRef || !component || !this.portalProviderAPI) {
|
||||||
console.warn("Cannot render node view", this.editor.storage);
|
console.warn("Cannot render node view");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
247
packages/editor/src/extensions/task-list/tests/task-list.test.ts
Normal file
247
packages/editor/src/extensions/task-list/tests/task-list.test.ts
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the Notesnook project (https://notesnook.com/)
|
||||||
|
|
||||||
|
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
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 tap from "tap";
|
||||||
|
import expect from "expect";
|
||||||
|
import { Editor, AnyExtension, Extensions } from "@tiptap/core";
|
||||||
|
import { TaskListNode } from "../index";
|
||||||
|
import { TaskItemNode } from "../../task-item";
|
||||||
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
|
import { builders, doc, NodeBuilder, p, eq } from "prosemirror-test-builder";
|
||||||
|
import { Node, Schema } from "@tiptap/pm/model";
|
||||||
|
import { countCheckedItems, deleteCheckedItems, sortList } from "../utils";
|
||||||
|
import { EditorState } from "@tiptap/pm/state";
|
||||||
|
|
||||||
|
type Builder<TNodes extends string> = {
|
||||||
|
scheme: Schema;
|
||||||
|
} & Record<TNodes, NodeBuilder>;
|
||||||
|
|
||||||
|
type EditorOptions<TNodes extends string> = {
|
||||||
|
extensions: Record<TNodes, AnyExtension>;
|
||||||
|
initialDoc?: (builder: Builder<TNodes>) => Node;
|
||||||
|
};
|
||||||
|
|
||||||
|
function createEditor<TNodes extends string>(options: EditorOptions<TNodes>) {
|
||||||
|
const { extensions, initialDoc } = options;
|
||||||
|
const editor = new Editor({
|
||||||
|
extensions: [StarterKit, ...(Object.values(extensions) as Extensions)]
|
||||||
|
});
|
||||||
|
|
||||||
|
const builder = builders(editor.schema) as unknown as Builder<TNodes>;
|
||||||
|
|
||||||
|
if (initialDoc) {
|
||||||
|
const doc = initialDoc(builder);
|
||||||
|
editor.view.updateState(
|
||||||
|
EditorState.create({
|
||||||
|
schema: editor.view.state.schema,
|
||||||
|
doc,
|
||||||
|
plugins: editor.state.plugins
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return { editor, builder, initialDoc: doc };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { editor, builder, initialDoc: editor.state.doc };
|
||||||
|
}
|
||||||
|
|
||||||
|
tap.test(`count items in a task list`, async () => {
|
||||||
|
const {
|
||||||
|
builder: { taskItem, taskList }
|
||||||
|
} = createEditor({
|
||||||
|
extensions: {
|
||||||
|
taskItem: TaskItemNode,
|
||||||
|
taskList: TaskListNode
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const taskListNode = taskList(
|
||||||
|
taskItem({ checked: true }, p("Task item 1")),
|
||||||
|
taskItem({ checked: false }, p("Task item 2")),
|
||||||
|
taskItem(
|
||||||
|
{ checked: false },
|
||||||
|
p("Task item 3"),
|
||||||
|
taskList(taskItem({ checked: true }, p("Task item 4")))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const { checked, total } = countCheckedItems(taskListNode);
|
||||||
|
expect(checked).toBe(2);
|
||||||
|
expect(total).toBe(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test(`delete checked items in a task list`, async (t) => {
|
||||||
|
const { editor } = createEditor({
|
||||||
|
initialDoc: ({ taskItem, taskList }) =>
|
||||||
|
doc(
|
||||||
|
taskList(
|
||||||
|
taskItem({ checked: true }, p("Task item 1")),
|
||||||
|
taskItem({ checked: false }, p("Task item 2"))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
extensions: {
|
||||||
|
taskItem: TaskItemNode,
|
||||||
|
taskList: TaskListNode
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let { tr } = editor.state;
|
||||||
|
tr = deleteCheckedItems(tr, 0) || tr;
|
||||||
|
editor.view.dispatch(tr);
|
||||||
|
|
||||||
|
t.matchSnapshot(editor.state.doc.content.toJSON());
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test(`delete checked items in a nested task list`, async (t) => {
|
||||||
|
const { editor } = createEditor({
|
||||||
|
initialDoc: ({ taskItem, taskList }) =>
|
||||||
|
doc(
|
||||||
|
taskList(
|
||||||
|
taskItem({ checked: true }, p("Task item 1")),
|
||||||
|
taskItem({ checked: false }, p("Task item 2")),
|
||||||
|
taskItem(
|
||||||
|
{ checked: false },
|
||||||
|
p("Task item 3"),
|
||||||
|
taskList(
|
||||||
|
taskItem({ checked: true }, p("Task item 4")),
|
||||||
|
taskItem({ checked: false }, p("Task item 5")),
|
||||||
|
taskItem({ checked: false }, p("Task item 6")),
|
||||||
|
taskItem(
|
||||||
|
{ checked: true },
|
||||||
|
p("Task item 7"),
|
||||||
|
taskList(
|
||||||
|
taskItem({ checked: true }, p("Task item 8")),
|
||||||
|
taskItem({ checked: true }, p("Task item 9")),
|
||||||
|
taskItem({ checked: false }, p("Task item 10")),
|
||||||
|
taskItem({ checked: true }, p("Task item 11"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
extensions: {
|
||||||
|
taskItem: TaskItemNode,
|
||||||
|
taskList: TaskListNode
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let { tr } = editor.state;
|
||||||
|
tr = deleteCheckedItems(tr, 0) || tr;
|
||||||
|
editor.view.dispatch(tr);
|
||||||
|
|
||||||
|
t.matchSnapshot(editor.state.doc.content.toJSON());
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test(
|
||||||
|
`delete checked items in a task list with no checked items should do nothing`,
|
||||||
|
async () => {
|
||||||
|
const { editor, initialDoc } = createEditor({
|
||||||
|
initialDoc: ({ taskItem, taskList }) =>
|
||||||
|
doc(
|
||||||
|
taskList(
|
||||||
|
taskItem({ checked: false }, p("Task item 2")),
|
||||||
|
taskItem(
|
||||||
|
{ checked: false },
|
||||||
|
p("Task item 3"),
|
||||||
|
taskList(
|
||||||
|
taskItem({ checked: false }, p("Task item 5")),
|
||||||
|
taskItem({ checked: false }, p("Task item 6")),
|
||||||
|
taskItem(
|
||||||
|
{ checked: false },
|
||||||
|
p("Task item 7"),
|
||||||
|
taskList(taskItem({ checked: false }, p("Task item 10")))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
extensions: {
|
||||||
|
taskItem: TaskItemNode,
|
||||||
|
taskList: TaskListNode
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.commands.command(({ tr }) => !!deleteCheckedItems(tr, 0));
|
||||||
|
|
||||||
|
expect(eq(editor.state.doc, initialDoc)).toBe(true);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
tap.test(`sort checked items to the bottom of the task list`, async (t) => {
|
||||||
|
const { editor } = createEditor({
|
||||||
|
initialDoc: ({ taskItem, taskList }) =>
|
||||||
|
doc(
|
||||||
|
taskList(
|
||||||
|
taskItem({ checked: true }, p("Task item 1")),
|
||||||
|
taskItem({ checked: false }, p("Task item 2")),
|
||||||
|
taskItem(
|
||||||
|
{ checked: false },
|
||||||
|
p("Task item 3"),
|
||||||
|
taskList(
|
||||||
|
taskItem({ checked: true }, p("Task item 4")),
|
||||||
|
taskItem({ checked: true }, p("Task item 5")),
|
||||||
|
taskItem({ checked: false }, p("Task item 6")),
|
||||||
|
taskItem(
|
||||||
|
{ checked: false },
|
||||||
|
p("Task item 7"),
|
||||||
|
taskList(
|
||||||
|
taskItem({ checked: true }, p("Task item 8")),
|
||||||
|
taskItem({ checked: true }, p("Task item 9")),
|
||||||
|
taskItem({ checked: false }, p("Task item 10")),
|
||||||
|
taskItem({ checked: true }, p("Task item 11"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
extensions: {
|
||||||
|
taskItem: TaskItemNode,
|
||||||
|
taskList: TaskListNode
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.commands.command(({ tr }) => !!sortList(tr, 0));
|
||||||
|
|
||||||
|
t.matchSnapshot(editor.state.doc.content.toJSON());
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test(
|
||||||
|
`sorting a task list with no checked items should do nothing`,
|
||||||
|
async () => {
|
||||||
|
const { editor, initialDoc } = createEditor({
|
||||||
|
initialDoc: ({ taskItem, taskList }) =>
|
||||||
|
doc(
|
||||||
|
taskList(
|
||||||
|
taskItem({ checked: false }, p("Task item 1")),
|
||||||
|
taskItem({ checked: false }, p("Task item 2"))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
extensions: {
|
||||||
|
taskItem: TaskItemNode,
|
||||||
|
taskList: TaskListNode
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.commands.command(({ tr }) => !!sortList(tr, 0));
|
||||||
|
expect(eq(editor.state.doc, initialDoc)).toBe(true);
|
||||||
|
}
|
||||||
|
);
|
||||||
@@ -57,11 +57,13 @@ export function deleteCheckedItems(tr: Transaction, pos: number) {
|
|||||||
listNode.forEach((node, _, index) => {
|
listNode.forEach((node, _, index) => {
|
||||||
if (!node.attrs.checked) children.push(listNode.child(index));
|
if (!node.attrs.checked) children.push(listNode.child(index));
|
||||||
});
|
});
|
||||||
|
// if all items are unchecked, skip
|
||||||
|
if (children.length === listNode.childCount) continue;
|
||||||
|
|
||||||
tr.replaceWith(
|
tr.replaceWith(
|
||||||
tr.mapping.map(list.pos),
|
tr.mapping.map(list.pos + 1),
|
||||||
tr.mapping.map(list.pos + list.node.nodeSize),
|
tr.mapping.map(list.pos + list.node.nodeSize - 1),
|
||||||
listNode.copy(Fragment.from(children))
|
Fragment.from(children)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,10 +97,16 @@ export function sortList(tr: Transaction, pos: number) {
|
|||||||
checked: node.attrs.checked ? 1 : 0
|
checked: node.attrs.checked ? 1 : 0
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// if every item is checked or unchecked, skip
|
||||||
|
if (
|
||||||
|
children.every((a) => a.checked === 1) ||
|
||||||
|
children.every((a) => a.checked === 0)
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
tr.replaceWith(
|
tr.replaceWith(
|
||||||
tr.mapping.map(list.pos),
|
tr.mapping.map(list.pos + 1),
|
||||||
tr.mapping.map(list.pos + list.node.nodeSize),
|
tr.mapping.map(list.pos + list.node.nodeSize - 1),
|
||||||
Fragment.from(
|
Fragment.from(
|
||||||
children
|
children
|
||||||
.sort((a, b) => a.checked - b.checked)
|
.sort((a, b) => a.checked - b.checked)
|
||||||
|
|||||||
@@ -0,0 +1,341 @@
|
|||||||
|
/* 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 {
|
||||||
|
"title": null,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": false,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 2",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": false,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 3",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"title": null,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": false,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 5",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": false,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 6",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskList",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"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 {
|
||||||
|
"title": null,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": false,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 2",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"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 {
|
||||||
|
"title": null,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": false,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 2",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": false,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 3",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"title": null,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": true,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 4",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": true,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 5",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": false,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 6",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": false,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 7",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"title": null,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": true,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 8",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": true,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 9",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": false,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 10",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": true,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 11",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskList",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskList",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"attrs": Null Object {
|
||||||
|
"checked": true,
|
||||||
|
},
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"content": Array [
|
||||||
|
Object {
|
||||||
|
"text": "Task item 1",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskItem",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "taskList",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`
|
||||||
22
packages/editor/tests.setup.ts
Normal file
22
packages/editor/tests.setup.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the Notesnook project (https://notesnook.com/)
|
||||||
|
|
||||||
|
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
|
GlobalRegistrator.register();
|
||||||
@@ -3,9 +3,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"outDir": "./dist/",
|
"outDir": "./dist/"
|
||||||
"experimentalDecorators": true,
|
|
||||||
"useDefineForClassFields": false
|
|
||||||
},
|
},
|
||||||
"include": ["src/"]
|
"include": ["src/"]
|
||||||
}
|
}
|
||||||
|
|||||||
19
packages/editor/tsconfig.tests.json
Normal file
19
packages/editor/tsconfig.tests.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig",
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"outDir": "./dist/",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ts-node": {
|
||||||
|
"transpileOnly": true,
|
||||||
|
"swc": true,
|
||||||
|
"require": ["tsconfig-paths/register"]
|
||||||
|
},
|
||||||
|
"include": ["src/", "index.ts"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user