Skip to content

Commit f603e80

Browse files
committed
test(comments-store): add unit tests for resolved TC pruning and snapshot restore
- Test that already-resolved tracked-change comments survive empty replay sync (the `if (comment.resolvedTime) return true` guard in pruneStaleTrackedChangeComments) - Test that snapshot restore works end-to-end: undo reopens thread, redo restores resolved state from WeakMap snapshot instead of hard-deleting
1 parent ff7d68f commit f603e80

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

packages/superdoc/src/stores/comments-store.test.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,81 @@ describe('comments-store', () => {
993993
expect(store.commentsList.filter((comment) => comment.commentId === 'tc-history-replay-reply')).toHaveLength(1);
994994
});
995995

996+
it('keeps already-resolved tracked-change comments during empty replay sync', () => {
997+
const editorDispatch = vi.fn();
998+
const tr = { setMeta: vi.fn() };
999+
const superdoc = { emit: vi.fn() };
1000+
const editor = {
1001+
state: {},
1002+
view: { state: { tr }, dispatch: editorDispatch },
1003+
options: { documentId: 'doc-1' },
1004+
};
1005+
1006+
trackChangesHelpersMock.getTrackChanges.mockReturnValue([]);
1007+
groupChangesMock.mockReturnValue([]);
1008+
1009+
const resolvedComment = {
1010+
commentId: 'tc-already-resolved',
1011+
trackedChange: true,
1012+
trackedChangeText: 'Accepted text',
1013+
resolvedTime: 999,
1014+
resolvedByEmail: 'reviewer@example.com',
1015+
resolvedByName: 'Reviewer',
1016+
fileId: 'doc-1',
1017+
getValues: vi.fn(() => ({ commentId: 'tc-already-resolved', fileId: 'doc-1' })),
1018+
};
1019+
store.commentsList = [resolvedComment];
1020+
1021+
store.syncTrackedChangeComments({ superdoc, editor });
1022+
1023+
expect(store.commentsList).toHaveLength(1);
1024+
expect(resolvedComment.resolvedTime).toBe(999);
1025+
expect(syncCommentsToClientsMock).not.toHaveBeenCalledWith(
1026+
superdoc,
1027+
expect.objectContaining({ type: comments_module_events.DELETED }),
1028+
);
1029+
});
1030+
1031+
it('restores resolution snapshot instead of deleting when pruning a previously-reopened thread', () => {
1032+
const editorDispatch = vi.fn();
1033+
const tr = { setMeta: vi.fn() };
1034+
const superdoc = { emit: vi.fn() };
1035+
const editor = {
1036+
state: {},
1037+
view: { state: { tr }, dispatch: editorDispatch },
1038+
options: { documentId: 'doc-1' },
1039+
};
1040+
1041+
const existingComment = {
1042+
commentId: 'tc-snapshot-restore',
1043+
trackedChange: true,
1044+
trackedChangeText: 'Existing',
1045+
resolvedTime: 555,
1046+
resolvedByEmail: 'reviewer@example.com',
1047+
resolvedByName: 'Reviewer',
1048+
fileId: 'doc-1',
1049+
getValues: vi.fn(() => ({ commentId: 'tc-snapshot-restore' })),
1050+
};
1051+
store.commentsList = [existingComment];
1052+
1053+
// Step 1: undo — mark reappears, thread reopens (snapshot saved, resolvedTime cleared)
1054+
trackChangesHelpersMock.getTrackChanges.mockReturnValueOnce([{ mark: { attrs: { id: 'tc-snapshot-restore' } } }]);
1055+
groupChangesMock.mockReturnValueOnce([{ insertedMark: { mark: { attrs: { id: 'tc-snapshot-restore' } } } }]);
1056+
store.syncTrackedChangeComments({ superdoc, editor });
1057+
1058+
expect(existingComment.resolvedTime).toBeNull();
1059+
1060+
// Step 2: redo — mark gone, snapshot should restore resolvedTime instead of deleting
1061+
trackChangesHelpersMock.getTrackChanges.mockReturnValueOnce([]);
1062+
groupChangesMock.mockReturnValueOnce([]);
1063+
store.syncTrackedChangeComments({ superdoc, editor });
1064+
1065+
expect(store.commentsList).toHaveLength(1);
1066+
expect(existingComment.resolvedTime).toBe(555);
1067+
expect(existingComment.resolvedByEmail).toBe('reviewer@example.com');
1068+
expect(existingComment.resolvedByName).toBe('Reviewer');
1069+
});
1070+
9961071
it('keeps tracked-change comments when importedId is live even if commentId differs', () => {
9971072
const editorDispatch = vi.fn();
9981073
const tr = { setMeta: vi.fn() };

0 commit comments

Comments
 (0)