migration.test.ts
1 /** 2 * Tests for workspace migration utilities 3 */ 4 5 import { describe, it, expect } from 'vitest'; 6 import { 7 CURRENT_VERSION, 8 needsMigration, 9 getConfigVersion, 10 migrateConfig, 11 validateMigratedConfig, 12 } from '../../../src/lib/workspace/migration'; 13 import { createDefaultConfig } from '../../../src/lib/types'; 14 15 describe('getConfigVersion', () => { 16 it('returns 0 for null/undefined', () => { 17 expect(getConfigVersion(null)).toBe(0); 18 expect(getConfigVersion(undefined)).toBe(0); 19 }); 20 21 it('returns 0 for non-object', () => { 22 expect(getConfigVersion('string')).toBe(0); 23 expect(getConfigVersion(123)).toBe(0); 24 }); 25 26 it('returns 0 for object without version', () => { 27 expect(getConfigVersion({})).toBe(0); 28 expect(getConfigVersion({ foo: 'bar' })).toBe(0); 29 }); 30 31 it('returns version from object', () => { 32 expect(getConfigVersion({ version: 1 })).toBe(1); 33 expect(getConfigVersion({ version: 5 })).toBe(5); 34 }); 35 }); 36 37 describe('needsMigration', () => { 38 it('returns true for null/undefined', () => { 39 expect(needsMigration(null)).toBe(true); 40 expect(needsMigration(undefined)).toBe(true); 41 }); 42 43 it('returns true for old version', () => { 44 expect(needsMigration({ version: 0 })).toBe(true); 45 expect(needsMigration({ version: CURRENT_VERSION - 1 })).toBe(true); 46 }); 47 48 it('returns false for current version', () => { 49 expect(needsMigration({ version: CURRENT_VERSION })).toBe(false); 50 }); 51 52 it('returns false for future version', () => { 53 expect(needsMigration({ version: CURRENT_VERSION + 1 })).toBe(false); 54 }); 55 }); 56 57 describe('migrateConfig', () => { 58 it('updates version to current', () => { 59 const oldConfig = { version: 0 }; 60 const migrated = migrateConfig(oldConfig); 61 expect(migrated.version).toBe(CURRENT_VERSION); 62 }); 63 64 it('preserves existing properties', () => { 65 const oldConfig = { 66 version: 0, 67 customField: 'preserved', 68 }; 69 const migrated = migrateConfig(oldConfig); 70 expect((migrated as Record<string, unknown>).customField).toBe('preserved'); 71 }); 72 }); 73 74 describe('validateMigratedConfig', () => { 75 it('returns no errors for valid config', () => { 76 const config = createDefaultConfig(); 77 const errors = validateMigratedConfig(config); 78 expect(errors).toHaveLength(0); 79 }); 80 81 it('detects version mismatch', () => { 82 const config = createDefaultConfig(); 83 config.version = 999; 84 const errors = validateMigratedConfig(config); 85 expect(errors.some((e) => e.includes('Version mismatch'))).toBe(true); 86 }); 87 88 it('detects missing workspaces', () => { 89 const config = createDefaultConfig(); 90 (config as Record<string, unknown>).workspaces = undefined; 91 const errors = validateMigratedConfig(config); 92 expect(errors.some((e) => e.includes('workspaces'))).toBe(true); 93 }); 94 95 it('detects missing context', () => { 96 const config = createDefaultConfig(); 97 (config as Record<string, unknown>).context = undefined; 98 const errors = validateMigratedConfig(config); 99 expect(errors.some((e) => e.includes('context'))).toBe(true); 100 }); 101 102 it('detects missing settings', () => { 103 const config = createDefaultConfig(); 104 (config as Record<string, unknown>).settings = undefined; 105 const errors = validateMigratedConfig(config); 106 expect(errors.some((e) => e.includes('settings'))).toBe(true); 107 }); 108 109 it('detects missing metadata', () => { 110 const config = createDefaultConfig(); 111 (config as Record<string, unknown>).metadata = undefined; 112 const errors = validateMigratedConfig(config); 113 expect(errors.some((e) => e.includes('metadata'))).toBe(true); 114 }); 115 });