|
1 | 1 | import { Block } from "@blocknote/core"; |
2 | 2 | import { describe, expect, it } from "vitest"; |
3 | | -import { ServerBlockNoteEditor } from "./ServerBlockNoteEditor.js"; |
| 3 | +import { JSDOM } from "jsdom"; |
| 4 | +import { DomShim, ServerBlockNoteEditor } from "./ServerBlockNoteEditor.js"; |
| 5 | + |
| 6 | +const jsdomShim: DomShim = { |
| 7 | + acquire() { |
| 8 | + const dom = new JSDOM(); |
| 9 | + return { |
| 10 | + window: dom.window as any, |
| 11 | + document: dom.window.document as any, |
| 12 | + }; |
| 13 | + }, |
| 14 | +}; |
4 | 15 |
|
5 | 16 | describe("Test ServerBlockNoteEditor", () => { |
6 | | - const editor = ServerBlockNoteEditor.create(); |
| 17 | + const editor = ServerBlockNoteEditor.create({}, jsdomShim); |
7 | 18 |
|
8 | 19 | const blocks: Block[] = [ |
9 | 20 | { |
@@ -124,3 +135,146 @@ describe("Test ServerBlockNoteEditor", () => { |
124 | 135 | expect(blockOutput).toMatchSnapshot(); |
125 | 136 | }); |
126 | 137 | }); |
| 138 | + |
| 139 | +describe("ServerBlockNoteEditor with domShim", () => { |
| 140 | + it("uses provided domShim correctly", async () => { |
| 141 | + let acquireCalled = false; |
| 142 | + let releaseCalled = false; |
| 143 | + let releasedGlobals: any = null; |
| 144 | + |
| 145 | + const testShim: DomShim = { |
| 146 | + acquire() { |
| 147 | + acquireCalled = true; |
| 148 | + const dom = new JSDOM(); |
| 149 | + return { |
| 150 | + window: dom.window as any, |
| 151 | + document: dom.window.document as any, |
| 152 | + }; |
| 153 | + }, |
| 154 | + release(globals) { |
| 155 | + releaseCalled = true; |
| 156 | + releasedGlobals = globals; |
| 157 | + }, |
| 158 | + }; |
| 159 | + |
| 160 | + const editor = ServerBlockNoteEditor.create({}, testShim); |
| 161 | + const blocks: Block[] = [ |
| 162 | + { |
| 163 | + id: "1", |
| 164 | + type: "paragraph", |
| 165 | + props: { |
| 166 | + backgroundColor: "default", |
| 167 | + textColor: "default", |
| 168 | + textAlignment: "left", |
| 169 | + }, |
| 170 | + content: [ |
| 171 | + { |
| 172 | + type: "text", |
| 173 | + text: "Test", |
| 174 | + styles: {}, |
| 175 | + }, |
| 176 | + ], |
| 177 | + children: [], |
| 178 | + }, |
| 179 | + ]; |
| 180 | + |
| 181 | + const html = await editor.blocksToFullHTML(blocks); |
| 182 | + |
| 183 | + expect(acquireCalled).toBe(true); |
| 184 | + expect(releaseCalled).toBe(true); |
| 185 | + expect(releasedGlobals).toBeTruthy(); |
| 186 | + expect(releasedGlobals.document).toBeTruthy(); |
| 187 | + expect(releasedGlobals.window).toBeTruthy(); |
| 188 | + expect(html).toBeTruthy(); |
| 189 | + }); |
| 190 | + |
| 191 | + it("throws error when no domShim is provided and globals don't exist", async () => { |
| 192 | + // Save original globals |
| 193 | + const originalWindow = globalThis.window; |
| 194 | + const originalDocument = globalThis.document; |
| 195 | + |
| 196 | + try { |
| 197 | + // Remove globals to simulate server environment |
| 198 | + delete (globalThis as any).window; |
| 199 | + delete (globalThis as any).document; |
| 200 | + |
| 201 | + const editor = ServerBlockNoteEditor.create(); |
| 202 | + const blocks: Block[] = [ |
| 203 | + { |
| 204 | + id: "1", |
| 205 | + type: "paragraph", |
| 206 | + props: { |
| 207 | + backgroundColor: "default", |
| 208 | + textColor: "default", |
| 209 | + textAlignment: "left", |
| 210 | + }, |
| 211 | + content: [ |
| 212 | + { |
| 213 | + type: "text", |
| 214 | + text: "Test", |
| 215 | + styles: {}, |
| 216 | + }, |
| 217 | + ], |
| 218 | + children: [], |
| 219 | + }, |
| 220 | + ]; |
| 221 | + |
| 222 | + await expect(editor.blocksToFullHTML(blocks)).rejects.toThrow( |
| 223 | + "DOM globals (window/document) are required but not available", |
| 224 | + ); |
| 225 | + |
| 226 | + await expect(editor.blocksToHTMLLossy(blocks)).rejects.toThrow( |
| 227 | + "DOM globals (window/document) are required but not available", |
| 228 | + ); |
| 229 | + |
| 230 | + await expect(editor.blocksToMarkdownLossy(blocks)).rejects.toThrow( |
| 231 | + "DOM globals (window/document) are required but not available", |
| 232 | + ); |
| 233 | + } finally { |
| 234 | + // Restore original globals |
| 235 | + globalThis.window = originalWindow; |
| 236 | + globalThis.document = originalDocument; |
| 237 | + } |
| 238 | + }); |
| 239 | + |
| 240 | + it("works when globals already exist without domShim", async () => { |
| 241 | + // This test verifies that if window/document already exist globally, |
| 242 | + // methods work without a domShim |
| 243 | + // Note: This test only works if the test environment has globals set up |
| 244 | + // (e.g., via jsdom in vitest config) |
| 245 | + if ( |
| 246 | + typeof globalThis.window !== "undefined" && |
| 247 | + typeof globalThis.document !== "undefined" |
| 248 | + ) { |
| 249 | + const editor = ServerBlockNoteEditor.create(); |
| 250 | + const blocks: Block[] = [ |
| 251 | + { |
| 252 | + id: "1", |
| 253 | + type: "paragraph", |
| 254 | + props: { |
| 255 | + backgroundColor: "default", |
| 256 | + textColor: "default", |
| 257 | + textAlignment: "left", |
| 258 | + }, |
| 259 | + content: [ |
| 260 | + { |
| 261 | + type: "text", |
| 262 | + text: "Test", |
| 263 | + styles: {}, |
| 264 | + }, |
| 265 | + ], |
| 266 | + children: [], |
| 267 | + }, |
| 268 | + ]; |
| 269 | + |
| 270 | + // Should work if globals exist (like in a test environment with jsdom) |
| 271 | + const html = await editor.blocksToFullHTML(blocks); |
| 272 | + // eslint-disable-next-line jest/no-conditional-expect |
| 273 | + expect(html).toBeTruthy(); |
| 274 | + } else { |
| 275 | + // Skip test if globals don't exist in this environment |
| 276 | + // eslint-disable-next-line jest/no-conditional-expect |
| 277 | + expect(true).toBe(true); |
| 278 | + } |
| 279 | + }); |
| 280 | +}); |
0 commit comments