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
143 changes: 134 additions & 9 deletions .github/workflows/impress-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,54 @@ jobs:
- name: Check linting
run: cd src/frontend/ && yarn lint

test-e2e-chromium:
prepare-e2e:
runs-on: ubuntu-latest
needs: install-dependencies
timeout-minutes: 10
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "22.x"

- name: Restore the frontend cache
uses: actions/cache@v5
with:
path: "src/frontend/**/node_modules"
key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }}
fail-on-cache-miss: true

- name: Restore Playwright browsers cache
id: playwright-cache
uses: actions/cache/restore@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('src/frontend/yarn.lock', 'src/frontend/apps/e2e/yarn.lock') }}
restore-keys: |
playwright-${{ runner.os }}-

- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: |
cd src/frontend/apps/e2e
yarn install-playwright chromium firefox webkit

- name: Save Playwright browsers cache
if: steps.playwright-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: ~/.cache/ms-playwright
key: ${{ steps.playwright-cache.outputs.cache-primary-key }}

test-e2e-chromium:
runs-on: ubuntu-latest
needs: prepare-e2e
timeout-minutes: 20
steps:
- name: Checkout repository
Expand All @@ -89,19 +134,59 @@ jobs:
- name: Set e2e env variables
run: cat env.d/development/common.e2e >> env.d/development/common.local

- name: Install Playwright Browsers
run: cd src/frontend/apps/e2e && yarn install --frozen-lockfile && yarn install-playwright chromium
- name: Restore Playwright browsers cache
uses: actions/cache@v5
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('src/frontend/yarn.lock', 'src/frontend/apps/e2e/yarn.lock') }}
fail-on-cache-miss: true

- name: Free disk space before Docker
uses: ./.github/actions/free-disk-space

- name: Start Docker services
run: make bootstrap-e2e FLUSH_ARGS='--no-input'

- name: Restore last-run cache
if: ${{ github.run_attempt > 1 }}
id: restore-last-run
uses: actions/cache/restore@v4
with:
path: src/frontend/apps/e2e/test-results/.last-run.json
key: playwright-last-run-${{ github.run_id }}-chromium

- name: Run e2e tests
run: cd src/frontend/ && yarn e2e:test --project='chromium'
env:
PLAYWRIGHT_LIST_PRINT_STEPS: true
FORCE_COLOR: true
run: |
cd src/frontend/

- uses: actions/upload-artifact@v4
LAST_FAILED_FLAG=""
if [ "${{ github.run_attempt }}" != "1" ]; then
LAST_FAILED_FLAG="--last-failed"
fi

yarn e2e:test --project='chromium' $LAST_FAILED_FLAG

- name: Save last-run cache
if: always()
uses: actions/cache/save@v4
with:
path: src/frontend/apps/e2e/test-results/.last-run.json
key: playwright-last-run-${{ github.run_id }}-chromium

- name: Upload last-run artifact
if: always()
uses: actions/upload-artifact@v6
with:
name: playwright-instance-last-run-chromium
path: src/frontend/apps/e2e/test-results/.last-run.json
include-hidden-files: true
if-no-files-found: warn
retention-days: 7

- uses: actions/upload-artifact@v6
if: always()
with:
name: playwright-chromium-report
Expand Down Expand Up @@ -131,19 +216,59 @@ jobs:
- name: Set e2e env variables
run: cat env.d/development/common.e2e >> env.d/development/common.local

- name: Install Playwright Browsers
run: cd src/frontend/apps/e2e && yarn install --frozen-lockfile && yarn install-playwright firefox webkit chromium
- name: Restore Playwright browsers cache
uses: actions/cache@v5
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('src/frontend/yarn.lock', 'src/frontend/apps/e2e/yarn.lock') }}
fail-on-cache-miss: true

- name: Free disk space before Docker
uses: ./.github/actions/free-disk-space

- name: Start Docker services
run: make bootstrap-e2e FLUSH_ARGS='--no-input'

- name: Restore last-run cache
if: ${{ github.run_attempt > 1 }}
id: restore-last-run
uses: actions/cache/restore@v4
with:
path: src/frontend/apps/e2e/test-results/.last-run.json
key: playwright-last-run-${{ github.run_id }}-other-browser

- name: Run e2e tests
run: cd src/frontend/ && yarn e2e:test --project=firefox --project=webkit
env:
PLAYWRIGHT_LIST_PRINT_STEPS: true
FORCE_COLOR: true
run: |
cd src/frontend/

