Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/resend

src/resend-core.test.ts

108 lines · 3.8 KB · TypeScript
import assert from 'node:assert/strict'
import test from 'node:test'
import { deleteContact } from './contacts.ts'
import { deleteDomain } from './domains.ts'
import { sendEmail } from './emails.ts'
import {
	DEFAULT_AUTH_NAME,
	mutationPreview,
	oauthConnectUrl,
	parseAction,
	requireConfirm,
	resolveIntegrationName,
	resolveSecretName,
	secretSetupUrl,
} from './resend-core.ts'
import { deleteTemplate } from './templates.ts'

test('resolveSecretName defaults and suffixes accounts', () => {
	assert.equal(resolveSecretName(), DEFAULT_AUTH_NAME)
	assert.equal(resolveSecretName({ account: 'default' }), DEFAULT_AUTH_NAME)
	assert.equal(resolveSecretName({ account: 'work' }), 'resend-work')
	assert.equal(resolveSecretName({ secretName: 'resend-live' }), 'resend-live')
})

test('resolveSecretName rejects Kent-style aliases and invalid names', () => {
	assert.throws(() => resolveSecretName({ secretName: 'resendApiKey' }), /resend or resend-/)
	assert.throws(() => resolveSecretName({ account: 'youtube-brand!' }), /short label/)
})

test('resolveIntegrationName is optional and uses the same name pattern', () => {
	assert.equal(resolveIntegrationName(), undefined)
	assert.equal(resolveIntegrationName({ integration: 'resend' }), 'resend')
	assert.equal(resolveIntegrationName({ integration: 'resend-work' }), 'resend-work')
	assert.throws(() => resolveIntegrationName({ integration: 'resend_oauth' }), /resend or resend-/)
})

test('setup URLs stay prefilled on kody.codes', () => {
	assert.match(secretSetupUrl(), /https:\/\/kody\.codes\/account\/secrets\/new\?/)
	assert.match(secretSetupUrl(), /name=resend/)
	assert.match(secretSetupUrl(), /allowedHosts=api\.resend\.com/)
	assert.match(secretSetupUrl('resend-work'), /name=resend-work/)
	assert.match(oauthConnectUrl(), /https:\/\/kody\.codes\/connect\/oauth\?/)
	assert.match(oauthConnectUrl(), /provider=resend/)
	assert.match(oauthConnectUrl(), /authorizeUrl=https%3A%2F%2Fapi\.resend\.com%2Foauth%2Fauthorize/)
	assert.match(oauthConnectUrl(), /scopes=full_access/)
})

test('requireConfirm blocks live mutations', () => {
	assert.throws(() => requireConfirm({}, 'send email'), /confirm: true/)
	requireConfirm({ confirm: true }, 'send email')
})

test('mutationPreview dryRun skips confirm', () => {
	const preview = mutationPreview(
		{ dryRun: true },
		{
			action: 'send email',
			method: 'POST',
			path: '/emails',
			body: { to: 'person@example.com' },
			requireConfirm: true,
		},
	)
	assert.deepEqual(preview, {
		dryRun: true,
		action: 'send email',
		method: 'POST',
		path: '/emails',
		body: { to: 'person@example.com' },
	})
})

test('sendEmail dryRun does not require confirm or a network call', async () => {
	const preview = await sendEmail({
		from: 'Name <hello@example.com>',
		to: 'person@example.com',
		subject: 'Hello',
		text: 'Hi',
		dryRun: true,
	})
	assert.equal(preview.dryRun, true)
	assert.equal(preview.path, '/emails')
	assert.equal((preview.body as { from?: string }).from, 'Name <hello@example.com>')
})

test('sendEmail without confirm or dryRun throws', async () => {
	await assert.rejects(
		sendEmail({
			from: 'Name <hello@example.com>',
			to: 'person@example.com',
			subject: 'Hello',
			text: 'Hi',
		}),
		/confirm: true/,
	)
})

test('delete helpers without confirm or dryRun throw', async () => {
	await assert.rejects(deleteDomain({ domainId: 'dom_123' }), /confirm: true/)
	await assert.rejects(deleteContact({ idOrEmail: 'ada@example.com' }), /confirm: true/)
	await assert.rejects(deleteTemplate({ templateId: 'tmpl_123' }), /confirm: true/)
})

test('parseAction is exhaustive for known unions', () => {
	const allowed = ['list-domains', 'get-domain'] as const
	assert.equal(parseAction(undefined, allowed, 'list-domains', 'domains'), 'list-domains')
	assert.throws(() => parseAction('explode', allowed, 'list-domains', 'domains'), /explode/)
})