- Open 「用户轨迹」 straight on the live map instead of a drawer, carrying the server, the focused user and a start/end window through the plugin page hash. - Default that window to one hour before the user's last seen time and keep the plugin page query available to bundles through the host context. - Replace the time range preset gate with always visible start/end datetime fields plus a quick-range select, so the user list rebuilds from the window. - Drop the bulky trajectory list and draw one compact colour legend under the map, keeping a stable colour per identity and restricting vehicle tracks to the vehicles the selected users actually rode.
105 lines
5.4 KiB
TypeScript
105 lines
5.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { defaultPageForUser, firstPartyRoutes, hashForPage, navigationRoutesForUser, resolveRouteHash, routeForPage } from "./routes";
|
|
import { initialNavigationState } from "../stores/navigation";
|
|
import { capabilitiesForRoles, type CurrentUserView } from "../contracts/workspace";
|
|
|
|
const platformAdmin: CurrentUserView = {
|
|
id: "user-admin",
|
|
displayName: "Admin",
|
|
status: "active",
|
|
roles: ["platformAdmin"],
|
|
capabilities: capabilitiesForRoles(["platformAdmin"]),
|
|
profile: {},
|
|
source: "local"
|
|
};
|
|
|
|
const serverAdmin: CurrentUserView = {
|
|
id: "user-server",
|
|
displayName: "Server Operator",
|
|
status: "active",
|
|
roles: ["serverAdmin"],
|
|
capabilities: capabilitiesForRoles(["serverAdmin"]),
|
|
profile: {},
|
|
source: "local"
|
|
};
|
|
|
|
describe("console shell routes", () => {
|
|
it("resolves known hashes and paths", () => {
|
|
expect(resolveRouteHash("#/servers", platformAdmin).route.id).toBe("servers");
|
|
expect(resolveRouteHash("#/profile", platformAdmin).route.id).toBe("profileSettings");
|
|
expect(resolveRouteHash("#/aiProviders", platformAdmin).route.id).toBe("aiProviders");
|
|
expect(resolveRouteHash("#/ai-providers", platformAdmin).route.id).toBe("aiProviders");
|
|
expect(resolveRouteHash("#/unknown", platformAdmin).route.id).toBe("home");
|
|
expect(resolveRouteHash("#/plugins", platformAdmin).route.id).toBe("plugins");
|
|
});
|
|
|
|
it("resolves server detail hashes with params", () => {
|
|
const resolved = resolveRouteHash("#/servers/server-example-1", platformAdmin);
|
|
expect(resolved.route.id).toBe("serverDetail");
|
|
expect(resolved.params.serverId).toBe("server-example-1");
|
|
expect(hashForPage("serverDetail", { serverId: "server-example-1" })).toBe("#/servers/server-example-1");
|
|
expect(hashForPage("serverDetail", { serverId: "server-example-1", routeKey: "overview" })).toBe("#/servers/server-example-1?focus=overview");
|
|
expect(resolveRouteHash("#/servers/server-example-1?focus=overview", platformAdmin).params).toEqual({ serverId: "server-example-1", routeKey: "overview" });
|
|
});
|
|
|
|
it("round-trips hosted plugin page hashes with server context", () => {
|
|
const hash = hashForPage("pluginPage", { pluginId: "game.scum", routeKey: "operations", serverId: "server/scum-1" });
|
|
expect(hash).toBe("#/plugin-pages/game.scum/operations?serverInstanceId=server%2Fscum-1");
|
|
const resolved = resolveRouteHash(hash, platformAdmin);
|
|
expect(resolved.route).toMatchObject({ id: "pluginPage", showInNav: false, requiredCapability: "servers.read" });
|
|
expect(resolved.params).toEqual({ pluginId: "game.scum", routeKey: "operations", serverId: "server/scum-1" });
|
|
});
|
|
|
|
it("carries hosted plugin page focus queries through the hash", () => {
|
|
const pageQuery = { focus: "76561198000000001", from: "2026-09-16T09:30:00Z", to: "2026-09-16T11:00:00Z" };
|
|
const hash = hashForPage("pluginPage", { pluginId: "game.scum", routeKey: "live-map", serverId: "server-1", pageQuery });
|
|
const resolved = resolveRouteHash(hash, platformAdmin);
|
|
expect(resolved.route.id).toBe("pluginPage");
|
|
expect(resolved.params).toEqual({ pluginId: "game.scum", routeKey: "live-map", serverId: "server-1", pageQuery });
|
|
});
|
|
|
|
it("keeps route metadata available for shell navigation", () => {
|
|
expect(firstPartyRoutes.map((route) => route.id)).toContain("maintenance");
|
|
expect(firstPartyRoutes.map((route) => route.id)).toContain("profileSettings");
|
|
expect(routeForPage("users")).toMatchObject({ label: "用户管理", hash: "#/users" });
|
|
expect(routeForPage("profileSettings")).toMatchObject({ label: "个人设置", hash: "#/profile" });
|
|
});
|
|
|
|
it("routes platform administrators to the platform overview by default", () => {
|
|
expect(defaultPageForUser(platformAdmin)).toBe("home");
|
|
expect(initialNavigationState(platformAdmin, "").pageId).toBe("home");
|
|
});
|
|
|
|
it("routes server owners and administrators to the server list by default", () => {
|
|
expect(defaultPageForUser(serverAdmin)).toBe("servers");
|
|
expect(initialNavigationState(serverAdmin, "").pageId).toBe("servers");
|
|
});
|
|
|
|
it("hides platform-only navigation from server-only users", () => {
|
|
const labels = navigationRoutesForUser(serverAdmin).map((route) => route.label);
|
|
expect(labels).toContain("服务器管理");
|
|
expect(labels).not.toContain("平台概览");
|
|
expect(labels).not.toContain("用户管理");
|
|
expect(labels).not.toContain("AI 提供商管理");
|
|
expect(labels).not.toContain("系统维护");
|
|
expect(labels).not.toContain("个人设置");
|
|
});
|
|
|
|
it("shows all platform areas to platform administrators", () => {
|
|
const labels = navigationRoutesForUser(platformAdmin).map((route) => route.label);
|
|
expect(labels).toEqual(["平台概览", "服务器管理", "插件市场", "用户管理", "AI 提供商管理", "系统维护"]);
|
|
});
|
|
|
|
it("allows every authenticated role to open profile settings", () => {
|
|
expect(initialNavigationState(platformAdmin, "#/profile").pageId).toBe("profileSettings");
|
|
expect(initialNavigationState(serverAdmin, "#/profile").pageId).toBe("profileSettings");
|
|
});
|
|
|
|
it("redirects unauthorized hashes to the role default workspace", () => {
|
|
expect(initialNavigationState(serverAdmin, "#/home").pageId).toBe("servers");
|
|
expect(initialNavigationState(serverAdmin, "#/users").pageId).toBe("servers");
|
|
expect(initialNavigationState(serverAdmin, "#/servers/server-1").pageId).toBe("serverDetail");
|
|
});
|
|
});
|