LAST_FAILED_FLAG=""
if [ "${{ github.run_attempt }}" != "1" ]; then
LAST_FAILED_FLAG="--last-failed"
fi

yarn e2e:test --project=firefox --project=webkit $LAST_FAILED_FLAG

- name: Save last-run cache
if: always()
uses: actions/cache/save@v4
with:
path: src/frontend/apps/e2e/test-results/.last-run.json
key: playwright-last-run-${{ github.run_id }}-other-browser

- name: Upload last-run artifact
if: always()
uses: actions/upload-artifact@v6
with:
name: playwright-instance-last-run-other-browser
path: src/frontend/apps/e2e/test-results/.last-run.json
include-hidden-files: true
if-no-files-found: warn
retention-days: 7

- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
if: always()
with:
name: playwright-other-report
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to
### Added

- 🚸(frontend) allow opening "@page" links with ctrl/command/middle-mouse click
- ✅ E2E - Any instance friendly #2142

## [v4.8.5] - 2026-04-03

Expand Down
22 changes: 22 additions & 0 deletions src/frontend/apps/e2e/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
PORT=3000
BASE_URL=http://localhost:3000
BASE_API_URL=http://localhost:8071/api/v1.0
COLLABORATION_WS_URL=ws://localhost:4444/collaboration/ws/
COLLABORATION_WS_NOT_CONNECTED_READY_ONLY=true
MEDIA_BASE_URL=http://localhost:8083
CUSTOM_SIGN_IN=false
IS_INSTANCE=false
SIGN_IN_EL_LOGIN_PAGE='.login-pf #kc-header-wrapper'
SIGN_IN_EL_TRIGGER=Start Writing
FIRST_NAME=E2E
SIGN_IN_USERNAME_CHROMIUM=user.test@chromium.test
USERNAME_CHROMIUM=E2E Chromium
SIGN_IN_USERNAME_WEBKIT=user.test@webkit.test
USERNAME_WEBKIT=E2E Webkit
SIGN_IN_USERNAME_FIREFOX=user.test@firefox.test
USERNAME_FIREFOX=E2E Firefox
# To test server to server API calls
SERVER_TO_SERVER_API_TOKENS='server-api-token'
SUB_CHROMIUM=user.test@chromium.test
SUB_WEBKIT=user.test@webkit.test
SUB_FIREFOX=user.test@firefox.test
29 changes: 29 additions & 0 deletions src/frontend/apps/e2e/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
PORT=3000
BASE_URL=http://localhost:3000
BASE_API_URL=http://localhost:8071/api/v1.0
COLLABORATION_WS_URL=ws://localhost:4444/collaboration/ws/
COLLABORATION_WS_NOT_CONNECTED_READY_ONLY=true
MEDIA_BASE_URL=http://localhost:8083
IS_INSTANCE=false
CUSTOM_SIGN_IN=false
SIGN_IN_EL_LOGIN_PAGE='.login-pf #kc-header-wrapper'
SIGN_IN_EL_TRIGGER=Start Writing
FIRST_NAME=E2E
SIGN_IN_USERNAME_CHROMIUM=user.test@chromium.test
USERNAME_CHROMIUM=E2E Chromium
SIGN_IN_USERNAME_WEBKIT=user.test@webkit.test
USERNAME_WEBKIT=E2E Webkit
SIGN_IN_USERNAME_FIREFOX=user.test@firefox.test
USERNAME_FIREFOX=E2E Firefox
# Used only on instance with custom sign in
SIGN_IN_EL_USERNAME_INPUT=
SIGN_IN_EL_USERNAME_VALIDATION=
SIGN_IN_EL_PASSWORD_INPUT=
SIGN_IN_PASSWORD_CHROMIUM=
SIGN_IN_PASSWORD_WEBKIT=
SIGN_IN_PASSWORD_FIREFOX=
# To test server to server API calls
SERVER_TO_SERVER_API_TOKENS='server-api-token'
SUB_CHROMIUM=user.test@chromium.test
SUB_WEBKIT=user.test@webkit.test
SUB_FIREFOX=user.test@firefox.test
1 change: 1 addition & 0 deletions src/frontend/apps/e2e/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ blob-report/
playwright/.auth/
playwright/.cache/
screenshots/
.env.local

Large diffs are not rendered by default.

