@lobehub/chat
Version:
Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.
260 lines (197 loc) • 8 kB
text/typescript
import dayjs from 'dayjs';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import {
daysAgo,
getYYYYmmddHHMMss,
hoursAgo,
lastMonth,
monthsAgo,
thisMonth,
thisQuarter,
thisWeek,
thisYear,
today,
weeksAgo,
} from './time';
describe('time utilities', () => {
beforeEach(() => {
vi.useFakeTimers();
// Set a fixed date for consistent testing: 2024-06-15 14:30:45 (local time)
vi.setSystemTime(new Date('2024-06-15T14:30:45.123'));
});
afterEach(() => {
vi.useRealTimers();
});
describe('today', () => {
it('should return the start of the current day', () => {
const result = today();
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-06-15 00:00:00');
});
});
describe('thisWeek', () => {
it('should return the start of the current week', () => {
const result = thisWeek();
// dayjs starts week on Sunday by default
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-06-09 00:00:00');
});
});
describe('thisMonth', () => {
it('should return the start of the current month', () => {
const result = thisMonth();
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-06-01 00:00:00');
});
});
describe('thisQuarter', () => {
it('should return the start of the current quarter (Q2)', () => {
const result = thisQuarter();
// June is in Q2, which starts in April (month 3, 0-indexed)
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-04-01 00:00:00');
});
it('should work correctly for Q1 (January)', () => {
vi.setSystemTime(new Date('2024-01-15T14:30:45.123'));
const result = thisQuarter();
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-01-01 00:00:00');
});
it('should work correctly for Q3 (September)', () => {
vi.setSystemTime(new Date('2024-09-15T14:30:45.123'));
const result = thisQuarter();
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-07-01 00:00:00');
});
it('should work correctly for Q4 (December)', () => {
vi.setSystemTime(new Date('2024-12-15T14:30:45.123'));
const result = thisQuarter();
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-10-01 00:00:00');
});
});
describe('thisYear', () => {
it('should return the start of the current year', () => {
const result = thisYear();
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-01-01 00:00:00');
});
});
describe('hoursAgo', () => {
it('should return the correct time hours ago', () => {
const result = hoursAgo(3);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-06-15 11:00:00');
});
it('should handle 0 hours ago', () => {
const result = hoursAgo(0);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-06-15 14:00:00');
});
it('should handle large hour values (cross day boundary)', () => {
const result = hoursAgo(25);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-06-14 13:00:00');
});
});
describe('daysAgo', () => {
it('should return the correct date days ago', () => {
const result = daysAgo(7);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-06-08 00:00:00');
});
it('should handle 0 days ago (today)', () => {
const result = daysAgo(0);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-06-15 00:00:00');
});
it('should handle large day values (cross month boundary)', () => {
const result = daysAgo(30);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-05-16 00:00:00');
});
});
describe('weeksAgo', () => {
it('should return the correct week weeks ago', () => {
const result = weeksAgo(2);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-05-26 00:00:00');
});
it('should handle 0 weeks ago (this week)', () => {
const result = weeksAgo(0);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-06-09 00:00:00');
});
});
describe('monthsAgo', () => {
it('should return the correct month months ago', () => {
const result = monthsAgo(3);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-03-01 00:00:00');
});
it('should handle 0 months ago (this month)', () => {
const result = monthsAgo(0);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-06-01 00:00:00');
});
it('should handle cross year boundary', () => {
const result = monthsAgo(12);
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2023-06-01 00:00:00');
});
});
describe('lastMonth', () => {
it('should return the end of last month', () => {
const result = lastMonth();
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-05-31 23:59:59');
});
it('should work correctly for January (December of previous year)', () => {
vi.setSystemTime(new Date('2024-01-15T14:30:45.123'));
const result = lastMonth();
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2023-12-31 23:59:59');
});
it('should work correctly for March (February with 29 days in leap year)', () => {
vi.setSystemTime(new Date('2024-03-15T14:30:45.123'));
const result = lastMonth();
expect(result.format('YYYY-MM-DD HH:mm:ss')).toBe('2024-02-29 23:59:59');
});
});
describe('getYYYYmmddHHMMss', () => {
it('should format date to YYYYMMDD_HHmmss format', () => {
const date = new Date('2024-01-01T23:59:59.123');
const result = getYYYYmmddHHMMss(date);
expect(result).toBe('20240101_235959');
});
it('should format date with zero padding', () => {
const date = new Date('2024-02-05T01:02:03.456');
const result = getYYYYmmddHHMMss(date);
expect(result).toBe('20240205_010203');
});
it('should handle end of year date', () => {
const date = new Date('2024-12-31T00:00:00.000');
const result = getYYYYmmddHHMMss(date);
expect(result).toBe('20241231_000000');
});
it('should handle leap year date', () => {
const date = new Date('2024-02-29T12:30:45.789');
const result = getYYYYmmddHHMMss(date);
expect(result).toBe('20240229_123045');
});
it('should work with the current mocked time', () => {
const date = new Date('2024-06-15T14:30:45.123');
const result = getYYYYmmddHHMMss(date);
expect(result).toBe('20240615_143045');
});
});
describe('edge cases and integration', () => {
it('should all return dayjs objects for date functions', () => {
expect(dayjs.isDayjs(today())).toBe(true);
expect(dayjs.isDayjs(thisWeek())).toBe(true);
expect(dayjs.isDayjs(thisMonth())).toBe(true);
expect(dayjs.isDayjs(thisQuarter())).toBe(true);
expect(dayjs.isDayjs(thisYear())).toBe(true);
expect(dayjs.isDayjs(hoursAgo(1))).toBe(true);
expect(dayjs.isDayjs(daysAgo(1))).toBe(true);
expect(dayjs.isDayjs(weeksAgo(1))).toBe(true);
expect(dayjs.isDayjs(monthsAgo(1))).toBe(true);
expect(dayjs.isDayjs(lastMonth())).toBe(true);
});
it('should maintain consistency between different time functions', () => {
const todayResult = today();
const daysAgoResult = daysAgo(0);
expect(todayResult.format('YYYY-MM-DD')).toBe(daysAgoResult.format('YYYY-MM-DD'));
});
it('should work with different time zones in getYYYYmmddHHMMss', () => {
// Note: dayjs uses the local timezone by default
const localDate = new Date('2024-06-15T14:30:45.000');
const result = getYYYYmmddHHMMss(localDate);
// The exact result depends on the test environment's timezone
// But it should always be a valid format
expect(result).toMatch(/^\d{8}_\d{6}$/);
expect(result).toHaveLength(15);
// Should match the local time format
expect(result).toBe('20240615_143045');
});
});
});