migration-utils.test.ts96 lines · main
| 1 | import dayjs from 'dayjs' |
| 2 | import utc from 'dayjs/plugin/utc' |
| 3 | import { describe, expect, it } from 'vitest' |
| 4 | |
| 5 | import { formatMigrationVersionLabel, parseMigrationVersion } from './migration-utils' |
| 6 | |
| 7 | dayjs.extend(utc) |
| 8 | |
| 9 | describe('parseMigrationVersion', () => { |
| 10 | it('should parse valid migration version in YYYYMMDDHHmmss format', () => { |
| 11 | const result = parseMigrationVersion('20231128095400') |
| 12 | |
| 13 | expect(result).not.toBeNull() |
| 14 | expect(result?.isValid()).toBe(true) |
| 15 | expect(result?.year()).toBe(2023) |
| 16 | expect(result?.month()).toBe(10) |
| 17 | expect(result?.date()).toBe(28) |
| 18 | expect(result?.hour()).toBe(9) |
| 19 | expect(result?.minute()).toBe(54) |
| 20 | expect(result?.second()).toBe(0) |
| 21 | }) |
| 22 | |
| 23 | it('should return undefined for invalid version format like "001"', () => { |
| 24 | const result = parseMigrationVersion('001') |
| 25 | |
| 26 | expect(result).toBeUndefined() |
| 27 | }) |
| 28 | |
| 29 | it('should return undefined for invalid version format like "002"', () => { |
| 30 | const result = parseMigrationVersion('002') |
| 31 | |
| 32 | expect(result).toBeUndefined() |
| 33 | }) |
| 34 | |
| 35 | it('should return undefined for invalid version format like "003"', () => { |
| 36 | const result = parseMigrationVersion('003') |
| 37 | |
| 38 | expect(result).toBeUndefined() |
| 39 | }) |
| 40 | |
| 41 | it('should return undefined for empty string', () => { |
| 42 | const result = parseMigrationVersion('') |
| 43 | |
| 44 | expect(result).toBeUndefined() |
| 45 | }) |
| 46 | |
| 47 | it('should return undefined for random string', () => { |
| 48 | const result = parseMigrationVersion('not-a-date') |
| 49 | |
| 50 | expect(result).toBeUndefined() |
| 51 | }) |
| 52 | |
| 53 | it('should return undefined for partial date format', () => { |
| 54 | const result = parseMigrationVersion('20231128') |
| 55 | |
| 56 | expect(result).toBeUndefined() |
| 57 | }) |
| 58 | |
| 59 | it('should handle edge case date values that dayjs can parse', () => { |
| 60 | // dayjs is lenient and will wrap invalid values to valid dates |
| 61 | // This is acceptable for our use case - the main goal is to reject |
| 62 | // non-date formats like "001", "002", etc. |
| 63 | const result = parseMigrationVersion('20231399000000') |
| 64 | |
| 65 | expect(result).not.toBeNull() |
| 66 | expect(result?.isValid()).toBe(true) |
| 67 | }) |
| 68 | |
| 69 | it('should allow chaining dayjs methods when valid', () => { |
| 70 | const result = parseMigrationVersion('20231128095400') |
| 71 | |
| 72 | expect(result?.fromNow()).toBeDefined() |
| 73 | expect(result?.toISOString()).toBeDefined() |
| 74 | expect(result?.format('DD MMM YYYY')).toBe('28 Nov 2023') |
| 75 | }) |
| 76 | |
| 77 | it('should parse version digits as UTC so the UTC time is preserved exactly', () => { |
| 78 | // Migration versions are stored as UTC in the DB. Parsing without UTC mode |
| 79 | // would shift the time by the viewer's local offset, showing wrong UTC values. |
| 80 | const result = parseMigrationVersion('20231128095400') |
| 81 | |
| 82 | expect(result?.toISOString()).toBe('2023-11-28T09:54:00.000Z') |
| 83 | }) |
| 84 | }) |
| 85 | |
| 86 | describe('formatMigrationVersionLabel', () => { |
| 87 | it('should format a valid version as a UTC date string', () => { |
| 88 | expect(formatMigrationVersionLabel('20231128095400')).toBe('28 Nov 2023, 09:54:00') |
| 89 | }) |
| 90 | |
| 91 | it('should return Unknown for an invalid version', () => { |
| 92 | expect(formatMigrationVersionLabel('001')).toBe('Unknown') |
| 93 | expect(formatMigrationVersionLabel(null)).toBe('Unknown') |
| 94 | expect(formatMigrationVersionLabel(undefined)).toBe('Unknown') |
| 95 | }) |
| 96 | }) |