forked from
npmx.dev/npmx.dev
[READ-ONLY]
a fast, modern browser for the npm registry
1import { describe, expect, it } from 'vitest'
2import { parsePackageParam } from '../../../../shared/utils/parse-package-param'
3
4describe('parsePackageParam', () => {
5 describe('unscoped packages', () => {
6 it('parses package name without version', () => {
7 const result = parsePackageParam('vue')
8 expect(result).toEqual({
9 packageName: 'vue',
10 version: undefined,
11 rest: [],
12 })
13 })
14
15 it('parses package name with version', () => {
16 const result = parsePackageParam('vue/v/3.4.0')
17 expect(result).toEqual({
18 packageName: 'vue',
19 version: '3.4.0',
20 rest: [],
21 })
22 })
23
24 it('parses package name with prerelease version', () => {
25 const result = parsePackageParam('nuxt/v/4.0.0-rc.1')
26 expect(result).toEqual({
27 packageName: 'nuxt',
28 version: '4.0.0-rc.1',
29 rest: [],
30 })
31 })
32
33 it('parses package name with version and file path', () => {
34 const result = parsePackageParam('vue/v/3.4.0/src/index.ts')
35 expect(result).toEqual({
36 packageName: 'vue',
37 version: '3.4.0',
38 rest: ['src', 'index.ts'],
39 })
40 })
41
42 it('parses package name with version and nested file path', () => {
43 const result = parsePackageParam('lodash/v/4.17.21/lib/fp/map.js')
44 expect(result).toEqual({
45 packageName: 'lodash',
46 version: '4.17.21',
47 rest: ['lib', 'fp', 'map.js'],
48 })
49 })
50 })
51
52 describe('scoped packages', () => {
53 it('parses scoped package name without version', () => {
54 const result = parsePackageParam('@nuxt/kit')
55 expect(result).toEqual({
56 packageName: '@nuxt/kit',
57 version: undefined,
58 rest: [],
59 })
60 })
61
62 it('parses scoped package name with version', () => {
63 const result = parsePackageParam('@nuxt/kit/v/1.0.0')
64 expect(result).toEqual({
65 packageName: '@nuxt/kit',
66 version: '1.0.0',
67 rest: [],
68 })
69 })
70
71 it('parses scoped package name with version and file path', () => {
72 const result = parsePackageParam('@vue/compiler-sfc/v/3.5.0/dist/index.d.ts')
73 expect(result).toEqual({
74 packageName: '@vue/compiler-sfc',
75 version: '3.5.0',
76 rest: ['dist', 'index.d.ts'],
77 })
78 })
79
80 it('parses deeply nested scoped packages', () => {
81 const result = parsePackageParam('@types/node/v/22.0.0')
82 expect(result).toEqual({
83 packageName: '@types/node',
84 version: '22.0.0',
85 rest: [],
86 })
87 })
88 })
89
90 describe('edge cases', () => {
91 it('handles package name that looks like a version marker', () => {
92 // Package named "v" shouldn't be confused with version separator
93 const result = parsePackageParam('v')
94 expect(result).toEqual({
95 packageName: 'v',
96 version: undefined,
97 rest: [],
98 })
99 })
100
101 it('handles version segment without actual version', () => {
102 // "v" at the end without a version after it
103 const result = parsePackageParam('vue/v')
104 expect(result).toEqual({
105 packageName: 'vue/v',
106 version: undefined,
107 rest: [],
108 })
109 })
110
111 it('handles package with "v" in the name followed by version', () => {
112 const result = parsePackageParam('vueuse/v/12.0.0')
113 expect(result).toEqual({
114 packageName: 'vueuse',
115 version: '12.0.0',
116 rest: [],
117 })
118 })
119
120 it('handles empty rest when file path is empty', () => {
121 const result = parsePackageParam('react/v/18.2.0')
122 expect(result.rest).toEqual([])
123 expect(result.rest.length).toBe(0)
124 })
125 })
126})