Binary file not shown.
Binary file not shown.
4 changes: 2 additions & 2 deletions src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FullConfig, FullProject, chromium, expect } from '@playwright/test';

import { keyCloakSignIn } from './utils-common';
import { SignIn } from './utils-signin';

const saveStorageState = async (
browserConfig: FullProject<unknown, unknown>,
Expand All @@ -22,7 +22,7 @@ const saveStorageState = async (
await page.content();
await expect(page.getByText('Docs').first()).toBeVisible();

await keyCloakSignIn(page, browserName);
await SignIn(page, browserName);

await expect(
page.locator('header').first().getByRole('button', {
Expand Down
69 changes: 36 additions & 33 deletions src/frontend/apps/e2e/__tests__/app-impress/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,25 @@ import { expect, test } from '@playwright/test';
import { CONFIG, createDoc, overrideConfig } from './utils-common';

test.describe('Config', () => {
test('it checks that sentry is trying to init from config endpoint', async ({
page,
}) => {
await overrideConfig(page, {
SENTRY_DSN: 'https://sentry.io/123',
if (process.env.IS_INSTANCE !== 'true') {
test('it checks that sentry is trying to init from config endpoint', async ({
page,
}) => {
await overrideConfig(page, {
SENTRY_DSN: 'https://sentry.io/123',
});

const invalidMsg = 'Invalid Sentry Dsn: https://sentry.io/123';
const consoleMessage = page.waitForEvent('console', {
timeout: 5000,
predicate: (msg) => msg.text().includes(invalidMsg),
});

await page.goto('/');

expect((await consoleMessage).text()).toContain(invalidMsg);
});

const invalidMsg = 'Invalid Sentry Dsn: https://sentry.io/123';
const consoleMessage = page.waitForEvent('console', {
timeout: 5000,
predicate: (msg) => msg.text().includes(invalidMsg),
});

await page.goto('/');

expect((await consoleMessage).text()).toContain(invalidMsg);
});
}

test('it checks that media server is configured from config endpoint', async ({
page,
Expand Down Expand Up @@ -55,7 +57,7 @@ test.describe('Config', () => {

// Check src of image
expect(await image.getAttribute('src')).toMatch(
/http:\/\/localhost:8083\/media\/.*\/attachments\/.*.png/,
new RegExp(`${process.env.MEDIA_BASE_URL}/media/.*?/attachments/.*?.png`),
);
});

Expand All @@ -71,9 +73,9 @@ test.describe('Config', () => {
.click();

const webSocket = await page.waitForEvent('websocket', (webSocket) => {
return webSocket.url().includes('ws://localhost:4444/collaboration/ws/');
return webSocket.url().includes(`${process.env.COLLABORATION_WS_URL}`);
});
expect(webSocket.url()).toContain('ws://localhost:4444/collaboration/ws/');
expect(webSocket.url()).toContain(`${process.env.COLLABORATION_WS_URL}`);
});

test('it checks that Crisp is trying to init from config endpoint', async ({
Expand All @@ -85,9 +87,8 @@ test.describe('Config', () => {

await page.goto('/');

await expect(
page.locator('#crisp-chatbox').getByText('Invalid website'),
).toBeVisible();
const crispElement = page.locator('#crisp-chatbox');
await expect(crispElement).toBeAttached();
});

test('it checks FRONTEND_CSS_URL config', async ({ page }) => {
Expand Down Expand Up @@ -118,20 +119,22 @@ test.describe('Config', () => {
).toBeAttached();
});

test('it checks the config api is called', async ({ page }) => {
const responsePromise = page.waitForResponse(
(response) =>
response.url().includes('/config/') && response.status() === 200,
);
if (process.env.IS_INSTANCE !== 'true') {
test('it checks the config api is called', async ({ page }) => {
const responsePromise = page.waitForResponse(
(response) =>
response.url().includes('/config/') && response.status() === 200,
);

await page.goto('/');
await page.goto('/');

const response = await responsePromise;
expect(response.ok()).toBeTruthy();
const response = await responsePromise;
expect(response.ok()).toBeTruthy();

const json = (await response.json()) as typeof CONFIG;
expect(json).toStrictEqual(CONFIG);
});
const json = (await response.json()) as typeof CONFIG;
expect(json).toStrictEqual(CONFIG);
});
}
});

test.describe('Config: Not logged', () => {
Expand Down
Loading
Loading