@@ -0,0 +1,162 @@
|
||||
import { dayOf, requestKey } from "../core/action-plan.js"
|
||||
// The crm use cases over a recording port: what each asks the service, with no client and no network.
|
||||
|
||||
import { actorRef } from "@conusai-kit/business"
|
||||
import type { ProjectScope } from "@conusai-kit/core"
|
||||
import { describe, expect, it } from "vitest"
|
||||
import type { PartyView } from "../contract/index.js"
|
||||
import { addContact, createParty, listParties } from "../core/crm.js"
|
||||
import { type CrmService, crmReadsOf } from "../core/ports.js"
|
||||
|
||||
const scope: ProjectScope = {
|
||||
level: "project",
|
||||
actor: { userId: "01900000-0000-7000-8000-000000000002" },
|
||||
orgId: "o1",
|
||||
workspaceId: "w1",
|
||||
projectId: "p1",
|
||||
}
|
||||
|
||||
const party: PartyView = {
|
||||
partyId: "x",
|
||||
kind: "person",
|
||||
displayName: "Ada",
|
||||
legalName: null,
|
||||
country: "LT",
|
||||
status: "active",
|
||||
linked: false,
|
||||
}
|
||||
|
||||
function recording() {
|
||||
const asked: Array<[string, unknown]> = []
|
||||
const service: CrmService = {
|
||||
bindingId: "01900000-0000-7000-8000-000000000001",
|
||||
listParties: async (query) => {
|
||||
asked.push(["listParties", query])
|
||||
return { rows: [] }
|
||||
},
|
||||
getParty: async () => party,
|
||||
listContacts: async () => ({ rows: [] }),
|
||||
createParty: async (input) => {
|
||||
asked.push(["createParty", input])
|
||||
return party
|
||||
},
|
||||
addContact: async (input) => {
|
||||
asked.push(["addContact", input])
|
||||
return {
|
||||
contactId: "c",
|
||||
kind: input.kind,
|
||||
value: input.value,
|
||||
purposes: input.purposes,
|
||||
isPrimary: input.isPrimary,
|
||||
erased: false,
|
||||
}
|
||||
},
|
||||
}
|
||||
return { service, asked }
|
||||
}
|
||||
|
||||
describe("the crm use cases", () => {
|
||||
it("list parties with a trimmed search and the module's page size", async () => {
|
||||
const { service, asked } = recording()
|
||||
await listParties(service, { q: " acme " })
|
||||
expect(asked).toEqual([["listParties", { q: "acme", limit: 50 }]])
|
||||
})
|
||||
|
||||
it("create a party with the project's request key and no identifier unless asked", async () => {
|
||||
const { service, asked } = recording()
|
||||
await createParty(service, scope, {
|
||||
kind: "organization",
|
||||
displayName: " Acme ",
|
||||
legalName: " ",
|
||||
country: "LT",
|
||||
requestId: "r1",
|
||||
})
|
||||
expect(asked).toEqual([
|
||||
[
|
||||
"createParty",
|
||||
{ kind: "organization", displayName: "Acme", country: "LT", identifiers: [], key: requestKey(scope, "r1") },
|
||||
],
|
||||
])
|
||||
})
|
||||
|
||||
it("link a person to the member with the member's subject reference, and only a person, and only a member", async () => {
|
||||
const { service, asked } = recording()
|
||||
await createParty(service, scope, {
|
||||
kind: "person",
|
||||
displayName: "Ada",
|
||||
country: "LT",
|
||||
linkSelf: true,
|
||||
requestId: "r2",
|
||||
})
|
||||
expect(asked[0]?.[1]).toMatchObject({
|
||||
identifiers: [
|
||||
{
|
||||
scheme: "conusai.subject",
|
||||
value: actorRef("01900000-0000-7000-8000-000000000001", "01900000-0000-7000-8000-000000000002"),
|
||||
},
|
||||
],
|
||||
})
|
||||
await expect(
|
||||
createParty(service, scope, {
|
||||
kind: "organization",
|
||||
displayName: "Acme",
|
||||
country: "LT",
|
||||
linkSelf: true,
|
||||
requestId: "r3",
|
||||
}),
|
||||
).rejects.toMatchObject({ problem: { status: 403 } })
|
||||
const system: ProjectScope = { ...scope, actor: { userId: "system:sweep", system: true } }
|
||||
await expect(
|
||||
createParty(service, system, {
|
||||
kind: "person",
|
||||
displayName: "Ada",
|
||||
country: "LT",
|
||||
linkSelf: true,
|
||||
requestId: "r4",
|
||||
}),
|
||||
).rejects.toMatchObject({ problem: { status: 403 } })
|
||||
expect(asked).toHaveLength(1)
|
||||
})
|
||||
|
||||
it("add a contact point from today, each purpose once", async () => {
|
||||
const { service, asked } = recording()
|
||||
const now = new Date("2026-11-02T23:30:00.000Z")
|
||||
await addContact(
|
||||
service,
|
||||
scope,
|
||||
{
|
||||
partyId: "x",
|
||||
kind: "phone",
|
||||
value: " +370 600 00000 ",
|
||||
purposes: ["billing", "billing"],
|
||||
isPrimary: false,
|
||||
requestId: "r5",
|
||||
},
|
||||
now,
|
||||
)
|
||||
expect(asked).toEqual([
|
||||
[
|
||||
"addContact",
|
||||
{
|
||||
partyId: "x",
|
||||
kind: "phone",
|
||||
value: "+370 600 00000",
|
||||
purposes: ["billing"],
|
||||
isPrimary: false,
|
||||
effectiveFrom: "2026-11-02",
|
||||
key: requestKey(scope, "r5"),
|
||||
},
|
||||
],
|
||||
])
|
||||
expect(dayOf(now)).toBe("2026-11-02")
|
||||
})
|
||||
|
||||
it("hand a read handler a view without a single write", () => {
|
||||
expect(Object.keys(crmReadsOf(recording().service)).sort()).toEqual([
|
||||
"bindingId",
|
||||
"getParty",
|
||||
"listContacts",
|
||||
"listParties",
|
||||
])
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user