import { tap, expect } from '@push.rocks/tapbundle'; import * as plugins from '../ts/plugins.js'; import * as paths from '../ts/paths.js'; // Import the components we want to test import { EmailValidator } from '../ts/mail/core/classes.emailvalidator.js'; import { TemplateManager } from '../ts/mail/core/classes.templatemanager.js'; import { Email } from '../ts/mail/core/classes.email.js'; // Ensure test directories exist paths.ensureDirectories(); tap.test('EmailValidator - should validate email formats correctly', async (tools) => { const validator = new EmailValidator(); // Test valid email formats expect(validator.isValidFormat('user@example.com')).toBeTrue(); expect(validator.isValidFormat('firstname.lastname@example.com')).toBeTrue(); expect(validator.isValidFormat('user+tag@example.com')).toBeTrue(); // Test invalid email formats expect(validator.isValidFormat('user@')).toBeFalse(); expect(validator.isValidFormat('@example.com')).toBeFalse(); expect(validator.isValidFormat('user@example')).toBeFalse(); expect(validator.isValidFormat('user.example.com')).toBeFalse(); }); tap.test('EmailValidator - should perform comprehensive validation', async (tools) => { const validator = new EmailValidator(); // Test basic validation (syntax-only) const basicResult = await validator.validate('user@example.com', { checkSyntaxOnly: true }); expect(basicResult.isValid).toBeTrue(); expect(basicResult.details.formatValid).toBeTrue(); // We can't reliably test MX validation in all environments, but the function should run const mxResult = await validator.validate('user@example.com', { checkMx: true }); expect(typeof mxResult.isValid).toEqual('boolean'); expect(typeof mxResult.hasMx).toEqual('boolean'); }); tap.test('EmailValidator - should detect invalid emails', async (tools) => { const validator = new EmailValidator(); const invalidResult = await validator.validate('invalid@@example.com', { checkSyntaxOnly: true }); expect(invalidResult.isValid).toBeFalse(); expect(invalidResult.details.formatValid).toBeFalse(); }); tap.test('TemplateManager - should register and retrieve templates', async (tools) => { const templateManager = new TemplateManager({ from: 'test@example.com' }); // Register a custom template templateManager.registerTemplate({ id: 'test-template', name: 'Test Template', description: 'A test template', from: 'test@example.com', subject: 'Test Subject: {{name}}', bodyHtml: '

Hello, {{name}}!

', bodyText: 'Hello, {{name}}!', category: 'test' }); // Get the template back const template = templateManager.getTemplate('test-template'); expect(template).toBeTruthy(); expect(template.id).toEqual('test-template'); expect(template.subject).toEqual('Test Subject: {{name}}'); // List templates const templates = templateManager.listTemplates(); expect(templates.length > 0).toBeTrue(); expect(templates.some(t => t.id === 'test-template')).toBeTrue(); }); tap.test('TemplateManager - should create smartmail from template', async (tools) => { const templateManager = new TemplateManager({ from: 'test@example.com' }); // Register a template templateManager.registerTemplate({ id: 'welcome-test', name: 'Welcome Test', description: 'A welcome test template', from: 'welcome@example.com', subject: 'Welcome, {{name}}!', bodyHtml: '

Hello, {{name}}! Welcome to our service.

', bodyText: 'Hello, {{name}}! Welcome to our service.', category: 'test' }); // Create smartmail from template const smartmail = await templateManager.createSmartmail('welcome-test', { name: 'John Doe' }); expect(smartmail).toBeTruthy(); expect(smartmail.options.from).toEqual('welcome@example.com'); expect(smartmail.getSubject()).toEqual('Welcome, John Doe!'); expect(smartmail.getBody(true).indexOf('Hello, John Doe!') > -1).toBeTrue(); }); tap.test('Email - should handle template variables', async (tools) => { // Create email with variables const email = new Email({ from: 'sender@example.com', to: 'recipient@example.com', subject: 'Hello {{name}}!', text: 'Welcome, {{name}}! Your order #{{orderId}} has been processed.', html: '

