Scert/frontend/src/views/SetupWizard/SetupWizard.test.js

193 lines
7.8 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import { nextTick } from "vue";
import { useSetupWizard } from "./SetupWizard.js";
import { aliyunProvider, deferred, mountComposable, verifiedResponse } from "../../test-support/mount.js";
test("全新初始化默认选择阿里云", async (t) => {
const { state } = await mountComposable(t, () => useSetupWizard({ status: {} }, () => {}),
async () => Response.json({ items: [aliyunProvider] }));
assert.equal(state.form.value.dns_provider, "aliyun");
assert.equal(state.form.value.propagation_timeout_secs, 300);
assert.equal(state.form.value.propagation_polling_interval_secs, 5);
});
test("已有初始化服务商选择保持兼容", async (t) => {
const provider = { ...aliyunProvider, id: "cloudflare" };
const { state } = await mountComposable(t, () => useSetupWizard({ status: { dns_provider: "cloudflare" } }, () => {}),
async () => Response.json({ items: [provider, aliyunProvider] }));
assert.equal(state.form.value.dns_provider, "cloudflare");
});
test("邮箱定时同步不能清除步骤校验错误,手动编辑仍可清除", async (t) => {
const { state, runIntervals } = await mountComposable(t,
() => useSetupWizard({ status: { mode: "bootstrap" } }, () => {}),
async () => Response.json({ items: [aliyunProvider] }));
Object.assign(state.form.value, {
admin_username: "test-admin",
admin_password: "TestPass123",
confirm_password: "TestPass123",
web_hostname: "scert.example.test",
});
state.emailInputElement.value = { value: "admin@example.test" };
state.emailAutofillElement.value = { value: "" };
state.handleEmailInput("admin@example.test");
state.handleSubmit();
assert.equal(state.error.value, "请先验证所选数据库的连接和写权限。");
for (let i = 0; i < 8; i += 1) runIntervals();
assert.equal(state.error.value, "请先验证所选数据库的连接和写权限。");
assert.equal(state.currentStep.value, 1);
state.handleEmailInput("changed@example.test");
assert.equal(state.error.value, "");
});
test("自动填充同步新邮箱时保留其他字段的错误", async (t) => {
const { state, runIntervals } = await mountComposable(t,
() => useSetupWizard({ status: {} }, () => {}),
async () => Response.json({ items: [aliyunProvider] }));
state.emailInputElement.value = { value: "" };
state.emailAutofillElement.value = { value: "autofill@example.test" };
state.error.value = "两次输入的超级管理员密码不一致。";
runIntervals();
assert.equal(state.form.value.admin_email, "autofill@example.test");
assert.equal(state.error.value, "两次输入的超级管理员密码不一致。");
});
async function setup(t, request) {
const mounted = await mountComposable(t, () => useSetupWizard({ status: { dns_provider: "aliyun" } }, () => {}),
async (path) => path.endsWith("/providers") ? Response.json({ items: [aliyunProvider] }) : request());
const { state } = mounted;
state.dnsCredentials.value = { access_key_id: "fake-key" };
state.dnsTestDomain.value = "example.test";
await nextTick();
return mounted;
}
test("初始化 DNS 验证显示等待进度,并采用服务端返回的最长等待时间", async (t) => {
const pending = deferred();
const { state, runIntervals, advanceTime } = await setup(t, () => pending.promise);
const task = state.testDNS();
assert.equal(state.dnsTesting.value, true);
assert.equal(state.dnsVerificationElapsedSeconds.value, 0);
assert.equal(state.dnsVerificationTimeoutSeconds.value, 6);
advanceTime(2500);
runIntervals();
assert.equal(state.dnsVerificationElapsedSeconds.value, 2);
pending.resolve(Response.json({
verified: true,
credential_ref: "secret://test/only",
verification_token: "test-token",
expires_at: new Date(Date.now() + 60000).toISOString(),
verification_timeout_secs: 6,
}));
await task;
assert.equal(state.dnsTesting.value, false);
assert.equal(state.dnsVerificationElapsedSeconds.value, 0);
assert.equal(state.dnsVerificationTimeoutSeconds.value, 6);
advanceTime(1000);
runIntervals();
assert.equal(state.dnsVerificationElapsedSeconds.value, 0);
});
test("初始化不接受输入修改前的在途 DNS 响应", async (t) => {
const pending = deferred();
const { state } = await setup(t, () => pending.promise);
const task = state.testDNS();
state.dnsCredentials.value.access_key_id = "changed-key";
await nextTick();
pending.resolve(verifiedResponse());
await task;
assert.equal(state.dnsVerificationValid.value, false);
assert.equal(state.dnsVerification.value, null);
});
test("初始化仅接受最新请求,旧失败不能覆盖新成功", async (t) => {
const first = deferred();
const second = deferred();
let count = 0;
const { state } = await setup(t, () => (++count === 1 ? first.promise : second.promise));
const oldTask = state.testDNS();
const newTask = state.testDNS();
second.resolve(verifiedResponse("new-token"));
await newTask;
first.reject(new Error("旧请求失败"));
await oldTask;
assert.equal(state.dnsVerification.value.verification_token, "new-token");
assert.equal(state.dnsTestError.value, "");
});
test("初始化当前 DNS 成功有效,修改域名立即失效", async (t) => {
const { state } = await setup(t, () => verifiedResponse());
await state.testDNS();
assert.equal(state.dnsVerificationValid.value, true);
state.dnsTestDomain.value = "other.test";
assert.equal(state.dnsVerificationValid.value, false);
});
test("初始化修改 DNS 输入后会停止等待计时器", async (t) => {
const pending = deferred();
const { state, runIntervals, advanceTime } = await setup(t, () => pending.promise);
const task = state.testDNS();
advanceTime(1000);
runIntervals();
assert.equal(state.dnsVerificationElapsedSeconds.value, 1);
state.dnsTestDomain.value = "other.test";
assert.equal(state.dnsTesting.value, false);
assert.equal(state.dnsVerificationElapsedSeconds.value, 0);
advanceTime(1000);
runIntervals();
assert.equal(state.dnsVerificationElapsedSeconds.value, 0);
pending.resolve(verifiedResponse());
await task;
});
test("初始化修改阿里云凭据立即作废旧验证", async (t) => {
const { state } = await setup(t, () => verifiedResponse());
await state.testDNS();
assert.equal(state.dnsVerificationValid.value, true);
state.dnsCredentials.value.access_key_id = "changed-key";
assert.equal(state.dnsVerificationValid.value, false);
assert.equal(state.dnsVerification.value, null);
});
test("初始化卸载后不恢复旧 DNS 验证结果或继续等待计时", async (t) => {
const pending = deferred();
const { state, unmount, runIntervals, advanceTime } = await setup(t, () => pending.promise);
const task = state.testDNS();
advanceTime(1000);
runIntervals();
assert.equal(state.dnsVerificationElapsedSeconds.value, 1);
unmount();
assert.equal(state.dnsVerificationElapsedSeconds.value, 0);
advanceTime(1000);
runIntervals();
assert.equal(state.dnsVerificationElapsedSeconds.value, 0);
pending.resolve(verifiedResponse());
await task;
assert.equal(state.dnsVerification.value, null);
});
test("初始化旧请求结束不清除新请求的加载状态", async (t) => {
const first = deferred();
const second = deferred();
let count = 0;
const { state } = await setup(t, () => (++count === 1 ? first.promise : second.promise));
const oldTask = state.testDNS();
state.dnsTestDomain.value = "other.test";
const newTask = state.testDNS();
first.resolve(verifiedResponse());
await oldTask;
assert.equal(state.dnsTesting.value, true);
assert.equal(state.dnsVerification.value, null);
second.resolve(verifiedResponse("current"));
await newTask;
assert.equal(state.dnsTesting.value, false);
assert.equal(state.dnsVerification.value.verification_token, "current");
});