diff --git a/CHANGELOG.md b/CHANGELOG.md index 2defd1da..2cb8bb88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts index b65bc9d0..97777711 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts @@ -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 ({ diff --git a/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersions.tsx b/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersions.tsx index 3d75f8ce..cd6adcdb 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersions.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersions.tsx @@ -77,7 +77,6 @@ export function useDocVersionsInfiniteQuery( getNextPageParam(lastPage) { return lastPage.next_version_id_marker || undefined; }, - ...queryConfig, }); } diff --git a/src/frontend/apps/impress/src/features/docs/doc-versioning/components/DocVersionEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-versioning/components/DocVersionEditor.tsx index fc1f76f9..3bb3c89c 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-versioning/components/DocVersionEditor.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-versioning/components/DocVersionEditor.tsx @@ -32,13 +32,18 @@ export const DocVersionEditor = ({ const { replace } = useRouter(); const [initialContent, setInitialContent] = useState(); + // 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) {