284 lines
10 KiB
TypeScript
284 lines
10 KiB
TypeScript
import { describe, test, expect } from "bun:test";
|
|
import { OpportunityController } from "../../../src/controllers/OpportunityController";
|
|
import { ActivityController } from "../../../src/controllers/ActivityController";
|
|
import { CompanyController } from "../../../src/controllers/CompanyController";
|
|
import {
|
|
buildMockOpportunity,
|
|
buildMockCompany,
|
|
buildMockCWActivity,
|
|
} from "../../setup";
|
|
|
|
describe("OpportunityController", () => {
|
|
// -------------------------------------------------------------------
|
|
// Constructor
|
|
// -------------------------------------------------------------------
|
|
describe("constructor", () => {
|
|
test("sets core identification fields", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
expect(ctrl.id).toBe("opp-1");
|
|
expect(ctrl.cwOpportunityId).toBe(1001);
|
|
expect(ctrl.name).toBe("Test Opportunity");
|
|
expect(ctrl.notes).toBe("Some notes");
|
|
});
|
|
|
|
test("sets type, stage, status references", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
expect(ctrl.typeName).toBe("New Business");
|
|
expect(ctrl.typeCwId).toBe(1);
|
|
expect(ctrl.stageName).toBe("Proposal");
|
|
expect(ctrl.stageCwId).toBe(2);
|
|
expect(ctrl.statusName).toBe("Active");
|
|
expect(ctrl.statusCwId).toBe(3);
|
|
});
|
|
|
|
test("sets priority, rating, source", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
expect(ctrl.priorityName).toBe("High");
|
|
expect(ctrl.priorityCwId).toBe(4);
|
|
expect(ctrl.ratingName).toBe("Hot");
|
|
expect(ctrl.ratingCwId).toBe(5);
|
|
expect(ctrl.source).toBe("Referral");
|
|
});
|
|
|
|
test("sets sales rep fields", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
expect(ctrl.primarySalesRepName).toBe("John");
|
|
expect(ctrl.primarySalesRepIdentifier).toBe("jroberts");
|
|
expect(ctrl.primarySalesRepCwId).toBe(10);
|
|
expect(ctrl.secondarySalesRepName).toBeNull();
|
|
});
|
|
|
|
test("sets company/contact/site fields", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
expect(ctrl.companyCwId).toBe(123);
|
|
expect(ctrl.companyName).toBe("Test Company");
|
|
expect(ctrl.contactCwId).toBe(200);
|
|
expect(ctrl.contactName).toBe("Jane Doe");
|
|
expect(ctrl.siteCwId).toBe(300);
|
|
expect(ctrl.siteName).toBe("Main Office");
|
|
});
|
|
|
|
test("sets financial and location fields", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
expect(ctrl.totalSalesTax).toBe(50.0);
|
|
expect(ctrl.customerPO).toBe("PO-12345");
|
|
expect(ctrl.locationName).toBe("HQ");
|
|
expect(ctrl.departmentName).toBe("Sales");
|
|
});
|
|
|
|
test("sets date fields", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
expect(ctrl.expectedCloseDate).toBeInstanceOf(Date);
|
|
expect(ctrl.pipelineChangeDate).toBeInstanceOf(Date);
|
|
expect(ctrl.dateBecameLead).toBeInstanceOf(Date);
|
|
expect(ctrl.closedDate).toBeNull();
|
|
expect(ctrl.closedFlag).toBe(false);
|
|
});
|
|
|
|
test("accepts company controller via opts", () => {
|
|
const company = new CompanyController(buildMockCompany());
|
|
const ctrl = new OpportunityController(buildMockOpportunity(), {
|
|
company,
|
|
});
|
|
const json = ctrl.toJson();
|
|
// Company should be a full object, not just {id, name}
|
|
expect(json.company.id).toBe("company-1");
|
|
expect(json.company.name).toBe("Test Company");
|
|
});
|
|
|
|
test("accepts activities via opts", () => {
|
|
const activities = [new ActivityController(buildMockCWActivity())];
|
|
const ctrl = new OpportunityController(buildMockOpportunity(), {
|
|
activities,
|
|
});
|
|
const json = ctrl.toJson();
|
|
expect(json.activities).toHaveLength(1);
|
|
expect(json.activities[0].cwActivityId).toBe(5001);
|
|
});
|
|
|
|
test("accepts customFields via opts", () => {
|
|
const customFields = [
|
|
{
|
|
id: 1,
|
|
caption: "Custom1",
|
|
type: "Text",
|
|
entryMethod: "EntryField",
|
|
numberOfDecimals: 0,
|
|
value: "test",
|
|
},
|
|
];
|
|
const ctrl = new OpportunityController(buildMockOpportunity(), {
|
|
customFields,
|
|
});
|
|
const json = ctrl.toJson();
|
|
expect(json.customFields).toHaveLength(1);
|
|
});
|
|
|
|
test("has empty activities/customFields without opts", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.activities).toEqual([]);
|
|
expect(json.customFields).toEqual([]);
|
|
});
|
|
});
|
|
|
|
// -------------------------------------------------------------------
|
|
// mapCwToDb (static)
|
|
// -------------------------------------------------------------------
|
|
describe("mapCwToDb()", () => {
|
|
const cwOpportunity = {
|
|
id: 1001,
|
|
name: "CW Opp",
|
|
notes: "CW notes",
|
|
type: { id: 1, name: "New Business" },
|
|
stage: { id: 2, name: "Proposal" },
|
|
status: { id: 3, name: "Active" },
|
|
priority: { id: 4, name: "High" },
|
|
rating: null,
|
|
source: "Web",
|
|
campaign: null,
|
|
primarySalesRep: { id: 10, identifier: "jroberts", name: "John" },
|
|
secondarySalesRep: null,
|
|
company: { id: 123, identifier: "TestCo", name: "Test Co" },
|
|
contact: { id: 200, name: "Jane" },
|
|
site: { id: 300, name: "Main" },
|
|
customerPO: "PO-1",
|
|
totalSalesTax: 25.5,
|
|
location: { id: 400, name: "HQ" },
|
|
department: { id: 500, name: "Sales" },
|
|
expectedCloseDate: "2026-04-01T00:00:00Z",
|
|
pipelineChangeDate: "2026-02-15T00:00:00Z",
|
|
dateBecameLead: "2026-01-01T00:00:00Z",
|
|
closedDate: null,
|
|
closedFlag: false,
|
|
closedBy: null,
|
|
customFields: [],
|
|
_info: { lastUpdated: "2026-02-28T12:00:00Z" },
|
|
} as any;
|
|
|
|
test("maps name and notes", () => {
|
|
const result = OpportunityController.mapCwToDb(cwOpportunity);
|
|
expect(result.name).toBe("CW Opp");
|
|
expect(result.notes).toBe("CW notes");
|
|
});
|
|
|
|
test("maps type, stage, status references", () => {
|
|
const result = OpportunityController.mapCwToDb(cwOpportunity);
|
|
expect(result.typeName).toBe("New Business");
|
|
expect(result.typeCwId).toBe(1);
|
|
expect(result.stageName).toBe("Proposal");
|
|
expect(result.statusName).toBe("Active");
|
|
});
|
|
|
|
test("maps null references to null", () => {
|
|
const result = OpportunityController.mapCwToDb(cwOpportunity);
|
|
expect(result.ratingName).toBeNull();
|
|
expect(result.ratingCwId).toBeNull();
|
|
expect(result.campaignName).toBeNull();
|
|
});
|
|
|
|
test("maps sales rep fields", () => {
|
|
const result = OpportunityController.mapCwToDb(cwOpportunity);
|
|
expect(result.primarySalesRepName).toBe("John");
|
|
expect(result.primarySalesRepIdentifier).toBe("jroberts");
|
|
expect(result.secondarySalesRepName).toBeNull();
|
|
});
|
|
|
|
test("maps dates to Date objects", () => {
|
|
const result = OpportunityController.mapCwToDb(cwOpportunity);
|
|
expect(result.expectedCloseDate).toBeInstanceOf(Date);
|
|
expect(result.closedDate).toBeNull();
|
|
});
|
|
|
|
test("maps closedFlag", () => {
|
|
const result = OpportunityController.mapCwToDb(cwOpportunity);
|
|
expect(result.closedFlag).toBe(false);
|
|
});
|
|
|
|
test("maps cwLastUpdated from _info", () => {
|
|
const result = OpportunityController.mapCwToDb(cwOpportunity);
|
|
expect(result.cwLastUpdated).toBeInstanceOf(Date);
|
|
});
|
|
});
|
|
|
|
// -------------------------------------------------------------------
|
|
// toJson
|
|
// -------------------------------------------------------------------
|
|
describe("toJson()", () => {
|
|
test("returns core fields", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.id).toBe("opp-1");
|
|
expect(json.cwOpportunityId).toBe(1001);
|
|
expect(json.name).toBe("Test Opportunity");
|
|
});
|
|
|
|
test("formats type as reference object", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.type).toEqual({ id: 1, name: "New Business" });
|
|
});
|
|
|
|
test("formats stage as reference object", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.stage).toEqual({ id: 2, name: "Proposal" });
|
|
});
|
|
|
|
test("formats status as reference object", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.status).toEqual({ id: 3, name: "Active" });
|
|
});
|
|
|
|
test("formats primarySalesRep with identifier", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.primarySalesRep).toEqual({
|
|
id: 10,
|
|
identifier: "jroberts",
|
|
name: "John",
|
|
});
|
|
});
|
|
|
|
test("secondarySalesRep is null when not set", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.secondarySalesRep).toBeNull();
|
|
});
|
|
|
|
test("contact formats as reference object", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.contact).toEqual({ id: 200, name: "Jane Doe" });
|
|
});
|
|
|
|
test("company falls back to CW reference when no controller", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.company).toEqual({ id: 123, name: "Test Company" });
|
|
});
|
|
|
|
test("includes financial data", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.totalSalesTax).toBe(50.0);
|
|
expect(json.customerPO).toBe("PO-12345");
|
|
});
|
|
|
|
test("includes dates", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.expectedCloseDate).toBeInstanceOf(Date);
|
|
expect(json.closedFlag).toBe(false);
|
|
});
|
|
|
|
test("includes timestamps", () => {
|
|
const ctrl = new OpportunityController(buildMockOpportunity());
|
|
const json = ctrl.toJson();
|
|
expect(json.createdAt).toBeInstanceOf(Date);
|
|
expect(json.updatedAt).toBeInstanceOf(Date);
|
|
});
|
|
});
|
|
});
|