|
| 1 | +import { |
| 2 | + normalizeName, |
| 3 | + normalizeNameSingular, |
| 4 | + fuzzyFindByName, |
| 5 | + namesMatch, |
| 6 | +} from '../src'; |
| 7 | + |
| 8 | +describe('normalizeName', () => { |
| 9 | + it('should lowercase and strip underscores', () => { |
| 10 | + expect(normalizeName('delivery_zone')).toBe('deliveryzone'); |
| 11 | + expect(normalizeName('DeliveryZone')).toBe('deliveryzone'); |
| 12 | + expect(normalizeName('deliveryZones')).toBe('deliveryzones'); |
| 13 | + expect(normalizeName('DELIVERY_ZONE')).toBe('deliveryzone'); |
| 14 | + expect(normalizeName('shipments')).toBe('shipments'); |
| 15 | + expect(normalizeName('Shipment')).toBe('shipment'); |
| 16 | + }); |
| 17 | +}); |
| 18 | + |
| 19 | +describe('normalizeNameSingular', () => { |
| 20 | + it('should normalize and strip trailing s', () => { |
| 21 | + expect(normalizeNameSingular('shipments')).toBe('shipment'); |
| 22 | + expect(normalizeNameSingular('routes')).toBe('route'); |
| 23 | + expect(normalizeNameSingular('deliveryZones')).toBe('deliveryzone'); |
| 24 | + expect(normalizeNameSingular('delivery_zones')).toBe('deliveryzone'); |
| 25 | + }); |
| 26 | + |
| 27 | + it('should not strip s from names that do not end in s', () => { |
| 28 | + expect(normalizeNameSingular('DeliveryZone')).toBe('deliveryzone'); |
| 29 | + expect(normalizeNameSingular('Shipment')).toBe('shipment'); |
| 30 | + expect(normalizeNameSingular('Route')).toBe('route'); |
| 31 | + }); |
| 32 | +}); |
| 33 | + |
| 34 | +describe('fuzzyFindByName', () => { |
| 35 | + const tables = [ |
| 36 | + { name: 'Shipment' }, |
| 37 | + { name: 'DeliveryZone' }, |
| 38 | + { name: 'Route' }, |
| 39 | + { name: 'DriverVehicleAssignment' }, |
| 40 | + ]; |
| 41 | + |
| 42 | + it('should match exact names', () => { |
| 43 | + expect(fuzzyFindByName(tables, 'Shipment', (t) => t.name)).toEqual({ |
| 44 | + name: 'Shipment', |
| 45 | + }); |
| 46 | + expect(fuzzyFindByName(tables, 'Route', (t) => t.name)).toEqual({ |
| 47 | + name: 'Route', |
| 48 | + }); |
| 49 | + }); |
| 50 | + |
| 51 | + it('should match snake_case codec names to PascalCase table names', () => { |
| 52 | + expect(fuzzyFindByName(tables, 'delivery_zone', (t) => t.name)).toEqual({ |
| 53 | + name: 'DeliveryZone', |
| 54 | + }); |
| 55 | + expect( |
| 56 | + fuzzyFindByName(tables, 'driver_vehicle_assignments', (t) => t.name), |
| 57 | + ).toEqual({ name: 'DriverVehicleAssignment' }); |
| 58 | + }); |
| 59 | + |
| 60 | + it('should match plural camelCase codec names to PascalCase table names', () => { |
| 61 | + expect(fuzzyFindByName(tables, 'shipments', (t) => t.name)).toEqual({ |
| 62 | + name: 'Shipment', |
| 63 | + }); |
| 64 | + expect(fuzzyFindByName(tables, 'routes', (t) => t.name)).toEqual({ |
| 65 | + name: 'Route', |
| 66 | + }); |
| 67 | + expect( |
| 68 | + fuzzyFindByName(tables, 'driverVehicleAssignments', (t) => t.name), |
| 69 | + ).toEqual({ name: 'DriverVehicleAssignment' }); |
| 70 | + }); |
| 71 | + |
| 72 | + it('should return undefined for no match', () => { |
| 73 | + expect(fuzzyFindByName(tables, 'NonExistent', (t) => t.name)).toBeUndefined(); |
| 74 | + expect(fuzzyFindByName(tables, 'zzz', (t) => t.name)).toBeUndefined(); |
| 75 | + }); |
| 76 | + |
| 77 | + it('should prefer exact match over fuzzy match', () => { |
| 78 | + const items = [{ name: 'routes' }, { name: 'Route' }]; |
| 79 | + expect(fuzzyFindByName(items, 'routes', (t) => t.name)).toEqual({ |
| 80 | + name: 'routes', |
| 81 | + }); |
| 82 | + expect(fuzzyFindByName(items, 'Route', (t) => t.name)).toEqual({ |
| 83 | + name: 'Route', |
| 84 | + }); |
| 85 | + }); |
| 86 | +}); |
| 87 | + |
| 88 | +describe('namesMatch', () => { |
| 89 | + it('should match identical names', () => { |
| 90 | + expect(namesMatch('Shipment', 'Shipment')).toBe(true); |
| 91 | + }); |
| 92 | + |
| 93 | + it('should match case-insensitive names', () => { |
| 94 | + expect(namesMatch('shipment', 'Shipment')).toBe(true); |
| 95 | + expect(namesMatch('ROUTE', 'route')).toBe(true); |
| 96 | + }); |
| 97 | + |
| 98 | + it('should match snake_case to PascalCase', () => { |
| 99 | + expect(namesMatch('delivery_zone', 'DeliveryZone')).toBe(true); |
| 100 | + }); |
| 101 | + |
| 102 | + it('should match plural to singular', () => { |
| 103 | + expect(namesMatch('shipments', 'Shipment')).toBe(true); |
| 104 | + expect(namesMatch('routes', 'Route')).toBe(true); |
| 105 | + }); |
| 106 | + |
| 107 | + it('should not match unrelated names', () => { |
| 108 | + expect(namesMatch('User', 'Post')).toBe(false); |
| 109 | + expect(namesMatch('Route', 'DeliveryZone')).toBe(false); |
| 110 | + }); |
| 111 | +}); |
| 112 | + |
| 113 | +describe('case helpers: toCamelCase, toPascalCase, toScreamingSnake', () => { |
| 114 | + // Import from index to verify they're exported |
| 115 | + const { |
| 116 | + toCamelCase, |
| 117 | + toPascalCase, |
| 118 | + toScreamingSnake, |
| 119 | + } = require('../src'); |
| 120 | + |
| 121 | + it('toCamelCase should convert hyphenated and underscored strings', () => { |
| 122 | + expect(toCamelCase('user-profile')).toBe('userProfile'); |
| 123 | + expect(toCamelCase('user_profile')).toBe('userProfile'); |
| 124 | + expect(toCamelCase('UserProfile')).toBe('userProfile'); |
| 125 | + expect(toCamelCase('some-long-name')).toBe('someLongName'); |
| 126 | + }); |
| 127 | + |
| 128 | + it('toPascalCase should convert hyphenated and underscored strings', () => { |
| 129 | + expect(toPascalCase('user-profile')).toBe('UserProfile'); |
| 130 | + expect(toPascalCase('user_profile')).toBe('UserProfile'); |
| 131 | + expect(toPascalCase('userProfile')).toBe('UserProfile'); |
| 132 | + }); |
| 133 | + |
| 134 | + it('toScreamingSnake should convert camelCase and PascalCase', () => { |
| 135 | + expect(toScreamingSnake('userProfile')).toBe('USER_PROFILE'); |
| 136 | + expect(toScreamingSnake('UserProfile')).toBe('USER_PROFILE'); |
| 137 | + expect(toScreamingSnake('displayName')).toBe('DISPLAY_NAME'); |
| 138 | + }); |
| 139 | +}); |
0 commit comments