|
| 1 | +import { describe, it, expect } from 'vitest'; |
| 2 | +import { sanitizeName } from '../sanitize.ts'; |
| 3 | + |
| 4 | +const testCases: Array<{ input: string; expected: string; expectedPackage?: string }> = [ |
| 5 | + // Basic cases |
| 6 | + { input: 'my-project', expected: 'my-project' }, |
| 7 | + { input: 'myproject', expected: 'myproject' }, |
| 8 | + |
| 9 | + // Dots |
| 10 | + { input: 'sub.example.com', expected: 'sub-example-com', expectedPackage: 'sub.example.com' }, |
| 11 | + { input: 'my.cool.app', expected: 'my-cool-app', expectedPackage: 'my.cool.app' }, |
| 12 | + |
| 13 | + // Underscores |
| 14 | + { input: 'my_project_name', expected: 'my-project-name' }, |
| 15 | + |
| 16 | + // Mixed cases |
| 17 | + { input: 'My_Project.Name', expected: 'my-project-name', expectedPackage: 'my-project.name' }, |
| 18 | + { input: 'MyAwesomeApp', expected: 'myawesomeapp' }, |
| 19 | + |
| 20 | + // Special characters |
| 21 | + { input: '@scope/package', expected: 'scope-package', expectedPackage: '@scope/package' }, |
| 22 | + { input: 'hello@world!test', expected: 'hello-world-test' }, |
| 23 | + |
| 24 | + // Multiple consecutive invalid chars |
| 25 | + { input: 'my..project__name', expected: 'my-project-name', expectedPackage: 'my..project-name' }, |
| 26 | + |
| 27 | + // Leading/trailing invalid chars |
| 28 | + { input: '.my-project.', expected: 'my-project', expectedPackage: 'my-project.' }, |
| 29 | + { input: '---test---', expected: 'test', expectedPackage: '---test---' }, |
| 30 | + |
| 31 | + // Numbers |
| 32 | + { input: 'project123', expected: 'project123' }, |
| 33 | + { input: '123project', expected: '123project' }, |
| 34 | + |
| 35 | + // Empty/invalid fallback |
| 36 | + { input: '___', expected: 'undefined-sv-name', expectedPackage: '-' }, |
| 37 | + { input: '!@#$%', expected: 'undefined-sv-name', expectedPackage: '-' }, |
| 38 | + { input: '', expected: 'undefined-sv-name' }, |
| 39 | + |
| 40 | + // Length limit (63 chars max) |
| 41 | + { input: 'a'.repeat(70), expected: 'a'.repeat(63), expectedPackage: 'a'.repeat(70) }, |
| 42 | + { |
| 43 | + input: 'my-very-long-project-name-that-exceeds-the-limit-of-63-characters-allowed', |
| 44 | + expected: 'my-very-long-project-name-that-exceeds-the-limit-of-63-characte', |
| 45 | + expectedPackage: 'my-very-long-project-name-that-exceeds-the-limit-of-63-characters-allowed' |
| 46 | + }, |
| 47 | + |
| 48 | + // Truncation trap: slice leaves trailing dash |
| 49 | + { |
| 50 | + input: 'a'.repeat(62) + '-b', |
| 51 | + expected: 'a'.repeat(62), |
| 52 | + expectedPackage: 'a'.repeat(62) + '-b' |
| 53 | + }, |
| 54 | + |
| 55 | + // Spaces |
| 56 | + { input: 'my cool project', expected: 'my-cool-project' }, |
| 57 | + { input: ' spaced out ', expected: 'spaced-out' }, |
| 58 | + |
| 59 | + // Exact boundary (off-by-one check) |
| 60 | + { input: 'a'.repeat(63), expected: 'a'.repeat(63) }, |
| 61 | + |
| 62 | + // Unicode / accents / emojis (replaced with dashes) |
| 63 | + { input: 'piñata', expected: 'pi-ata' }, |
| 64 | + { input: 'café', expected: 'caf', expectedPackage: 'caf-' }, |
| 65 | + { input: 'cool 🚀 app', expected: 'cool-app', expectedPackage: 'cool---app' } |
| 66 | +]; |
| 67 | + |
| 68 | +describe('sanitizeName wrangler', () => { |
| 69 | + it.each(testCases)('sanitizes $input to $expected', ({ input, expected }) => { |
| 70 | + expect(sanitizeName(input, 'wrangler')).toBe(expected); |
| 71 | + }); |
| 72 | +}); |
| 73 | + |
| 74 | +describe('sanitizeName package', () => { |
| 75 | + it.each(testCases)('sanitizes $input to $expected', ({ input, expected, expectedPackage }) => { |
| 76 | + expect(sanitizeName(input, 'package')).toBe(expectedPackage ?? expected); |
| 77 | + }); |
| 78 | +}); |
0 commit comments