@@ -38,6 +38,15 @@ describe('isStandardReadme', () => {
3838} )
3939
4040describe ( 'fetchReadmeFromJsdelivr' , ( ) => {
41+ beforeEach ( ( ) => {
42+ vi . unstubAllGlobals ( )
43+ vi . stubGlobal ( 'defineCachedFunction' , ( fn : Function ) => fn )
44+ vi . stubGlobal ( '$fetch' , $fetchMock )
45+ vi . stubGlobal ( 'parsePackageParams' , parsePackageParams )
46+ vi . stubGlobal ( 'fetchNpmPackage' , fetchNpmPackageMock )
47+ vi . stubGlobal ( 'parseRepositoryInfo' , parseRepositoryInfoMock )
48+ } )
49+
4150 it ( 'returns content when first filename succeeds' , async ( ) => {
4251 const content = '# Package'
4352 const fetchMock = vi . fn ( ) . mockResolvedValue ( {
@@ -73,6 +82,86 @@ describe('fetchReadmeFromJsdelivr', () => {
7382 expect ( result ) . toBeNull ( )
7483 expect ( fetchMock ) . toHaveBeenCalledTimes ( 2 )
7584 } )
85+
86+ it ( 'starts a small batch of candidate fetches in parallel' , async ( ) => {
87+ let resolveReadmeMd ! : ( value : { ok : false } ) => void
88+ let resolveLowercase ! : ( value : { ok : false } ) => void
89+ let resolveReadme ! : ( value : { ok : true ; text : ( ) => Promise < string > } ) => void
90+
91+ const fetchMock = vi . fn ( ( url : string ) => {
92+ if ( url . endsWith ( '/README.md' ) ) {
93+ return new Promise ( resolve => {
94+ resolveReadmeMd = resolve
95+ } )
96+ }
97+
98+ if ( url . endsWith ( '/readme.md' ) ) {
99+ return new Promise ( resolve => {
100+ resolveLowercase = resolve
101+ } )
102+ }
103+
104+ if ( url . endsWith ( '/README' ) ) {
105+ return new Promise ( resolve => {
106+ resolveReadme = resolve
107+ } )
108+ }
109+
110+ return Promise . resolve ( { ok : false } )
111+ } )
112+ vi . stubGlobal ( 'fetch' , fetchMock )
113+
114+ const resultPromise = fetchReadmeFromJsdelivr ( 'pkg' , [
115+ 'README.md' ,
116+ 'readme.md' ,
117+ 'README' ,
118+ 'readme' ,
119+ ] )
120+
121+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 3 )
122+ expect ( fetchMock . mock . calls . map ( ( [ url ] ) => url ) ) . toEqual ( [
123+ 'https://cdn.jsdelivr.net/npm/pkg/README.md' ,
124+ 'https://cdn.jsdelivr.net/npm/pkg/readme.md' ,
125+ 'https://cdn.jsdelivr.net/npm/pkg/README' ,
126+ ] )
127+
128+ resolveReadmeMd ( { ok : false } )
129+ resolveLowercase ( { ok : false } )
130+ resolveReadme ( {
131+ ok : true ,
132+ text : async ( ) => '# Package' ,
133+ } )
134+
135+ await expect ( resultPromise ) . resolves . toBe ( '# Package' )
136+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 3 )
137+ } )
138+
139+ it ( 'reads only the matched successful response body' , async ( ) => {
140+ const firstTextMock = vi . fn ( ) . mockResolvedValue ( '# First' )
141+ const secondTextMock = vi . fn ( ) . mockResolvedValue ( '# Second' )
142+ const secondCancelMock = vi . fn ( ) . mockResolvedValue ( undefined )
143+ const fetchMock = vi
144+ . fn ( )
145+ . mockResolvedValueOnce ( {
146+ ok : true ,
147+ text : firstTextMock ,
148+ } )
149+ . mockResolvedValueOnce ( {
150+ ok : true ,
151+ text : secondTextMock ,
152+ body : {
153+ cancel : secondCancelMock ,
154+ } ,
155+ } )
156+ vi . stubGlobal ( 'fetch' , fetchMock )
157+
158+ const result = await fetchReadmeFromJsdelivr ( 'pkg' , [ 'README.md' , 'readme.md' ] )
159+
160+ expect ( result ) . toBe ( '# First' )
161+ expect ( firstTextMock ) . toHaveBeenCalledTimes ( 1 )
162+ expect ( secondTextMock ) . not . toHaveBeenCalled ( )
163+ expect ( secondCancelMock ) . toHaveBeenCalledTimes ( 1 )
164+ } )
76165} )
77166
78167describe ( 'resolvePackageReadmeSource' , ( ) => {
@@ -172,6 +261,80 @@ describe('resolvePackageReadmeSource', () => {
172261 const result = await resolvePackageReadmeSource ( 'pkg' )
173262
174263 expect ( result ) . toMatchObject ( { markdown : jsdelivrContent } )
264+ expect ( fetchMock ) . toHaveBeenNthCalledWith ( 1 , 'https://cdn.jsdelivr.net/npm/pkg/DOCS.md' )
265+ } )
266+
267+ it ( 'tries a provided readmeFilename before starting the fallback batch' , async ( ) => {
268+ let resolveDocs ! : ( value : { ok : false } ) => void
269+ let resolveReadmeMd ! : ( value : { ok : false } ) => void
270+ let resolveLowercase ! : ( value : { ok : false } ) => void
271+ let resolveReadmeCase ! : ( value : { ok : true ; text : ( ) => Promise < string > } ) => void
272+
273+ fetchNpmPackageMock . mockResolvedValue ( {
274+ readme : undefined ,
275+ readmeFilename : 'DOCS.md' ,
276+ repository : undefined ,
277+ versions : { } ,
278+ } )
279+ parseRepositoryInfoMock . mockReturnValue ( undefined )
280+
281+ const fetchMock = vi . fn ( ( url : string ) => {
282+ if ( url . endsWith ( '/DOCS.md' ) ) {
283+ return new Promise ( resolve => {
284+ resolveDocs = resolve
285+ } )
286+ }
287+
288+ if ( url . endsWith ( '/README.md' ) ) {
289+ return new Promise ( resolve => {
290+ resolveReadmeMd = resolve
291+ } )
292+ }
293+
294+ if ( url . endsWith ( '/readme.md' ) ) {
295+ return new Promise ( resolve => {
296+ resolveLowercase = resolve
297+ } )
298+ }
299+
300+ if ( url . endsWith ( '/Readme.md' ) ) {
301+ return new Promise ( resolve => {
302+ resolveReadmeCase = resolve
303+ } )
304+ }
305+
306+ return Promise . resolve ( { ok : false } )
307+ } )
308+ vi . stubGlobal ( 'fetch' , fetchMock )
309+
310+ const resultPromise = resolvePackageReadmeSource ( 'pkg' )
311+
312+ await new Promise ( resolve => setTimeout ( resolve , 0 ) )
313+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 1 )
314+ expect ( fetchMock ) . toHaveBeenNthCalledWith ( 1 , 'https://cdn.jsdelivr.net/npm/pkg/DOCS.md' )
315+
316+ resolveDocs ( { ok : false } )
317+
318+ await new Promise ( resolve => setTimeout ( resolve , 0 ) )
319+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 4 )
320+ expect ( fetchMock . mock . calls . slice ( 1 ) . map ( ( [ url ] ) => url ) ) . toEqual ( [
321+ 'https://cdn.jsdelivr.net/npm/pkg/README.md' ,
322+ 'https://cdn.jsdelivr.net/npm/pkg/readme.md' ,
323+ 'https://cdn.jsdelivr.net/npm/pkg/Readme.md' ,
324+ ] )
325+
326+ resolveReadmeMd ( { ok : false } )
327+ resolveLowercase ( { ok : false } )
328+ resolveReadmeCase ( {
329+ ok : true ,
330+ text : async ( ) => '# From fallback batch' ,
331+ } )
332+
333+ await expect ( resultPromise ) . resolves . toMatchObject ( {
334+ packageName : 'pkg' ,
335+ markdown : '# From fallback batch' ,
336+ repoInfo : undefined ,
337+ } )
175338 } )
176339
177340 it ( 'returns undefined markdown when no content and jsdelivr fails' , async ( ) => {
0 commit comments