Scert/frontend/src/views/Dashboard/SettingsModal.test.js

131 lines
5.3 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import { readFileSync } from "node:fs";
import { parse, compileScript, compileTemplate } from "@vue/compiler-sfc";
import { useSettingsModal } from "./SettingsModal.js";
import { settingsPayload } from "./SettingsPayload.js";
const source = readFileSync(new URL("./SettingsModal.vue", import.meta.url), "utf8");
test("邮件通知组件只保留 SMTP 通道和收件人配置", () => {
const mailSource = readFileSync(new URL("./MailNotificationSettings.vue", import.meta.url), "utf8");
const { descriptor, errors } = parse(mailSource);
assert.deepEqual(errors, []);
const script = compileScript(descriptor, { id: "mail-settings-test" });
const compiled = compileTemplate({
source: descriptor.template.content,
filename: "MailNotificationSettings.vue",
id: "mail-settings-test",
compilerOptions: { bindingMetadata: script.bindings },
});
assert.deepEqual(compiled.errors, []);
for (const field of ["smtp_enabled", "smtp_password"]) {
assert.equal(mailSource.split(`v-model="notification.${field}"`).length - 1, 1);
}
assert.doesNotMatch(mailSource, /HTTP 接口|sender_email|notification\.http_enabled/);
assert.equal(mailSource.split(':value="notification.recipients.join').length - 1, 1);
assert.match(source, /<MailNotificationSettings :notification="settingsForm.notification"/);
assert.doesNotMatch(mailSource, /role="tab"/);
});
test("邮件设置只提交 SMTP 配置,不提交 HTTP 和自定义发件人", () => {
const notification = {
http_enabled: true,
smtp_enabled: true,
endpoint: "https://mail.example.com",
sender_email: "sender@example.com",
recipients: ["recipient@example.com"],
smtp_host: "smtp.example.com",
smtp_port: 587,
smtp_username: "notify:system@example.com",
smtp_password: "",
smtp_mode: "starttls",
smtp_credential_configured: true,
};
const payload = settingsPayload({ notification }).notification;
assert.deepEqual(payload, {
smtp_enabled: true,
smtp_host: "smtp.example.com",
smtp_port: 587,
smtp_username: "notify:system@example.com",
smtp_password: "",
smtp_mode: "starttls",
recipients: ["recipient@example.com"],
});
assert.equal(notification.http_enabled, true);
assert.equal(notification.sender_email, "sender@example.com");
});
test("通知字段校验失败时切换到合并后的邮件通知页", async () => {
let saved = false;
const state = useSettingsModal(() => { saved = true; });
const sections = [];
const invalid = {
closest: () => ({ dataset: { settingsSection: "notification" } }),
focus: () => sections.push(state.activeSection.value),
reportValidity: () => sections.push(state.activeSection.value),
};
await state.submitSettings({ currentTarget: { querySelector: () => invalid } });
assert.equal(saved, false);
assert.deepEqual(sections, ["notification", "notification"]);
});
test("settings.componentCompilesWithFourAccessiblePanels", () => {
const { descriptor, errors } = parse(source);
assert.deepEqual(errors, []);
const script = compileScript(descriptor, { id: "settings-test" });
assert.ok(script.bindings.saveSettings);
const result = compileTemplate({
source: descriptor.template.content,
filename: "SettingsModal.vue",
id: "settings-test",
compilerOptions: { bindingMetadata: script.bindings },
});
assert.deepEqual(result.errors, []);
assert.equal((source.match(/role="tab"/g) || []).length, 4);
assert.equal((source.match(/role="tabpanel"/g) || []).length, 4);
assert.match(source, /id="settings-tab-notification"/);
assert.doesNotMatch(source, /settings-tab-(http|smtp)/);
assert.match(source, /:required="field.required && dnsVerificationRequired"/);
assert.match(source, /<form novalidate @submit.prevent="submitSettings">/);
assert.ok(!source.includes('<p class="field-hint"'));
});
test("settings.invalidHiddenFieldOpensItsPanelBeforeReporting", async () => {
let saved = false;
const calls = [];
const state = useSettingsModal(() => { saved = true; });
const invalid = {
closest: () => ({ dataset: { settingsSection: "acme" } }),
focus: () => calls.push(["focus", state.activeSection.value]),
reportValidity: () => calls.push(["report", state.activeSection.value]),
};
await state.submitSettings({ currentTarget: { querySelector: () => invalid } });
assert.equal(saved, false);
assert.deepEqual(calls, [["focus", "acme"], ["report", "acme"]]);
});
test("settings.validFormUsesExistingSaveFlow", async () => {
let count = 0;
const state = useSettingsModal(async () => { count += 1; });
await state.submitSettings({ currentTarget: { querySelector: () => null } });
assert.equal(count, 1);
});
test("settings.keyboardNavigationWrapsAndFocusesTabs", async () => {
const state = useSettingsModal(() => {});
const focused = [];
const event = {
key: "ArrowLeft",
preventDefault() {},
currentTarget: { parentElement: {
querySelector: (selector) => ({ focus: () => focused.push(selector) }),
} },
};
await state.navigateTabs(event);
assert.equal(state.activeSection.value, "notification");
assert.deepEqual(focused, ["#settings-tab-notification"]);
await state.navigateTabs({ ...event, key: "Home" });
assert.equal(state.activeSection.value, "service");
});