mirror of
https://github.com/go-gitea/gitea.git
synced 2026-04-27 01:57:05 +00:00
The `events › logout propagation` e2e test ([example flake](https://github.com/go-gitea/gitea/actions/runs/24878089698/job/72839454932)) was racing the SSE connection setup: if page2's SharedWorker had not finished registering its messenger by the time page1 triggered logout, the event was silently dropped and page2 stayed on the authenticated page. Wait 500ms after verifying page2 is signed in, before triggering the logout from page1, so the SharedWorker has time to register. Comment points at a cleaner future fix (expose a ready attribute on the page) that will also work for the planned WebSocket SharedWorker. --- This PR was written with the help of Claude Opus 4.7 --------- Signed-off-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
85 lines
3.5 KiB
TypeScript
85 lines
3.5 KiB
TypeScript
import {test, expect} from '@playwright/test';
|
|
import {loginUser, baseUrl, apiUserHeaders, apiCreateUser, apiCreateRepo, apiCreateIssue, apiStartStopwatch, timeoutFactor, randomString} from './utils.ts';
|
|
|
|
// These tests rely on a short EVENT_SOURCE_UPDATE_TIME in the e2e server config.
|
|
test.describe('events', () => {
|
|
test('notification count', async ({page, request}) => {
|
|
const owner = `ev-notif-owner-${randomString(8)}`;
|
|
const commenter = `ev-notif-commenter-${randomString(8)}`;
|
|
const repoName = `ev-notif-${randomString(8)}`;
|
|
|
|
await Promise.all([apiCreateUser(request, owner), apiCreateUser(request, commenter)]);
|
|
|
|
// Create repo and login in parallel — repo is needed for the issue, login for the event stream
|
|
await Promise.all([
|
|
apiCreateRepo(request, {name: repoName, headers: apiUserHeaders(owner)}),
|
|
loginUser(page, owner),
|
|
]);
|
|
await page.goto('/');
|
|
const badge = page.locator('a.not-mobile .notification_count');
|
|
await expect(badge).toBeHidden();
|
|
|
|
// Create issue as another user — this generates a notification delivered via server push
|
|
await apiCreateIssue(request, owner, repoName, {title: 'events notification test', headers: apiUserHeaders(commenter)});
|
|
|
|
// Wait for the notification badge to appear via server event
|
|
await expect(badge).toBeVisible({timeout: 15000 * timeoutFactor});
|
|
});
|
|
|
|
test('stopwatch', async ({page, request}) => {
|
|
const name = `ev-sw-${randomString(8)}`;
|
|
const headers = apiUserHeaders(name);
|
|
|
|
await apiCreateUser(request, name);
|
|
|
|
// Login in parallel with repo+issue+stopwatch setup (all independent after user exists)
|
|
await Promise.all([
|
|
loginUser(page, name),
|
|
(async () => {
|
|
await apiCreateRepo(request, {name, headers});
|
|
await apiCreateIssue(request, name, name, {title: 'events stopwatch test', headers});
|
|
await apiStartStopwatch(request, name, name, 1, {headers});
|
|
})(),
|
|
]);
|
|
await page.goto('/');
|
|
|
|
// Verify stopwatch is visible and links to the correct issue
|
|
const stopwatch = page.locator('.active-stopwatch.not-mobile');
|
|
await expect(stopwatch).toBeVisible();
|
|
});
|
|
|
|
test('logout propagation', async ({browser, request}) => {
|
|
const name = `ev-logout-${randomString(8)}`;
|
|
|
|
await apiCreateUser(request, name);
|
|
|
|
// Use a single context so both pages share the same session and SharedWorker
|
|
const context = await browser.newContext({baseURL: baseUrl()});
|
|
const page1 = await context.newPage();
|
|
const page2 = await context.newPage();
|
|
|
|
await loginUser(page1, name);
|
|
|
|
// Navigate page2 so it connects to the shared event stream
|
|
await page2.goto('/');
|
|
|
|
// Verify page2 is logged in
|
|
await expect(page2.getByRole('link', {name: 'Sign In'})).toBeHidden();
|
|
|
|
// Give page2's SharedWorker time to register its SSE connection on the
|
|
// server — otherwise the logout event can race the connection and be
|
|
// silently dropped. See https://github.com/go-gitea/gitea/pull/37403
|
|
// In the future, we can set an attribute to HTML page when the connection is established,
|
|
// then here we can just wait for that attribute (it should also work for the planned WebSocket SharedWorker)
|
|
await page2.waitForTimeout(500); // eslint-disable-line playwright/no-wait-for-timeout
|
|
|
|
// Logout from page1 — this sends a logout event to all tabs
|
|
await page1.goto('/user/logout');
|
|
|
|
// page2 should be redirected via the logout event
|
|
await expect(page2.getByRole('link', {name: 'Sign In'})).toBeVisible();
|
|
|
|
await context.close();
|
|
});
|
|
});
|