diff --git a/app/pages/index.vue b/app/pages/index.vue index 97eef99..7998050 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -255,7 +255,14 @@ var w = { to: `/account`, }, ); - let n = X.value; + let n = X.value, + personStatus = Number(n?.person?.status || 0), + companyStatus = Number(n?.company?.status || 0), + statusLabels = { + 2: `认证未通过`, + 3: `待审核`, + 4: `待核验`, + }; return ( n ? (t.push( @@ -270,10 +277,10 @@ var w = { value: n.person?.card_name || `已认证`, kind: n.person?.card_name ? `name` : void 0, } - : n.person?.status + : personStatus ? { label: `实名认证`, - value: `审核中`, + value: statusLabels[personStatus] || `待核验`, } : { label: `实名认证`, @@ -284,18 +291,23 @@ var w = { ), n.certification_company_open === 1 ? t.push( - n.company?.status + companyStatus === 1 ? { label: `组织机构认证`, value: n.company?.company || `已认证`, kind: n.company?.company ? `text` : void 0, } - : { - label: `组织机构认证`, - value: `未认证`, - action: `去认证`, - to: `/account/realname`, - }, + : companyStatus + ? { + label: `组织机构认证`, + value: statusLabels[companyStatus] || `待核验`, + } + : { + label: `组织机构认证`, + value: `未认证`, + action: `去认证`, + to: `/account/realname`, + }, ) : t.push({ label: `组织机构认证`, diff --git a/tests/review-certification-summary.e2e.test.mjs b/tests/review-certification-summary.e2e.test.mjs new file mode 100644 index 0000000..f54e9a9 --- /dev/null +++ b/tests/review-certification-summary.e2e.test.mjs @@ -0,0 +1,160 @@ +/** + * Certification summaries must preserve the API state instead of treating every nonzero status as approval. + * Gap: home and the real-name page were never exercised with the same failed/submitted/review payload. + * Only the external HTTP backend is replaced; login, home tiles, real-name routes and certification forms stay real. + */ +import assert from "node:assert/strict"; +import test from "node:test"; +import { + appOrigin, + backendOrigin, + eventually, + login, + scenario, +} from "./helpers/console-browser.mjs"; + +const states = [ + { name: "failed", status: "2", summary: /未通过|失败/, application: true }, + { name: "submitted", status: "4", summary: /待核验/, continuation: true }, + { name: "under review", status: "3", summary: /待审核|审核中/ }, + { name: "approved", status: "1", approved: true }, + { name: "not applied", status: "0", application: true }, + { name: "without records", application: true }, +]; + +for (const state of states) + test( + `home and real-name actions agree when certification is ${state.name}`, + { timeout: 30000 }, + (t) => + scenario(t, {}, async (page) => { + const requests = []; + await page + .context() + .route(`${backendOrigin}/console/v1/certification/**`, (route) => { + const request = route.request(); + requests.push({ + method: request.method(), + path: new URL(request.url()).pathname, + authenticated: Boolean(request.headers().authorization), + }); + if (!request.url().endsWith("/info")) return route.fallback(); + return route.fulfill({ + json: { + status: 200, + msg: "", + data: { + certification_open: 1, + certification_company_open: 1, + certification_company_need_person: 0, + certification_upload: 0, + is_certification: state.approved ? 1 : 0, + ...(state.status === undefined + ? {} + : { + person: { + status: state.status, + card_name: "本地认证用户", + auth_fail: state.status === "2" ? "本地驳回原因" : "", + }, + company: { + status: state.status, + company: "本地认证企业", + auth_fail: state.status === "2" ? "本地驳回原因" : "", + }, + }), + }, + }, + headers: { "Access-Control-Allow-Origin": "*" }, + }); + }); + await login(page, "/"); + const tile = (label) => + page.locator(".tile").filter({ + has: page.locator("dt").getByText(label, { exact: true }), + }); + const person = tile("实名认证"); + const company = tile("组织机构认证"); + await eventually( + () => person.locator("dd").innerText(), + (text) => text.trim().length > 0, + "The certification summary must finish loading", + ); + const home = { + person: await person.locator("dd").innerText(), + company: await company.locator("dd").innerText(), + }; + if (state.summary) { + assert.match(home.person, state.summary); + assert.match(home.company, state.summary); + } else if (state.approved) { + assert.equal(await person.getByRole("button").count(), 1); + assert.equal(await company.getByRole("button").count(), 1); + assert.doesNotMatch(home.company, /去认证|未通过|待审核|待核验/); + } else { + assert.equal( + await person.getByRole("link", { name: "去认证" }).count(), + 1, + ); + assert.equal( + await company.getByRole("link", { name: "去认证" }).count(), + 1, + ); + } + + if (state.application && state.status !== "2") + await person.getByRole("link", { name: "去认证" }).click(); + else await page.goto(`${appOrigin}/account/realname`); + const personApplication = page.getByPlaceholder("请输入真实姓名", { + exact: true, + }); + const continuePerson = page.getByRole("button", { + name: "继续扫码核验", + exact: true, + }); + const continueCompany = page.getByRole("button", { + name: "继续企业核验", + exact: true, + }); + if (state.application) { + await personApplication.waitFor(); + await page + .getByRole("tab", { name: "企业认证", exact: true }) + .click(); + await page.getByPlaceholder("营业执照上的企业全称").waitFor(); + } else if (state.continuation) { + await continuePerson.waitFor(); + assert.equal(await continuePerson.isEnabled(), true); + assert.equal(await continueCompany.isEnabled(), true); + assert.equal(await personApplication.count(), 0); + } else { + await page + .getByText( + state.approved + ? "已完成实名认证" + : "资料正在审核,请等待审核结果。", + { + exact: true, + }, + ) + .waitFor(); + assert.equal(await personApplication.count(), 0); + assert.equal(await continuePerson.count(), 0); + assert.equal(await continueCompany.count(), 0); + } + assert.equal(requests.length, 2); + assert.ok(requests.every((request) => request.authenticated)); + assert.ok( + requests.every( + (request) => + request.method === "GET" && request.path.endsWith("/info"), + ), + ); + return { + home, + applicationAvailable: Boolean(state.application), + verificationContinuationAvailable: Boolean(state.continuation), + authenticatedReadOnlyCertificationRequests: requests, + }; + }), + );