Skip to content

Commit b56710f

Browse files
Merge pull request #89 from railsware/contact-fields
Contact fields
2 parents 674de14 + 38b8e02 commit b56710f

File tree

8 files changed

+515
-0
lines changed

8 files changed

+515
-0
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Currently, with this SDK you can:
3232
- Contact management
3333
- Contacts CRUD
3434
- Lists CRUD
35+
- Contact Fields CRUD
3536
- General
3637
- Templates CRUD
3738
- Suppressions management (find and delete)
@@ -121,6 +122,10 @@ Refer to the [`examples`](examples) folder for the source code of this and other
121122

122123
- [Contact Lists](examples/contact-lists/everything.ts)
123124

125+
### Contact Fields API
126+
127+
- [Contact Fields](examples/contact-fields/everything.ts)
128+
124129
### Sending API
125130

126131
- [Advanced](examples/sending/everything.ts)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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 contactFieldsExample() {
12+
try {
13+
// Get all contact fields
14+
const fields = await client.contactFields.getList();
15+
console.log("All contact fields:", fields);
16+
17+
// Use the first field from the list for operations
18+
const firstField = (fields as any)[0];
19+
if (!firstField) {
20+
console.log("No contact fields found");
21+
return;
22+
}
23+
24+
// Get a specific contact field
25+
const field = await client.contactFields.get(firstField.id);
26+
console.log("Retrieved field:", field);
27+
28+
// Update a contact field
29+
const updatedField = await client.contactFields.update(firstField.id, {
30+
name: "Updated First Name",
31+
});
32+
console.log("Updated field:", updatedField);
33+
34+
// Delete a contact field
35+
await client.contactFields.delete(firstField.id);
36+
console.log("Field deleted successfully");
37+
} catch (error) {
38+
console.error("Error:", error);
39+
}
40+
}
41+
42+
contactFieldsExample();
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 ContactFields from "../../../lib/api/ContactFields";
4+
5+
describe("lib/api/ContactFields: ", () => {
6+
const accountId = 100;
7+
const contactFieldsAPI = new ContactFields(axios, accountId);
8+
9+
describe("class ContactFields(): ", () => {
10+
describe("init: ", () => {
11+
it("initializes with all necessary params.", () => {
12+
expect(contactFieldsAPI).toHaveProperty("create");
13+
expect(contactFieldsAPI).toHaveProperty("get");
14+
expect(contactFieldsAPI).toHaveProperty("getList");
15+
expect(contactFieldsAPI).toHaveProperty("update");
16+
expect(contactFieldsAPI).toHaveProperty("delete");
17+
});
18+
});
19+
});
20+
});
Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
import axios from "axios";
2+
import AxiosMockAdapter from "axios-mock-adapter";
3+
4+
import ContactFieldsApi from "../../../../lib/api/resources/ContactFields";
5+
import handleSendingError from "../../../../lib/axios-logger";
6+
import MailtrapError from "../../../../lib/MailtrapError";
7+
8+
import CONFIG from "../../../../config";
9+
import { ContactFieldOptions } from "../../../../types/api/contact-fields";
10+
11+
const { CLIENT_SETTINGS } = CONFIG;
12+
const { GENERAL_ENDPOINT } = CLIENT_SETTINGS;
13+
14+
describe("lib/api/resources/ContactFields: ", () => {
15+
let mock: AxiosMockAdapter;
16+
const accountId = 100;
17+
const contactFieldsAPI = new ContactFieldsApi(axios, accountId);
18+
19+
const createContactFieldRequest: ContactFieldOptions = {
20+
name: "Phone Number",
21+
merge_tag: "phone",
22+
data_type: "text",
23+
};
24+
25+
const createContactFieldResponse = {
26+
data: {
27+
id: 4134638,
28+
name: "Phone Number",
29+
merge_tag: "phone",
30+
data_type: "text",
31+
created_at: 1742820600230,
32+
updated_at: 1742820600230,
33+
},
34+
};
35+
36+
const updateContactFieldRequest: ContactFieldOptions = {
37+
name: "Mobile Phone",
38+
merge_tag: "mobile_phone",
39+
data_type: "text",
40+
};
41+
42+
const updateContactFieldResponse = {
43+
data: {
44+
id: 4134638,
45+
name: "Mobile Phone",
46+
merge_tag: "mobile_phone",
47+
data_type: "text",
48+
created_at: 1742820600230,
49+
updated_at: 1742820600230,
50+
},
51+
};
52+
53+
const getContactFieldResponse = {
54+
data: {
55+
id: 4134638,
56+
name: "Phone Number",
57+
merge_tag: "phone",
58+
data_type: "text",
59+
created_at: 1742820600230,
60+
updated_at: 1742820600230,
61+
},
62+
};
63+
64+
const getContactFieldsResponse = {
65+
data: [
66+
{
67+
id: 3059351,
68+
name: "First name",
69+
merge_tag: "first_name",
70+
data_type: "text",
71+
created_at: 1742820600230,
72+
updated_at: 1742820600230,
73+
},
74+
{
75+
id: 3059352,
76+
name: "Last name",
77+
merge_tag: "last_name",
78+
data_type: "text",
79+
created_at: 1742820600230,
80+
updated_at: 1742820600230,
81+
},
82+
],
83+
};
84+
85+
describe("class ContactFieldsApi(): ", () => {
86+
describe("init: ", () => {
87+
it("initializes with all necessary params.", () => {
88+
expect(contactFieldsAPI).toHaveProperty("create");
89+
expect(contactFieldsAPI).toHaveProperty("get");
90+
expect(contactFieldsAPI).toHaveProperty("getList");
91+
expect(contactFieldsAPI).toHaveProperty("update");
92+
expect(contactFieldsAPI).toHaveProperty("delete");
93+
});
94+
});
95+
});
96+
97+
beforeAll(() => {
98+
/**
99+
* Init Axios interceptors for handling response.data, errors.
100+
*/
101+
axios.interceptors.response.use(
102+
(response) => response.data,
103+
handleSendingError
104+
);
105+
mock = new AxiosMockAdapter(axios);
106+
});
107+
108+
afterEach(() => {
109+
mock.reset();
110+
});
111+
112+
describe("getList(): ", () => {
113+
it("successfully gets all contact fields.", async () => {
114+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields`;
115+
const expectedResponseData = getContactFieldsResponse;
116+
117+
expect.assertions(2);
118+
119+
mock.onGet(endpoint).reply(200, expectedResponseData);
120+
const result = await contactFieldsAPI.getList();
121+
122+
expect(mock.history.get[0].url).toEqual(endpoint);
123+
expect(result).toEqual(expectedResponseData);
124+
});
125+
126+
it("fails with error when getting contact fields.", async () => {
127+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields`;
128+
const expectedErrorMessage = "Request failed with status code 500";
129+
130+
expect.assertions(2);
131+
132+
mock.onGet(endpoint).reply(500, { error: expectedErrorMessage });
133+
134+
try {
135+
await contactFieldsAPI.getList();
136+
} catch (error) {
137+
expect(error).toBeInstanceOf(MailtrapError);
138+
if (error instanceof MailtrapError) {
139+
expect(error.message).toEqual(expectedErrorMessage);
140+
}
141+
}
142+
});
143+
});
144+
145+
describe("get(): ", () => {
146+
const fieldId = 4134638;
147+
148+
it("successfully gets a contact field by ID.", async () => {
149+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields/${fieldId}`;
150+
const expectedResponseData = getContactFieldResponse;
151+
152+
expect.assertions(2);
153+
154+
mock.onGet(endpoint).reply(200, expectedResponseData);
155+
const result = await contactFieldsAPI.get(fieldId);
156+
157+
expect(mock.history.get[0].url).toEqual(endpoint);
158+
expect(result).toEqual(expectedResponseData);
159+
});
160+
161+
it("fails with error when getting a contact field.", async () => {
162+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields/${fieldId}`;
163+
const expectedErrorMessage = "Contact field not found";
164+
165+
expect.assertions(2);
166+
167+
mock.onGet(endpoint).reply(404, { error: expectedErrorMessage });
168+
169+
try {
170+
await contactFieldsAPI.get(fieldId);
171+
} catch (error) {
172+
expect(error).toBeInstanceOf(MailtrapError);
173+
if (error instanceof MailtrapError) {
174+
expect(error.message).toEqual(expectedErrorMessage);
175+
}
176+
}
177+
});
178+
});
179+
180+
describe("create(): ", () => {
181+
it("successfully creates a contact field.", async () => {
182+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields`;
183+
const expectedResponseData = createContactFieldResponse;
184+
185+
expect.assertions(2);
186+
187+
mock
188+
.onPost(endpoint, createContactFieldRequest)
189+
.reply(200, expectedResponseData);
190+
const result = await contactFieldsAPI.create(createContactFieldRequest);
191+
192+
expect(mock.history.post[0].url).toEqual(endpoint);
193+
expect(result).toEqual(expectedResponseData);
194+
});
195+
196+
it("fails with error when creating a contact field.", async () => {
197+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields`;
198+
const expectedErrorMessage = "Request failed with status code 422";
199+
200+
expect.assertions(2);
201+
202+
mock.onPost(endpoint).reply(422, { error: expectedErrorMessage });
203+
204+
try {
205+
await contactFieldsAPI.create(createContactFieldRequest);
206+
} catch (error) {
207+
expect(error).toBeInstanceOf(MailtrapError);
208+
if (error instanceof MailtrapError) {
209+
expect(error.message).toEqual(expectedErrorMessage);
210+
}
211+
}
212+
});
213+
});
214+
215+
describe("update(): ", () => {
216+
const fieldId = 4134638;
217+
218+
it("successfully updates a contact field.", async () => {
219+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields/${fieldId}`;
220+
const expectedResponseData = updateContactFieldResponse;
221+
222+
expect.assertions(2);
223+
224+
mock
225+
.onPatch(endpoint, updateContactFieldRequest)
226+
.reply(200, expectedResponseData);
227+
const result = await contactFieldsAPI.update(
228+
fieldId,
229+
updateContactFieldRequest
230+
);
231+
232+
expect(mock.history.patch[0].url).toEqual(endpoint);
233+
expect(result).toEqual(expectedResponseData);
234+
});
235+
236+
it("successfully updates a contact field with partial data.", async () => {
237+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields/${fieldId}`;
238+
const partialUpdateRequest = { name: "Work Phone" };
239+
const expectedResponseData = {
240+
data: {
241+
id: fieldId,
242+
name: "Work Phone",
243+
merge_tag: "phone",
244+
data_type: "text",
245+
created_at: 1742820600230,
246+
updated_at: 1742820600230,
247+
},
248+
};
249+
250+
expect.assertions(2);
251+
252+
mock
253+
.onPatch(endpoint, partialUpdateRequest)
254+
.reply(200, expectedResponseData);
255+
const result = await contactFieldsAPI.update(
256+
fieldId,
257+
partialUpdateRequest
258+
);
259+
260+
expect(mock.history.patch[0].url).toEqual(endpoint);
261+
expect(result).toEqual(expectedResponseData);
262+
});
263+
264+
it("fails with error when updating a contact field.", async () => {
265+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields/${fieldId}`;
266+
const expectedErrorMessage = "Request failed with status code 404";
267+
268+
expect.assertions(2);
269+
270+
mock.onPatch(endpoint).reply(404, { error: expectedErrorMessage });
271+
272+
try {
273+
await contactFieldsAPI.update(fieldId, updateContactFieldRequest);
274+
} catch (error) {
275+
expect(error).toBeInstanceOf(MailtrapError);
276+
if (error instanceof MailtrapError) {
277+
expect(error.message).toEqual(expectedErrorMessage);
278+
}
279+
}
280+
});
281+
});
282+
283+
describe("delete(): ", () => {
284+
const fieldId = 4134638;
285+
286+
it("successfully deletes a contact field.", async () => {
287+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields/${fieldId}`;
288+
289+
expect.assertions(1);
290+
291+
mock.onDelete(endpoint).reply(204);
292+
await contactFieldsAPI.delete(fieldId);
293+
294+
expect(mock.history.delete[0].url).toEqual(endpoint);
295+
});
296+
297+
it("fails with error when deleting a contact field.", async () => {
298+
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/fields/${fieldId}`;
299+
const expectedErrorMessage = "Request failed with status code 404";
300+
301+
expect.assertions(2);
302+
303+
mock.onDelete(endpoint).reply(404, { error: expectedErrorMessage });
304+
305+
try {
306+
await contactFieldsAPI.delete(fieldId);
307+
} catch (error) {
308+
expect(error).toBeInstanceOf(MailtrapError);
309+
if (error instanceof MailtrapError) {
310+
expect(error.message).toEqual(expectedErrorMessage);
311+
}
312+
}
313+
});
314+
});
315+
});

0 commit comments

Comments
 (0)