diff --git a/Makefile b/Makefile index 11633f84ab..7742e91132 100644 --- a/Makefile +++ b/Makefile @@ -928,7 +928,7 @@ docker: .PHONY: e2e-test e2e-test: @echo "正在启动E2E-TEST..." - @./run-e2e-tests.sh + @./tests/e2e/run-e2e-tests.sh # This endif closes the if at the top of the file diff --git a/tests/e2e/.dockerignore b/tests/e2e/.dockerignore new file mode 100644 index 0000000000..f0d0cf7e83 --- /dev/null +++ b/tests/e2e/.dockerignore @@ -0,0 +1,11 @@ +# 1. 忽略 Node.js 依赖目录 +/node_modules +# 2. 忽略本地的测试报告和结果 +/reports +/test-data +/test-artifacts +/Readme.md +/utils_e2e.ts +/utils_e2e_test.go +/e2e_test.go + diff --git a/docker-compose.test.yml b/tests/e2e/docker-compose.test.yml similarity index 87% rename from docker-compose.test.yml rename to tests/e2e/docker-compose.test.yml index abe4a73aee..22fb127282 100644 --- a/docker-compose.test.yml +++ b/tests/e2e/docker-compose.test.yml @@ -8,7 +8,7 @@ services: # pull_policy: always # 我们告诉 Compose 在本地构建 build: - context: . + context: ../.. dockerfile: docker/Dockerfile.devstar # image: devstar-e2e-test:latest # @@ -20,8 +20,8 @@ services: # 挂载 Docker Socket,允许 DevStar 创建 Devcontainer - /var/run/docker.sock:/var/run/docker.sock # 挂载数据卷,使用相对路径,保证测试环境可移植 - - ./tests/e2e/test-data/devstar_data:/var/lib/gitea - - ./tests/e2e/test-data/devstar_data:/etc/gitea + - ./test-data/devstar_data:/var/lib/gitea + - ./test-data/devstar_data:/etc/gitea # 健康检查。test-runner 会等待这个检查通过 healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:3000/ || exit 1"] @@ -32,7 +32,7 @@ services: test-runner: # 从 'tests/' 目录下的 Dockerfile 构建 build: - context: ./tests/e2e + context: . # 等待 devstar 的 "healthcheck" 通过后,才启动 depends_on: devstar: @@ -44,7 +44,7 @@ services: # 也挂载 Docker Socket - /var/run/docker.sock:/var/run/docker.sock # 将测试报告写回到宿主机的 ./reports 目录 - - ./tests/e2e/reports:/app/playwright-report + - ./reports:/app/playwright-report # 覆盖默认命令,强制运行测试并生成我们想要的报告 command: > npx playwright test diff --git a/tests/e2e/global-setup.ts b/tests/e2e/global-setup.ts index 42ec6d0ee2..11163b7e89 100644 --- a/tests/e2e/global-setup.ts +++ b/tests/e2e/global-setup.ts @@ -9,31 +9,21 @@ } - - const browser = await chromium.launch(); const page = await browser.newPage(); try { - await page.goto(baseURL!, { timeout: 15000 }); - - console.log('[GlobalSetup] 检测到安装界面!正在开始自动化安装...'); - - await page.getByRole('textbox', { name: 'Server Domain *' }).click(); await page.getByRole('textbox', { name: 'Server Domain *' }).fill('172.17.0.1'); await page.getByRole('textbox', { name: 'Gitea Base URL *' }).click(); await page.getByRole('textbox', { name: 'Gitea Base URL *' }).fill('http://172.17.0.1:80'); await page.getByText('Server and Third-Party Service Settings').click(); await page.getByRole('checkbox', { name: 'Enable user sign-in via Wechat QR Code.' }).uncheck(); - await page.getByRole('checkbox', { name: 'Require a CAPTCHA for user' }).uncheck(); - - await page.getByText('Administrator Account Settings').click(); await page.getByRole('textbox', { name: 'Administrator Username' }).click(); await page.getByRole('textbox', { name: 'Administrator Username' }).fill('testuser'); @@ -43,23 +33,11 @@ await page.getByRole('textbox', { name: 'Password', exact: true }).fill('12345678'); await page.getByRole('textbox', { name: 'Confirm Password' }).click(); await page.getByRole('textbox', { name: 'Confirm Password' }).fill('12345678'); - - - - - - await page.getByRole('button', { name: 'Install Gitea'}).click(); // 'Install' (英文) 或 '安装' (中文) 都能匹配 - - + await page.getByRole('button', { name: 'Install Gitea'}).click(); // 'Install' (英文) 或 '安装' (中文) 都能匹配 // 4. 等待安装完成 - - await page.waitForTimeout(240*1000); - - console.log('[GlobalSetup] 安装成功!'); - - - + await page.waitForTimeout(240*1000); + console.log('[GlobalSetup] 安装成功!'); } catch (error) { // 5. 截图并报错 diff --git a/run-e2e-tests.sh b/tests/e2e/run-e2e-tests.sh similarity index 86% rename from run-e2e-tests.sh rename to tests/e2e/run-e2e-tests.sh index debe96fc29..231618e51d 100755 --- a/run-e2e-tests.sh +++ b/tests/e2e/run-e2e-tests.sh @@ -3,10 +3,16 @@ # 它会处理所有清理、权限、拉取和执行工作 # 任何命令失败立即退出 set -e +# +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +# +PROJECT_ROOT=$( cd -- "$SCRIPT_DIR/../.." &> /dev/null && pwd ) +# +cd "$PROJECT_ROOT" echo "===== [1/5] 清理旧的测试环境... =====" # 彻底销毁旧的 compose 环境,-v 会删除关联的数据卷 -docker compose -f docker-compose.test.yml down -v --remove-orphans +docker compose -f tests/e2e/docker-compose.test.yml down -v --remove-orphans docker image prune -f docker builder prune -f # 清理并重建报告和数据目录 @@ -36,7 +42,7 @@ echo "===== [4/5] 启动并运行测试... =====" # --build: 确保 test-runner 镜像是最新的 # --abort-on-container-exit: 如果 devstar 挂了, 测试立即停止 # --exit-code-from test-runner: 运行结束后,将 test-runner 的退出码(0=成功, 1=失败)作为本命令的退出码 -docker compose -f docker-compose.test.yml up \ +docker compose -f ./tests/e2e/docker-compose.test.yml up \ --build \ --abort-on-container-exit \ --exit-code-from test-runner diff --git a/tests/e2e/utils_e2e.ts b/tests/e2e/utils_e2e.ts index 6eaef4cb10..3e92e0d3c2 100644 --- a/tests/e2e/utils_e2e.ts +++ b/tests/e2e/utils_e2e.ts @@ -22,7 +22,7 @@ export async function login_user(browser: Browser, workerInfo: WorkerInfo, user: await page.locator('input[name=password]').fill(LOGIN_PASSWORD); await page.click('form button.ui.primary.button:visible'); - //await page.waitForLoadState('networkidle'); // eslint-disable-line playwright/no-networkidle + await page.waitForLoadState('networkidle'); // eslint-disable-line playwright/no-networkidle expect(page.url(), {message: `Failed to login user ${user}`}).toBe(`${workerInfo.project.use.baseURL}/`); diff --git a/tests/sqlite.ini.tmpl b/tests/sqlite.ini.tmpl index 31ac00c070..938f203633 100644 --- a/tests/sqlite.ini.tmpl +++ b/tests/sqlite.ini.tmpl @@ -1,5 +1,5 @@ APP_NAME = Gitea: Git with a cup of tea -RUN_MODE = dev +RUN_MODE = prod [database] DB_TYPE = sqlite3