UNPKG

@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
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] ); }); } }); } });