Skip to content

Commit 245c756

Browse files
fix: ignore live collab fragment when replaceFile rebuilds doc (#2636)
1 parent 9f4d7db commit 245c756

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

packages/super-editor/src/editors/v1/core/Editor.replace-file.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { resolve, dirname } from 'node:path';
33
import { fileURLToPath } from 'node:url';
44
import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest';
55
import { Doc as YDoc } from 'yjs';
6+
import { yXmlFragmentToProseMirrorRootNode } from 'y-prosemirror';
67

78
const { seedPartsFromEditorSpy } = vi.hoisted(() => ({
89
seedPartsFromEditorSpy: vi.fn(),
@@ -33,6 +34,13 @@ function createProviderStub() {
3334
};
3435

3536
const provider = {
37+
awareness: {
38+
getStates() {
39+
return new Map();
40+
},
41+
on() {},
42+
off() {},
43+
},
3644
synced: false,
3745
isSynced: false,
3846
on(event: 'sync' | 'synced', handler: SyncHandler) {
@@ -64,11 +72,13 @@ function createTestEditor(options: Partial<Parameters<(typeof Editor)['prototype
6472

6573
describe('Editor.replaceFile', () => {
6674
let blankDocData: { docx: unknown; mediaFiles: unknown; fonts: unknown };
75+
let initialCollaborativeBuffer: Buffer;
6776
let replacementBuffer: Buffer;
6877
let multiSectionReplacementBuffer: Buffer;
6978

7079
beforeAll(async () => {
7180
blankDocData = await loadTestDataForEditorTests('blank-doc.docx');
81+
initialCollaborativeBuffer = await getTestDataAsFileBuffer('advanced-text.docx');
7282
replacementBuffer = await getTestDataAsFileBuffer('Hello docx world.docx');
7383
multiSectionReplacementBuffer = await getTestDataAsFileBuffer('multi_section_doc.docx');
7484
});
@@ -207,6 +217,54 @@ describe('Editor.replaceFile', () => {
207217
}
208218
});
209219

220+
it('replaces an already-seeded collaborative room cleanly', async () => {
221+
const provider = createProviderStub();
222+
const ydoc = new YDoc();
223+
224+
const editor = createTestEditor({
225+
ydoc,
226+
collaborationProvider: provider,
227+
});
228+
const expectedEditor = createTestEditor();
229+
try {
230+
await editor.open(initialCollaborativeBuffer, {
231+
mode: 'docx',
232+
isNewFile: true,
233+
});
234+
235+
provider.emit('synced', true);
236+
await new Promise((resolve) => setTimeout(resolve, 0));
237+
238+
const roomFragmentBeforeReplace = ydoc.getXmlFragment('supereditor');
239+
expect(roomFragmentBeforeReplace.length).toBeGreaterThan(0);
240+
241+
const initialText = editor.state.doc.textContent;
242+
243+
await expectedEditor.open(replacementBuffer, { mode: 'docx' });
244+
const expectedText = expectedEditor.state.doc.textContent;
245+
246+
const replacePromise = editor.replaceFile(replacementBuffer);
247+
await Promise.resolve();
248+
249+
provider.emit('synced', true);
250+
await replacePromise;
251+
252+
const sharedRoot = yXmlFragmentToProseMirrorRootNode(ydoc.getXmlFragment('supereditor'), editor.schema);
253+
expect(sharedRoot.textContent).toBe(expectedText);
254+
expect(editor.state.doc.textContent).toBe(expectedText);
255+
expect(editor.state.doc.textContent).not.toBe(initialText);
256+
} finally {
257+
if (editor.lifecycleState === 'ready') {
258+
editor.close();
259+
}
260+
if (expectedEditor.lifecycleState === 'ready') {
261+
expectedEditor.close();
262+
}
263+
editor.destroy();
264+
expectedEditor.destroy();
265+
}
266+
});
267+
210268
it('runs collaborative replace side effects once when the provider is already synced', async () => {
211269
const provider = createProviderStub();
212270
provider.synced = true;

packages/super-editor/src/editors/v1/core/Editor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3697,6 +3697,7 @@ export class Editor extends EventEmitter<EditorEventMap> {
36973697

36983698
const doReplaceFileSync = () => {
36993699
// 1. Insert new PM doc into Y fragment (must happen first)
3700+
this.options.fragment = null;
37003701
this.#insertNewFileData();
37013702

37023703
// 2. Seed parts from new converter snapshot (prunes stale parts)

0 commit comments

Comments
 (0)