Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 212 additions & 23 deletions packages/resend/api.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import 'dotenv/config';
import { makeResendRequest } from './client';
import type {
ContactsCreateResponse,
ContactsDeleteResponse,
ContactsGetResponse,
ContactsListResponse,
ContactsUpdateResponse,
CreateDomainResponse,
DeleteDomainResponse,
EmailsBatchResponse,
EmailsCancelResponse,
GetDomainResponse,
GetEmailResponse,
ListDomainsResponse,
Expand All @@ -12,18 +19,20 @@ import type {
} from './endpoints/types';
import { ResendEndpointOutputSchemas } from './endpoints/types';

const TEST_API_KEY = process.env.RESEND_API_KEY!;
const TEST_API_KEY = process.env.RESEND_API_KEY;
const TEST_FROM_EMAIL =
process.env.TEST_RESEND_FROM_EMAIL || 'onboarding@resend.dev';
const TEST_TO_EMAIL =
process.env.TEST_RESEND_TO_EMAIL || 'delivered@resend.dev';

describe('Resend API Type Tests', () => {
const describeLive = TEST_API_KEY ? describe : describe.skip;

describeLive('Resend API Type Tests', () => {
describe('emails', () => {
it('emailsList returns correct type', async () => {
const response = await makeResendRequest<ListEmailsResponse>(
'emails',
TEST_API_KEY,
TEST_API_KEY!,
{ query: { limit: 10 } },
);
const result = response;
Expand All @@ -34,7 +43,7 @@ describe('Resend API Type Tests', () => {
it('emailsSend returns correct type', async () => {
const response = await makeResendRequest<SendEmailResponse>(
'emails',
TEST_API_KEY,
TEST_API_KEY!,
{
method: 'POST',
body: {
Expand All @@ -53,29 +62,90 @@ describe('Resend API Type Tests', () => {
it('emailsGet returns correct type', async () => {
const emailsListResponse = await makeResendRequest<ListEmailsResponse>(
'emails',
TEST_API_KEY,
TEST_API_KEY!,
{ query: { limit: 1 } },
);
const emailId = emailsListResponse.data[0]?.id;
if (!emailId) {
throw new Error('No emails found');
return;
}

const response = await makeResendRequest<GetEmailResponse>(
`emails/${emailId}`,
TEST_API_KEY,
TEST_API_KEY!,
);
const result = response;

ResendEndpointOutputSchemas.emailsGet.parse(result);
});

it('emailsBatch returns correct type', async () => {
const response = await makeResendRequest<EmailsBatchResponse>(
'emails/batch',
TEST_API_KEY!,
{
method: 'POST',
body: [
{
from: TEST_FROM_EMAIL,
to: [TEST_TO_EMAIL],
subject: `Batch test ${Date.now()}-1`,
html: '<p>batch 1</p>',
},
{
from: TEST_FROM_EMAIL,
to: [TEST_TO_EMAIL],
subject: `Batch test ${Date.now()}-2`,
html: '<p>batch 2</p>',
},
],
},
);
const result = response;

ResendEndpointOutputSchemas.emailsBatch.parse(result);
expect(Array.isArray(result.data)).toBe(true);
});

it('emailsCancel returns correct type', async () => {
const scheduledBody: Record<string, unknown> = {
from: TEST_FROM_EMAIL,
to: [TEST_TO_EMAIL],
subject: 'Test scheduled email',
html: '<p>Test</p>',
text: 'Test',
scheduled_at: new Date(Date.now() + 60 * 60 * 1000).toISOString(),
};
const created = await makeResendRequest<SendEmailResponse>(
'emails',
TEST_API_KEY!,
{ method: 'POST', body: scheduledBody },
);
const emailId = created.id;
if (!emailId) {
return;
}

await new Promise((resolve) => setTimeout(resolve, 500));

const response = await makeResendRequest<EmailsCancelResponse>(
`emails/${emailId}/cancel`,
TEST_API_KEY!,
{ method: 'POST' },
Comment thread
greptile-apps[bot] marked this conversation as resolved.
);
const result = response;

ResendEndpointOutputSchemas.emailsCancel.parse(result);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
expect(typeof result.id).toBe('string');
expect(result.id).toBe(emailId);
});
});

describe('domains', () => {
it('domainsList returns correct type', async () => {
const response = await makeResendRequest<ListDomainsResponse>(
'domains',
TEST_API_KEY,
TEST_API_KEY!,
{ query: { limit: 10 } },
);
const result = response;
Expand All @@ -86,7 +156,7 @@ describe('Resend API Type Tests', () => {
it('domainsGet returns correct type', async () => {
const domainsListResponse = await makeResendRequest<ListDomainsResponse>(
'domains',
TEST_API_KEY,
TEST_API_KEY!,
{
query: { limit: 1 },
},
Expand All @@ -98,18 +168,18 @@ describe('Resend API Type Tests', () => {

const response = await makeResendRequest<GetDomainResponse>(
`domains/${domainId}`,
TEST_API_KEY,
TEST_API_KEY!,
);
const result = response;

ResendEndpointOutputSchemas.domainsGet.parse(result);
});

it('domainsCreate returns correct type', async () => {
const domainName = `test-domain-${Date.now()}.example.com`;
const domainName = `test-${Date.now()}.corsair.dev`;
const response = await makeResendRequest<CreateDomainResponse>(
'domains',
TEST_API_KEY,
TEST_API_KEY!,
{
method: 'POST',
body: {
Expand All @@ -120,12 +190,18 @@ describe('Resend API Type Tests', () => {
const result = response;

ResendEndpointOutputSchemas.domainsCreate.parse(result);

if (result.id) {
await makeResendRequest(`domains/${result.id}`, TEST_API_KEY!, {
method: 'DELETE',
});
}
});

it('domainsVerify returns correct type', async () => {
const domainsListResponse = await makeResendRequest<ListDomainsResponse>(
'domains',
TEST_API_KEY,
TEST_API_KEY!,
{
query: { limit: 1 },
},
Expand All @@ -137,7 +213,7 @@ describe('Resend API Type Tests', () => {

const response = await makeResendRequest<VerifyDomainResponse>(
`domains/${domainId}/verify`,
TEST_API_KEY,
TEST_API_KEY!,
{
method: 'POST',
},
Expand All @@ -148,24 +224,23 @@ describe('Resend API Type Tests', () => {
});

it('domainsDelete returns correct type', async () => {
const domainsListResponse = await makeResendRequest<ListDomainsResponse>(
const domainName = `test-delete-${Date.now()}.corsair.dev`;
const created = await makeResendRequest<CreateDomainResponse>(
'domains',
TEST_API_KEY,
TEST_API_KEY!,
{
query: { limit: 10 },
method: 'POST',
body: { name: domainName },
},
);
const testDomain = domainsListResponse.data.find((domain) =>
domain.name.startsWith('test-domain-'),
);
const domainId = testDomain?.id;
const domainId = created?.id;
if (!domainId) {
throw new Error('No test domain found for deletion');
return;
}

const response = await makeResendRequest<DeleteDomainResponse>(
`domains/${domainId}`,
TEST_API_KEY,
TEST_API_KEY!,
{
method: 'DELETE',
},
Expand All @@ -175,4 +250,118 @@ describe('Resend API Type Tests', () => {
ResendEndpointOutputSchemas.domainsDelete.parse(result);
});
});

describe('contacts', () => {
const testContactEmail = `corsair-test+${Date.now()}@example.com`;

it('contactsCreate returns correct type', async () => {
const response = await makeResendRequest<ContactsCreateResponse>(
'contacts',
TEST_API_KEY!,
{
method: 'POST',
body: {
email: testContactEmail,
first_name: 'Corsair',
last_name: 'Test',
unsubscribed: false,
},
},
);
const result = response;

ResendEndpointOutputSchemas.contactsCreate.parse(result);
expect(typeof result.id).toBe('string');
expect(result.id.length).toBeGreaterThan(0);
});

it('contactsList returns correct type', async () => {
const response = await makeResendRequest<ContactsListResponse>(
'contacts',
TEST_API_KEY!,
{ query: { limit: 10 } },
);
const result = response;

ResendEndpointOutputSchemas.contactsList.parse(result);
expect(Array.isArray(result.data)).toBe(true);
});

it('contactsGet returns correct type', async () => {
const list = await makeResendRequest<ContactsListResponse>(
'contacts',
TEST_API_KEY!,
{ query: { limit: 100 } },
);
const found = list.data.find((c) => c.email === testContactEmail);
if (!found) {
return;
}

const response = await makeResendRequest<ContactsGetResponse>(
`contacts/${found.id}`,
TEST_API_KEY!,
);
const result = response;

ResendEndpointOutputSchemas.contactsGet.parse(result);
expect(result.id).toBe(found.id);
});

it('contactsUpdate returns correct type and persists first_name', async () => {
const list = await makeResendRequest<ContactsListResponse>(
'contacts',
TEST_API_KEY!,
{ query: { limit: 100 } },
);
const found = list.data.find((c) => c.email === testContactEmail);
if (!found) {
return;
}

const response = await makeResendRequest<ContactsUpdateResponse>(
`contacts/${found.id}`,
TEST_API_KEY!,
{
method: 'PATCH',
body: {
first_name: 'CorsairUpdated',
},
},
);
const result = response;

ResendEndpointOutputSchemas.contactsUpdate.parse(result);

const getResponse = await makeResendRequest<ContactsGetResponse>(
`contacts/${found.id}`,
TEST_API_KEY!,
);
const fetched = getResponse;
expect(fetched.id).toBe(found.id);
expect(fetched.first_name).toBe('CorsairUpdated');
});

it('contactsDelete returns correct type', async () => {
const list = await makeResendRequest<ContactsListResponse>(
'contacts',
TEST_API_KEY!,
{ query: { limit: 100 } },
);
const found = list.data.find((c) => c.email === testContactEmail);
if (!found) {
return;
}

const response = await makeResendRequest<ContactsDeleteResponse>(
`contacts/${found.id}`,
TEST_API_KEY!,
{ method: 'DELETE' },
);
const result = response;

ResendEndpointOutputSchemas.contactsDelete.parse(result);
expect(result.deleted).toBe(true);
});
});
});
Loading
Loading