85 lines
3.1 KiB
TypeScript
85 lines
3.1 KiB
TypeScript
declare const process: { cwd(): string };
|
|
declare function require(name: string): {
|
|
readFileSync?: (path: string, encoding: string) => string;
|
|
join?: (...parts: string[]) => string;
|
|
};
|
|
|
|
const { readFileSync } = require("node:fs");
|
|
const { join } = require("node:path");
|
|
|
|
if (!readFileSync || !join) {
|
|
throw new Error("测试运行环境缺少文件读取能力");
|
|
}
|
|
|
|
const root = process.cwd();
|
|
const view = readFileSync(join(root, "src/views/UsersView.vue"), "utf-8");
|
|
const css = readFileSync(join(root, "src/assets/styles.css"), "utf-8");
|
|
|
|
assertIncludes(view, "view-stack users-page");
|
|
assertIncludes(view, "showUserModal");
|
|
assertIncludes(view, "openCreateModal");
|
|
assertIncludes(view, "closeUserModal");
|
|
assertIncludes(view, "user-list-panel");
|
|
assertIncludes(view, "user-list-header");
|
|
assertIncludes(view, "@click=\"openCreateModal\"");
|
|
assertIncludes(view, "Teleport to=\"body\"");
|
|
assertIncludes(view, "modal-backdrop user-modal-backdrop");
|
|
assertIncludes(view, "profile-modal user-modal");
|
|
assertIncludes(view, "aria-label=\"用户维护\"");
|
|
assertIncludes(view, "user-modal-form");
|
|
assertIncludes(view, "user-modal-fields");
|
|
assertIncludes(view, "user-modal-actions");
|
|
assertIncludes(view, "@click=\"closeUserModal\"");
|
|
assertNotIncludes(view, "<section class=\"panel\">\n <div class=\"panel-header\">\n <div>\n <h2>新增用户</h2>");
|
|
|
|
const pageBlock = cssBlock(".users-page");
|
|
assertIncludes(pageBlock, "gap: 14px;");
|
|
|
|
const listPanelBlock = cssBlock(".user-list-panel");
|
|
assertIncludes(listPanelBlock, "overflow: hidden;");
|
|
|
|
const listHeaderBlock = cssBlock(".user-list-header");
|
|
assertIncludes(listHeaderBlock, "align-items: center;");
|
|
|
|
const modalBlock = cssBlock(".user-modal");
|
|
assertIncludes(modalBlock, "width: min(920px, 100%);");
|
|
assertIncludes(modalBlock, "max-height: min(760px, calc(100vh - 48px));");
|
|
|
|
const modalFormBlock = cssBlock(".user-modal-form");
|
|
assertIncludes(modalFormBlock, "padding: 14px var(--panel-padding) var(--panel-padding);");
|
|
|
|
const modalFieldsBlock = cssBlock(".user-modal-fields");
|
|
assertIncludes(modalFieldsBlock, "grid-template-columns: repeat(4, minmax(0, 1fr));");
|
|
|
|
const modalActionsBlock = cssBlock(".user-modal-actions");
|
|
assertIncludes(modalActionsBlock, "grid-column: 1 / -1;");
|
|
assertIncludes(modalActionsBlock, "justify-content: flex-end;");
|
|
|
|
assertIncludes(css, ".user-modal-fields {\n grid-template-columns: 1fr;");
|
|
assertIncludes(css, ".user-modal-actions {\n justify-content: stretch;");
|
|
|
|
function cssBlock(selector: string): string {
|
|
const pattern = new RegExp(`${escapeRegExp(selector)}\\s*\\{([\\s\\S]*?)\\n\\}`, "m");
|
|
const match = css.match(pattern);
|
|
if (!match) {
|
|
throw new Error(`缺少样式块 ${selector}`);
|
|
}
|
|
return match[1];
|
|
}
|
|
|
|
function assertIncludes(content: string, expected: string): void {
|
|
if (!content.includes(expected)) {
|
|
throw new Error(`期望包含 ${expected}`);
|
|
}
|
|
}
|
|
|
|
function assertNotIncludes(content: string, unexpected: string): void {
|
|
if (content.includes(unexpected)) {
|
|
throw new Error(`不应包含 ${unexpected}`);
|
|
}
|
|
}
|
|
|
|
function escapeRegExp(value: string): string {
|
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
}
|