Rework e2e test setup for full isolation

Always start an isolated ephemeral Gitea instance with its own temp
directory, SQLite database, and config file. This addresses review
feedback that using the developer's existing instance is unreliable.

- Rewrite test-e2e.sh to create a temp workdir, find a free port,
  write a minimal app.ini, start the server, and clean up on exit
- Build a separate gitea-e2e binary using TEST_TAGS (includes sqlite)
- Simplify CI workflow: remove manual app.ini, server start, and
  redundant build steps
- Rename all env vars to use GITEA_TEST_E2E_* prefix
- Rename test user from "e2e" to "e2e-user"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
silverwindandClaude Opus 4.6 committed 2026-02-20 03:59:33 +01:00
1 parent 6f0497a894
commit f6037c90d3
12 files changed
+87 -106

No files matched your search

+4 -3
View File
@@ -1,7 +1,8 @@
declare namespace NodeJS {
interface ProcessEnv {
E2E_USER: string;
E2E_PASSWORD: string;
E2E_URL: string;
GITEA_TEST_E2E_USER: string;
GITEA_TEST_E2E_EMAIL: string;
GITEA_TEST_E2E_PASSWORD: string;
GITEA_TEST_E2E_URL: string;
}
}
+2 -2
View File
@@ -6,9 +6,9 @@ test('create a milestone', async ({page}) => {
const repoName = `e2e-milestone-${Date.now()}`;
await login(page);
await apiCreateRepo(page.request, {name: repoName});
await page.goto(`/${env.E2E_USER}/${repoName}/milestones/new`);
await page.goto(`/${env.GITEA_TEST_E2E_USER}/${repoName}/milestones/new`);
await page.getByPlaceholder('Title').fill('Test Milestone');
await page.getByRole('button', {name: 'Create Milestone'}).click();
await expect(page.locator('.milestone-list')).toContainText('Test Milestone');
await apiDeleteRepo(page.request, env.E2E_USER, repoName);
await apiDeleteRepo(page.request, env.GITEA_TEST_E2E_USER, repoName);
});
+2 -2
View File
@@ -5,7 +5,7 @@ import {apiCreateRepo, apiDeleteRepo} from './utils.ts';
test('README renders on repository page', async ({page}) => {
const repoName = `e2e-readme-${Date.now()}`;
await apiCreateRepo(page.request, {name: repoName});
await page.goto(`/${env.E2E_USER}/${repoName}`);
await page.goto(`/${env.GITEA_TEST_E2E_USER}/${repoName}`);
await expect(page.locator('#readme')).toContainText(repoName);
await apiDeleteRepo(page.request, env.E2E_USER, repoName);
await apiDeleteRepo(page.request, env.GITEA_TEST_E2E_USER, repoName);
});
+2 -2
View File
@@ -51,13 +51,13 @@ test('register then login', async ({page}) => {
// delete via API because of issues related to form-fetch-action
const response = await page.request.delete(`/api/v1/admin/users/${username}?purge=true`, {
headers: {Authorization: `Basic ${btoa(`${env.E2E_USER}:${env.E2E_PASSWORD}`)}`},
headers: {Authorization: `Basic ${btoa(`${env.GITEA_TEST_E2E_USER}:${env.GITEA_TEST_E2E_PASSWORD}`)}`},
});
expect(response.ok()).toBeTruthy();
});
test('register with existing username shows error', async ({page}) => {
await page.getByLabel('Username').fill('e2e');
await page.getByLabel('Username').fill('e2e-user');
await page.getByLabel('Email Address').fill('e2e-duplicate@e2e.gitea.com');
await page.getByLabel('Password', {exact: true}).fill('password123!');
await page.getByLabel('Confirm Password').fill('password123!');
+2 -2
View File
@@ -8,6 +8,6 @@ test('create a repository', async ({page}) => {
await page.goto('/repo/create');
await page.locator('input[name="repo_name"]').fill(repoName);
await page.getByRole('button', {name: 'Create Repository'}).click();
await page.waitForURL(new RegExp(`/${env.E2E_USER}/${repoName}$`));
await apiDeleteRepo(page.request, env.E2E_USER, repoName);
await page.waitForURL(new RegExp(`/${env.GITEA_TEST_E2E_USER}/${repoName}$`));
await apiDeleteRepo(page.request, env.GITEA_TEST_E2E_USER, repoName);
});
+3 -3
View File
@@ -3,11 +3,11 @@ import {expect} from '@playwright/test';
import type {APIRequestContext, Locator, Page} from '@playwright/test';
export function apiBaseUrl() {
return env.E2E_URL?.replace(/\/$/g, '');
return env.GITEA_TEST_E2E_URL?.replace(/\/$/g, '');
}
export function apiHeaders() {
return {Authorization: `Basic ${globalThis.btoa(`${env.E2E_USER}:${env.E2E_PASSWORD}`)}`};
return {Authorization: `Basic ${globalThis.btoa(`${env.GITEA_TEST_E2E_USER}:${env.GITEA_TEST_E2E_PASSWORD}`)}`};
}
async function apiRetry(fn: () => Promise<{ok: () => boolean; status: () => number; text: () => Promise<string>}>, label: string) {
@@ -48,7 +48,7 @@ export async function clickDropdownItem(page: Page, trigger: Locator, itemText:
await page.getByText(itemText).click();
}
export async function login(page: Page, username = env.E2E_USER, password = env.E2E_PASSWORD) {
export async function login(page: Page, username = env.GITEA_TEST_E2E_USER, password = env.GITEA_TEST_E2E_PASSWORD) {
await page.goto('/user/login');
await page.getByLabel('Username or Email Address').fill(username);
await page.getByLabel('Password').fill(password);