383 lines
10 KiB
JavaScript
383 lines
10 KiB
JavaScript
// Mock dependencies
|
|
jest.mock('../../../../../services/email/core/EmailClient', () => {
|
|
return jest.fn().mockImplementation(() => ({
|
|
initialize: jest.fn().mockResolvedValue(),
|
|
sendEmail: jest.fn().mockResolvedValue({ success: true, messageId: 'msg-123' }),
|
|
}));
|
|
});
|
|
|
|
jest.mock('../../../../../services/email/core/TemplateManager', () => {
|
|
return jest.fn().mockImplementation(() => ({
|
|
initialize: jest.fn().mockResolvedValue(),
|
|
renderTemplate: jest.fn().mockResolvedValue('<html>Test</html>'),
|
|
}));
|
|
});
|
|
|
|
jest.mock('../../../../../utils/logger', () => ({
|
|
info: jest.fn(),
|
|
error: jest.fn(),
|
|
warn: jest.fn(),
|
|
}));
|
|
|
|
const CustomerServiceEmailService = require('../../../../../services/email/domain/CustomerServiceEmailService');
|
|
|
|
describe('CustomerServiceEmailService', () => {
|
|
let service;
|
|
const originalEnv = process.env;
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
process.env = {
|
|
...originalEnv,
|
|
CUSTOMER_SUPPORT_EMAIL: 'support@example.com',
|
|
};
|
|
service = new CustomerServiceEmailService();
|
|
});
|
|
|
|
afterEach(() => {
|
|
process.env = originalEnv;
|
|
});
|
|
|
|
describe('initialize', () => {
|
|
it('should initialize only once', async () => {
|
|
await service.initialize();
|
|
await service.initialize();
|
|
|
|
expect(service.emailClient.initialize).toHaveBeenCalledTimes(1);
|
|
expect(service.templateManager.initialize).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe('sendLateReturnToCustomerService', () => {
|
|
const rental = {
|
|
id: 123,
|
|
endDateTime: '2024-01-16T10:00:00Z',
|
|
actualReturnDateTime: '2024-01-16T15:00:00Z',
|
|
item: { name: 'Power Drill' },
|
|
};
|
|
const owner = {
|
|
firstName: 'John',
|
|
lastName: 'Doe',
|
|
email: 'john@example.com',
|
|
};
|
|
const renter = {
|
|
firstName: 'Jane',
|
|
lastName: 'Smith',
|
|
email: 'jane@example.com',
|
|
};
|
|
const lateCalculation = {
|
|
lateHours: 5,
|
|
lateFee: 25.00,
|
|
};
|
|
|
|
it('should send late return notification with correct variables', async () => {
|
|
const result = await service.sendLateReturnToCustomerService(
|
|
rental,
|
|
owner,
|
|
renter,
|
|
lateCalculation
|
|
);
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(service.templateManager.renderTemplate).toHaveBeenCalledWith(
|
|
'lateReturnToCS',
|
|
expect.objectContaining({
|
|
rentalId: 123,
|
|
itemName: 'Power Drill',
|
|
ownerName: 'John Doe',
|
|
ownerEmail: 'john@example.com',
|
|
renterName: 'Jane Smith',
|
|
renterEmail: 'jane@example.com',
|
|
hoursLate: '5.0',
|
|
lateFee: '25.00',
|
|
})
|
|
);
|
|
expect(service.emailClient.sendEmail).toHaveBeenCalledWith(
|
|
'support@example.com',
|
|
'Late Return Detected - Action Required',
|
|
expect.any(String)
|
|
);
|
|
});
|
|
|
|
it('should return error when customer service email is not configured', async () => {
|
|
delete process.env.CUSTOMER_SUPPORT_EMAIL;
|
|
|
|
const result = await service.sendLateReturnToCustomerService(
|
|
rental,
|
|
owner,
|
|
renter,
|
|
lateCalculation
|
|
);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toBe('No customer service email configured');
|
|
expect(service.emailClient.sendEmail).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle errors gracefully', async () => {
|
|
service.templateManager.renderTemplate.mockRejectedValueOnce(new Error('Template error'));
|
|
|
|
const result = await service.sendLateReturnToCustomerService(
|
|
rental,
|
|
owner,
|
|
renter,
|
|
lateCalculation
|
|
);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toBe('Template error');
|
|
});
|
|
});
|
|
|
|
describe('sendDamageReportToCustomerService', () => {
|
|
const rental = {
|
|
id: 123,
|
|
item: { name: 'Power Drill' },
|
|
};
|
|
const owner = {
|
|
firstName: 'John',
|
|
lastName: 'Doe',
|
|
email: 'john@example.com',
|
|
};
|
|
const renter = {
|
|
firstName: 'Jane',
|
|
lastName: 'Smith',
|
|
email: 'jane@example.com',
|
|
};
|
|
const damageAssessment = {
|
|
description: 'Drill bit broken',
|
|
canBeFixed: true,
|
|
repairCost: 30,
|
|
needsReplacement: false,
|
|
replacementCost: null,
|
|
feeCalculation: {
|
|
type: 'repair',
|
|
amount: 30,
|
|
},
|
|
proofOfOwnership: ['receipt.jpg'],
|
|
};
|
|
|
|
it('should send damage report with correct variables', async () => {
|
|
const result = await service.sendDamageReportToCustomerService(
|
|
rental,
|
|
owner,
|
|
renter,
|
|
damageAssessment
|
|
);
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(service.templateManager.renderTemplate).toHaveBeenCalledWith(
|
|
'damageReportToCS',
|
|
expect.objectContaining({
|
|
rentalId: 123,
|
|
itemName: 'Power Drill',
|
|
ownerName: 'John Doe',
|
|
ownerEmail: 'john@example.com',
|
|
renterName: 'Jane Smith',
|
|
renterEmail: 'jane@example.com',
|
|
damageDescription: 'Drill bit broken',
|
|
canBeFixed: 'Yes',
|
|
repairCost: '30.00',
|
|
needsReplacement: 'No',
|
|
feeTypeDescription: 'Repair Cost',
|
|
damageFee: '30.00',
|
|
lateFee: '0.00',
|
|
totalFees: '30.00',
|
|
hasProofOfOwnership: 'Yes',
|
|
})
|
|
);
|
|
expect(service.emailClient.sendEmail).toHaveBeenCalledWith(
|
|
'support@example.com',
|
|
'Damage Report Filed - Action Required',
|
|
expect.any(String)
|
|
);
|
|
});
|
|
|
|
it('should include late fee when provided', async () => {
|
|
const lateCalculation = { lateFee: 15 };
|
|
|
|
await service.sendDamageReportToCustomerService(
|
|
rental,
|
|
owner,
|
|
renter,
|
|
damageAssessment,
|
|
lateCalculation
|
|
);
|
|
|
|
expect(service.templateManager.renderTemplate).toHaveBeenCalledWith(
|
|
'damageReportToCS',
|
|
expect.objectContaining({
|
|
lateFee: '15.00',
|
|
totalFees: '45.00',
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should handle replacement fee type', async () => {
|
|
const replacementAssessment = {
|
|
...damageAssessment,
|
|
canBeFixed: false,
|
|
needsReplacement: true,
|
|
replacementCost: 150,
|
|
feeCalculation: {
|
|
type: 'replacement',
|
|
amount: 150,
|
|
},
|
|
};
|
|
|
|
await service.sendDamageReportToCustomerService(
|
|
rental,
|
|
owner,
|
|
renter,
|
|
replacementAssessment
|
|
);
|
|
|
|
expect(service.templateManager.renderTemplate).toHaveBeenCalledWith(
|
|
'damageReportToCS',
|
|
expect.objectContaining({
|
|
feeTypeDescription: 'Replacement Cost',
|
|
needsReplacement: 'Yes',
|
|
replacementCost: '150.00',
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should handle unknown fee type', async () => {
|
|
const unknownTypeAssessment = {
|
|
...damageAssessment,
|
|
feeCalculation: {
|
|
type: 'other',
|
|
amount: 50,
|
|
},
|
|
};
|
|
|
|
await service.sendDamageReportToCustomerService(
|
|
rental,
|
|
owner,
|
|
renter,
|
|
unknownTypeAssessment
|
|
);
|
|
|
|
expect(service.templateManager.renderTemplate).toHaveBeenCalledWith(
|
|
'damageReportToCS',
|
|
expect.objectContaining({
|
|
feeTypeDescription: 'Damage Assessment Fee',
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should indicate no proof of ownership when not provided', async () => {
|
|
const noProofAssessment = {
|
|
...damageAssessment,
|
|
proofOfOwnership: [],
|
|
};
|
|
|
|
await service.sendDamageReportToCustomerService(
|
|
rental,
|
|
owner,
|
|
renter,
|
|
noProofAssessment
|
|
);
|
|
|
|
expect(service.templateManager.renderTemplate).toHaveBeenCalledWith(
|
|
'damageReportToCS',
|
|
expect.objectContaining({
|
|
hasProofOfOwnership: 'No',
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should return error when customer service email is not configured', async () => {
|
|
delete process.env.CUSTOMER_SUPPORT_EMAIL;
|
|
|
|
const result = await service.sendDamageReportToCustomerService(
|
|
rental,
|
|
owner,
|
|
renter,
|
|
damageAssessment
|
|
);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toBe('No customer service email configured');
|
|
});
|
|
|
|
it('should handle errors gracefully', async () => {
|
|
service.emailClient.sendEmail.mockRejectedValueOnce(new Error('Send error'));
|
|
|
|
const result = await service.sendDamageReportToCustomerService(
|
|
rental,
|
|
owner,
|
|
renter,
|
|
damageAssessment
|
|
);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toBe('Send error');
|
|
});
|
|
});
|
|
|
|
describe('sendLostItemToCustomerService', () => {
|
|
const rental = {
|
|
id: 123,
|
|
endDateTime: '2024-01-16T10:00:00Z',
|
|
itemLostReportedAt: '2024-01-17T10:00:00Z',
|
|
item: {
|
|
name: 'Power Drill',
|
|
replacementCost: 200,
|
|
},
|
|
};
|
|
const owner = {
|
|
firstName: 'John',
|
|
lastName: 'Doe',
|
|
email: 'john@example.com',
|
|
};
|
|
const renter = {
|
|
firstName: 'Jane',
|
|
lastName: 'Smith',
|
|
email: 'jane@example.com',
|
|
};
|
|
|
|
it('should send lost item notification with correct variables', async () => {
|
|
const result = await service.sendLostItemToCustomerService(rental, owner, renter);
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(service.templateManager.renderTemplate).toHaveBeenCalledWith(
|
|
'lostItemToCS',
|
|
expect.objectContaining({
|
|
rentalId: 123,
|
|
itemName: 'Power Drill',
|
|
ownerName: 'John Doe',
|
|
ownerEmail: 'john@example.com',
|
|
renterName: 'Jane Smith',
|
|
renterEmail: 'jane@example.com',
|
|
replacementCost: '200.00',
|
|
})
|
|
);
|
|
expect(service.emailClient.sendEmail).toHaveBeenCalledWith(
|
|
'support@example.com',
|
|
'Lost Item Claim Filed - Action Required',
|
|
expect.any(String)
|
|
);
|
|
});
|
|
|
|
it('should return error when customer service email is not configured', async () => {
|
|
delete process.env.CUSTOMER_SUPPORT_EMAIL;
|
|
|
|
const result = await service.sendLostItemToCustomerService(rental, owner, renter);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toBe('No customer service email configured');
|
|
expect(service.emailClient.sendEmail).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle errors gracefully', async () => {
|
|
service.templateManager.renderTemplate.mockRejectedValueOnce(new Error('Template error'));
|
|
|
|
const result = await service.sendLostItemToCustomerService(rental, owner, renter);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toBe('Template error');
|
|
});
|
|
});
|
|
});
|