docs(roadmap): 记下邮箱注册的生产验收,附注册页实拍
CI / backend (push) Canceled after 0s

This commit is contained in:
Steven
2026-11-03 01:06:59 +08:00
parent b5170ad1ce
commit 127303b7aa
3 changed files with 48 additions and 1 deletions
+13 -1
View File
@@ -647,4 +647,16 @@
- `backend/tests/test_email_signup.py`(9 例):真走 SMTP(monkeypatch 记账)、dev echo 不发信、 - `backend/tests/test_email_signup.py`(9 例):真走 SMTP(monkeypatch 记账)、dev echo 不发信、
注册即登录、码用完不能重放、错码/过期、试错上限、邮箱占用、发码节流、弱密码、注册关闭时两条接口都回 2017。 注册即登录、码用完不能重放、错码/过期、试错上限、邮箱占用、发码节流、弱密码、注册关闭时两条接口都回 2017。
- e2e `web/e2e/register.mjs`:登录页进注册页 → 拿码(dev echo)→ 注册 → 落进首页 → 退出用「邮箱 + 密码」登回来 → - e2e `web/e2e/register.mjs`:登录页进注册页 → 拿码(dev echo)→ 注册 → 落进首页 → 退出用「邮箱 + 密码」登回来 →
同一个邮箱再发码回 `2019`。 同一个邮箱再发码回 `2019`。7 项全绿。
- `pytest` 139 passed、`ruff check` / `format --check` 全绿、`tsc --noEmit` 0、`vite build` 通过;
回归 `account.mjs`(14 项)、`knowledge.mjs`、`login-email-smtp.mjs`(15 项,含真发一封测试信)全绿。
### 10.6 上线情况(2026-11-03,commit b5170ad)
- 生产 `/auth/methods` → `{"password":true,"email_password":true,"sms_code":false,"email_register":true}`。
- 已注册的邮箱再发码回 `2019`;未注册的地址 `POST /auth/email/code` 返回 `sent:true`(真走了 126 的 SMTP)。
- 生产登录页出现「用邮箱注册」,注册页渲染正常、控制台零报错(`web/e2e/prod-register-check.mjs`,
截图 `web/e2e/artifacts/prod-register.png`)。
- 生产 env **不带** `EMAIL_CODE_DEV_ECHO`:码只发到邮箱,页面不回显。
- 踩到的坑:dev 库要先 `alembic upgrade head` 到 0011,否则注册接口报
`column "email_verified_at" of relation "app_user" does not exist` 直接 500——迁移写好不等于跑过。
Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

+35
View File
@@ -0,0 +1,35 @@
/**
* 生产上确认注册页真的开出来了(截图留证)。
*
* 只读:填一个邮箱、看页面长什么样,不点「获取验证码」——那会真的发信,
* 而且生产没有 dev echo,码只能到收件人邮箱里。
*/
import { chromium } from "playwright-core";
const WEB = process.env.WEB ?? "http://192.168.8.188:8200";
const OUT = "e2e/artifacts";
const browser = await chromium.launch({
executablePath:
process.env.CHROME ??
`${process.env.LOCALAPPDATA}/ms-playwright/chromium-1223/chrome-win64/chrome.exe`,
});
const page = await browser.newPage({ viewport: { width: 1440, height: 960 } });
const errors = [];
page.on("console", (m) => m.type() === "error" && errors.push(m.text()));
page.on("pageerror", (e) => errors.push(String(e)));
await page.goto(`${WEB}/login`);
await page.waitForSelector("#account");
const hasLink = (await page.getByRole("link", { name: "用邮箱注册" }).count()) > 0;
console.log(`登录页有注册入口:${hasLink}`);
await page.getByRole("link", { name: "用邮箱注册" }).click();
await page.waitForURL("**/register");
await page.waitForSelector("#email");
await page.locator("#email").fill("someone@example.com");
await page.screenshot({ path: `${OUT}/prod-register.png` });
console.log(`控制台报错:${errors.length}`);
await browser.close();
process.exit(hasLink && errors.length === 0 ? 0 : 1);