104 lines
4.2 KiB
TypeScript
104 lines
4.2 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/EmployeesView.vue"), "utf-8");
|
|
const css = readFileSync(join(root, "src/assets/styles.css"), "utf-8");
|
|
|
|
assertIncludes(view, "view-stack employees-page");
|
|
assertIncludes(view, "employee-list-header");
|
|
assertIncludes(view, "employee-list-title");
|
|
assertIncludes(view, "employee-inline-metric");
|
|
assertNotIncludes(view, "employee-header-actions");
|
|
assertIncludes(view, "employee_info_keyword");
|
|
assertIncludes(view, "organization_keyword");
|
|
assertIncludes(view, "employee-filter-employee");
|
|
assertIncludes(view, "employee-filter-organization");
|
|
assertIncludes(view, "employee-filter-status");
|
|
assertIncludes(view, "employee-search-button");
|
|
assertIncludes(view, "employee-status-pill");
|
|
assertIncludes(view, "employee-status-dot");
|
|
assertNotIncludes(view, "placeholder=\"编号、姓名、钉钉ID、部门或岗位\"");
|
|
assertNotIncludes(view, "class=\"status-chip\"");
|
|
assertIncludes(view, "管理员工资料,工资核算会优先使用这里的信息。");
|
|
assertIncludes(view, "在职员工");
|
|
assertIncludes(view, "<em>人</em>");
|
|
assertIncludes(view, "<span>找员工</span>");
|
|
assertIncludes(view, "placeholder=\"输入姓名、编号或手机号\"");
|
|
assertIncludes(view, "<span>找部门/岗位</span>");
|
|
assertIncludes(view, "placeholder=\"输入部门或岗位名称\"");
|
|
assertIncludes(view, "<th>钉钉账号</th>");
|
|
assertIncludes(view, "employee.dingtalk_user_id || \"未绑定\"");
|
|
assertIncludes(view, "<span>钉钉账号</span>");
|
|
assertIncludes(view, "placeholder=\"用于匹配钉钉考勤,可不填\"");
|
|
assertNotIncludes(view, "钉钉用户ID");
|
|
assertNotIncludes(view, "<span>组织</span>");
|
|
assertNotIncludes(view, "参与薪资计算");
|
|
|
|
const pageBlock = cssBlock(".employees-page");
|
|
assertIncludes(pageBlock, "gap: 14px;");
|
|
|
|
const headerBlock = cssBlock(".employee-list-header");
|
|
assertIncludes(headerBlock, "display: grid;");
|
|
assertIncludes(headerBlock, "grid-template-columns: minmax(0, 1fr) auto;");
|
|
|
|
const titleBlock = cssBlock(".employee-list-title");
|
|
assertIncludes(titleBlock, "display: flex;");
|
|
assertIncludes(titleBlock, "align-items: center;");
|
|
|
|
const metricBlock = cssBlock(".employee-inline-metric");
|
|
assertIncludes(metricBlock, "min-height: 30px;");
|
|
assertIncludes(metricBlock, "box-shadow: none;");
|
|
|
|
const filterBlock = cssBlock(".employee-filter-bar");
|
|
assertIncludes(filterBlock, "grid-template-columns: minmax(180px, 260px) minmax(180px, 260px) minmax(130px, 160px) 104px minmax(0, 1fr);");
|
|
|
|
const scopedFilterBlock = cssBlock(".table-filter-bar.employee-filter-bar");
|
|
assertIncludes(scopedFilterBlock, "grid-template-columns: minmax(180px, 260px) minmax(180px, 260px) minmax(130px, 160px) 104px minmax(0, 1fr);");
|
|
|
|
const statusBlock = cssBlock(".employee-status-pill");
|
|
assertIncludes(statusBlock, "display: inline-flex;");
|
|
assertIncludes(statusBlock, "min-width: 0;");
|
|
assertIncludes(statusBlock, "background: transparent;");
|
|
|
|
const dotBlock = cssBlock(".employee-status-dot");
|
|
assertIncludes(dotBlock, "width: 7px;");
|
|
assertIncludes(dotBlock, "height: 7px;");
|
|
|
|
assertIncludes(css, ".table-filter-bar.employee-filter-bar {\n grid-template-columns: 1fr;");
|
|
|
|
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, "\\$&");
|
|
}
|