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
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to

### Changed

- ♻️(frontend) adapt custom blocks to new implementation #1375
- ♻️(backend) increase user short_name field length

### Fixed
Expand Down Expand Up @@ -42,10 +43,6 @@ and this project adheres to
- ✨(frontend) add pdf block to the editor #1293
- ✨List and restore deleted docs #1450

### Fixed

- 🐛(frontend) show full nested doc names with ajustable bar #1456

### Changed

- ♻️(frontend) Refactor Auth component for improved redirection logic #1461
Expand Down Expand Up @@ -88,6 +85,10 @@ and this project adheres to
- ✨(frontend) load docs logo from public folder via url #1462
- 🔧(keycloak) Fix https required issue in dev mode #1286

## Removed

- 🔥(frontend) remove custom DividerBlock ##1375

## [3.7.0] - 2025-09-12

### Added
Expand Down
2 changes: 0 additions & 2 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
"groupName": "ignored js dependencies",
"matchManagers": ["npm"],
"matchPackageNames": [
"@hocuspocus/provider",
"@hocuspocus/server",
"docx",
"fetch-mock",
"node",
Expand Down
18 changes: 8 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 @@ -676,10 +676,9 @@ test.describe('Doc Editor', () => {

await calloutBlock.locator('.inline-content').fill('example text');

await expect(page.locator('.bn-block').first()).toHaveAttribute(
'data-background-color',
'yellow',
);
await expect(
page.locator('.bn-block-content[data-content-type="callout"]').first(),
).toHaveAttribute('data-background-color', 'yellow');

const emojiButton = calloutBlock.getByRole('button');
await expect(emojiButton).toHaveText('💡');
Expand All @@ -703,10 +702,9 @@ test.describe('Doc Editor', () => {
await page.locator('.mantine-Menu-dropdown > button').last().click();
await page.locator('.bn-color-picker-dropdown > button').last().click();

await expect(page.locator('.bn-block').first()).toHaveAttribute(
'data-background-color',
'pink',
);
await expect(
page.locator('.bn-block-content[data-content-type="callout"]').first(),
).toHaveAttribute('data-background-color', 'pink');
});

test('it checks interlink feature', async ({ page, browserName }) => {
Expand Down Expand Up @@ -844,10 +842,10 @@ test.describe('Doc Editor', () => {

await expect(pdfBlock).toBeVisible();

await page.getByText('Add PDF').click();
await page.getByText(/Add (PDF|file)/).click();
const fileChooserPromise = page.waitForEvent('filechooser');
const downloadPromise = page.waitForEvent('download');
await page.getByText('Upload file').click();
await page.getByText(/Upload (PDF|file)/).click();
const fileChooser = await fileChooserPromise;

await fileChooser.setFiles(path.join(__dirname, 'assets/test-pdf.pdf'));
Expand Down
67 changes: 10 additions & 57 deletions src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import path from 'path';

import { expect, test } from '@playwright/test';
import cs from 'convert-stream';
import pdf from 'pdf-parse';
import { pdf } from 'pdf-parse';

import {
TestLanguage,
Expand Down Expand Up @@ -59,20 +59,16 @@ test.describe('Doc Export', () => {

await verifyDocName(page, randomDoc);

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

await editor.click();
await editor.locator('.bn-block-outer').last().fill('Hello');

const editor = await writeInEditor({ page, text: 'Hello' });
await page.keyboard.press('Enter');
await editor.locator('.bn-block-outer').last().fill('/');
await openSuggestionMenu({ page });
await page.getByText('Page Break').click();

await expect(editor.locator('.bn-page-break')).toBeVisible();

await page.keyboard.press('Enter');
await expect(
editor.locator('div[data-content-type="pageBreak"]'),
).toBeVisible();

await editor.locator('.bn-block-outer').last().fill('World');
await writeInEditor({ page, text: 'World' });

await page
.getByRole('button', {
Expand All @@ -92,9 +88,9 @@ test.describe('Doc Export', () => {
const pdfBuffer = await cs.toBuffer(await download.createReadStream());
const pdfData = await pdf(pdfBuffer);

expect(pdfData.numpages).toBe(2);
expect(pdfData.text).toContain('\n\nHello\n\nWorld'); // This is the doc text
expect(pdfData.info.Title).toBe(randomDoc);
expect(pdfData.total).toBe(2);
expect(pdfData.text).toContain('Hello\n\nWorld\n\n'); // This is the doc text
expect(pdfData.info?.Title).toBe(randomDoc);
});

test('it exports the doc to docx', async ({ page, browserName }) => {
Expand Down Expand Up @@ -274,49 +270,6 @@ test.describe('Doc Export', () => {
expect(pdfData.text).toContain('Hello World'); // This is the pdf text
});

/**
* We cannot assert the line break is visible in the pdf, but we can assert the
* line break is visible in the editor and that the pdf is generated.
*/
test('it exports the doc with divider', async ({ page, browserName }) => {
const [randomDoc] = await createDoc(page, 'export-divider', browserName, 1);

const editor = page.locator('.ProseMirror');
await editor.click();
await editor.fill('Hello World');

// Trigger slash menu to show menu
await editor.locator('.bn-block-outer').last().fill('/');
await page.getByText('Add a horizontal line').click();

await expect(
editor.locator('.bn-block-content[data-content-type="divider"]'),
).toBeVisible();

await page
.getByRole('button', {
name: 'Export the document',
})
.click();

await expect(
page.getByTestId('doc-open-modal-download-button'),
).toBeVisible();

const downloadPromise = page.waitForEvent('download', (download) => {
return download.suggestedFilename().includes(`${randomDoc}.pdf`);
});

void page.getByTestId('doc-export-download-button').click();

const download = await downloadPromise;
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);

const pdfBuffer = await cs.toBuffer(await download.createReadStream());
const pdfData = await pdf(pdfBuffer);
expect(pdfData.text).toContain('Hello World');
});

test('it exports the doc with multi columns', async ({
page,
browserName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
randomName,
verifyDocName,
} from './utils-common';
import { writeInEditor } from './utils-editor';
import { connectOtherUserToDoc, updateRoleUser } from './utils-share';
import { createRootSubPage } from './utils-sub-pages';

Expand Down Expand Up @@ -240,11 +241,7 @@ test.describe('Document create member', () => {

await verifyDocName(page, docTitle);

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

const docUrl = page.url();

Expand Down
14 changes: 11 additions & 3 deletions src/frontend/apps/e2e/__tests__/app-impress/doc-routing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
mockedDocument,
verifyDocName,
} from './utils-common';
import { writeInEditor } from './utils-editor';
import { createRootSubPage } from './utils-sub-pages';

test.describe('Doc Routing', () => {
Expand Down Expand Up @@ -58,16 +59,23 @@ test.describe('Doc Routing', () => {

await createRootSubPage(page, browserName, '401-doc-child');

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

const responsePromise = page.route(
/.*\/documents\/.*\/$|users\/me\/$/,
async (route) => {
const request = route.request();

// When we quit a document, a PATCH request is sent to save the document.
// We intercept this request to simulate a 401 error from the backend.
// The GET request to users/me is also intercepted to simulate the user
// being logged out when trying to fetch user info.
// This way we can test the 401 error handling when saving the document
if (
request.method().includes('PATCH') ||
request.method().includes('GET')
(request.url().includes('/documents/') &&
request.method().includes('PATCH')) ||
(request.url().includes('/users/me/') &&
request.method().includes('GET'))
) {
await route.fulfill({
status: 401,
Expand Down
22 changes: 12 additions & 10 deletions src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
keyCloakSignIn,
verifyDocName,
} from './utils-common';
import { writeInEditor } from './utils-editor';
import { addNewMember, connectOtherUserToDoc } from './utils-share';
import { createRootSubPage } from './utils-sub-pages';

Expand Down Expand Up @@ -151,18 +152,15 @@ test.describe('Doc Visibility: Restricted', () => {

await verifyDocName(page, docTitle);

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

const docUrl = page.url();

const { otherBrowserName, otherPage } = await connectOtherUserToDoc({
browserName,
docUrl,
});
const { otherBrowserName, otherPage, cleanup } =
await connectOtherUserToDoc({
browserName,
docUrl,
});

await expect(
otherPage.getByText('Insufficient access rights to view the document.'),
Expand All @@ -175,7 +173,11 @@ test.describe('Doc Visibility: Restricted', () => {
await addNewMember(page, 0, 'Reader', otherBrowserName);

await otherPage.reload();
await expect(otherPage.getByText('Hello World')).toBeVisible();
await expect(otherPage.getByText('Hello World')).toBeVisible({
timeout: 10000,
});

await cleanup();
});
});

Expand Down
14 changes: 8 additions & 6 deletions src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { expect, test } from '@playwright/test';

import { TestLanguage, createDoc, waitForLanguageSwitch } from './utils-common';
import { openSuggestionMenu } from './utils-editor';

test.describe('Language', () => {
test.beforeEach(async ({ page }) => {
Expand Down Expand Up @@ -51,6 +52,7 @@ test.describe('Language', () => {
await expect(page.locator('html')).toHaveAttribute('lang', 'en');
await expect(languagePicker).toContainText('English');
});

test('can switch language using only keyboard', async ({ page }) => {
await page.goto('/');
await waitForLanguageSwitch(page, TestLanguage.English);
Expand Down Expand Up @@ -106,18 +108,18 @@ test.describe('Language', () => {
}) => {
await createDoc(page, 'doc-toolbar', browserName, 1);

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

// Trigger slash menu to show english menu
await editor.click();
await editor.fill('/');
const editor = await openSuggestionMenu({ page });
await expect(page.getByText('Headings', { exact: true })).toBeVisible();

await editor.click(); // close the menu

await expect(page.getByText('Headings', { exact: true })).toBeHidden();

// Change language to French
await waitForLanguageSwitch(page, TestLanguage.French);

// Trigger slash menu to show french menu
await editor.locator('.bn-block-outer').last().fill('/');
await openSuggestionMenu({ page });
await expect(page.getByText('Titres', { exact: true })).toBeVisible();
});
});
37 changes: 37 additions & 0 deletions src/frontend/apps/e2e/__tests__/app-impress/types/pdf-parse.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Type definitions for pdf-parse library
* The library doesn't export complete type definitions for the parsed PDF data
*/

declare module 'pdf-parse' {
export interface PdfInfo {
Title?: string;
Author?: string;
Subject?: string;
Keywords?: string;
Creator?: string;
Producer?: string;
CreationDate?: string;
ModDate?: string;
[key: string]: unknown;
}

export interface PdfData {
/** Total number of pages */
numpages: number;
/** Alias for numpages */
total?: number;
/** Extracted text content from the PDF */
text: string;
/** PDF metadata information */
info?: PdfInfo;
/** PDF metadata (alternative structure) */
metadata?: unknown;
/** PDF version */
version?: string;
}

export function pdf(buffer: Buffer): Promise<PdfData>;

export default pdf;
}
4 changes: 2 additions & 2 deletions src/frontend/apps/e2e/__tests__/app-impress/utils-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const getEditor = async ({ page }: { page: Page }) => {
export const openSuggestionMenu = async ({ page }: { page: Page }) => {
const editor = await getEditor({ page });
await editor.click();
await page.locator('.bn-block-outer').last().fill('/');
await writeInEditor({ page, text: '/' });

return editor;
};
Expand All @@ -22,6 +22,6 @@ export const writeInEditor = async ({
text: string;
}) => {
const editor = await getEditor({ page });
await editor.locator('.bn-block-outer').last().fill(text);
await editor.locator('.bn-block-outer .bn-inline-content').last().fill(text);
return editor;
};
4 changes: 2 additions & 2 deletions src/frontend/apps/e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
"test:ui::chromium": "yarn test:ui --project=chromium"
},
"devDependencies": {
"@playwright/test": "1.55.0",
"@playwright/test": "1.55.1",
"@types/node": "*",
"@types/pdf-parse": "1.1.5",
"eslint-plugin-docs": "*",
"typescript": "*"
},
"dependencies": {
"convert-stream": "1.0.2",
"pdf-parse": "1.1.1"
"pdf-parse": "2.1.7"
},
"packageManager": "[email protected]"
}
Loading
Loading