[READ-ONLY] a fast, modern browser for the npm registry
at main 152 lines 5.6 kB view raw
1import { describe, expect, it, vi } from 'vitest' 2import type { PackumentVersion } from '../../../../shared/types' 3 4// Mock Nitro globals before importing the module 5vi.stubGlobal('defineCachedFunction', (fn: Function) => fn) 6vi.stubGlobal('$fetch', vi.fn()) 7 8const { TARGET_PLATFORM, matchesPlatform, resolveVersion } = 9 await import('../../../../server/utils/dependency-resolver') 10 11describe('dependency-resolver', () => { 12 describe('TARGET_PLATFORM', () => { 13 it('is configured for linux-x64-glibc', () => { 14 expect(TARGET_PLATFORM).toEqual({ 15 os: 'linux', 16 cpu: 'x64', 17 libc: 'glibc', 18 }) 19 }) 20 }) 21 22 describe('matchesPlatform', () => { 23 it('returns true for packages without platform restrictions', () => { 24 const version = {} as PackumentVersion 25 expect(matchesPlatform(version)).toBe(true) 26 }) 27 28 it('returns true when os includes linux', () => { 29 const version = { os: ['linux', 'darwin'] } as PackumentVersion 30 expect(matchesPlatform(version)).toBe(true) 31 }) 32 33 it('returns false when os excludes linux', () => { 34 const version = { os: ['darwin', 'win32'] } as PackumentVersion 35 expect(matchesPlatform(version)).toBe(false) 36 }) 37 38 it('handles negated os values (!linux)', () => { 39 const version = { os: ['!win32'] } as PackumentVersion 40 expect(matchesPlatform(version)).toBe(true) 41 42 const excluded = { os: ['!linux'] } as PackumentVersion 43 expect(matchesPlatform(excluded)).toBe(false) 44 }) 45 46 it('returns true when cpu includes x64', () => { 47 const version = { cpu: ['x64', 'arm64'] } as PackumentVersion 48 expect(matchesPlatform(version)).toBe(true) 49 }) 50 51 it('returns false when cpu excludes x64', () => { 52 const version = { cpu: ['arm64', 'arm'] } as PackumentVersion 53 expect(matchesPlatform(version)).toBe(false) 54 }) 55 56 it('handles negated cpu values (!x64)', () => { 57 const version = { cpu: ['!arm64'] } as PackumentVersion 58 expect(matchesPlatform(version)).toBe(true) 59 60 const excluded = { cpu: ['!x64'] } as PackumentVersion 61 expect(matchesPlatform(excluded)).toBe(false) 62 }) 63 64 it('returns true when libc includes glibc', () => { 65 const version = { libc: ['glibc'] } as unknown as PackumentVersion 66 expect(matchesPlatform(version)).toBe(true) 67 }) 68 69 it('returns false when libc is musl only', () => { 70 const version = { libc: ['musl'] } as unknown as PackumentVersion 71 expect(matchesPlatform(version)).toBe(false) 72 }) 73 74 it('handles negated libc values (!glibc)', () => { 75 const version = { libc: ['!musl'] } as unknown as PackumentVersion 76 expect(matchesPlatform(version)).toBe(true) 77 78 const excluded = { libc: ['!glibc'] } as unknown as PackumentVersion 79 expect(matchesPlatform(excluded)).toBe(false) 80 }) 81 82 it('requires all platform constraints to match', () => { 83 const version = { 84 os: ['linux'], 85 cpu: ['arm64'], // doesn't match x64 86 } as PackumentVersion 87 expect(matchesPlatform(version)).toBe(false) 88 }) 89 90 it('ignores empty arrays', () => { 91 const version = { os: [], cpu: [], libc: [] } as unknown as PackumentVersion 92 expect(matchesPlatform(version)).toBe(true) 93 }) 94 }) 95 96 describe('resolveVersion', () => { 97 const versions = ['1.0.0', '1.0.1', '1.1.0', '2.0.0', '2.0.0-beta.1', '3.0.0'] 98 99 it('returns exact version if it exists', () => { 100 expect(resolveVersion('1.0.0', versions)).toBe('1.0.0') 101 expect(resolveVersion('2.0.0', versions)).toBe('2.0.0') 102 }) 103 104 it('returns null for exact version that does not exist', () => { 105 expect(resolveVersion('1.0.2', versions)).toBe(null) 106 }) 107 108 it('resolves semver ranges', () => { 109 expect(resolveVersion('^1.0.0', versions)).toBe('1.1.0') 110 expect(resolveVersion('~1.0.0', versions)).toBe('1.0.1') 111 expect(resolveVersion('>=2.0.0', versions)).toBe('3.0.0') 112 expect(resolveVersion('<2.0.0', versions)).toBe('1.1.0') 113 }) 114 115 it('resolves * to latest stable', () => { 116 expect(resolveVersion('*', versions)).toBe('3.0.0') 117 }) 118 119 it('handles npm: protocol aliases', () => { 120 expect(resolveVersion('npm:other-pkg@^1.0.0', versions)).toBe('1.1.0') 121 expect(resolveVersion('npm:@scope/pkg@2.0.0', versions)).toBe('2.0.0') 122 }) 123 124 it('returns null for invalid npm: protocol', () => { 125 expect(resolveVersion('npm:', versions)).toBe(null) 126 expect(resolveVersion('npm:pkg', versions)).toBe(null) 127 }) 128 129 it('returns null for URLs', () => { 130 expect(resolveVersion('https://github.com/user/repo', versions)).toBe(null) 131 expect(resolveVersion('http://example.com/pkg.tgz', versions)).toBe(null) 132 expect(resolveVersion('git://github.com/user/repo.git', versions)).toBe(null) 133 expect(resolveVersion('git+https://github.com/user/repo.git', versions)).toBe(null) 134 }) 135 136 it('returns null for file: protocol', () => { 137 expect(resolveVersion('file:../local-pkg', versions)).toBe(null) 138 }) 139 140 it('returns null for GitHub shorthand (contains /)', () => { 141 expect(resolveVersion('user/repo', versions)).toBe(null) 142 expect(resolveVersion('user/repo#branch', versions)).toBe(null) 143 }) 144 145 it('handles prerelease versions when explicitly requested', () => { 146 // Exact prerelease version match 147 expect(resolveVersion('2.0.0-beta.1', versions)).toBe('2.0.0-beta.1') 148 // Range with prerelease - semver correctly prefers stable 2.0.0 over 2.0.0-beta.1 149 expect(resolveVersion('^2.0.0-beta.0', versions)).toBe('2.0.0') 150 }) 151 }) 152})