From feda065b45bc7ccc85ddc67967faea00ac1e7a7d Mon Sep 17 00:00:00 2001 From: xuans Date: Fri, 25 Sep 2026 02:33:06 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AF=81=E4=B9=A6=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E5=A4=B1=E8=B4=A5=E5=90=8E=E7=8A=B6=E6=80=81=E5=88=B7?= =?UTF-8?q?=E6=96=B0=E5=8F=8A=E5=A4=B1=E8=B4=A5=E5=AE=A1=E8=AE=A1=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/views/Dashboard/Dashboard.js | 6 ++- .../src/views/Dashboard/Dashboard.test.js | 52 ++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/frontend/src/views/Dashboard/Dashboard.js b/frontend/src/views/Dashboard/Dashboard.js index 6af2df5..4e075d3 100644 --- a/frontend/src/views/Dashboard/Dashboard.js +++ b/frontend/src/views/Dashboard/Dashboard.js @@ -125,6 +125,7 @@ export function useDashboard() { failed: "失败", cancelled: "已取消", }; + taskStatusLabels.error = taskStatusLabels.failed; const taskTypeLabels = { management_renewal: "管理证书续期", certificate_issue: "申请证书", @@ -687,9 +688,12 @@ export function useDashboard() { const result = await response.json().catch(() => ({})); if (!response.ok) throw new Error(result.error || "域名操作失败"); notice.value = successMessage; - await loadData(); } catch (err) { error.value = err.message || "域名操作失败"; + } finally { + const actionError = error.value; + await loadData(); + if (actionError) error.value = actionError; } } function issueDomain(item) { diff --git a/frontend/src/views/Dashboard/Dashboard.test.js b/frontend/src/views/Dashboard/Dashboard.test.js index bb198c5..50db230 100644 --- a/frontend/src/views/Dashboard/Dashboard.test.js +++ b/frontend/src/views/Dashboard/Dashboard.test.js @@ -515,4 +515,54 @@ test("sshKeyModal.compilesAndPreservesCredentialFields", async () => { } const css = await readFile(new URL("./SSHKeyModal.css", import.meta.url), "utf8"); assert.match(css, /\.ssh-key-modal\s*\{[^}]*overflow:\s*auto;/); -}); \ No newline at end of file +});test("domainAction.refreshesPersistedFailureWithoutLosingError", async (t) => { + let issued = false; + const { state } = await mountComposable(t, useDashboard, async (path) => { + if (path.endsWith("/issue")) { + issued = true; + return Response.json({ error: "test-issue-failure" }, { status: 502 }); + } + if (path.startsWith("/api/v1/tasks?")) { + return Response.json({ items: issued ? [{ id: "task-1", status: "failed" }] : [] }); + } + return Response.json({ items: [] }); + }); + await state.issueDomain({ id: "domain-1", name: "example.test" }); + assert.equal(state.error.value, "test-issue-failure"); + assert.equal(state.notice.value, ""); + assert.deepEqual(state.tasks.value, [{ id: "task-1", status: "failed" }]); + assert.equal(state.displayLabel(state.taskStatusLabels, "error"), state.taskStatusLabels.failed); +}); + +test("domainAction.preservesOriginalErrorWhenRefreshAlsoFails", async (t) => { + let issued = false; + const { state } = await mountComposable(t, useDashboard, async (path) => { + if (path.endsWith("/issue")) { + issued = true; + return Response.json({ error: "test-original-failure" }, { status: 502 }); + } + if (issued) return Response.json({ error: "test-refresh-failure" }, { status: 503 }); + return Response.json({ items: [] }); + }); + await state.issueDomain({ id: "domain-1", name: "example.test" }); + assert.equal(state.error.value, "test-original-failure"); + assert.equal(state.loading.value, false); +}); + +test("domainAction.refreshesSuccessfulResultAndRetainsNotice", async (t) => { + let completed = false; + const { state } = await mountComposable(t, useDashboard, async (path) => { + if (path.endsWith("/certificate/validate")) { + completed = true; + return Response.json({ valid: true }); + } + if (path.startsWith("/api/v1/tasks?")) { + return Response.json({ items: completed ? [{ id: "task-2", status: "success" }] : [] }); + } + return Response.json({ items: [] }); + }); + await state.validateDomain({ id: "domain-1", name: "example.test" }); + assert.equal(state.error.value, ""); + assert.match(state.notice.value, /example\.test/); + assert.deepEqual(state.tasks.value, [{ id: "task-2", status: "success" }]); +});