migration-utils.test.ts 3.1 KB

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