import { describe, expect, it } from "vitest"; import { readFileSync } from "node:fs"; import { resolve } from "node:path"; const readSource = (path: string) => readFileSync(resolve(__dirname, path), "utf8"); describe("admin user login status", () => { it("shows server-provided session state with login source details and grouped history", () => { const users = readSource("./Users.vue"); const drawer = readSource("./UserLoginActivitiesDrawer.vue"); expect(users).toContain("当前在线"); expect(users).toContain("login_status"); expect(users).toContain("last_login_at"); expect(users).toContain("openLoginActivities"); expect(users).toContain("UserLoginActivitiesDrawer"); expect(drawer).toContain("登录记录"); expect(drawer).toContain("登录 IP(位置)"); expect(drawer).toContain("scope.row.login_ip"); expect(drawer).toContain("scope.row.ip_location"); expect(drawer).toContain("activity_status"); expect(drawer).toContain("resolvedActivityStatus"); expect(drawer).toContain("最近来源"); expect(drawer).toContain("全部会话"); expect(drawer).toContain("groupLoginActivitiesBySource"); expect(drawer).toContain("grouped_count"); expect(drawer).toContain("scope.row.ended_at"); expect(drawer).not.toContain("const isRecent"); expect(drawer).not.toContain("access_token"); const usersApi = readSource("../../api/users.ts"); expect(usersApi).toContain("limit = 100"); }); it("offers responsive account and login-status filters with clear reset feedback", () => { const users = readSource("./Users.vue"); expect(users).toContain('placeholder="账号状态"'); expect(users).toContain('placeholder="登录状态"'); expect(users).toContain('login_status: loginStatusFilter.value || undefined'); expect(users).toContain('class="account-overview"'); expect(users).toContain("position: sticky"); expect(users).not.toContain("filterByStat"); expect(users).not.toContain("账号与登录会话状态"); expect(users).toContain("min-height: 48px"); expect(users).toContain('class-name="actions-column"'); expect(users).toContain("text-overflow: clip"); expect(users).toContain(".department-text,\n.account-status-cell"); expect(users).toContain("padding: 0 !important;"); expect(users).toContain("border-radius: 0;"); expect(users).toContain("content-wrapper:has(.users-page)"); expect(users).toContain("resetFilters"); expect(users).toContain("筛选结果"); }); it("mounts account edit and emergency-reset dialogs to a container shared by web and desktop layouts", () => { const userForm = readSource("./UserForm.vue"); const resetPassword = readSource("./UserResetPassword.vue"); expect(userForm).toContain('append-to="body"'); expect(resetPassword).toContain('append-to="body"'); expect(userForm).not.toContain('append-to=".layout-main .content-wrapper"'); expect(resetPassword).not.toContain('append-to=".layout-main .content-wrapper"'); expect(userForm).not.toContain('class="form-header"'); expect(userForm).not.toContain("填写以下信息创建系统账号"); }); it("uses the desktop dialog treatment without an additional outer card for account actions", () => { const desktopStyles = readFileSync(resolve(__dirname, "../../styles/main.css"), "utf8"); expect(desktopStyles).toContain("body.is-desktop-runtime .user-form-dialog"); expect(desktopStyles).toContain("body.is-desktop-runtime .reset-password-dialog"); expect(desktopStyles).toContain("background: transparent !important;"); expect(desktopStyles).toContain("box-shadow: none !important;"); expect(desktopStyles).toContain(".user-form-dialog .el-dialog__body"); expect(desktopStyles).toContain(".reset-password-dialog .el-dialog__body"); expect(desktopStyles).toContain("border-radius: 8px !important;"); expect(desktopStyles).toContain("padding: 0 !important;"); expect(desktopStyles).toContain(".user-form-dialog .el-dialog__headerbtn"); expect(desktopStyles).toContain("top: 5px;"); expect(desktopStyles).toContain("right: 7px;"); }); });