migration-utils.test.ts96 lines · main
1import dayjs from 'dayjs'
2import utc from 'dayjs/plugin/utc'
3import { describe, expect, it } from 'vitest'
4
5import { formatMigrationVersionLabel, parseMigrationVersion } from './migration-utils'
6
7dayjs.extend(utc)
8
9describe('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
86describe('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})