Initial hop. implementation and UGREEN NAS deployment guide
This commit is contained in:
66
apps/server/test/mail.test.ts
Normal file
66
apps/server/test/mail.test.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { createResendMailer } from '../src/mail.js';
|
||||
import { ApiError } from '../src/security.js';
|
||||
|
||||
test('Resend 키가 없으면 발송 모듈은 비활성', () => {
|
||||
assert.equal(createResendMailer({ mailFrom: 'hop. <hello@noname.company>' }), undefined);
|
||||
});
|
||||
test('Resend 발송 계약과 고정 중복 키: 키는 서버 Authorization에만 전달', async () => {
|
||||
const calls: { url: unknown; options: RequestInit | undefined }[] = [];
|
||||
const fakeFetch = (async (url: unknown, options: RequestInit) => {
|
||||
calls.push({ url, options });
|
||||
return new Response(JSON.stringify({ id: 'test-message' }), { status: 200 });
|
||||
}) as typeof fetch;
|
||||
const mailer = createResendMailer(
|
||||
{ resendApiKey: 're_test_fixture', mailFrom: 'hop. <hello@noname.company>' },
|
||||
fakeFetch,
|
||||
)!;
|
||||
await mailer({
|
||||
to: 'recipient@example.com',
|
||||
subject: '인증',
|
||||
text: 'test body',
|
||||
idempotencyKey: 'auth-verify-fixture',
|
||||
});
|
||||
assert.equal(calls.length, 1);
|
||||
assert.equal(calls[0]!.url, 'https://api.resend.com/emails');
|
||||
const options = calls[0]!.options!,
|
||||
headers = new Headers(options.headers);
|
||||
assert.equal(headers.get('Authorization'), 'Bearer re_test_fixture');
|
||||
assert.equal(headers.get('Idempotency-Key'), 'auth-verify-fixture');
|
||||
assert.equal(options.redirect, 'error');
|
||||
assert(options.signal instanceof AbortSignal);
|
||||
assert.deepEqual(JSON.parse(String(options.body)), {
|
||||
from: 'hop. <hello@noname.company>',
|
||||
to: ['recipient@example.com'],
|
||||
subject: '인증',
|
||||
text: 'test body',
|
||||
});
|
||||
assert(!String(options.body).includes('re_test_fixture'));
|
||||
});
|
||||
test('Resend 거절·타임아웃·잘못된 응답은 민감한 원문 없이 오류를 반환', async () => {
|
||||
for (const fakeFetch of [
|
||||
async () =>
|
||||
new Response(JSON.stringify({ message: 'private provider response re_test_fixture' }), {
|
||||
status: 401,
|
||||
}),
|
||||
async () => {
|
||||
throw Error('private credential re_test_fixture');
|
||||
},
|
||||
async () => new Response('{}', { status: 200 }),
|
||||
]) {
|
||||
const mailer = createResendMailer(
|
||||
{ resendApiKey: 're_test_fixture', mailFrom: 'hop. <hello@noname.company>' },
|
||||
fakeFetch as typeof fetch,
|
||||
)!;
|
||||
await assert.rejects(
|
||||
mailer({ to: 'recipient@example.com', subject: '인증', text: 'test body' }),
|
||||
(error) =>
|
||||
error instanceof ApiError &&
|
||||
error.code === 'MAIL_DELIVERY_FAILED' &&
|
||||
error.status === 503 &&
|
||||
!error.message.includes('re_test_fixture') &&
|
||||
!error.message.includes('private'),
|
||||
);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user