BREAKING CHANGE(mta): migrate internal MTA to @push.rocks/smartmta and remove legacy mail/deliverability implementation
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import * as errors from '../ts/errors/index.js';
|
||||
import {
|
||||
PlatformError,
|
||||
PlatformError,
|
||||
ValidationError,
|
||||
NetworkError,
|
||||
ResourceError,
|
||||
@@ -12,19 +12,6 @@ import {
|
||||
ErrorCategory,
|
||||
ErrorRecoverability
|
||||
} from '../ts/errors/error.codes.js';
|
||||
import {
|
||||
EmailServiceError,
|
||||
EmailTemplateError,
|
||||
EmailValidationError,
|
||||
EmailSendError,
|
||||
EmailReceiveError
|
||||
} from '../ts/errors/email.errors.js';
|
||||
import {
|
||||
MtaConnectionError,
|
||||
MtaAuthenticationError,
|
||||
MtaDeliveryError,
|
||||
MtaConfigurationError
|
||||
} from '../ts/errors/mta.errors.js';
|
||||
import {
|
||||
ErrorHandler
|
||||
} from '../ts/errors/error-handler.js';
|
||||
@@ -75,126 +62,6 @@ tap.test('Base error classes should set properties correctly', async () => {
|
||||
expect(resourceError.category).toEqual(ErrorCategory.RESOURCE);
|
||||
});
|
||||
|
||||
// Test 7: Error withRetry() method
|
||||
tap.test('PlatformError withRetry creates new instance with retry info', async () => {
|
||||
const originalError = new EmailSendError('Send failed', {
|
||||
data: { someData: true }
|
||||
});
|
||||
|
||||
const retryError = originalError.withRetry(3, 1, 1000);
|
||||
|
||||
// Verify it's a new instance
|
||||
expect(retryError === originalError).toEqual(false);
|
||||
expect(retryError).toBeInstanceOf(EmailSendError);
|
||||
|
||||
// Verify original data is preserved
|
||||
expect(retryError.context?.data?.someData).toEqual(true);
|
||||
|
||||
// Verify retry info is added
|
||||
expect(retryError.context?.retry?.maxRetries).toEqual(3);
|
||||
expect(retryError.context?.retry?.currentRetry).toEqual(1);
|
||||
expect(retryError.context?.retry?.retryDelay).toEqual(1000);
|
||||
expect(retryError.context?.retry?.nextRetryAt).toBeTypeofNumber();
|
||||
});
|
||||
|
||||
// Test email error classes
|
||||
tap.test('Email error classes should be properly constructed', async () => {
|
||||
try {
|
||||
// Test EmailServiceError
|
||||
const emailServiceError = new EmailServiceError('Email service error', {
|
||||
component: 'EmailService',
|
||||
operation: 'sendEmail'
|
||||
});
|
||||
expect(emailServiceError.code).toEqual('EMAIL_SERVICE_ERROR');
|
||||
expect(emailServiceError.name).toEqual('EmailServiceError');
|
||||
|
||||
// Test EmailTemplateError
|
||||
const templateError = new EmailTemplateError('Template not found: welcome_email', {
|
||||
data: { templateId: 'welcome_email' }
|
||||
});
|
||||
expect(templateError.code).toEqual('EMAIL_TEMPLATE_ERROR');
|
||||
expect(templateError.context.data?.templateId).toEqual('welcome_email');
|
||||
|
||||
// Test EmailSendError with permanent flag
|
||||
const permanentError = EmailSendError.permanent(
|
||||
'Invalid recipient: user@example.com',
|
||||
{ data: { details: 'DNS not found', recipient: 'user@example.com' } }
|
||||
);
|
||||
expect(permanentError.code).toEqual('EMAIL_SEND_ERROR');
|
||||
expect(permanentError.isPermanent()).toEqual(true);
|
||||
expect(permanentError.context.data?.permanent).toEqual(true);
|
||||
|
||||
// Test EmailSendError with temporary flag and retry
|
||||
const tempError = EmailSendError.temporary(
|
||||
'Server busy',
|
||||
3,
|
||||
0,
|
||||
1000,
|
||||
{ data: { server: 'smtp.example.com' } }
|
||||
);
|
||||
expect(tempError.isPermanent()).toEqual(false);
|
||||
expect(tempError.context.data?.permanent).toEqual(false);
|
||||
expect(tempError.context.retry?.maxRetries).toEqual(3);
|
||||
expect(tempError.shouldRetry()).toEqual(true);
|
||||
} catch (error) {
|
||||
console.error('Test failed with error:', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// Test MTA error classes
|
||||
tap.test('MTA error classes should be properly constructed', async () => {
|
||||
try {
|
||||
// Test MtaConnectionError
|
||||
const dnsError = MtaConnectionError.dnsError('mail.example.com', new Error('DNS lookup failed'));
|
||||
expect(dnsError.code).toEqual('MTA_CONNECTION_ERROR');
|
||||
expect(dnsError.category).toEqual(ErrorCategory.CONNECTIVITY);
|
||||
expect(dnsError.context.data?.hostname).toEqual('mail.example.com');
|
||||
|
||||
// Test MtaTimeoutError via MtaConnectionError.timeout
|
||||
const timeoutError = MtaConnectionError.timeout('mail.example.com', 25, 30000);
|
||||
expect(timeoutError.code).toEqual('MTA_CONNECTION_ERROR');
|
||||
expect(timeoutError.context.data?.timeout).toEqual(30000);
|
||||
|
||||
// Test MtaAuthenticationError
|
||||
const authError = MtaAuthenticationError.invalidCredentials('mail.example.com', 'user@example.com');
|
||||
expect(authError.code).toEqual('MTA_AUTHENTICATION_ERROR');
|
||||
expect(authError.category).toEqual(ErrorCategory.AUTHENTICATION);
|
||||
expect(authError.context.data?.username).toEqual('user@example.com');
|
||||
|
||||
// Test MtaDeliveryError
|
||||
const permDeliveryError = MtaDeliveryError.permanent(
|
||||
'User unknown',
|
||||
'nonexistent@example.com',
|
||||
'550',
|
||||
'550 5.1.1 User unknown',
|
||||
{}
|
||||
);
|
||||
expect(permDeliveryError.code).toEqual('MTA_DELIVERY_ERROR');
|
||||
expect(permDeliveryError.isPermanent()).toEqual(true);
|
||||
expect(permDeliveryError.getRecipientAddress()).toEqual('nonexistent@example.com');
|
||||
expect(permDeliveryError.getStatusCode()).toEqual('550');
|
||||
|
||||
// Test temporary delivery error with retry
|
||||
const tempDeliveryError = MtaDeliveryError.temporary(
|
||||
'Mailbox temporarily unavailable',
|
||||
'user@example.com',
|
||||
'450',
|
||||
'450 4.2.1 Mailbox temporarily unavailable',
|
||||
3,
|
||||
1,
|
||||
5000
|
||||
);
|
||||
expect(tempDeliveryError.isPermanent()).toEqual(false);
|
||||
expect(tempDeliveryError.shouldRetry()).toEqual(true);
|
||||
expect(tempDeliveryError.context.retry?.currentRetry).toEqual(1);
|
||||
expect(tempDeliveryError.context.retry?.maxRetries).toEqual(3);
|
||||
} catch (error) {
|
||||
console.error('MTA test failed with error:', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// Test error handler utility
|
||||
tap.test('ErrorHandler should properly handle and format errors', async () => {
|
||||
// Configure error handler
|
||||
@@ -291,7 +158,6 @@ tap.test('ErrorHandler should properly handle and format errors', async () => {
|
||||
// Test retry utilities
|
||||
tap.test('Error retry utilities should work correctly', async () => {
|
||||
let attempts = 0;
|
||||
const start = Date.now();
|
||||
|
||||
try {
|
||||
await errors.retry(
|
||||
@@ -383,7 +249,7 @@ tap.test('Error handling can be combined with retry for robust operations', asyn
|
||||
|
||||
// Reset and test failure case
|
||||
flaky.reset();
|
||||
|
||||
|
||||
try {
|
||||
await errors.retry(
|
||||
() => flaky(5, 'never reached'),
|
||||
@@ -405,4 +271,4 @@ tap.test('stop', async () => {
|
||||
await tap.stopForcefully();
|
||||
});
|
||||
|
||||
export default tap.start();
|
||||
export default tap.start();
|
||||
|
||||
Reference in New Issue
Block a user