snapshot of https://github.com/marmelab/atomic-crm.git (main, 2026-09-18; blobs > 131072B omitted)
Some checks failed
✅ Check / 🔬 ESLint (push) Failing after 21s
✅ Check / 🏷️ Typecheck (push) Failing after 11s
✅ Check / 🔎 Test (push) Failing after 11s
✅ Check / e2e-test (push) Failing after 11s
✅ Check / 🔨 Build (push) Failing after 11s
🚀 Deploy / 🚀 Deploy (doc) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (demo) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (supabase) (push) Failing after 18s

This commit is contained in:
upstream-mirror
2026-09-18 01:48:50 +05:00
commit 93ecc1a6f8
787 changed files with 75240 additions and 0 deletions

View File

@@ -0,0 +1,647 @@
// @vitest-environment node
import { describe, it, expect, vi, beforeEach } from "vitest";
import {
addNoteToContact,
findActiveSaleByEmail,
getOrCreateCompanyFromDomain,
getOrCreateContactFromEmailInfo,
} from "./addNoteToContact";
const mockFrom = vi.hoisted(() => vi.fn());
vi.mock("../_shared/supabaseAdmin.ts", () => ({
supabaseAdmin: {
from: (...args: unknown[]) => mockFrom(...args),
},
}));
const secondaryLookupResult = (
rows: unknown[],
error: { message: string } | null = null,
) => ({
neq: () => ({
order: () => ({
limit: () => Promise.resolve({ data: error ? null : rows, error }),
}),
}),
});
const primaryLookupMiss = {
select: () => ({
eq: () => ({
neq: () => ({
maybeSingle: () => Promise.resolve({ data: null, error: null }),
}),
}),
}),
};
describe("addNoteToContact", () => {
beforeEach(() => {
vi.clearAllMocks();
});
afterAll(() => {
vi.resetAllMocks();
});
describe("getOrCreateCompanyFromDomain", () => {
it("returns the existing company when it already exists in the database", async () => {
const existingCompany = {
id: 1,
name: "Acme",
website: "https://acme.com",
sales_id: 42,
};
mockFrom.mockReturnValue({
select: () => ({
or: () => ({
maybeSingle: () =>
Promise.resolve({ data: existingCompany, error: null }),
}),
}),
});
const result = await getOrCreateCompanyFromDomain({
domain: "acme.com",
salesId: 42,
companyName: "Acme",
website: "https://acme.com",
});
expect(result).toEqual(existingCompany);
expect(mockFrom).toHaveBeenCalledWith("companies");
});
it("throws when fetching the company fails", async () => {
mockFrom.mockReturnValue({
select: () => ({
or: () => ({
maybeSingle: () =>
Promise.resolve({ data: null, error: { message: "DB error" } }),
}),
}),
});
await expect(
getOrCreateCompanyFromDomain({
domain: "acme.com",
salesId: 42,
companyName: "Acme",
website: "https://acme.com",
}),
).rejects.toThrow(
"Could not fetch companies from database, name: acme.com, error: DB error",
);
});
it("returns null for a known mail provider domain without creating a company", async () => {
const result = await getOrCreateCompanyFromDomain({
domain: "gmail.com",
salesId: 42,
companyName: "Gmail",
website: "https://gmail.com",
});
expect(result).toBeNull();
// No database calls should be made for mail providers
expect(mockFrom).not.toHaveBeenCalled();
});
it("creates and returns a new company when it does not exist and domain is not a mail provider", async () => {
const newCompany = {
id: 2,
name: "Acme",
website: "https://acme.com",
sales_id: 42,
};
mockFrom
.mockReturnValueOnce({
// first call: fetch
select: () => ({
or: () => ({
maybeSingle: () => Promise.resolve({ data: null, error: null }),
}),
}),
})
.mockReturnValueOnce({
// second call: insert
insert: () => ({
select: () => Promise.resolve({ data: [newCompany], error: null }),
}),
});
const result = await getOrCreateCompanyFromDomain({
domain: "acme.com",
salesId: 42,
companyName: "Acme",
website: "https://acme.com",
});
expect(result).toEqual(newCompany);
expect(mockFrom).toHaveBeenCalledTimes(2);
expect(mockFrom).toHaveBeenNthCalledWith(2, "companies");
});
it("throws when creating the company fails", async () => {
mockFrom
.mockReturnValueOnce({
select: () => ({
or: () => ({
maybeSingle: () => Promise.resolve({ data: null, error: null }),
}),
}),
})
.mockReturnValueOnce({
insert: () => ({
select: () =>
Promise.resolve({
data: null,
error: { message: "Insert failed" },
}),
}),
});
await expect(
getOrCreateCompanyFromDomain({
domain: "acme.com",
salesId: 42,
companyName: "Acme",
website: "https://acme.com",
}),
).rejects.toThrow(
"Could not create company in database, domain: acme.com, error: Insert failed",
);
});
});
describe("getOrCreateContactFromEmailInfo", () => {
const contactParams = {
email: "alice@acme.com",
firstName: "Alice",
lastName: "Smith",
salesId: 42,
domain: "acme.com",
companyName: "Acme",
website: "https://acme.com",
};
it("returns the existing contact when it already exists in the database", async () => {
const existingContact = {
id: 10,
first_name: "Alice",
last_name: "Smith",
};
mockFrom.mockReturnValue({
select: () => ({
contains: () => ({
maybeSingle: () =>
Promise.resolve({ data: existingContact, error: null }),
}),
}),
});
const result = await getOrCreateContactFromEmailInfo(contactParams);
expect(result).toEqual(existingContact);
expect(mockFrom).toHaveBeenCalledWith("contacts");
});
it("throws when fetching the contact fails", async () => {
mockFrom.mockReturnValue({
select: () => ({
contains: () => ({
maybeSingle: () =>
Promise.resolve({ data: null, error: { message: "DB error" } }),
}),
}),
});
await expect(
getOrCreateContactFromEmailInfo(contactParams),
).rejects.toThrow(
"Could not fetch contact from database, email: alice@acme.com, error: DB error",
);
});
it("creates and returns a new contact with the associated company", async () => {
const newContact = {
id: 11,
first_name: "Alice",
last_name: "Smith",
company_id: 1,
};
const existingCompany = {
id: 1,
name: "Acme",
website: "https://acme.com",
sales_id: 42,
};
mockFrom
.mockReturnValueOnce({
// 1st call: fetch contact → not found
select: () => ({
contains: () => ({
maybeSingle: () => Promise.resolve({ data: null, error: null }),
}),
}),
})
.mockReturnValueOnce({
// 2nd call: fetch company → found
select: () => ({
or: () => ({
maybeSingle: () =>
Promise.resolve({ data: existingCompany, error: null }),
}),
}),
})
.mockReturnValueOnce({
// 3rd call: insert contact
insert: () => ({
select: () => Promise.resolve({ data: [newContact], error: null }),
}),
});
const result = await getOrCreateContactFromEmailInfo(contactParams);
expect(result).toEqual(newContact);
expect(mockFrom).toHaveBeenCalledTimes(3);
});
it("creates a contact with null company_id when domain is a mail provider", async () => {
const newContact = {
id: 12,
first_name: "Alice",
last_name: "Smith",
company_id: null,
};
mockFrom
.mockReturnValueOnce({
// 1st call: fetch contact → not found
select: () => ({
contains: () => ({
maybeSingle: () => Promise.resolve({ data: null, error: null }),
}),
}),
})
.mockReturnValueOnce({
// 2nd call: insert contact (with null company_id)
insert: () => ({
select: () => Promise.resolve({ data: [newContact], error: null }),
}),
});
const result = await getOrCreateContactFromEmailInfo({
...contactParams,
email: "alice@gmail.com",
domain: "gmail.com",
companyName: "Gmail",
website: "https://gmail.com",
});
expect(result).toEqual(newContact);
// Only 2 froms: contacts fetch, contacts insert (no company fetch/insert for mail provider)
expect(mockFrom).toHaveBeenCalledTimes(2);
});
it("throws when creating the contact fails", async () => {
const existingCompany = {
id: 1,
name: "Acme",
website: "https://acme.com",
sales_id: 42,
};
mockFrom
.mockReturnValueOnce({
select: () => ({
contains: () => ({
maybeSingle: () => Promise.resolve({ data: null, error: null }),
}),
}),
})
.mockReturnValueOnce({
select: () => ({
or: () => ({
maybeSingle: () =>
Promise.resolve({ data: existingCompany, error: null }),
}),
}),
})
.mockReturnValueOnce({
insert: () => ({
select: () =>
Promise.resolve({
data: null,
error: { message: "Insert failed" },
}),
}),
});
await expect(
getOrCreateContactFromEmailInfo(contactParams),
).rejects.toThrow(
"Could not create contact in database, email: alice@acme.com, error: Insert failed",
);
});
});
describe("findActiveSaleByEmail", () => {
it("returns the active sale whose primary email matches the sender", async () => {
const salesRecord = { id: 1, email: "sales@company.com" };
mockFrom.mockReturnValueOnce({
select: () => ({
eq: () => ({
neq: () => ({
maybeSingle: () =>
Promise.resolve({ data: salesRecord, error: null }),
}),
}),
}),
});
const result = await findActiveSaleByEmail("sales@company.com");
expect(result.data).toEqual(salesRecord);
expect(mockFrom).toHaveBeenCalledTimes(1);
});
it("looks up the secondary emails when no primary email matches", async () => {
const salesRecord = {
id: 1,
email: "sales@company.com",
secondary_emails: ["perso@gmail.com"],
};
const contains = vi
.fn()
.mockReturnValue(secondaryLookupResult([salesRecord]));
mockFrom
.mockReturnValueOnce({
select: () => ({
eq: () => ({
neq: () => ({
maybeSingle: () => Promise.resolve({ data: null, error: null }),
}),
}),
}),
})
.mockReturnValueOnce({ select: () => ({ contains }) });
const result = await findActiveSaleByEmail("perso@gmail.com");
expect(result.data).toEqual(salesRecord);
expect(contains).toHaveBeenCalledWith(
"secondary_emails",
'["perso@gmail.com"]',
);
});
it("attributes to nobody when two sales share the same secondary email", async () => {
const consoleSpy = vi
.spyOn(console, "error")
.mockImplementation(() => {});
mockFrom.mockReturnValueOnce(primaryLookupMiss).mockReturnValueOnce({
select: () => ({
contains: () =>
secondaryLookupResult([
{ id: 3, email: "a@company.com" },
{ id: 9, email: "b@company.com" },
]),
}),
});
const result = await findActiveSaleByEmail("shared@x.com");
expect(result.data).toBe(null);
expect(result.error).toBe(null);
consoleSpy.mockRestore();
});
it("names both sales in the logs when it refuses an ambiguous sender", async () => {
const consoleSpy = vi
.spyOn(console, "error")
.mockImplementation(() => {});
mockFrom.mockReturnValueOnce(primaryLookupMiss).mockReturnValueOnce({
select: () => ({
contains: () =>
secondaryLookupResult([
{ id: 3, email: "a@company.com" },
{ id: 9, email: "b@company.com" },
]),
}),
});
await findActiveSaleByEmail("shared@x.com");
expect(consoleSpy).toHaveBeenCalledWith(
expect.stringContaining("shared@x.com"),
);
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("3, 9"));
consoleSpy.mockRestore();
});
it("surfaces a failure of the secondary lookup instead of reporting no sale", async () => {
mockFrom.mockReturnValueOnce(primaryLookupMiss).mockReturnValueOnce({
select: () => ({
contains: () => secondaryLookupResult([], { message: "DB error" }),
}),
});
const result = await findActiveSaleByEmail("perso@gmail.com");
expect(result.data).toBe(null);
expect(result.error).toEqual({ message: "DB error" });
});
it("returns no sale rather than an error when nothing matches", async () => {
mockFrom
.mockReturnValueOnce({
select: () => ({
eq: () => ({
neq: () => ({
maybeSingle: () => Promise.resolve({ data: null, error: null }),
}),
}),
}),
})
.mockReturnValueOnce({
select: () => ({ contains: () => secondaryLookupResult([]) }),
});
const result = await findActiveSaleByEmail("nobody@x.com");
expect(result.data).toBe(null);
expect(result.error).toBe(null);
});
it("lowercases the sender, since the jsonb lookup is case sensitive unlike the citext column", async () => {
const salesRecord = {
id: 1,
email: "sales@company.com",
secondary_emails: ["perso@gmail.com"],
};
const eq = vi.fn().mockReturnValue({
neq: () => ({
maybeSingle: () => Promise.resolve({ data: null, error: null }),
}),
});
const contains = vi
.fn()
.mockReturnValue(secondaryLookupResult([salesRecord]));
mockFrom
.mockReturnValueOnce({ select: () => ({ eq }) })
.mockReturnValueOnce({ select: () => ({ contains }) });
const result = await findActiveSaleByEmail(" Perso@Gmail.COM ");
expect(eq).toHaveBeenCalledWith("email", "perso@gmail.com");
expect(contains).toHaveBeenCalledWith(
"secondary_emails",
'["perso@gmail.com"]',
);
expect(result.data).toEqual(salesRecord);
});
it("does not look up the secondary emails when the first query fails", async () => {
mockFrom.mockReturnValueOnce({
select: () => ({
eq: () => ({
neq: () => ({
maybeSingle: () =>
Promise.resolve({ data: null, error: { message: "DB error" } }),
}),
}),
}),
});
const result = await findActiveSaleByEmail("sales@company.com");
expect(result.error).toEqual({ message: "DB error" });
expect(mockFrom).toHaveBeenCalledTimes(1);
});
});
describe("addNoteToContact", () => {
const sales = { id: 1 };
const baseParams = {
sales,
salesEmail: "sales@company.com",
email: "alice@acme.com",
domain: "acme.com",
firstName: "Alice",
lastName: "Smith",
noteContent: "A note",
attachments: [],
companyName: "Acme",
website: "https://acme.com",
};
const contactFound = (contact: unknown) => ({
select: () => ({
contains: () => ({
maybeSingle: () => Promise.resolve({ data: contact, error: null }),
}),
}),
});
it("creates a note and returns undefined on success", async () => {
const existingContact = {
id: 10,
first_name: "Alice",
last_name: "Smith",
};
mockFrom
.mockReturnValueOnce(contactFound(existingContact))
.mockReturnValueOnce({
insert: () => Promise.resolve({ error: null }),
})
.mockReturnValueOnce({
update: () => ({
eq: () => Promise.resolve({ error: null }),
}),
});
const result = await addNoteToContact(baseParams);
expect(result).toBeUndefined();
expect(mockFrom).toHaveBeenCalledTimes(3);
expect(mockFrom).toHaveBeenNthCalledWith(2, "contact_notes");
expect(mockFrom).toHaveBeenNthCalledWith(3, "contacts");
});
it("files the note under the sale it was given, without looking one up", async () => {
const insertNote = vi.fn().mockResolvedValue({ error: null });
mockFrom
.mockReturnValueOnce(contactFound({ id: 10 }))
.mockReturnValueOnce({ insert: insertNote })
.mockReturnValueOnce({
update: () => ({
eq: () => Promise.resolve({ error: null }),
}),
});
const result = await addNoteToContact({
...baseParams,
sales: { id: 7 },
});
expect(result).toBeUndefined();
expect(insertNote).toHaveBeenCalledWith(
expect.objectContaining({ sales_id: 7, contact_id: 10 }),
);
expect(mockFrom).not.toHaveBeenCalledWith("sales");
});
it("returns 500 when inserting the note into contact_notes fails", async () => {
mockFrom
.mockReturnValueOnce(contactFound({ id: 10 }))
.mockReturnValueOnce({
insert: () =>
Promise.resolve({ error: { message: "Insert failed" } }),
});
const response = await addNoteToContact(baseParams);
expect(response).toBeInstanceOf(Response);
expect(response!.status).toBe(500);
expect(await response!.text()).toBe(
"Could not add note to contact alice@acme.com, sales sales@company.com",
);
expect(mockFrom).toHaveBeenCalledTimes(2);
});
it("returns 500 when getOrCreateContactFromEmailInfo throws", async () => {
const consoleSpy = vi
.spyOn(console, "error")
.mockImplementation(() => {});
mockFrom.mockReturnValueOnce({
select: () => ({
contains: () => ({
maybeSingle: () =>
Promise.resolve({ data: null, error: { message: "DB error" } }),
}),
}),
});
const response = await addNoteToContact(baseParams);
expect(response).toBeInstanceOf(Response);
expect(response!.status).toBe(500);
expect(await response!.text()).toBe(
"Could not get or create contact from database, email: alice@acme.com, sales: sales@company.com",
);
expect(consoleSpy).toHaveBeenCalled();
consoleSpy.mockRestore();
});
});
});