Welcome, {{name}}! Your order #{{orderId}} has been processed.

', variables: { name: 'John Doe', orderId: '12345' } }); // Test variable substitution expect(email.getSubjectWithVariables()).toEqual('Hello John Doe!'); expect(email.getTextWithVariables()).toEqual('Welcome, John Doe! Your order #12345 has been processed.'); expect(email.getHtmlWithVariables().indexOf('John Doe') > -1).toBeTrue(); // Test with additional variables const additionalVars = { name: 'Jane Smith', // Override existing variable status: 'shipped' // Add new variable }; expect(email.getSubjectWithVariables(additionalVars)).toEqual('Hello Jane Smith!'); // Add a new variable email.setVariable('trackingNumber', 'TRK123456'); expect(email.getTextWithVariables().indexOf('12345') > -1).toBeTrue(); // Update multiple variables at once email.setVariables({ orderId: '67890', status: 'delivered' }); expect(email.getTextWithVariables().indexOf('67890') > -1).toBeTrue(); }); tap.test('Email and Smartmail compatibility - should convert between formats', async (tools) => { // Create a Smartmail instance const smartmail = new plugins.smartmail.Smartmail({ from: 'smartmail@example.com', subject: 'Test Subject', body: '

This is a test email.

', creationObjectRef: { orderId: '12345' } }); // Add recipient and attachment smartmail.addRecipient('recipient@example.com'); const attachment = await plugins.smartfile.SmartFile.fromString( 'test.txt', 'This is a test attachment', 'utf8', ); smartmail.addAttachment(attachment); // Convert to Email const resolvedSmartmail = await smartmail; const email = Email.fromSmartmail(resolvedSmartmail); // Verify first conversion (Smartmail to Email) expect(email.from).toEqual('smartmail@example.com'); expect(email.to.indexOf('recipient@example.com') > -1).toBeTrue(); expect(email.subject).toEqual('Test Subject'); expect(email.html?.indexOf('This is a test email') > -1).toBeTrue(); expect(email.attachments.length).toEqual(1); // Convert back to Smartmail const convertedSmartmail = await email.toSmartmail(); // Verify second conversion (Email back to Smartmail) with simplified assertions expect(convertedSmartmail.options.from).toEqual('smartmail@example.com'); expect(Array.isArray(convertedSmartmail.options.to)).toBeTrue(); expect(convertedSmartmail.options.to.length).toEqual(1); expect(convertedSmartmail.getSubject()).toEqual('Test Subject'); expect(convertedSmartmail.getBody(true).indexOf('This is a test email') > -1).toBeTrue(); expect(convertedSmartmail.attachments.length).toEqual(1); }); tap.test('Email - should validate email addresses', async (tools) => { // Attempt to create an email with invalid addresses let errorThrown = false; try { const email = new Email({ from: 'invalid-email', to: 'recipient@example.com', subject: 'Test', text: 'Test' }); } catch (error) { errorThrown = true; expect(error.message.indexOf('Invalid sender email address') > -1).toBeTrue(); } expect(errorThrown).toBeTrue(); // Attempt with invalid recipient errorThrown = false; try { const email = new Email({ from: 'sender@example.com', to: 'invalid-recipient', subject: 'Test', text: 'Test' }); } catch (error) { errorThrown = true; expect(error.message.indexOf('Invalid recipient email address') > -1).toBeTrue(); } expect(errorThrown).toBeTrue(); // Valid email should not throw let validEmail: Email; try { validEmail = new Email({ from: 'sender@example.com', to: 'recipient@example.com', subject: 'Test', text: 'Test' }); expect(validEmail).toBeTruthy(); expect(validEmail.from).toEqual('sender@example.com'); } catch (error) { expect(error === undefined).toBeTrue(); // This should not happen } }); tap.test('stop', async () => { tap.stopForcefully(); }) export default tap.start();