import { Contacts } from "../../src/models/Contact"; import { Api } from "../../src/utils/api"; import { Paginator } from "../../src/utils/paginator"; describe("Contacts", () => { let api: Api; let contacts: Contacts; beforeEach(() => { api = new Api("valid-api-key"); contacts = new Contacts(api); }); it("should create a new Contacts instance", () => { expect(contacts).toBeInstanceOf(Contacts); }); describe("getContacts", () => { it("should return contacts with pagination if found", async () => { const contactsData = [ { id: 1, name: "John Doe" }, { id: 2, name: "Jane Doe" }, ]; jest.spyOn(api, "makeApiCall").mockResolvedValueOnce({ contacts: contactsData, count: contactsData.length, next: "https://example.com", previous: "https://example.com", }); const result = await contacts.getContacts(); expect(result).toBeInstanceOf(Paginator); expect(result).toBeDefined(); expect(result?.getItems()).toHaveLength(contactsData.length); expect(typeof result?.next).toBe("function"); expect(typeof result?.previous).toBe("function"); }); it("should throw an error if the API call fails", async () => { jest.spyOn(api, "makeApiCall").mockResolvedValueOnce({ contacts: null, }); expect(async () => await contacts.getContacts()).rejects.toThrowError( "No contacts found" ); }); it("should throw an error if the API call fails and throw is true", async () => { jest.spyOn(api, "makeApiCall").mockResolvedValueOnce({ contacts: [ { id: 1, name: "John Doe" }, { id: 2, name: "Jane Doe" }, null, ], }); await expect(contacts.getContacts()).rejects.toThrowError( "Contact data is null" ); }); }); describe("createContact", () => { it("should succesfully create a contact", async () => { jest.spyOn(api, "makeApiCall").mockResolvedValueOnce({ id: 1, given_name: "John", family_name: "Doe", }); const result = await contacts.createContact({ given_name: "John", family_name: "Doe", email_addresses: [ { email: "string@example.com", field: "EMAIL1", }, ], }); expect(result).toBeInstanceOf(Object); expect(result).toBeDefined(); expect(result).toHaveProperty("id"); expect(result).toHaveProperty("given_name"); expect(result).toHaveProperty("family_name"); }); it("should throw an error if the API call fails", async () => { jest.spyOn(api, "makeApiCall").mockResolvedValueOnce(undefined); await expect( contacts.createContact({ given_name: "John", family_name: "Doe", email_addresses: [ { email: "string@example.com", field: "EMAIL1", }, ], }) ).rejects.toThrowError( "Cannot read properties of undefined (reading 'id')" ); }); it("should throw if no mail or phone is provided", async () => { await expect( contacts.createContact({ given_name: "John", family_name: "Doe", }) ).rejects.toThrowError( "Contact must contain at least one item in email_addresses or phone_numbers" ); }); it("should throw if no country code is provided if region is provided", async () => { await expect( contacts.createContact({ given_name: "John", family_name: "Doe", email_addresses: [ { email: "string@example.com", field: "EMAIL1", }, ], addresses: [ // @ts-expect-error - region is required if country_code is provided { region: "CA", line1: "123 Main St", postal_code: "12345", locality: "San Francisco", zip_code: "12345", zip_four: "1234", field: "HOME", line2: "Apt 1", }, ], }) ).rejects.toThrowError( "Contact must contain a country code if a region is provided" ); }); }); describe("updateContact", () => { it("should succesfully update a contact", async () => { jest.spyOn(api, "makeApiCall").mockResolvedValueOnce({ id: 1, given_name: "John", family_name: "Doe", }); const result = await contacts.updateContact(1, { id: 1, given_name: "John", family_name: "Doe", }); expect(result).toBeInstanceOf(Object); expect(result).toBeDefined(); expect(result).toHaveProperty("id"); expect(result).toHaveProperty("given_name"); expect(result).toHaveProperty("family_name"); }); it("should throw an error if the API call fails", async () => { jest.spyOn(api, "makeApiCall").mockResolvedValueOnce(undefined); await expect( contacts.updateContact(1, { id: 1, given_name: "John", family_name: "Doe", }) ).rejects.toThrowError( "Cannot read properties of undefined (reading 'id')" ); }); }); describe("deleteContact", () => { it("should succesfully delete a contact", async () => { api.makeApiCall = jest.fn().mockResolvedValueOnce(true); const result = await contacts.deleteContact(1); expect(result).toBe(true); api.makeApiCall = jest.fn().mockClear(); }); it("should return undefined if the API call fails", async () => { contacts.deleteContact = jest.fn().mockResolvedValueOnce(undefined); const result = await contacts.deleteContact(1); expect(result).toBeUndefined(); api.makeApiCall = jest.fn().mockClear(); }); }); describe("getContact", () => { it("should succesfully get a contact", async () => { jest.spyOn(api, "makeApiCall").mockResolvedValueOnce({ id: 1, given_name: "John", family_name: "Doe", }); const result = await contacts.getContact(1); expect(result).toBeInstanceOf(Object); expect(result).toBeDefined(); expect(result).toHaveProperty("id"); expect(result).toHaveProperty("given_name"); expect(result).toHaveProperty("family_name"); }); it("should throw an error if the API call fails", async () => { jest.spyOn(api, "makeApiCall").mockResolvedValueOnce(undefined); await expect(contacts.getContact(1)).rejects.toThrowError( "Cannot read properties of undefined (reading 'id')" ); }); }); describe("getContactModel", () => { it("should succesfully get a contact model", async () => { jest.spyOn(api, "makeApiCall").mockResolvedValueOnce({ id: 1, given_name: "John", family_name: "Doe", }); const result = await contacts.getContactModel(); expect(result).toBeInstanceOf(Object); expect(result).toBeDefined(); expect(result).toHaveProperty("id"); expect(result).toHaveProperty("given_name"); expect(result).toHaveProperty("family_name"); }); it("should return undefined if the API call fails", async () => { jest.spyOn(api, "makeApiCall").mockResolvedValueOnce(undefined); const result = await contacts.getContactModel(); expect(result).toBeUndefined(); }); }); });