🐛(frontend) fix 404 page when reload 403 page

When users were reloading a 403 page, they were
redirected to the 404 page because of Nextjs
routing mechanism. This commit fixes this issue by
removing the 403 page from the pages directory
and creating a component that is used directly
in the layout when a 403 error is detected.
This commit is contained in:
Anthony LC
2025-09-17 14:48:10 +02:00
parent 1e39d17914
commit d8c9283dd1
8 changed files with 121 additions and 150 deletions

View File

@@ -7,6 +7,7 @@ import {
randomName,
verifyDocName,
} from './utils-common';
import { connectOtherUserToDoc } from './utils-share';
import { createRootSubPage } from './utils-sub-pages';
test.describe('Document create member', () => {
@@ -209,10 +210,6 @@ test.describe('Document create member', () => {
await expect(userInvitation).toBeHidden();
});
});
test.describe('Document create member: Multiple login', () => {
test.use({ storageState: { cookies: [], origins: [] } });
test('It creates a member from a request coming from a 403 page', async ({
page,
@@ -220,9 +217,6 @@ test.describe('Document create member: Multiple login', () => {
}) => {
test.slow();
await page.goto('/');
await keyCloakSignIn(page, browserName);
const [docTitle] = await createDoc(
page,
'Member access request',
@@ -232,55 +226,37 @@ test.describe('Document create member: Multiple login', () => {
await verifyDocName(page, docTitle);
await page
.locator('.ProseMirror')
.locator('.bn-block-outer')
.last()
.fill('Hello World');
const urlDoc = page.url();
await page
.getByRole('button', {
name: 'Logout',
})
.click();
const otherBrowser = BROWSERS.find((b) => b !== browserName);
await keyCloakSignIn(page, otherBrowser!);
await expect(page.getByTestId('header-logo-link')).toBeVisible();
await page.goto(urlDoc);
// Other user will request access
const { otherPage, otherBrowserName, cleanup } =
await connectOtherUserToDoc(browserName, urlDoc);
await expect(
page.getByText('Insufficient access rights to view the document.'),
otherPage.getByText('Insufficient access rights to view the document.'),
).toBeVisible({
timeout: 10000,
});
await page.getByRole('button', { name: 'Request access' }).click();
await otherPage.getByRole('button', { name: 'Request access' }).click();
await expect(
page.getByText('Your access request for this document is pending.'),
otherPage.getByText('Your access request for this document is pending.'),
).toBeVisible();
await page
.getByRole('button', {
name: 'Logout',
})
.click();
await page.goto('/');
await keyCloakSignIn(page, browserName);
await expect(page.getByTestId('header-logo-link')).toBeVisible({
timeout: 10000,
});
await page.goto(urlDoc);
// First user approves the request
await page.getByRole('button', { name: 'Share' }).click();
await expect(page.getByText('Access Requests')).toBeVisible();
await expect(page.getByText(`E2E ${otherBrowser}`)).toBeVisible();
await expect(page.getByText(`E2E ${otherBrowserName}`)).toBeVisible();
const emailRequest = `user.test@${otherBrowser}.test`;
const emailRequest = `user.test@${otherBrowserName}.test`;
await expect(page.getByText(emailRequest)).toBeVisible();
const container = page.getByTestId(
`doc-share-access-request-row-${emailRequest}`,
@@ -291,8 +267,20 @@ test.describe('Document create member: Multiple login', () => {
await expect(page.getByText('Access Requests')).toBeHidden();
await expect(page.getByText('Share with 2 users')).toBeVisible();
await expect(page.getByText(`E2E ${otherBrowser}`)).toBeVisible();
await expect(page.getByText(`E2E ${otherBrowserName}`)).toBeVisible();
// Other user verifies he has access
await otherPage.reload();
await verifyDocName(otherPage, docTitle);
await expect(otherPage.getByText('Hello World')).toBeVisible();
// Cleanup: other user logout
await cleanup();
});
});
test.describe('Document create member: Multiple login', () => {
test.use({ storageState: { cookies: [], origins: [] } });
test('It cannot request member access on child doc on a 403 page', async ({
page,

View File

@@ -7,6 +7,7 @@ import {
keyCloakSignIn,
verifyDocName,
} from './utils-common';
import { addNewMember, connectOtherUserToDoc } from './utils-share';
import { createRootSubPage } from './utils-sub-pages';
test.describe('Doc Visibility', () => {
@@ -146,47 +147,31 @@ test.describe('Doc Visibility: Restricted', () => {
await verifyDocName(page, docTitle);
await page.getByRole('button', { name: 'Share' }).click();
const inputSearch = page.getByRole('combobox', {
name: 'Quick search input',
});
const otherBrowser = BROWSERS.find((b) => b !== browserName);
if (!otherBrowser) {
throw new Error('No alternative browser found');
}
const username = `user.test@${otherBrowser}.test`;
await inputSearch.fill(username);
await page.getByRole('option', { name: username }).click();
// Choose a role
const container = page.getByTestId('doc-share-add-member-list');
await container.getByLabel('doc-role-dropdown').click();
await page.getByLabel('Reader').click();
await page.getByRole('button', { name: 'Invite' }).click();
await page.locator('.c__modal__backdrop').click({
position: { x: 0, y: 0 },
});
await page
.locator('.ProseMirror')
.locator('.bn-block-outer')
.last()
.fill('Hello World');
const urlDoc = page.url();
await page
.getByRole('button', {
name: 'Logout',
})
.click();
const { otherBrowserName, otherPage } = await connectOtherUserToDoc(
browserName,
urlDoc,
);
await keyCloakSignIn(page, otherBrowser);
await expect(
otherPage.getByText('Insufficient access rights to view the document.'),
).toBeVisible({
timeout: 10000,
});
await expect(page.getByTestId('header-logo-link')).toBeVisible();
await page.getByRole('button', { name: 'Share' }).click();
await page.goto(urlDoc);
await addNewMember(page, 0, 'Reader', otherBrowserName);
await verifyDocName(page, docTitle);
await expect(page.getByLabel('Share button')).toBeVisible();
await otherPage.reload();
await expect(otherPage.getByText('Hello World')).toBeVisible();
});
});

View File

@@ -1,6 +1,7 @@
import { Page, expect } from '@playwright/test';
export const BROWSERS = ['chromium', 'webkit', 'firefox'];
export type BrowserName = 'chromium' | 'firefox' | 'webkit';
export const BROWSERS: BrowserName[] = ['chromium', 'webkit', 'firefox'];
export const CONFIG = {
AI_FEATURE_ENABLED: true,

View File

@@ -1,4 +1,11 @@
import { Page, expect } from '@playwright/test';
import { Page, chromium, expect } from '@playwright/test';
import {
BROWSERS,
BrowserName,
keyCloakSignIn,
verifyDocName,
} from './utils-common';
export type Role = 'Administrator' | 'Owner' | 'Member' | 'Editor' | 'Reader';
export type LinkReach = 'Private' | 'Connected' | 'Public';
@@ -61,6 +68,56 @@ export const updateShareLink = async (
}
};
/**
* Connects another user to a document.
* Useful to test real-time collaboration features.
* @param browserName The name of the browser to use.
* @param docUrl The URL of the document to connect to.
* @param docTitle The title of the document (optional).
* @returns An object containing the other browser, context, and page.
*/
export const connectOtherUserToDoc = async (
browserName: BrowserName,
docUrl: string,
docTitle?: string,
) => {
const otherBrowserName = BROWSERS.find((b) => b !== browserName);
if (!otherBrowserName) {
throw new Error('No alternative browser found');
}
const otherBrowser = await chromium.launch({ headless: true });
const otherContext = await otherBrowser.newContext({
locale: 'en-US',
timezoneId: 'Europe/Paris',
permissions: [],
storageState: {
cookies: [],
origins: [],
},
});
const otherPage = await otherContext.newPage();
await otherPage.goto(docUrl);
await otherPage.getByRole('button', { name: 'Login' }).click({
timeout: 15000,
});
await keyCloakSignIn(otherPage, otherBrowserName, false);
if (docTitle) {
await verifyDocName(otherPage, docTitle);
}
const cleanup = async () => {
await otherPage.close();
await otherContext.close();
await otherBrowser.close();
};
return { otherBrowser, otherContext, otherPage, otherBrowserName, cleanup };
};
export const mockedInvitations = async (page: Page, json?: object) => {
let result = [
{