d7b374f8ab
New features: - ActivityController and manager for CW sales activities (CRUD) - ForecastProductController for opportunity forecast/product lines - CW member cache with dual-layer (in-memory + Redis) resolution - Catalog category/subcategory/ecosystem taxonomy module - Quote statuses type definitions with CW mapping - User-defined fields (UDF) module with cache and event refresh - Company sites CW module with serialization - Procurement manager filters (category, ecosystem, manufacturer, price, stock) - Opportunity notes CRUD and product line management via CW API - Opportunity type definitions endpoint Updates: - OpportunityController: CW refresh, company hydration, activities, custom fields - UserController: cwIdentifier field for CW member linking - CatalogItemController: category/subcategory fields from CW - PermissionNodes: sales note/product CRUD nodes, subCategories, collectPermissions - API routes: procurement categories/filters, sales notes/products, opportunity types - Global events: UDF and member refresh intervals on startup Tests (414 passing): - ActivityController, ForecastProductController, OpportunityController unit tests - UserController cwIdentifier tests - catalogCategories, companySites, memberCache, procurement module tests - activityTypes, opportunityTypes, quoteStatuses type tests - permissionNodes subCategories and getAllPermissionNodes tests - Updated test setup with redis mock, API method mocks, and builder helpers
135 lines
4.6 KiB
TypeScript
135 lines
4.6 KiB
TypeScript
import { describe, test, expect } from "bun:test";
|
|
import UserController from "../../../src/controllers/UserController";
|
|
import { buildMockUser } from "../../setup";
|
|
|
|
describe("UserController", () => {
|
|
// -------------------------------------------------------------------
|
|
// Constructor
|
|
// -------------------------------------------------------------------
|
|
describe("constructor", () => {
|
|
test("sets all public properties", () => {
|
|
const ctrl = new UserController(buildMockUser());
|
|
expect(ctrl.id).toBe("user-1");
|
|
expect(ctrl.name).toBe("Test User");
|
|
expect(ctrl.login).toBe("test@example.com");
|
|
expect(ctrl.email).toBe("test@example.com");
|
|
expect(ctrl.image).toBeNull();
|
|
expect(ctrl.cwIdentifier).toBeNull();
|
|
});
|
|
|
|
test("sets cwIdentifier when provided", () => {
|
|
const ctrl = new UserController(
|
|
buildMockUser({ cwIdentifier: "jroberts" }),
|
|
);
|
|
expect(ctrl.cwIdentifier).toBe("jroberts");
|
|
});
|
|
|
|
test("sets timestamps", () => {
|
|
const ctrl = new UserController(buildMockUser());
|
|
expect(ctrl.createdAt).toBeInstanceOf(Date);
|
|
expect(ctrl.updatedAt).toBeInstanceOf(Date);
|
|
});
|
|
|
|
test("builds roles collection", () => {
|
|
const mockRole = {
|
|
id: "role-1",
|
|
title: "Admin",
|
|
moniker: "admin",
|
|
permissions: "tok",
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
};
|
|
const ctrl = new UserController(buildMockUser({ roles: [mockRole] }));
|
|
// _roles is private, but we can verify via toJson
|
|
const json = ctrl.toJson();
|
|
expect(json.roles).toContain("admin");
|
|
});
|
|
});
|
|
|
|
// -------------------------------------------------------------------
|
|
// toJson
|
|
// -------------------------------------------------------------------
|
|
describe("toJson()", () => {
|
|
test("returns full JSON by default", () => {
|
|
const ctrl = new UserController(buildMockUser());
|
|
const json = ctrl.toJson();
|
|
expect(json.id).toBe("user-1");
|
|
expect(json.name).toBe("Test User");
|
|
expect(json.login).toBe("test@example.com");
|
|
expect(json.email).toBe("test@example.com");
|
|
expect(json.image).toBeNull();
|
|
expect(json.createdAt).toBeDefined();
|
|
expect(json.updatedAt).toBeDefined();
|
|
});
|
|
|
|
test("safeReturn hides sensitive fields", () => {
|
|
const ctrl = new UserController(buildMockUser());
|
|
const json = ctrl.toJson({ safeReturn: true });
|
|
expect(json.id).toBe("user-1");
|
|
expect(json.name).toBe("Test User");
|
|
expect(json.login).toBeUndefined();
|
|
expect(json.email).toBeUndefined();
|
|
expect(json.cwIdentifier).toBeUndefined();
|
|
expect(json.roles).toBeUndefined();
|
|
expect(json.permissions).toBeUndefined();
|
|
});
|
|
|
|
test("cwIdentifier included in full JSON", () => {
|
|
const ctrl = new UserController(
|
|
buildMockUser({ cwIdentifier: "jroberts" }),
|
|
);
|
|
const json = ctrl.toJson();
|
|
expect(json.cwIdentifier).toBe("jroberts");
|
|
});
|
|
|
|
test("roles is undefined when user has no roles", () => {
|
|
const ctrl = new UserController(buildMockUser({ roles: [] }));
|
|
const json = ctrl.toJson();
|
|
// _roles.size == 0, so roles is undefined
|
|
expect(json.roles).toBeUndefined();
|
|
});
|
|
|
|
test("roles returns monikers when present", () => {
|
|
const mockRoles = [
|
|
{
|
|
id: "r1",
|
|
title: "Admin",
|
|
moniker: "admin",
|
|
permissions: "t",
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
},
|
|
{
|
|
id: "r2",
|
|
title: "User",
|
|
moniker: "user",
|
|
permissions: "t",
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
},
|
|
];
|
|
const ctrl = new UserController(buildMockUser({ roles: mockRoles }));
|
|
const json = ctrl.toJson();
|
|
expect(json.roles).toHaveLength(2);
|
|
expect(json.roles).toContain("admin");
|
|
expect(json.roles).toContain("user");
|
|
});
|
|
|
|
test("permissions returns empty array when user has no permissions token", () => {
|
|
const ctrl = new UserController(buildMockUser({ permissions: null }));
|
|
const json = ctrl.toJson();
|
|
expect(json.permissions).toEqual([]);
|
|
});
|
|
});
|
|
|
|
// -------------------------------------------------------------------
|
|
// readPermissions
|
|
// -------------------------------------------------------------------
|
|
describe("readPermissions()", () => {
|
|
test("returns empty array when permissions is null", () => {
|
|
const ctrl = new UserController(buildMockUser({ permissions: null }));
|
|
expect(ctrl.readPermissions()).toEqual([]);
|
|
});
|
|
});
|
|
});
|