Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ and this project adheres to
- ⚗️(service-worker) remove index from cache first strategy #1395
- 🐛(frontend) fix 404 page when reload 403 page #1402
- 🐛(frontend) fix legacy role computation #1376
- 🐛(frontend) scroll back to top when navigate to a document #1406

## [3.7.0] - 2025-09-12

Expand Down
63 changes: 53 additions & 10 deletions src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
overrideConfig,
verifyDocName,
} from './utils-common';
import { createRootSubPage } from './utils-sub-pages';
import { getEditor, openSuggestionMenu, writeInEditor } from './utils-editor';
import { createRootSubPage, navigateToPageFromTree } from './utils-sub-pages';

test.beforeEach(async ({ page }) => {
await page.goto('/');
Expand Down Expand Up @@ -86,8 +87,7 @@ test.describe('Doc Editor', () => {
// Is connected
let framesentPromise = webSocket.waitForEvent('framesent');

await page.locator('.ProseMirror.bn-editor').click();
await page.locator('.ProseMirror.bn-editor').fill('Hello World');
await writeInEditor({ page, text: 'Hello World' });

let framesent = await framesentPromise;
expect(framesent.payload).not.toBeNull();
Expand Down Expand Up @@ -505,10 +505,7 @@ test.describe('Doc Editor', () => {

await verifyDocName(page, randomDoc);

const editor = page.locator('.ProseMirror.bn-editor');

await editor.click();
await editor.locator('.bn-block-outer').last().fill('/');
const editor = await openSuggestionMenu({ page });
await page.getByText('Embedded file').click();
await page.getByText('Upload file').click();

Expand Down Expand Up @@ -675,9 +672,7 @@ test.describe('Doc Editor', () => {
test('it checks if callout custom block', async ({ page, browserName }) => {
await createDoc(page, 'doc-toolbar', browserName, 1);

const editor = page.locator('.ProseMirror');
await editor.click();
await page.locator('.bn-block-outer').last().fill('/');
await openSuggestionMenu({ page });
await page.getByText('Add a callout block').click();

const calloutBlock = page
Expand Down Expand Up @@ -791,4 +786,52 @@ test.describe('Doc Editor', () => {
),
).toBeVisible();
});

test('it checks multiple big doc scroll to the top', async ({
page,
browserName,
}) => {
const [randomDoc] = await createDoc(page, 'doc-scroll', browserName, 1);

for (let i = 0; i < 15; i++) {
await page.keyboard.press('Enter');
await writeInEditor({ page, text: 'Hello Parent ' + i });
}

const editor = await getEditor({ page });
await expect(
editor.getByText('Hello Parent 1', { exact: true }),
).not.toBeInViewport();
await expect(editor.getByText('Hello Parent 14')).toBeInViewport();

const { name: docChild } = await createRootSubPage(
page,
browserName,
'doc-scroll-child',
);

for (let i = 0; i < 15; i++) {
await page.keyboard.press('Enter');
await writeInEditor({ page, text: 'Hello Child ' + i });
}

await expect(
editor.getByText('Hello Child 1', { exact: true }),
).not.toBeInViewport();
await expect(editor.getByText('Hello Child 14')).toBeInViewport();

await navigateToPageFromTree({ page, title: randomDoc });

await expect(
editor.getByText('Hello Parent 1', { exact: true }),
).toBeInViewport();
await expect(editor.getByText('Hello Parent 14')).not.toBeInViewport();

await navigateToPageFromTree({ page, title: docChild });

await expect(
editor.getByText('Hello Child 1', { exact: true }),
).toBeInViewport();
await expect(editor.getByText('Hello Child 14')).not.toBeInViewport();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ test.beforeEach(async ({ page }) => {

test.describe('Doc Table Content', () => {
test('it checks the doc table content', async ({ page, browserName }) => {
test.setTimeout(60000);

const [randomDoc] = await createDoc(
page,
'doc-table-content',
Expand Down
27 changes: 27 additions & 0 deletions src/frontend/apps/e2e/__tests__/app-impress/utils-editor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Page } from '@playwright/test';

export const getEditor = async ({ page }: { page: Page }) => {
const editor = page.locator('.ProseMirror');
await editor.click();
return editor;
};

export const openSuggestionMenu = async ({ page }: { page: Page }) => {
const editor = await getEditor({ page });
await editor.click();
await page.locator('.bn-block-outer').last().fill('/');

return editor;
};

export const writeInEditor = async ({
page,
text,
}: {
page: Page;
text: string;
}) => {
const editor = await getEditor({ page });
editor.locator('.bn-block-outer').last().fill(text);
return editor;
};
13 changes: 13 additions & 0 deletions src/frontend/apps/e2e/__tests__/app-impress/utils-sub-pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Page, expect } from '@playwright/test';
import {
randomName,
updateDocTitle,
verifyDocName,
waitForResponseCreateDoc,
} from './utils-common';

Expand Down Expand Up @@ -65,3 +66,15 @@ export const clickOnAddRootSubPage = async (page: Page) => {
await rootItem.hover();
await rootItem.getByRole('button', { name: /add subpage/i }).click();
};

export const navigateToPageFromTree = async ({
page,
title,
}: {
page: Page;
title: string;
}) => {
const docTree = page.getByTestId('doc-tree');
await docTree.getByText(title).click();
await verifyDocName(page, title);
};
21 changes: 21 additions & 0 deletions src/frontend/apps/impress/src/pages/docs/[id]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import { KEY_AUTH, setAuthUrl, useAuth } from '@/features/auth';
import { getDocChildren, subPageToTree } from '@/features/docs/doc-tree/';
import { MainLayout } from '@/layouts';
import { MAIN_LAYOUT_ID } from '@/layouts/conf';
import { useBroadcastStore } from '@/stores';
import { NextPageWithLayout } from '@/types/next';

Expand Down Expand Up @@ -89,6 +90,26 @@ const DocPage = ({ id }: DocProps) => {
const { t } = useTranslation();
const { authenticated } = useAuth();

/**
* Scroll to top when navigating to a new document
* We use a timeout to ensure the scroll happens after the layout has updated.
*/
useEffect(() => {
let timeoutId: NodeJS.Timeout | undefined;
const mainElement = document.getElementById(MAIN_LAYOUT_ID);
if (mainElement) {
timeoutId = setTimeout(() => {
mainElement.scrollTop = 0;
}, 150);
}

return () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
};
}, [id]);

// Invalidate when provider store reports a lost connection
useEffect(() => {
if (hasLostConnection && doc?.id) {
Expand Down
Loading