Skip to content

Commit abaea8a

Browse files
Merge pull request #65 from railsware/contact-lists-api
Contact lists api
2 parents f97f15f + 0cbb795 commit abaea8a

File tree

9 files changed

+486
-2
lines changed

9 files changed

+486
-2
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ Refer to the [`examples`](examples) folder for the source code of this and other
6363

6464
- [Contacts](examples/contacts/everything.ts)
6565

66+
### Contact Lists API
67+
68+
- [Contact Lists](examples/contact-lists/everything.ts)
69+
6670
### Sending API
6771

6872
- [Advanced](examples/sending/everything.ts)

examples/contact-lists/everything.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { MailtrapClient } from "mailtrap";
2+
3+
const TOKEN = "<YOUR-TOKEN-HERE>";
4+
const ACCOUNT_ID = "<YOUR-ACCOUNT-ID-HERE>"
5+
6+
const client = new MailtrapClient({
7+
token: TOKEN,
8+
accountId: ACCOUNT_ID,
9+
});
10+
11+
async function contactListsFlow() {
12+
// Create a new contact list
13+
await client.contactLists.create({
14+
name: "Test List",
15+
});
16+
17+
// Get all contact lists
18+
const all = await client.contactLists.getList();
19+
console.log("All contact lists:", all);
20+
21+
// Get a specific contact list
22+
const one = await client.contactLists.get(all[0].id);
23+
console.log("One contact list:", one);
24+
25+
// Update a contact list
26+
const updated = await client.contactLists.update(all[0].id, {
27+
name: "Updated Test List",
28+
});
29+
console.log("Updated contact list:", updated);
30+
31+
// Delete a contact list
32+
await client.contactLists.delete(all[0].id);
33+
}
34+
35+
contactListsFlow();
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import axios from "axios";
2+
3+
import ContactLists from "../../../lib/api/ContactLists";
4+
5+
describe("lib/api/ContactLists: ", () => {
6+
const accountId = 100;
7+
const contactListsAPI = new ContactLists(axios, accountId);
8+
9+
describe("class ContactLists(): ", () => {
10+
describe("init: ", () => {
11+
it("initalizes with all necessary params.", () => {
12+
expect(contactListsAPI).toHaveProperty("create");
13+
expect(contactListsAPI).toHaveProperty("getList");
14+
expect(contactListsAPI).toHaveProperty("get");
15+
expect(contactListsAPI).toHaveProperty("update");
16+
expect(contactListsAPI).toHaveProperty("delete");
17+
});
18+
});
19+
});
20+
});
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
import axios from "axios";
2+
import AxiosMockAdapter from "axios-mock-adapter";
3+
4+
import ContactListsApi from "../../../../lib/api/resources/ContactLists";
5+
import handleSendingError from "../../../../lib/axios-logger";
6+
import MailtrapError from "../../../../lib/MailtrapError";
7+
import { ContactList, ContactLists } from "../../../../types/api/contactlist";
8+
9+
import CONFIG from "../../../../config";
10+
11+
const { CLIENT_SETTINGS } = CONFIG;
12+
const { GENERAL_ENDPOINT } = CLIENT_SETTINGS;
13+
14+
describe("lib/api/resources/ContactLists: ", () => {
15+
let mock: AxiosMockAdapter;
16+
const accountId = 100;
17+
const contactListsAPI = new ContactListsApi(axios, accountId);
18+
19+
const createListRequest = {
20+
name: "Test List",
21+
};
22+
23+
const createListResponse: ContactList = {
24+
id: 1,
25+
name: "Test List",
26+
};
27+
28+
const updateListRequest = {
29+
name: "Updated Test List",
30+
};
31+
32+
const updateListResponse: ContactList = {
33+
id: 1,
34+
name: "Updated Test List",
35+
};
36+
37+
describe("class ContactListsApi(): ", () => {
38+
describe("init: ", () => {
39+
it("initializes with all necessary params.", () => {
40+
expect(contactListsAPI).toHaveProperty("create");
41+
expect(contactListsAPI).toHaveProperty("update");
42+
expect(contactListsAPI).toHaveProperty("delete");
43+
expect(contactListsAPI).toHaveProperty("get");
44+
expect(contactListsAPI).toHaveProperty("getList");
45+
});
46+
});
47+
});
48+
49+
beforeAll(() => {
50+
axios.interceptors.response.use(
51+
(response) => response.data,
52+
handleSendingError
53+
);
54+
mock = new AxiosMockAdapter(axios);
55+
});
56+
57+
afterEach(() => {
58+
mock.reset();
59+
});
60+
61+
describe("getAll(): ", () => {
62+
it("successfully gets all contact lists.", async () => {
63+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/lists`;
64+
const expectedResponseData: ContactLists = [
65+
{ id: 1, name: "Test List 1" },
66+
{ id: 2, name: "Test List 2" },
67+
];
68+
69+
expect.assertions(2);
70+
71+
mock.onGet(endpoint).reply(200, expectedResponseData);
72+
const result = await contactListsAPI.getList();
73+
74+
expect(mock.history.get[0].url).toEqual(endpoint);
75+
expect(result).toEqual(expectedResponseData);
76+
});
77+
78+
it("fails with error.", async () => {
79+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/lists`;
80+
const expectedErrorMessage = "Request failed with status code 400";
81+
82+
expect.assertions(2);
83+
84+
mock.onGet(endpoint).reply(400, { error: expectedErrorMessage });
85+
86+
try {
87+
await contactListsAPI.getList();
88+
} catch (error) {
89+
expect(error).toBeInstanceOf(MailtrapError);
90+
if (error instanceof MailtrapError) {
91+
expect(error.message).toEqual(expectedErrorMessage);
92+
}
93+
}
94+
});
95+
});
96+
97+
describe("get(): ", () => {
98+
it("successfully gets a contact list by ID.", async () => {
99+
const listId = 1;
100+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/lists/${listId}`;
101+
const expectedResponseData: ContactList = {
102+
id: listId,
103+
name: "Test List",
104+
};
105+
106+
expect.assertions(2);
107+
108+
mock.onGet(endpoint).reply(200, expectedResponseData);
109+
const result = await contactListsAPI.get(listId);
110+
111+
expect(mock.history.get[0].url).toEqual(endpoint);
112+
expect(result).toEqual(expectedResponseData);
113+
});
114+
115+
it("fails with error when getting a contact list.", async () => {
116+
const listId = 999;
117+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/lists/${listId}`;
118+
const expectedErrorMessage = "Contact list not found";
119+
120+
expect.assertions(2);
121+
122+
mock.onGet(endpoint).reply(404, { error: expectedErrorMessage });
123+
124+
try {
125+
await contactListsAPI.get(listId);
126+
} catch (error) {
127+
expect(error).toBeInstanceOf(MailtrapError);
128+
if (error instanceof MailtrapError) {
129+
expect(error.message).toEqual(expectedErrorMessage);
130+
}
131+
}
132+
});
133+
});
134+
135+
describe("create(): ", () => {
136+
it("successfully creates a contact list.", async () => {
137+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/lists`;
138+
const expectedResponseData = createListResponse;
139+
140+
expect.assertions(2);
141+
142+
mock.onPost(endpoint, createListRequest).reply(200, expectedResponseData);
143+
const result = await contactListsAPI.create(createListRequest);
144+
145+
expect(mock.history.post[0].url).toEqual(endpoint);
146+
expect(result).toEqual(expectedResponseData);
147+
});
148+
149+
it("fails with error.", async () => {
150+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/lists`;
151+
const expectedErrorMessage = "Request failed with status code 400";
152+
153+
expect.assertions(2);
154+
155+
mock.onPost(endpoint).reply(400, { error: expectedErrorMessage });
156+
157+
try {
158+
await contactListsAPI.create(createListRequest);
159+
} catch (error) {
160+
expect(error).toBeInstanceOf(MailtrapError);
161+
if (error instanceof MailtrapError) {
162+
expect(error.message).toEqual(expectedErrorMessage);
163+
}
164+
}
165+
});
166+
});
167+
168+
describe("update(): ", () => {
169+
const listId = 1;
170+
171+
it("successfully updates a contact list.", async () => {
172+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/lists/${listId}`;
173+
const expectedResponseData = updateListResponse;
174+
175+
expect.assertions(2);
176+
177+
mock
178+
.onPatch(endpoint, updateListRequest)
179+
.reply(200, expectedResponseData);
180+
const result = await contactListsAPI.update(listId, updateListRequest);
181+
182+
expect(mock.history.patch[0].url).toEqual(endpoint);
183+
expect(result).toEqual(expectedResponseData);
184+
});
185+
186+
it("fails with error.", async () => {
187+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/lists/${listId}`;
188+
const expectedErrorMessage = "Request failed with status code 404";
189+
190+
expect.assertions(2);
191+
192+
mock.onPatch(endpoint).reply(404, { error: expectedErrorMessage });
193+
194+
try {
195+
await contactListsAPI.update(listId, updateListRequest);
196+
} catch (error) {
197+
expect(error).toBeInstanceOf(MailtrapError);
198+
if (error instanceof MailtrapError) {
199+
expect(error.message).toEqual(expectedErrorMessage);
200+
}
201+
}
202+
});
203+
});
204+
205+
describe("delete(): ", () => {
206+
const listId = 1;
207+
208+
it("successfully deletes a contact list.", async () => {
209+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/lists/${listId}`;
210+
211+
expect.assertions(1);
212+
213+
mock.onDelete(endpoint).reply(204);
214+
await contactListsAPI.delete(listId);
215+
216+
expect(mock.history.delete[0].url).toEqual(endpoint);
217+
});
218+
219+
it("fails with error.", async () => {
220+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/lists/${listId}`;
221+
const expectedErrorMessage = "Request failed with status code 404";
222+
223+
expect.assertions(2);
224+
225+
mock.onDelete(endpoint).reply(404, { error: expectedErrorMessage });
226+
227+
try {
228+
await contactListsAPI.delete(listId);
229+
} catch (error) {
230+
expect(error).toBeInstanceOf(MailtrapError);
231+
if (error instanceof MailtrapError) {
232+
expect(error.message).toEqual(expectedErrorMessage);
233+
}
234+
}
235+
});
236+
});
237+
});

