🐛(frontend) scroll back to top when navigate to a document
When navigating to a new document, the scroll position was preserved. This commit changes this behavior to scroll back to the top of the page when navigating to a new document.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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('/');
|
||||
@@ -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();
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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',
|
||||
|
||||
27
src/frontend/apps/e2e/__tests__/app-impress/utils-editor.ts
Normal file
27
src/frontend/apps/e2e/__tests__/app-impress/utils-editor.ts
Normal file
@@ -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;
|
||||
};
|
||||
@@ -3,6 +3,7 @@ import { Page, expect } from '@playwright/test';
|
||||
import {
|
||||
randomName,
|
||||
updateDocTitle,
|
||||
verifyDocName,
|
||||
waitForResponseCreateDoc,
|
||||
} from './utils-common';
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user