more unit tests
This commit is contained in:
@@ -0,0 +1,382 @@
|
||||
// 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');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user