src/__tests__/lib/mailtrap-client.test.ts

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import MailtrapError from "../../lib/MailtrapError";
99
import CONFIG from "../../config";
1010
import GeneralAPI from "../../lib/api/General";
1111
import TestingAPI from "../../lib/api/Testing";
12+
import ContactLists from "../../lib/api/ContactLists";
13+
import Contacts from "../../lib/api/Contacts";
1214

1315
const { ERRORS, CLIENT_SETTINGS } = CONFIG;
1416
const { TESTING_ENDPOINT, BULK_ENDPOINT, SENDING_ENDPOINT } = CLIENT_SETTINGS;
@@ -704,15 +706,81 @@ describe("lib/mailtrap-client: ", () => {
704706
});
705707

706708
describe("get general(): ", () => {
707-
it("returns testing API object, console warn is called twice.", () => {
709+
it("rejects with Mailtrap error, when `accountId` is missing.", () => {
708710
const client = new MailtrapClient({
709711
token: "MY_API_TOKEN",
710712
});
711713
expect.assertions(1);
712714

715+
try {
716+
client.general;
717+
} catch (error) {
718+
expect(error).toEqual(new MailtrapError(ACCOUNT_ID_MISSING));
719+
}
720+
});
721+
722+
it("returns general API object when accountId is provided.", () => {
723+
const client = new MailtrapClient({
724+
token: "MY_API_TOKEN",
725+
accountId: 10,
726+
});
727+
expect.assertions(1);
728+
713729
const generalClient = client.general;
714730
expect(generalClient).toBeInstanceOf(GeneralAPI);
715731
});
716732
});
733+
734+
describe("get contacts(): ", () => {
735+
it("rejects with Mailtrap error, when `accountId` is missing.", () => {
736+
const client = new MailtrapClient({
737+
token: "MY_API_TOKEN",
738+
});
739+
expect.assertions(1);
740+
741+
try {
742+
client.contacts;
743+
} catch (error) {
744+
expect(error).toEqual(new MailtrapError(ACCOUNT_ID_MISSING));
745+
}
746+
});
747+
748+
it("returns contacts API object when accountId is provided.", () => {
749+
const client = new MailtrapClient({
750+
token: "MY_API_TOKEN",
751+
accountId: 10,
752+
});
753+
expect.assertions(1);
754+
755+
const contactsClient = client.contacts;
756+
expect(contactsClient).toBeInstanceOf(Contacts);
757+
});
758+
});
759+
760+
describe("get contactLists(): ", () => {
761+
it("rejects with Mailtrap error, when `accountId` is missing.", () => {
762+
const client = new MailtrapClient({
763+
token: "MY_API_TOKEN",
764+
});
765+
expect.assertions(1);
766+
767+
try {
768+
client.contactLists;
769+
} catch (error) {
770+
expect(error).toEqual(new MailtrapError(ACCOUNT_ID_MISSING));
771+
}
772+
});
773+
774+
it("returns contact lists API object when accountId is provided.", () => {
775+
const client = new MailtrapClient({
776+
token: "MY_API_TOKEN",
777+
accountId: 10,
778+
});
779+
expect.assertions(1);
780+
781+
const contactListsClient = client.contactLists;
782+
expect(contactListsClient).toBeInstanceOf(ContactLists);
783+
});
784+
});
717785
});
718786
});

0 commit comments

Comments
 (0)