Add user alias to user table

This commit is contained in:
yuneng-jiang 2025-12-01 12:28:53 -08:00
parent 3347e4de11
commit 69a6c25a5f
3 changed files with 68 additions and 126 deletions

View file

@ -46,6 +46,12 @@ export const columns = (
enableSorting: true,
cell: ({ row }) => <span className="text-xs">{possibleUIRoles?.[row.original.user_role]?.ui_label || "-"}</span>,
},
{
header: "User Alias",
accessorKey: "user_alias",
enableSorting: false,
cell: ({ row }) => <span className="text-xs">{row.original.user_alias || "-"}</span>,
},
{
header: "Spend (USD)",
accessorKey: "spend",

View file

@ -1,63 +1,52 @@
import { act, fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { UserDataTable } from "./table";
const defaultFilters = {
email: "",
user_id: "",
user_role: "",
sso_user_id: "",
team: "",
model: "",
min_spend: null,
max_spend: null,
sort_by: "",
sort_order: "asc" as const,
};
const getDefaultProps = () => ({
data: [] as any[],
columns: [] as any[],
accessToken: null,
userRole: "Admin",
possibleUIRoles: null as Record<string, Record<string, string>> | null,
filters: defaultFilters,
updateFilters: vi.fn(),
initialFilters: defaultFilters,
teams: [] as any[],
handleEdit: vi.fn(),
handleDelete: vi.fn(),
handleResetPassword: vi.fn(),
userListResponse: { users: [], total: 0, page: 1, page_size: 25, total_pages: 1 },
currentPage: 1,
handlePageChange: vi.fn(),
});
describe("UserDataTable", () => {
it("should render the UserDataTable component", () => {
const filters = {
email: "",
user_id: "",
user_role: "",
sso_user_id: "",
team: "",
model: "",
min_spend: null,
max_spend: null,
sort_by: "",
sort_order: "asc" as const,
};
const updateFilters = vi.fn();
render(
<UserDataTable
data={[]}
columns={[]}
accessToken={null}
userRole={"Admin"}
possibleUIRoles={null}
filters={filters}
updateFilters={updateFilters}
initialFilters={filters}
teams={[]}
handleEdit={vi.fn()}
handleDelete={vi.fn()}
handleResetPassword={vi.fn()}
userListResponse={{ users: [], total: 0, page: 1, page_size: 25, total_pages: 1 }}
currentPage={1}
handlePageChange={vi.fn()}
/>,
);
render(<UserDataTable {...getDefaultProps()} />);
expect(screen.getByText("Filters")).toBeInTheDocument();
});
it("should call onSortChange when clicking a sortable header", () => {
const filters = {
email: "",
user_id: "",
user_role: "",
sso_user_id: "",
team: "",
model: "",
min_spend: null,
max_spend: null,
...defaultFilters,
sort_by: "created_at",
sort_order: "desc" as const,
};
const updateFilters = vi.fn();
const onSortChange = vi.fn();
const possibleUIRoles = {
@ -67,21 +56,10 @@ describe("UserDataTable", () => {
render(
<UserDataTable
data={[]}
columns={[]}
accessToken={null}
userRole={"Admin"}
{...getDefaultProps()}
possibleUIRoles={possibleUIRoles}
filters={filters}
updateFilters={updateFilters}
initialFilters={filters}
teams={[]}
handleEdit={vi.fn()}
handleDelete={vi.fn()}
handleResetPassword={vi.fn()}
userListResponse={{ users: [], total: 0, page: 1, page_size: 25, total_pages: 1 }}
currentPage={1}
handlePageChange={vi.fn()}
onSortChange={onSortChange}
currentSort={{ sortBy: filters.sort_by, sortOrder: filters.sort_order }}
/>,
@ -96,41 +74,7 @@ describe("UserDataTable", () => {
});
it("should show skeleton loaders when isLoading is true", () => {
const filters = {
email: "",
user_id: "",
user_role: "",
sso_user_id: "",
team: "",
model: "",
min_spend: null,
max_spend: null,
sort_by: "",
sort_order: "asc" as const,
};
const updateFilters = vi.fn();
render(
<UserDataTable
data={[]}
columns={[]}
accessToken={null}
userRole={"Admin"}
possibleUIRoles={null}
filters={filters}
updateFilters={updateFilters}
initialFilters={filters}
teams={[]}
handleEdit={vi.fn()}
handleDelete={vi.fn()}
handleResetPassword={vi.fn()}
userListResponse={{ users: [], total: 0, page: 1, page_size: 25, total_pages: 1 }}
currentPage={1}
handlePageChange={vi.fn()}
isLoading={true}
/>,
);
render(<UserDataTable {...getDefaultProps()} isLoading={true} />);
expect(screen.queryByText(/Showing/i)).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: /Previous/i })).not.toBeInTheDocument();
@ -138,44 +82,35 @@ describe("UserDataTable", () => {
});
it("should show actual content when isLoading is false", () => {
const filters = {
email: "",
user_id: "",
user_role: "",
sso_user_id: "",
team: "",
model: "",
min_spend: null,
max_spend: null,
sort_by: "",
sort_order: "asc" as const,
};
const updateFilters = vi.fn();
render(
<UserDataTable
data={[]}
columns={[]}
accessToken={null}
userRole={"Admin"}
possibleUIRoles={null}
filters={filters}
updateFilters={updateFilters}
initialFilters={filters}
teams={[]}
handleEdit={vi.fn()}
handleDelete={vi.fn()}
handleResetPassword={vi.fn()}
userListResponse={{ users: [], total: 0, page: 1, page_size: 25, total_pages: 1 }}
currentPage={1}
handlePageChange={vi.fn()}
isLoading={false}
/>,
);
render(<UserDataTable {...getDefaultProps()} isLoading={false} />);
expect(screen.getByText(/Showing/i)).toBeInTheDocument();
expect(screen.getByRole("button", { name: /Previous/i })).toBeInTheDocument();
expect(screen.getByRole("button", { name: /Next/i })).toBeInTheDocument();
});
it("should render all column headers", () => {
const possibleUIRoles = {
admin: { ui_label: "Admin" },
user: { ui_label: "User" },
};
render(<UserDataTable {...getDefaultProps()} possibleUIRoles={possibleUIRoles} />);
[
"User ID",
"Email",
"Global Proxy Role",
"User Alias",
"Spend (USD)",
"Budget (USD)",
"SSO ID",
"API Keys",
"Created At",
"Updated At",
"Actions",
].forEach((header) => {
expect(screen.getByRole("columnheader", { name: header })).toBeInTheDocument();
});
});
});

View file

@ -1,6 +1,7 @@
export interface UserInfo {
user_id: string;
user_email: string;
user_alias: string | null;
user_role: string;
spend: number;
max_budget: number | null;