-
Notifications
You must be signed in to change notification settings - Fork 11
Contacts api #64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Contacts api #64
Changes from all commits
Commits
Show all changes
65 commits
Select commit
Hold shift + click to select a range
7431edd
docs: update README to include Contacts API examples
narekhovhannisyan 55aaa1e
examples: add examples for listing contacts and contact lists using M…
narekhovhannisyan 0ae5397
feat: add getter for Contacts API in MailtrapClient
narekhovhannisyan ebc3855
feat: implement Contacts API class for managing contacts and contact …
narekhovhannisyan 497f1c5
feat: add ContactLists API class for managing contact lists
narekhovhannisyan 6598f3a
Merge branch 'batch-sending-api' of github.com:railsware/mailtrap-nod…
narekhovhannisyan 8b86d36
examples: add examples for creating, deleting, and updating contacts …
narekhovhannisyan 2e5af4d
types: add ContactFields and ContactData interfaces for managing cont…
narekhovhannisyan c7a75f3
refactor: update create and update methods in ContactsApi to use Cont…
narekhovhannisyan 62032eb
revert: remove deprecated example files for listing contacts and cont…
narekhovhannisyan 71c477f
examples: remove outdated contact example files and consolidate funct…
narekhovhannisyan 81d6ef9
docs: update Contacts API examples to consolidate and improve clarity
narekhovhannisyan 5ca3119
examples: add example for listing contact lists using MailtrapClient
narekhovhannisyan f992507
test: add comprehensive tests for contacts and contact lists API in M…
narekhovhannisyan 4a7d388
feat: add getter for Contact Lists API in MailtrapClient
narekhovhannisyan 63f4b79
test: refine update contact test to include email field in payload
narekhovhannisyan 91b0cde
test: format update contact test for improved readability
narekhovhannisyan 9f0a69a
docs: fix typo in Contacts API example file path in README
narekhovhannisyan e971cc8
fix: update ContactListsApi initialization to include accountId for p…
narekhovhannisyan 7f75f82
types: update custom_variables and template_variables types to accept…
narekhovhannisyan 47b77d4
fix: correct method call for deleting a contact in the contacts example
narekhovhannisyan 25619ca
Merge branch 'main' of github.com:railsware/mailtrap-nodejs into cont…
narekhovhannisyan 38ee629
feat: add ContactListsApi and ContactsApi classes for managing contac…
narekhovhannisyan ac9323b
refactor: rename ContactsApi and ContactListsApi imports for consistency
narekhovhannisyan 398c486
refactor: update MailtrapClient to use ContactsBaseAPI and remove Con…
narekhovhannisyan 891fff6
test: add unit tests for ContactListsApi and ContactsApi classes
narekhovhannisyan 535b25b
test: add unit tests for Contacts class initialization
narekhovhannisyan 72a7bd4
test: remove deprecated contact-related tests and update imports in m…
narekhovhannisyan ab67329
fix: update contact list retrieval to use the correct client structure
narekhovhannisyan c0d6116
docs: update README to include Contacts API section and correct links
narekhovhannisyan 608fb4f
fix: ensure newline at end of file in everything.ts
narekhovhannisyan df7e902
feat: add Contact interface and related types for managing contacts i…
narekhovhannisyan e972d48
feat: add ContactList and ContactListData interfaces for API contact …
narekhovhannisyan b168aa7
resources: update ContactsApi to use new ContactUpdateData type and i…
narekhovhannisyan 32f5cbd
resources: enhance ContactListsApi to return typed contact lists for …
narekhovhannisyan 317e038
fix: update logging for contact lists retrieval to display full respo…
narekhovhannisyan d0a2a1e
test: update error handling test for ContactLists API to check for 40…
narekhovhannisyan de5cb1c
fix: change Contact id type from number to string for better compatib…
narekhovhannisyan fb3d521
types: update Contact interface to include status and change timestam…
narekhovhannisyan 54365d2
resources: update ContactsApi to improve API methods for creating, up…
narekhovhannisyan e58c703
refactor: remove unused ContactListsApi class to streamline codebase
narekhovhannisyan ad40640
api: simplify ContactsBaseAPI by directly exposing ContactsApi method…
narekhovhannisyan 4344a16
test: update Contacts tests to use string contactId and add list() me…
narekhovhannisyan 7479575
test: remove ContactList tests as the ContactListsApi class has been …
narekhovhannisyan 1dedd74
test: update Contacts tests to verify presence of create, update, del…
narekhovhannisyan a155271
examples: remove deprecated contact-lists.ts file to clean up the cod…
narekhovhannisyan 36dc156
types: refactor Contact interface to export it and reorder properties…
narekhovhannisyan fb67805
resources: rename parameter in update method of ContactsApi for clarity
narekhovhannisyan 1bf1854
api: bind ContactsApi methods in ContactsBaseAPI to maintain context …
narekhovhannisyan 5c3e4ca
test: update Contacts test data for consistency and accuracy in updat…
narekhovhannisyan d697894
examples: enhance contact management by adding list functionality and…
narekhovhannisyan 44aa5e2
doc: update Contacts reference to everything.ts for improved clarity
narekhovhannisyan 18eef15
examples: remove contact listing code from everything.ts
narekhovhannisyan 3d18a03
api: remove list method binding from ContactsBaseAPI to streamline fu…
narekhovhannisyan e2eac12
resources: remove contactListsURL and list method from ContactsApi
narekhovhannisyan 8d01d01
test: change testInboxId to accountId in Contacts test suite
narekhovhannisyan 2c9e1c4
types: update ContactFields and ContactData interfaces to allow field…
narekhovhannisyan 86003d2
types: remove first_name and last_name fields from ContactFields inte…
narekhovhannisyan 5a4c562
test: remove list() tests from Contacts test suite following API changes
narekhovhannisyan ca246cd
resources: add get method to ContactsApi for retrieving a contact by …
narekhovhannisyan 970fe76
examples: update everything.ts to retrieve a contact by email before …
narekhovhannisyan 3532edb
test: add get method assertion to Contacts test suite
narekhovhannisyan a07ebbf
test: enhance Contacts test suite with get() method assertions for su…
narekhovhannisyan 272964f
api: bind get method in ContactsBaseAPI to enhance functionality
narekhovhannisyan 26f43e4
examples: refactor everything.ts to create a contact before retrievin…
narekhovhannisyan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { MailtrapClient } from "mailtrap"; | ||
|
||
const TOKEN = "<YOUR-TOKEN-HERE>"; | ||
const ACCOUNT_ID = "<YOUR-ACCOUNT-ID-HERE>" | ||
|
||
const client = new MailtrapClient({ | ||
token: TOKEN, | ||
accountId: ACCOUNT_ID | ||
}); | ||
|
||
const contactData = { | ||
email: "[email protected]", | ||
fields: { | ||
first_name: "John", | ||
last_name: "Smith" | ||
}, | ||
}; | ||
|
||
// Create contact first | ||
client.contacts | ||
.create(contactData) | ||
.then(async (createResponse) => { | ||
console.log("Contact created:", createResponse.data); | ||
const contactId = createResponse.data.id; | ||
|
||
// Get contact by email | ||
const getResponse = await client.contacts.get(contactData.email); | ||
console.log("Contact retrieved:", getResponse.data); | ||
|
||
// Update contact | ||
const updateResponse = await client.contacts | ||
.update(contactId, { | ||
email: contactData.email, | ||
fields: { | ||
first_name: "Johnny", | ||
last_name: "Smith", | ||
} | ||
}) | ||
console.log("Contact updated:", updateResponse.data); | ||
|
||
// Delete contact | ||
await client.contacts.delete(contactId); | ||
console.log("Contact deleted"); | ||
}) | ||
.catch(error => { | ||
console.error("Error in contact lifecycle:", error); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import axios from "axios"; | ||
|
||
import Contacts from "../../../lib/api/Contacts"; | ||
|
||
describe("lib/api/Contacts: ", () => { | ||
const accountId = 100; | ||
const contactsAPI = new Contacts(axios, accountId); | ||
|
||
describe("class Contacts(): ", () => { | ||
describe("init: ", () => { | ||
it("initalizes with all necessary params.", () => { | ||
expect(contactsAPI).toHaveProperty("create"); | ||
expect(contactsAPI).toHaveProperty("get"); | ||
expect(contactsAPI).toHaveProperty("update"); | ||
expect(contactsAPI).toHaveProperty("delete"); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
import axios from "axios"; | ||
import AxiosMockAdapter from "axios-mock-adapter"; | ||
|
||
import ContactsApi from "../../../../lib/api/resources/Contacts"; | ||
import handleSendingError from "../../../../lib/axios-logger"; | ||
import MailtrapError from "../../../../lib/MailtrapError"; | ||
|
||
import CONFIG from "../../../../config"; | ||
|
||
const { CLIENT_SETTINGS } = CONFIG; | ||
const { GENERAL_ENDPOINT } = CLIENT_SETTINGS; | ||
|
||
describe("lib/api/resources/Contacts: ", () => { | ||
let mock: AxiosMockAdapter; | ||
const accountId = 100; | ||
const contactsAPI = new ContactsApi(axios, accountId); | ||
|
||
const createContactRequest = { | ||
contact: { | ||
email: "[email protected]", | ||
fields: { | ||
first_name: "John", | ||
last_name: "Smith", | ||
}, | ||
list_ids: [1, 2, 3], | ||
}, | ||
}; | ||
|
||
const createContactResponse = { | ||
data: { | ||
id: "018dd5e3-f6d2-7c00-8f9b-e5c3f2d8a132", | ||
status: "subscribed", | ||
email: "[email protected]", | ||
fields: { | ||
first_name: "John", | ||
last_name: "Smith", | ||
}, | ||
list_ids: [1, 2, 3], | ||
created_at: 1742820600230, | ||
updated_at: 1742820600230, | ||
narekhovhannisyan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
}; | ||
|
||
const updateContactRequest = { | ||
contact: { | ||
email: "[email protected]", | ||
fields: { | ||
first_name: "John", | ||
last_name: "Smith", | ||
zip_code: "11111", | ||
}, | ||
list_ids_included: [1, 2, 3], | ||
list_ids_excluded: [4, 5, 6], | ||
unsubscribed: false, | ||
}, | ||
}; | ||
|
||
const updateContactResponse = { | ||
data: { | ||
id: "01972696-84ef-783b-8a87-48067db2d16b", | ||
email: "[email protected]", | ||
created_at: 1748699088076, | ||
updated_at: 1748700400794, | ||
list_ids: [], | ||
status: "subscribed", | ||
fields: { | ||
first_name: "Johnny", | ||
last_name: "Smith", | ||
}, | ||
}, | ||
}; | ||
|
||
describe("class ContactsApi(): ", () => { | ||
describe("init: ", () => { | ||
it("initializes with all necessary params.", () => { | ||
expect(contactsAPI).toHaveProperty("create"); | ||
expect(contactsAPI).toHaveProperty("update"); | ||
expect(contactsAPI).toHaveProperty("delete"); | ||
}); | ||
}); | ||
}); | ||
|
||
beforeAll(() => { | ||
/** | ||
* Init Axios interceptors for handling response.data, errors. | ||
*/ | ||
axios.interceptors.response.use( | ||
(response) => response.data, | ||
handleSendingError | ||
); | ||
mock = new AxiosMockAdapter(axios); | ||
}); | ||
|
||
afterEach(() => { | ||
mock.reset(); | ||
}); | ||
|
||
describe("get(): ", () => { | ||
it("successfully gets a contact by email.", async () => { | ||
const email = "[email protected]"; | ||
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/${email}`; | ||
const expectedResponseData = { | ||
data: { | ||
id: "018dd5e3-f6d2-7c00-8f9b-e5c3f2d8a132", | ||
email: "[email protected]", | ||
created_at: 1748699088076, | ||
updated_at: 1748699088076, | ||
list_ids: [1, 2, 3], | ||
status: "subscribed", | ||
fields: { | ||
first_name: "John", | ||
last_name: "Smith", | ||
zip_code: "11111", | ||
}, | ||
}, | ||
}; | ||
|
||
expect.assertions(2); | ||
|
||
mock.onGet(endpoint).reply(200, expectedResponseData); | ||
const result = await contactsAPI.get(email); | ||
|
||
expect(mock.history.get[0].url).toEqual(endpoint); | ||
expect(result).toEqual(expectedResponseData); | ||
}); | ||
|
||
it("fails with error when getting a contact.", async () => { | ||
const email = "[email protected]"; | ||
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/${email}`; | ||
const expectedErrorMessage = "Contact not found"; | ||
|
||
expect.assertions(2); | ||
|
||
mock.onGet(endpoint).reply(404, { error: expectedErrorMessage }); | ||
|
||
try { | ||
await contactsAPI.get(email); | ||
} catch (error) { | ||
expect(error).toBeInstanceOf(MailtrapError); | ||
if (error instanceof MailtrapError) { | ||
expect(error.message).toEqual(expectedErrorMessage); | ||
} | ||
} | ||
}); | ||
}); | ||
|
||
describe("create(): ", () => { | ||
it("successfully creates a contact.", async () => { | ||
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts`; | ||
const expectedResponseData = createContactResponse; | ||
|
||
expect.assertions(2); | ||
|
||
mock | ||
.onPost(endpoint, createContactRequest) | ||
.reply(200, expectedResponseData); | ||
const result = await contactsAPI.create(createContactRequest.contact); | ||
|
||
expect(mock.history.post[0].url).toEqual(endpoint); | ||
expect(result).toEqual(expectedResponseData); | ||
}); | ||
|
||
it("fails with error.", async () => { | ||
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts`; | ||
const expectedErrorMessage = "Request failed with status code 400"; | ||
|
||
expect.assertions(2); | ||
|
||
mock.onPost(endpoint).reply(400, { error: expectedErrorMessage }); | ||
|
||
try { | ||
await contactsAPI.create(createContactRequest.contact); | ||
} catch (error) { | ||
expect(error).toBeInstanceOf(MailtrapError); | ||
if (error instanceof MailtrapError) { | ||
expect(error.message).toEqual(expectedErrorMessage); | ||
} | ||
} | ||
}); | ||
}); | ||
|
||
describe("update(): ", () => { | ||
const contactId = "018dd5e3-f6d2-7c00-8f9b-e5c3f2d8a132"; | ||
|
||
it("successfully updates a contact.", async () => { | ||
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/${contactId}`; | ||
const expectedResponseData = updateContactResponse; | ||
|
||
expect.assertions(2); | ||
|
||
mock | ||
.onPatch(endpoint, updateContactRequest) | ||
.reply(200, expectedResponseData); | ||
const result = await contactsAPI.update( | ||
contactId, | ||
updateContactRequest.contact | ||
); | ||
|
||
expect(mock.history.patch[0].url).toEqual(endpoint); | ||
expect(result).toEqual(expectedResponseData); | ||
}); | ||
|
||
it("fails with error.", async () => { | ||
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/${contactId}`; | ||
const expectedErrorMessage = "Request failed with status code 404"; | ||
|
||
expect.assertions(2); | ||
|
||
mock.onPatch(endpoint).reply(404, { error: expectedErrorMessage }); | ||
|
||
try { | ||
await contactsAPI.update(contactId, updateContactRequest.contact); | ||
} catch (error) { | ||
expect(error).toBeInstanceOf(MailtrapError); | ||
if (error instanceof MailtrapError) { | ||
expect(error.message).toEqual(expectedErrorMessage); | ||
} | ||
} | ||
}); | ||
}); | ||
|
||
describe("delete(): ", () => { | ||
const contactId = "018dd5e3-f6d2-7c00-8f9b-e5c3f2d8a132"; | ||
|
||
it("successfully deletes a contact.", async () => { | ||
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/${contactId}`; | ||
const expectedResponseData = { | ||
data: { | ||
id: contactId, | ||
status: "unsubscribed", | ||
email: "[email protected]", | ||
fields: { | ||
first_name: "John", | ||
last_name: "Smith", | ||
}, | ||
list_ids: [], | ||
created_at: 1740659901189, | ||
updated_at: 1742903266889, | ||
}, | ||
}; | ||
|
||
expect.assertions(2); | ||
|
||
mock.onDelete(endpoint).reply(200, expectedResponseData); | ||
const result = await contactsAPI.delete(contactId); | ||
|
||
expect(mock.history.delete[0].url).toEqual(endpoint); | ||
expect(result).toEqual(expectedResponseData); | ||
}); | ||
|
||
it("fails with error.", async () => { | ||
const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/${contactId}`; | ||
const expectedErrorMessage = "Request failed with status code 404"; | ||
|
||
expect.assertions(2); | ||
|
||
mock.onDelete(endpoint).reply(404, { error: expectedErrorMessage }); | ||
|
||
try { | ||
await contactsAPI.delete(contactId); | ||
} catch (error) { | ||
expect(error).toBeInstanceOf(MailtrapError); | ||
if (error instanceof MailtrapError) { | ||
expect(error.message).toEqual(expectedErrorMessage); | ||
} | ||
} | ||
}); | ||
}); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.