🐛(frontend) fix versioning conflict

We switching from one version to the other, depending on
the blocks inside, the version editor could
crash due to conflicts between the different versions.
We now reset the previous content
when switching version to avoid these conflicts.
This commit is contained in:
Anthony LC
2025-12-17 17:00:47 +01:00
parent 344e9a83e4
commit e340463d35
4 changed files with 63 additions and 16 deletions

View File

@@ -26,6 +26,7 @@ and this project adheres to
- 🐛(frontend) paste content with comments from another document #1732
- 🐛(frontend) Select text + Go back one page crash the app #1733
- 🐛(frontend) fix versioning conflict #1742
## [4.1.0] - 2025-12-09

View File

@@ -6,6 +6,7 @@ import {
mockedDocument,
verifyDocName,
} from './utils-common';
import { openSuggestionMenu, writeInEditor } from './utils-editor';
test.beforeEach(async ({ page }) => {
await page.goto('/');
@@ -17,6 +18,7 @@ test.describe('Doc Version', () => {
await verifyDocName(page, randomDoc);
// Initially, there is no version
await page.getByLabel('Open the document options').click();
await page.getByRole('menuitem', { name: 'Version history' }).click();
await expect(page.getByText('History', { exact: true })).toBeVisible();
@@ -26,31 +28,49 @@ test.describe('Doc Version', () => {
await expect(panel).toBeVisible();
await expect(modal.getByText('No versions')).toBeVisible();
const editor = page.locator('.ProseMirror');
await modal.getByRole('button', { name: 'close' }).click();
await editor.click();
await page.keyboard.type('# Hello World');
await writeInEditor({ page, text: 'Hello World' });
// It will trigger a save, no version created yet (initial version is not counted)
await goToGridDoc(page, {
title: randomDoc,
});
await expect(
page.getByRole('heading', { name: 'Hello World' }),
).toBeVisible();
await expect(page.getByText('Hello World')).toBeVisible();
await page
.locator('.ProseMirror .bn-block')
.getByRole('heading', { name: 'Hello World' })
.fill('It will create a version');
// Write more
await writeInEditor({ page, text: 'It will create a version' });
await openSuggestionMenu({ page });
await page.getByText('Add a callout block').click();
const calloutBlock = page
.locator('div[data-content-type="callout"]')
.first();
await expect(calloutBlock).toBeVisible();
// It will trigger a save and create a version this time
await goToGridDoc(page, {
title: randomDoc,
});
await expect(page.getByText('Hello World')).toBeHidden();
await expect(page.getByText('It will create a version')).toBeVisible();
await expect(calloutBlock).toBeVisible();
// Write more
await writeInEditor({ page, text: 'It will create a second version' });
// It will trigger a save and create a second version
await goToGridDoc(page, {
title: randomDoc,
});
await expect(
page.getByRole('heading', { name: 'It will create a version' }),
page.getByText('It will create a second version'),
).toBeVisible();
await page.getByLabel('Open the document options').click();
@@ -60,11 +80,33 @@ test.describe('Doc Version', () => {
await expect(page.getByText('History', { exact: true })).toBeVisible();
await expect(page.getByRole('status')).toBeHidden();
const items = await panel.locator('.version-item').all();
expect(items.length).toBe(1);
await items[0].click();
expect(items.length).toBe(2);
await items[1].click();
await expect(modal.getByText('Hello World')).toBeVisible();
await expect(modal.getByText('It will create a version')).toBeHidden();
await expect(
modal.locator('div[data-content-type="callout"]').first(),
).toBeHidden();
await items[0].click();
await expect(modal.getByText('Hello World')).toBeVisible();
await expect(modal.getByText('It will create a version')).toBeVisible();
await expect(
modal.locator('div[data-content-type="callout"]').first(),
).toBeVisible();
await expect(
modal.getByText('It will create a second version'),
).toBeHidden();
await items[1].click();
await expect(modal.getByText('Hello World')).toBeVisible();
await expect(modal.getByText('It will create a version')).toBeHidden();
await expect(
modal.locator('div[data-content-type="callout"]').first(),
).toBeHidden();
});
test('it does not display the doc versions if not allowed', async ({

View File

@@ -77,7 +77,6 @@ export function useDocVersionsInfiniteQuery(
getNextPageParam(lastPage) {
return lastPage.next_version_id_marker || undefined;
},
...queryConfig,
});
}

View File

@@ -32,13 +32,18 @@ export const DocVersionEditor = ({
const { replace } = useRouter();
const [initialContent, setInitialContent] = useState<Y.XmlFragment>();
// Reset initialContent when versionId changes to avoid conflicts between versions
useEffect(() => {
if (!version?.content) {
setInitialContent(undefined);
}, [versionId]);
useEffect(() => {
if (!version?.content || isLoading || initialContent) {
return;
}
setInitialContent(base64ToBlocknoteXmlFragment(version.content));
}, [version?.content]);
}, [versionId, version?.content, isLoading, initialContent]);
if (isError && error) {
if (error.status === 404) {