Skip to content

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

Package listing

@kody/postmark

src/core.test.ts

188 lines · 5.9 KB · TypeScript
import assert from 'node:assert/strict'
import test from 'node:test'
import {
	DEFAULT_ACCOUNT_SECRET,
	DEFAULT_SERVER_SECRET,
	mutationPreview,
	parseAction,
	requireConfirm,
	resolveAccountSecretName,
	resolveServerSecretName,
	sanitizePostmarkPayload,
	secretSetupUrl,
} from './core.ts'
import { deleteDomain } from './domains.ts'
import { sendBatch, sendEmail, sendTemplateEmail } from './emails.ts'
import { deleteServer } from './servers.ts'

test('resolveServerSecretName defaults and suffixes accounts', () => {
	assert.equal(resolveServerSecretName(), DEFAULT_SERVER_SECRET)
	assert.equal(resolveServerSecretName({ account: 'default' }), DEFAULT_SERVER_SECRET)
	assert.equal(resolveServerSecretName({ account: 'work' }), 'postmark-work')
	assert.equal(resolveServerSecretName({ secretName: 'postmark-live' }), 'postmark-live')
})

test('resolveAccountSecretName defaults and suffixes accounts', () => {
	assert.equal(resolveAccountSecretName(), DEFAULT_ACCOUNT_SECRET)
	assert.equal(resolveAccountSecretName({ account: 'work' }), 'postmark-account-work')
	assert.equal(
		resolveAccountSecretName({ accountSecretName: 'postmark-account-live' }),
		'postmark-account-live',
	)
})

test('secret names reject Kent-style aliases and invalid labels', () => {
	assert.throws(() => resolveServerSecretName({ secretName: 'kentPostmark' }), /postmark or postmark-/)
	assert.throws(
		() => resolveAccountSecretName({ accountSecretName: 'POSTMARK_ACCOUNT_TOKEN' }),
		/postmark-account/,
	)
	assert.throws(() => resolveServerSecretName({ account: 'youtube-brand!' }), /short label/)
})

test('setup URLs stay prefilled on kody.codes', () => {
	assert.match(secretSetupUrl(), /https:\/\/kody\.codes\/account\/secrets\/new\?/)
	assert.match(secretSetupUrl(), /name=postmark/)
	assert.match(secretSetupUrl(), /allowedHosts=api\.postmarkapp\.com/)
	assert.match(secretSetupUrl('postmark-work', 'server'), /name=postmark-work/)
	assert.match(secretSetupUrl(DEFAULT_ACCOUNT_SECRET, 'account'), /name=postmark-account/)
	assert.match(secretSetupUrl(DEFAULT_ACCOUNT_SECRET, 'account'), /Account/)
})

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: '/email',
			body: { To: 'person@example.com' },
			requireConfirm: true,
			tokenKind: 'server',
		},
	)
	assert.deepEqual(preview, {
		dryRun: true,
		action: 'send email',
		method: 'POST',
		path: '/email',
		body: { To: 'person@example.com' },
		tokenKind: 'server',
	})
})

test('sanitizePostmarkPayload strips ApiTokens', () => {
	const sanitized = sanitizePostmarkPayload({
		ID: 12,
		Name: 'Transactional',
		ApiTokens: ['should-never-leak'],
		Servers: [{ ID: 1, ApiTokens: ['also-secret'], apiTokens: ['camel'] }],
	}) as {
		ID: number
		Name: string
		ApiTokens?: unknown
		Servers: Array<{ ID: number; ApiTokens?: unknown; apiTokens?: unknown }>
	}
	assert.equal(sanitized.ID, 12)
	assert.equal(sanitized.Name, 'Transactional')
	assert.equal(sanitized.ApiTokens, undefined)
	assert.equal(sanitized.Servers[0]?.ApiTokens, undefined)
	assert.equal(sanitized.Servers[0]?.apiTokens, undefined)
	assert.equal(sanitized.Servers[0]?.ID, 1)
})

test('parseAction defaults and rejects unknown actions', () => {
	assert.equal(parseAction(undefined, ['smoke-test', 'get-server'] as const, 'smoke-test', 'Postmark'), 'smoke-test')
	assert.throws(() => parseAction('explode', ['smoke-test'] as const, 'smoke-test', 'Postmark'), /Unknown Postmark/)
})

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',
		textBody: 'Hi',
		dryRun: true,
	})
	assert.deepEqual(preview, {
		dryRun: true,
		action: 'send email',
		method: 'POST',
		path: '/email',
		tokenKind: 'server',
		body: {
			From: 'Name <hello@example.com>',
			To: 'person@example.com',
			Subject: 'Hello',
			HtmlBody: undefined,
			TextBody: 'Hi',
			Cc: undefined,
			Bcc: undefined,
			ReplyTo: undefined,
			Tag: undefined,
			MessageStream: undefined,
			TrackOpens: undefined,
			TrackLinks: undefined,
			Metadata: undefined,
			Headers: undefined,
			Attachments: undefined,
		},
	})
})

test('sendEmail live path requires from, to, body, and confirm', async () => {
	await assert.rejects(
		() => sendEmail({ to: 'person@example.com', subject: 'Hi', textBody: 'x' } as never),
		/from is required/,
	)
	await assert.rejects(
		() =>
			sendEmail({
				from: 'Name <hello@example.com>',
				to: 'person@example.com',
				subject: 'Hi',
				textBody: 'x',
			}),
		/confirm: true/,
	)
})

test('sendBatch and sendTemplateEmail dryRun stay local', async () => {
	const batch = await sendBatch({
		dryRun: true,
		emails: [
			{
				from: 'Name <hello@example.com>',
				to: 'one@example.com',
				subject: 'One',
				textBody: '1',
			},
		],
	})
	assert.equal((batch as { dryRun: boolean }).dryRun, true)
	assert.equal((batch as { path: string }).path, '/email/batch')

	const templated = await sendTemplateEmail({
		from: 'Name <hello@example.com>',
		to: 'person@example.com',
		templateAlias: 'welcome',
		templateModel: { name: 'Ada' },
		dryRun: true,
	})
	assert.equal((templated as { dryRun: boolean }).dryRun, true)
	assert.equal((templated as { path: string }).path, '/email/withTemplate')
})

test('delete helpers require confirm unless dryRun', async () => {
	await assert.rejects(() => deleteServer({ serverId: 9 }), /confirm: true/)
	await assert.rejects(() => deleteDomain({ domainId: 3 }), /confirm: true/)
	const serverPreview = await deleteServer({ serverId: 9, dryRun: true })
	assert.equal((serverPreview as { dryRun: boolean }).dryRun, true)
	const domainPreview = await deleteDomain({ domainId: 3, dryRun: true })
	assert.equal((domainPreview as { dryRun: boolean }).dryRun, true)
})