|
describe('DateBuilder', () => { |
|
let fixedDate; |
|
|
|
beforeEach(() => { |
|
// Fix the date to ensure consistent testing |
|
fixedDate = new Date('2024-01-01T00:00:00.000Z'); |
|
jest.useFakeTimers(); |
|
jest.setSystemTime(fixedDate); |
|
}); |
|
|
|
afterEach(() => { |
|
jest.useRealTimers(); |
|
}); |
|
|
|
describe('constructor', () => { |
|
it('should initialize with current date when no arguments provided', () => { |
|
const builder = new DateBuilder(); |
|
expect(builder.build().toISOString()).toBe(fixedDate.toISOString()); |
|
}); |
|
|
|
it('should initialize with a provided Date object', () => { |
|
const customDate = new Date('2023-12-25T00:00:00.000Z'); |
|
const builder = new DateBuilder(customDate); |
|
expect(builder.build().toISOString()).toBe(customDate.toISOString()); |
|
}); |
|
|
|
it('should initialize with a date string', () => { |
|
const builder = new DateBuilder('2023-12-25'); |
|
expect(builder.build().toISOString()).startsWith('2023-12-25'); |
|
}); |
|
|
|
it('should throw TypeError for invalid date input', () => { |
|
expect(() => new DateBuilder('invalid-date')).toThrow(TypeError); |
|
expect(() => new DateBuilder('2024-13-45')).toThrow(TypeError); |
|
}); |
|
}); |
|
|
|
describe('add operations', () => { |
|
let builder; |
|
|
|
beforeEach(() => { |
|
builder = new DateBuilder(fixedDate); |
|
}); |
|
|
|
it('should add days correctly', () => { |
|
const result = builder.addDays(5).build(); |
|
expect(result.getDate()).toBe(6); // Jan 1 + 5 days = Jan 6 |
|
}); |
|
|
|
it('should handle month rollover when adding days', () => { |
|
const result = builder.addDays(31).build(); |
|
expect(result.getMonth()).toBe(1); // February |
|
expect(result.getDate()).toBe(1); |
|
}); |
|
|
|
it('should add months correctly', () => { |
|
const result = builder.addMonths(3).build(); |
|
expect(result.getMonth()).toBe(3); // April |
|
}); |
|
|
|
it('should handle year rollover when adding months', () => { |
|
const result = builder.addMonths(12).build(); |
|
expect(result.getFullYear()).toBe(2025); |
|
expect(result.getMonth()).toBe(0); // January |
|
}); |
|
|
|
it('should add years correctly', () => { |
|
const result = builder.addYears(5).build(); |
|
expect(result.getFullYear()).toBe(2029); |
|
}); |
|
|
|
it('should add hours correctly', () => { |
|
const result = builder.addHours(25).build(); |
|
expect(result.getDate()).toBe(2); // Next day |
|
expect(result.getHours()).toBe(1); |
|
}); |
|
|
|
it('should add minutes correctly', () => { |
|
const result = builder.addMinutes(150).build(); |
|
expect(result.getHours()).toBe(2); |
|
expect(result.getMinutes()).toBe(30); |
|
}); |
|
|
|
it('should add seconds correctly', () => { |
|
const result = builder.addSeconds(3665).build(); // 1 hour + 1 minute + 5 seconds |
|
expect(result.getHours()).toBe(1); |
|
expect(result.getMinutes()).toBe(1); |
|
expect(result.getSeconds()).toBe(5); |
|
}); |
|
}); |
|
|
|
describe('subtract operations', () => { |
|
let builder; |
|
|
|
beforeEach(() => { |
|
builder = new DateBuilder(fixedDate); |
|
}); |
|
|
|
it('should subtract days correctly', () => { |
|
const result = builder.subtractDays(5).build(); |
|
expect(result.getMonth()).toBe(11); // December |
|
expect(result.getDate()).toBe(27); |
|
}); |
|
|
|
it('should subtract months correctly', () => { |
|
const result = builder.subtractMonths(2).build(); |
|
expect(result.getMonth()).toBe(10); // November |
|
}); |
|
|
|
it('should subtract years correctly', () => { |
|
const result = builder.subtractYears(3).build(); |
|
expect(result.getFullYear()).toBe(2021); |
|
}); |
|
|
|
it('should subtract hours correctly', () => { |
|
const result = builder.subtractHours(25).build(); |
|
expect(result.getDate()).toBe(30); // Previous day |
|
expect(result.getHours()).toBe(23); |
|
}); |
|
|
|
it('should subtract minutes correctly', () => { |
|
const result = builder.subtractMinutes(150).build(); |
|
expect(result.getHours()).toBe(21); |
|
expect(result.getMinutes()).toBe(30); |
|
expect(result.getDate()).toBe(31); // Previous day |
|
}); |
|
|
|
it('should subtract seconds correctly', () => { |
|
const result = builder.subtractSeconds(3665).build(); |
|
expect(result.getHours()).toBe(22); |
|
expect(result.getMinutes()).toBe(58); |
|
expect(result.getSeconds()).toBe(55); |
|
expect(result.getDate()).toBe(31); // Previous day |
|
}); |
|
}); |
|
|
|
describe('method chaining', () => { |
|
it('should support multiple add operations', () => { |
|
const result = new DateBuilder(fixedDate) |
|
.addDays(1) |
|
.addMonths(1) |
|
.addYears(1) |
|
.addHours(2) |
|
.addMinutes(30) |
|
.addSeconds(15) |
|
.build(); |
|
|
|
expect(result.getFullYear()).toBe(2025); |
|
expect(result.getMonth()).toBe(1); // February |
|
expect(result.getDate()).toBe(2); |
|
expect(result.getHours()).toBe(2); |
|
expect(result.getMinutes()).toBe(30); |
|
expect(result.getSeconds()).toBe(15); |
|
}); |
|
|
|
it('should support multiple subtract operations', () => { |
|
const result = new DateBuilder(fixedDate) |
|
.subtractDays(1) |
|
.subtractMonths(1) |
|
.subtractYears(1) |
|
.subtractHours(2) |
|
.subtractMinutes(30) |
|
.subtractSeconds(15) |
|
.build(); |
|
|
|
expect(result.getFullYear()).toBe(2022); |
|
expect(result.getMonth()).toBe(11); // December |
|
expect(result.getDate()).toBe(30); |
|
expect(result.getHours()).toBe(21); |
|
expect(result.getMinutes()).toBe(29); |
|
expect(result.getSeconds()).toBe(45); |
|
}); |
|
|
|
it('should support mixing add and subtract operations', () => { |
|
const result = new DateBuilder(fixedDate) |
|
.addYears(1) |
|
.subtractMonths(6) |
|
.addDays(15) |
|
.subtractHours(12) |
|
.build(); |
|
|
|
expect(result.getFullYear()).toBe(2024); |
|
expect(result.getMonth()).toBe(6); // July |
|
expect(result.getDate()).toBe(16); |
|
expect(result.getHours()).toBe(12); |
|
}); |
|
}); |
|
|
|
describe('build method', () => { |
|
it('should return a new Date instance', () => { |
|
const builder = new DateBuilder(fixedDate); |
|
const result = builder.build(); |
|
|
|
expect(result).toBeInstanceOf(Date); |
|
expect(result).not.toBe(builder.date); // Should be a new instance |
|
}); |
|
|
|
it('should not modify original date when building multiple times', () => { |
|
const builder = new DateBuilder(fixedDate); |
|
const result1 = builder.build(); |
|
const result2 = builder.build(); |
|
|
|
expect(result1.getTime()).toBe(result2.getTime()); |
|
expect(result1).not.toBe(result2); // Should be different instances |
|
}); |
|
}); |
|
}); |