@blocknote/core
Version:
A "Notion-style" block-based extensible text editor built on top of Prosemirror and Tiptap.
111 lines (97 loc) • 3.83 kB
text/typescript
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { PartialBlock } from "../../../blocks/defaultBlocks.js";
import { BlockNoteEditor } from "../../../editor/BlockNoteEditor.js";
import {
addIdsToBlocks,
partialBlocksToBlocksForTesting,
} from "../../../index.js";
import {
BlockSchema,
InlineContentSchema,
StyleSchema,
} from "../../../schema/index.js";
import { initializeESMDependencies } from "../../../util/esmDependencies.js";
import { customBlocksTestCases } from "../../testUtil/cases/customBlocks.js";
import { customInlineContentTestCases } from "../../testUtil/cases/customInlineContent.js";
import { customStylesTestCases } from "../../testUtil/cases/customStyles.js";
import { defaultSchemaTestCases } from "../../testUtil/cases/defaultSchema.js";
import { createExternalHTMLExporter } from "./externalHTMLExporter.js";
import { createInternalHTMLSerializer } from "./internalHTMLSerializer.js";
async function convertToHTMLAndCompareSnapshots<
B extends BlockSchema,
I extends InlineContentSchema,
S extends StyleSchema
>(
editor: BlockNoteEditor<B, I, S>,
blocks: PartialBlock<B, I, S>[],
snapshotDirectory: string,
snapshotName: string
) {
addIdsToBlocks(blocks);
const serializer = createInternalHTMLSerializer(editor.pmSchema, editor);
const internalHTML = serializer.serializeBlocks(blocks, {});
const internalHTMLSnapshotPath =
"./__snapshots__/" +
snapshotDirectory +
"/" +
snapshotName +
"/internal.html";
expect(internalHTML).toMatchFileSnapshot(internalHTMLSnapshotPath);
// turn the internalHTML back into blocks, and make sure no data was lost
const fullBlocks = partialBlocksToBlocksForTesting(editor.schema, blocks);
const parsed = await editor.tryParseHTMLToBlocks(internalHTML);
expect(parsed).toStrictEqual(fullBlocks);
await initializeESMDependencies();
// Create the "external" HTML, which is a cleaned up HTML representation, but lossy
const exporter = createExternalHTMLExporter(editor.pmSchema, editor);
const externalHTML = exporter.exportBlocks(blocks, {});
const externalHTMLSnapshotPath =
"./__snapshots__/" +
snapshotDirectory +
"/" +
snapshotName +
"/external.html";
expect(externalHTML).toMatchFileSnapshot(externalHTMLSnapshotPath);
}
const testCases = [
defaultSchemaTestCases,
customBlocksTestCases,
customStylesTestCases,
customInlineContentTestCases,
];
describe("Test HTML conversion", () => {
for (const testCase of testCases) {
describe("Case: " + testCase.name, () => {
let editor: BlockNoteEditor<any, any, any>;
const div = document.createElement("div");
beforeEach(() => {
editor = testCase.createEditor();
// Note that we don't necessarily need to mount a root
// Currently, we do mount to a root so that it reflects the "production" use-case more closely.
// However, it would be nice to increased converage and share the same set of tests for these cases:
// - does render to a root
// - does not render to a root
// - runs in server (jsdom) environment using server-util
editor.mount(div);
});
afterEach(() => {
editor.mount(undefined);
editor._tiptapEditor.destroy();
editor = undefined as any;
delete (window as Window & { __TEST_OPTIONS?: any }).__TEST_OPTIONS;
});
for (const document of testCase.documents) {
// eslint-disable-next-line no-loop-func
it("Convert " + document.name + " to HTML", async () => {
const nameSplit = document.name.split("/");
await convertToHTMLAndCompareSnapshots(
editor,
document.blocks,
nameSplit[0],
nameSplit[1]
);
});
}
});
}
});