@@ -14,29 +14,9 @@ vi.stubGlobal('fetchNpmPackage', fetchNpmPackageMock)
1414const parseRepositoryInfoMock = vi . fn ( )
1515vi . stubGlobal ( 'parseRepositoryInfo' , parseRepositoryInfoMock )
1616
17- const { fetchReadmeFromJsdelivr, isStandardReadme , resolvePackageReadmeSource } =
17+ const { fetchReadmeFromJsdelivr, resolvePackageReadmeSource } =
1818 await import ( '../../../../server/utils/readme-loaders' )
1919
20- describe ( 'isStandardReadme' , ( ) => {
21- it ( 'returns true for standard README filenames' , ( ) => {
22- expect ( isStandardReadme ( 'README.md' ) ) . toBe ( true )
23- expect ( isStandardReadme ( 'readme.md' ) ) . toBe ( true )
24- expect ( isStandardReadme ( 'Readme.md' ) ) . toBe ( true )
25- expect ( isStandardReadme ( 'README' ) ) . toBe ( true )
26- expect ( isStandardReadme ( 'readme' ) ) . toBe ( true )
27- expect ( isStandardReadme ( 'README.markdown' ) ) . toBe ( true )
28- expect ( isStandardReadme ( 'readme.markdown' ) ) . toBe ( true )
29- } )
30-
31- it ( 'returns false for non-standard filenames' , ( ) => {
32- expect ( isStandardReadme ( 'CONTRIBUTING.md' ) ) . toBe ( false )
33- expect ( isStandardReadme ( 'README.txt' ) ) . toBe ( false )
34- expect ( isStandardReadme ( 'readme.rst' ) ) . toBe ( false )
35- expect ( isStandardReadme ( undefined ) ) . toBe ( false )
36- expect ( isStandardReadme ( '' ) ) . toBe ( false )
37- } )
38- } )
39-
4020describe ( 'fetchReadmeFromJsdelivr' , ( ) => {
4121 it ( 'returns content when first filename succeeds' , async ( ) => {
4222 const content = '# Package'
@@ -81,13 +61,14 @@ describe('resolvePackageReadmeSource', () => {
8161 parseRepositoryInfoMock . mockReset ( )
8262 } )
8363
84- it ( 'returns markdown and repoInfo when package has valid npm readme (latest)' , async ( ) => {
85- const markdown = '# Hello '
64+ it ( 'prefers jsDelivr readme over packument readme (latest)' , async ( ) => {
65+ const jsdelivrContent = '# Full README from CDN '
8666 fetchNpmPackageMock . mockResolvedValue ( {
87- readme : markdown ,
88- readmeFilename : 'README.md' ,
89- repository : { url : 'https://github.com/u/r' } ,
90- versions : { } ,
67+ 'readme' : '# Truncated' ,
68+ 'readmeFilename' : 'README.md' ,
69+ 'repository' : { url : 'https://github.com/u/r' } ,
70+ 'versions' : { } ,
71+ 'dist-tags' : { latest : '2.0.0' } ,
9172 } )
9273 parseRepositoryInfoMock . mockReturnValue ( {
9374 provider : 'github' ,
@@ -96,90 +77,122 @@ describe('resolvePackageReadmeSource', () => {
9677 rawBaseUrl : 'https://raw.githubusercontent.com/u/r/HEAD' ,
9778 blobBaseUrl : 'https://github.com/u/r/blob/HEAD' ,
9879 } )
80+ const fetchMock = vi . fn ( ) . mockResolvedValue ( {
81+ ok : true ,
82+ text : async ( ) => jsdelivrContent ,
83+ } )
84+ vi . stubGlobal ( 'fetch' , fetchMock )
9985
10086 const result = await resolvePackageReadmeSource ( 'some-pkg' )
10187
10288 expect ( result ) . toMatchObject ( {
10389 packageName : 'some-pkg' ,
10490 version : undefined ,
105- markdown,
91+ markdown : jsdelivrContent ,
10692 repoInfo : { provider : 'github' , owner : 'u' , repo : 'r' } ,
10793 } )
10894 expect ( fetchNpmPackageMock ) . toHaveBeenCalledWith ( 'some-pkg' )
10995 } )
11096
111- it ( 'returns markdown from version when packagePath includes version' , async ( ) => {
112- const markdown = '# Version readme'
97+ it ( 'uses resolved latest version for jsDelivr when no version specified' , async ( ) => {
11398 fetchNpmPackageMock . mockResolvedValue ( {
114- readme : 'latest readme' ,
115- readmeFilename : 'README.md' ,
116- repository : undefined ,
117- versions : {
118- '1.0.0' : { readme : markdown , readmeFilename : 'README.md' } ,
99+ 'readme' : '# Packument' ,
100+ 'readmeFilename' : 'README.md' ,
101+ 'repository' : undefined ,
102+ 'versions' : { } ,
103+ 'dist-tags' : { latest : '3.1.0' } ,
104+ } )
105+ parseRepositoryInfoMock . mockReturnValue ( undefined )
106+ const fetchMock = vi . fn ( ) . mockResolvedValue ( {
107+ ok : true ,
108+ text : async ( ) => '# CDN' ,
109+ } )
110+ vi . stubGlobal ( 'fetch' , fetchMock )
111+
112+ await resolvePackageReadmeSource ( 'pkg' )
113+
114+ expect ( fetchMock ) . toHaveBeenCalledWith ( expect . stringContaining ( 'pkg@3.1.0' ) )
115+ } )
116+
117+ it ( 'returns markdown from specific version jsDelivr when packagePath includes version' , async ( ) => {
118+ const jsdelivrContent = '# Version readme from CDN'
119+ fetchNpmPackageMock . mockResolvedValue ( {
120+ 'readme' : 'latest readme' ,
121+ 'readmeFilename' : 'README.md' ,
122+ 'repository' : undefined ,
123+ 'versions' : {
124+ '1.0.0' : { readme : 'version readme from packument' , readmeFilename : 'README.md' } ,
119125 } ,
126+ 'dist-tags' : { latest : '2.0.0' } ,
120127 } )
121128 parseRepositoryInfoMock . mockReturnValue ( undefined )
129+ const fetchMock = vi . fn ( ) . mockResolvedValue ( {
130+ ok : true ,
131+ text : async ( ) => jsdelivrContent ,
132+ } )
133+ vi . stubGlobal ( 'fetch' , fetchMock )
122134
123135 const result = await resolvePackageReadmeSource ( 'some-pkg/v/1.0.0' )
124136
125137 expect ( result ) . toMatchObject ( {
126138 packageName : 'some-pkg' ,
127139 version : '1.0.0' ,
128- markdown,
140+ markdown : jsdelivrContent ,
129141 } )
142+ expect ( fetchMock ) . toHaveBeenCalledWith ( expect . stringContaining ( 'some-pkg@1.0.0' ) )
130143 } )
131144
132- it ( 'falls back to jsdelivr when npm readme is missing sentinel ' , async ( ) => {
133- const jsdelivrContent = '# From CDN '
145+ it ( 'falls back to packument readme when jsDelivr fails ' , async ( ) => {
146+ const packumentReadme = '# From packument '
134147 fetchNpmPackageMock . mockResolvedValue ( {
135- readme : NPM_MISSING_README_SENTINEL ,
136- readmeFilename : 'README.md' ,
137- repository : undefined ,
138- versions : { } ,
148+ 'readme' : packumentReadme ,
149+ 'readmeFilename' : 'README.md' ,
150+ 'repository' : undefined ,
151+ 'versions' : { } ,
152+ 'dist-tags' : { latest : '1.0.0' } ,
139153 } )
140154 parseRepositoryInfoMock . mockReturnValue ( undefined )
141- const fetchMock = vi . fn ( ) . mockResolvedValue ( {
142- ok : true ,
143- text : async ( ) => jsdelivrContent ,
144- } )
155+ const fetchMock = vi . fn ( ) . mockResolvedValue ( { ok : false } )
145156 vi . stubGlobal ( 'fetch' , fetchMock )
146157
147158 const result = await resolvePackageReadmeSource ( 'pkg' )
148159
149160 expect ( result ) . toMatchObject ( {
150161 packageName : 'pkg' ,
151- markdown : jsdelivrContent ,
152- repoInfo : undefined ,
162+ markdown : packumentReadme ,
153163 } )
154- expect ( fetchMock ) . toHaveBeenCalled ( )
155164 } )
156165
157- it ( 'falls back to jsdelivr when readmeFilename is not standard ' , async ( ) => {
158- const jsdelivrContent = '# From CDN '
166+ it ( 'falls back to version packument readme when jsDelivr fails ' , async ( ) => {
167+ const versionReadme = '# Version readme '
159168 fetchNpmPackageMock . mockResolvedValue ( {
160- readme : 'content' ,
161- readmeFilename : 'DOCS.md' ,
162- repository : undefined ,
163- versions : { } ,
169+ 'readme' : 'latest readme' ,
170+ 'repository' : undefined ,
171+ 'versions' : {
172+ '1.0.0' : { readme : versionReadme } ,
173+ } ,
174+ 'dist-tags' : { latest : '1.0.0' } ,
164175 } )
165176 parseRepositoryInfoMock . mockReturnValue ( undefined )
166- const fetchMock = vi . fn ( ) . mockResolvedValue ( {
167- ok : true ,
168- text : async ( ) => jsdelivrContent ,
169- } )
177+ const fetchMock = vi . fn ( ) . mockResolvedValue ( { ok : false } )
170178 vi . stubGlobal ( 'fetch' , fetchMock )
171179
172- const result = await resolvePackageReadmeSource ( 'pkg' )
180+ const result = await resolvePackageReadmeSource ( 'pkg/v/1.0.0 ' )
173181
174- expect ( result ) . toMatchObject ( { markdown : jsdelivrContent } )
182+ expect ( result ) . toMatchObject ( {
183+ packageName : 'pkg' ,
184+ version : '1.0.0' ,
185+ markdown : versionReadme ,
186+ } )
175187 } )
176188
177- it ( 'returns undefined markdown when no content and jsdelivr fails ' , async ( ) => {
189+ it ( 'skips packument readme with missing sentinel in fallback ' , async ( ) => {
178190 fetchNpmPackageMock . mockResolvedValue ( {
179- readme : undefined ,
180- readmeFilename : undefined ,
181- repository : undefined ,
182- versions : { } ,
191+ 'readme' : NPM_MISSING_README_SENTINEL ,
192+ 'readmeFilename' : 'README.md' ,
193+ 'repository' : undefined ,
194+ 'versions' : { } ,
195+ 'dist-tags' : { latest : '1.0.0' } ,
183196 } )
184197 parseRepositoryInfoMock . mockReturnValue ( undefined )
185198 const fetchMock = vi . fn ( ) . mockResolvedValue ( { ok : false } )
@@ -189,37 +202,40 @@ describe('resolvePackageReadmeSource', () => {
189202
190203 expect ( result ) . toMatchObject ( {
191204 packageName : 'pkg' ,
192- version : undefined ,
193205 markdown : undefined ,
194206 repoInfo : undefined ,
195207 } )
196208 } )
197209
198- it ( 'returns undefined markdown when content is NPM_MISSING_README_SENTINEL and jsdelivr fails ' , async ( ) => {
210+ it ( 'returns undefined markdown when no content anywhere ' , async ( ) => {
199211 fetchNpmPackageMock . mockResolvedValue ( {
200- readme : NPM_MISSING_README_SENTINEL ,
201- readmeFilename : 'README.md' ,
202- repository : undefined ,
203- versions : { } ,
212+ 'readme' : undefined ,
213+ 'readmeFilename' : undefined ,
214+ 'repository' : undefined ,
215+ 'versions' : { } ,
216+ 'dist-tags' : { latest : '1.0.0' } ,
204217 } )
218+ parseRepositoryInfoMock . mockReturnValue ( undefined )
205219 const fetchMock = vi . fn ( ) . mockResolvedValue ( { ok : false } )
206220 vi . stubGlobal ( 'fetch' , fetchMock )
207221
208222 const result = await resolvePackageReadmeSource ( 'pkg' )
209223
210224 expect ( result ) . toMatchObject ( {
211225 packageName : 'pkg' ,
226+ version : undefined ,
212227 markdown : undefined ,
213228 repoInfo : undefined ,
214229 } )
215230 } )
216231
217232 it ( 'uses package repository for repoInfo when markdown is present' , async ( ) => {
218233 fetchNpmPackageMock . mockResolvedValue ( {
219- readme : '# Hi' ,
220- readmeFilename : 'README.md' ,
221- repository : { url : 'https://github.com/a/b' } ,
222- versions : { } ,
234+ 'readme' : '# Hi' ,
235+ 'readmeFilename' : 'README.md' ,
236+ 'repository' : { url : 'https://github.com/a/b' } ,
237+ 'versions' : { } ,
238+ 'dist-tags' : { latest : '1.0.0' } ,
223239 } )
224240 const repoInfo = {
225241 provider : 'github' as const ,
@@ -229,6 +245,11 @@ describe('resolvePackageReadmeSource', () => {
229245 blobBaseUrl : 'https://github.com/a/b/blob/HEAD' ,
230246 }
231247 parseRepositoryInfoMock . mockReturnValue ( repoInfo )
248+ const fetchMock = vi . fn ( ) . mockResolvedValue ( {
249+ ok : true ,
250+ text : async ( ) => '# CDN' ,
251+ } )
252+ vi . stubGlobal ( 'fetch' , fetchMock )
232253
233254 const result = await resolvePackageReadmeSource ( 'pkg' )
234255
0 commit comments