mirror of
https://github.com/go-gitea/gitea.git
synced 2026-04-19 10:23:19 +02:00
add 6 new e2e tests and tighten timeouts
This commit is contained in:
parent
4af15206cd
commit
2314ea3194
@ -7,16 +7,15 @@ export default defineConfig({
|
||||
testMatch: /.*\.test\.ts/,
|
||||
forbidOnly: Boolean(env.CI),
|
||||
reporter: 'list',
|
||||
timeout: env.CI ? 30000 : 10000,
|
||||
timeout: env.CI ? 6000 : 2000,
|
||||
expect: {
|
||||
timeout: env.CI ? 15000 : 5000,
|
||||
timeout: env.CI ? 3000 : 1000,
|
||||
},
|
||||
use: {
|
||||
baseURL: env.E2E_URL?.replace?.(/\/$/g, '') || 'http://localhost:3000',
|
||||
baseURL: env.E2E_URL?.replace?.(/\/$/g, ''),
|
||||
locale: 'en-US',
|
||||
trace: 'off',
|
||||
screenshot: 'off',
|
||||
video: 'off',
|
||||
actionTimeout: env.CI ? 3000 : 1000,
|
||||
navigationTimeout: env.CI ? 6000 : 2000,
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
|
||||
17
tests/e2e/explore.test.ts
Normal file
17
tests/e2e/explore.test.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import {test, expect} from '@playwright/test';
|
||||
|
||||
test('explore repositories', async ({page}) => {
|
||||
await page.goto('/explore/repos');
|
||||
await expect(page.getByPlaceholder('Search repos…')).toBeVisible();
|
||||
await expect(page.getByRole('link', {name: 'Repositories'})).toBeVisible();
|
||||
});
|
||||
|
||||
test('explore users', async ({page}) => {
|
||||
await page.goto('/explore/users');
|
||||
await expect(page.getByPlaceholder('Search users…')).toBeVisible();
|
||||
});
|
||||
|
||||
test('explore organizations', async ({page}) => {
|
||||
await page.goto('/explore/organizations');
|
||||
await expect(page.getByPlaceholder('Search orgs…')).toBeVisible();
|
||||
});
|
||||
16
tests/e2e/milestone.test.ts
Normal file
16
tests/e2e/milestone.test.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {env} from 'node:process';
|
||||
import {test, expect} from '@playwright/test';
|
||||
import {login, createRepoApi, deleteRepoApi} from './utils.ts';
|
||||
|
||||
test('create a milestone', async ({page}) => {
|
||||
const repoName = `e2e-milestone-${Date.now()}`;
|
||||
await login(page);
|
||||
await createRepoApi(page.request, {name: repoName});
|
||||
await page.goto(`/${env.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');
|
||||
|
||||
// cleanup
|
||||
await deleteRepoApi(page.request, env.E2E_USER!, repoName);
|
||||
});
|
||||
14
tests/e2e/org.test.ts
Normal file
14
tests/e2e/org.test.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {test, expect} from '@playwright/test';
|
||||
import {login, deleteOrgApi} from './utils.ts';
|
||||
|
||||
test('create an organization', async ({page}) => {
|
||||
const orgName = `e2e-org-${Date.now()}`;
|
||||
await login(page);
|
||||
await page.goto('/org/create');
|
||||
await page.getByLabel('Organization Name').fill(orgName);
|
||||
await page.getByRole('button', {name: 'Create Organization'}).click();
|
||||
await expect(page).toHaveURL(new RegExp(`/org/${orgName}`));
|
||||
|
||||
// cleanup
|
||||
await deleteOrgApi(page.request, orgName);
|
||||
});
|
||||
13
tests/e2e/readme.test.ts
Normal file
13
tests/e2e/readme.test.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import {env} from 'node:process';
|
||||
import {test, expect} from '@playwright/test';
|
||||
import {createRepoApi, deleteRepoApi} from './utils.ts';
|
||||
|
||||
test('README renders on repository page', async ({page}) => {
|
||||
const repoName = `e2e-readme-${Date.now()}`;
|
||||
await createRepoApi(page.request, {name: repoName});
|
||||
await page.goto(`/${env.E2E_USER}/${repoName}`);
|
||||
await expect(page.locator('#readme')).toContainText(repoName);
|
||||
|
||||
// cleanup
|
||||
await deleteRepoApi(page.request, env.E2E_USER!, repoName);
|
||||
});
|
||||
15
tests/e2e/repo.test.ts
Normal file
15
tests/e2e/repo.test.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import {env} from 'node:process';
|
||||
import {test, expect} from '@playwright/test';
|
||||
import {login, deleteRepoApi} from './utils.ts';
|
||||
|
||||
test('create a repository', async ({page}) => {
|
||||
const repoName = `e2e-repo-${Date.now()}`;
|
||||
await login(page);
|
||||
await page.goto('/repo/create');
|
||||
await page.getByLabel('Repository Name').fill(repoName);
|
||||
await page.getByRole('button', {name: 'Create Repository'}).click();
|
||||
await expect(page).toHaveURL(new RegExp(`/${env.E2E_USER}/${repoName}$`));
|
||||
|
||||
// cleanup
|
||||
await deleteRepoApi(page.request, env.E2E_USER!, repoName);
|
||||
});
|
||||
16
tests/e2e/user-settings.test.ts
Normal file
16
tests/e2e/user-settings.test.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {test, expect} from '@playwright/test';
|
||||
import {login} from './utils.ts';
|
||||
|
||||
test('update profile biography', async ({page}) => {
|
||||
const bio = `e2e-bio-${Date.now()}`;
|
||||
await login(page);
|
||||
await page.goto('/user/settings');
|
||||
await page.getByLabel('Biography').fill(bio);
|
||||
await page.getByRole('button', {name: 'Update Profile'}).click();
|
||||
await expect(page.getByLabel('Biography')).toHaveValue(bio);
|
||||
|
||||
// cleanup: clear the biography
|
||||
await page.getByLabel('Biography').fill('');
|
||||
await page.getByRole('button', {name: 'Update Profile'}).click();
|
||||
await expect(page.getByLabel('Biography')).toHaveValue('');
|
||||
});
|
||||
@ -1,6 +1,47 @@
|
||||
import {env} from 'node:process';
|
||||
import {expect} from '@playwright/test';
|
||||
import type {Locator, Page} from '@playwright/test';
|
||||
import type {APIRequestContext, Locator, Page} from '@playwright/test';
|
||||
|
||||
export function apiBaseUrl() {
|
||||
return env.E2E_URL?.replace(/\/$/g, '') || 'http://localhost:3000';
|
||||
}
|
||||
|
||||
export function apiHeaders() {
|
||||
return {Authorization: `Basic ${globalThis.btoa(`${env.E2E_USER}:${env.E2E_PASSWORD}`)}`};
|
||||
}
|
||||
|
||||
async function apiRetry(fn: () => Promise<{ok: () => boolean; status: () => number; text: () => Promise<string>}>, label: string) {
|
||||
const maxAttempts = 5;
|
||||
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||
const response = await fn();
|
||||
if (response.ok()) return;
|
||||
if (response.status() === 500 && attempt < maxAttempts - 1) {
|
||||
const jitter = Math.random() * 500;
|
||||
await new Promise((resolve) => globalThis.setTimeout(resolve, 1000 * (attempt + 1) + jitter));
|
||||
continue;
|
||||
}
|
||||
throw new Error(`${label} failed: ${response.status()} ${await response.text()}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function createRepoApi(requestContext: APIRequestContext, {name, autoInit = true}: {name: string; autoInit?: boolean}) {
|
||||
await apiRetry(() => requestContext.post(`${apiBaseUrl()}/api/v1/user/repos`, {
|
||||
headers: apiHeaders(),
|
||||
data: {name, auto_init: autoInit},
|
||||
}), 'createRepoApi');
|
||||
}
|
||||
|
||||
export async function deleteRepoApi(requestContext: APIRequestContext, owner: string, name: string) {
|
||||
await apiRetry(() => requestContext.delete(`${apiBaseUrl()}/api/v1/repos/${owner}/${name}`, {
|
||||
headers: apiHeaders(),
|
||||
}), 'deleteRepoApi');
|
||||
}
|
||||
|
||||
export async function deleteOrgApi(requestContext: APIRequestContext, name: string) {
|
||||
await apiRetry(() => requestContext.delete(`${apiBaseUrl()}/api/v1/orgs/${name}`, {
|
||||
headers: apiHeaders(),
|
||||
}), 'deleteOrgApi');
|
||||
}
|
||||
|
||||
export async function clickDropdownItem(page: Page, trigger: Locator, itemText: string) {
|
||||
await trigger.click();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user