mirror of
https://github.com/go-gitea/gitea.git
synced 2026-11-02 13:44:16 +09:00
WebKit was removed from the e2e tests in https://github.com/go-gitea/gitea/pull/37315 because Linux WebKit kept crashing. The crashes came from a use-after-free in the libsoup bundled with WebKit, which killed the network process and surfaced as `WebKit encountered an internal error`. macOS WebKit never had them because it does not use libsoup. Playwright 1.64 bundles libsoup 3.6.6 with the fix (https://github.com/microsoft/playwright/issues/42803), so WebKit now runs on all platforms. Builds on https://github.com/go-gitea/gitea/pull/40140. The e2e job ran 50 times on `ubuntu-latest` with WebKit enabled, and all runs passed without WebKit errors. The third browser adds about 1.5 to 2 minutes per run. 1. Playwright installs its system dependencies on GitHub runners too, which only come with the Chromium and Firefox libraries 1. The passkey test skips Linux WebKit, which has no WebAuthn, Playwright only stubs `PublicKeyCredential` there --------- Signed-off-by: silverwind <me@silverwind.io>
71 lines
3.0 KiB
TypeScript
71 lines
3.0 KiB
TypeScript
import {platform} from 'node:process';
|
|
import {test, expect, type Page} from '@playwright/test';
|
|
import {apiCreateUser, loginUser, randomString, testUserPassword} from './utils.ts';
|
|
|
|
const signedIn = /^(?!.*\/user\/(login|webauthn))/; // the target of a finished login varies
|
|
|
|
async function registerKey(page: Page, nickname: string) {
|
|
await page.goto('/user/settings/security');
|
|
await page.getByRole('textbox', {name: 'Nickname'}).fill(nickname);
|
|
await page.getByRole('button', {name: 'Add Security Key'}).click();
|
|
}
|
|
|
|
async function signInWithPassword(page: Page, username: string) {
|
|
await page.context().clearCookies();
|
|
await page.goto('/user/login');
|
|
await page.getByLabel('Username or Email Address').fill(username);
|
|
await page.getByLabel('Password').fill(testUserPassword);
|
|
await page.getByRole('button', {name: 'Sign In'}).click();
|
|
}
|
|
|
|
// regression: credProtect level 3 hid the credential from the second-factor login
|
|
test('security key survives credProtect', async ({page, request, browserName}) => {
|
|
test.skip(browserName !== 'chromium', 'only the CDP authenticator emulates credProtect'); // eslint-disable-line playwright/no-skipped-test -- conditional skip, the reason is in the message
|
|
|
|
const username = `e2e-credprotect-${randomString(8)}`;
|
|
await apiCreateUser(request, username);
|
|
|
|
const cdp = await page.context().newCDPSession(page);
|
|
await cdp.send('WebAuthn.enable');
|
|
await cdp.send('WebAuthn.addVirtualAuthenticator', {options: {
|
|
protocol: 'ctap2',
|
|
ctap2Version: 'ctap2_1',
|
|
transport: 'usb',
|
|
hasResidentKey: true,
|
|
hasUserVerification: true,
|
|
hasCredBlob: true, // CDP only emulates credProtect together with credBlob
|
|
isUserVerified: true,
|
|
}});
|
|
|
|
await loginUser(page, username);
|
|
await registerKey(page, 'e2e-key');
|
|
await expect(page.getByText('e2e-key')).toBeVisible();
|
|
|
|
await registerKey(page, 'e2e-key-again');
|
|
await expect(page.locator('#webauthn-error-msg')).toContainText('already registered');
|
|
|
|
await signInWithPassword(page, username);
|
|
await expect(page).toHaveURL(signedIn);
|
|
});
|
|
|
|
// this authenticator has no credProtect, so it cannot replace the test above
|
|
test('security key signs in as second factor and as passkey', async ({page, request, browserName}) => {
|
|
test.skip(browserName === 'webkit' && platform === 'linux', 'linux webkit has no webauthn, playwright only stubs PublicKeyCredential'); // eslint-disable-line playwright/no-skipped-test -- conditional skip, the reason is in the message
|
|
|
|
const username = `e2e-passkey-${randomString(8)}`;
|
|
await apiCreateUser(request, username);
|
|
await page.context().credentials.install();
|
|
|
|
await loginUser(page, username);
|
|
await registerKey(page, 'e2e-key');
|
|
await expect(page.getByText('e2e-key')).toBeVisible();
|
|
|
|
await signInWithPassword(page, username);
|
|
await expect(page).toHaveURL(signedIn);
|
|
|
|
await page.context().clearCookies();
|
|
await page.goto('/user/login');
|
|
await page.getByText('Sign in with a passkey').click();
|
|
await expect(page).toHaveURL(signedIn);
|
|
});
|