@@ -17,6 +17,7 @@ const {
1717 getFileName,
1818 getMediaDownloadInfo,
1919 buildRedditApiUrl,
20+ extractName,
2021 DEFAULT_REQUEST_TIMEOUT ,
2122} = require ( '../lib/utils' ) ;
2223
@@ -125,9 +126,13 @@ describe('Reddit API Integration', () => {
125126 } ) ;
126127
127128 test ( 'handles non-existent subreddit gracefully' , async ( ) => {
128- await expect (
129- fetchRedditPosts ( 'thisdoesnotexist123456789xyz' , 1 ) ,
130- ) . rejects . toThrow ( ) ;
129+ try {
130+ await fetchRedditPosts ( 'thisdoesnotexist123456789xyz' , 1 ) ;
131+ expect ( true ) . toBe ( false ) ;
132+ } catch ( err ) {
133+ expect ( err ) . toBeDefined ( ) ;
134+ expect ( err . message || err . response ?. status ) . toBeDefined ( ) ;
135+ }
131136 } ) ;
132137} ) ;
133138
@@ -338,6 +343,105 @@ describe('User Profile Downloads', () => {
338343 } ) ;
339344} ) ;
340345
346+ describe ( 'Search Query Downloads' , ( ) => {
347+ test ( 'can fetch posts from a search query' , async ( ) => {
348+ const query = 'search:subreddit:aww cats AND cute' ;
349+ const url = buildRedditApiUrl ( {
350+ target : extractName ( query ) ,
351+ isUser : false ,
352+ isSearch : true ,
353+ sorting : 'new' ,
354+ time : 'all' ,
355+ limit : 5 ,
356+ } ) ;
357+
358+ const response = await axios . get ( url , {
359+ timeout : DEFAULT_REQUEST_TIMEOUT ,
360+ headers : {
361+ 'User-Agent' : 'RedditDownloaderTest/1.0' ,
362+ } ,
363+ } ) ;
364+
365+ const posts = response . data . data . children . map ( ( child ) => child . data ) ;
366+
367+ expect ( posts . length ) . toBeGreaterThan ( 0 ) ;
368+ expect ( posts [ 0 ] ) . toHaveProperty ( 'title' ) ;
369+ } ) ;
370+ } ) ;
371+
372+ describe ( 'Multiple subreddits (one search, one not)' , ( ) => {
373+ test ( 'can download from multiple targets: one subreddit and one search query' , async ( ) => {
374+ const regularSubreddit = 'pics' ;
375+ const searchQuery = 'search:subreddit:aww cats AND cute' ;
376+
377+ // Fetch from regular subreddit
378+ const regularPosts = await fetchRedditPosts ( regularSubreddit , 15 ) ;
379+ expect ( regularPosts . length ) . toBeGreaterThan ( 0 ) ;
380+
381+ // Fetch from search query
382+ const searchUrl = buildRedditApiUrl ( {
383+ target : extractName ( searchQuery ) ,
384+ isUser : false ,
385+ isSearch : true ,
386+ sorting : 'new' ,
387+ time : 'all' ,
388+ limit : 15 ,
389+ } ) ;
390+ const searchResponse = await axios . get ( searchUrl , {
391+ timeout : DEFAULT_REQUEST_TIMEOUT ,
392+ headers : { 'User-Agent' : 'RedditDownloaderTest/1.0' } ,
393+ } ) ;
394+ const searchPosts = searchResponse . data . data . children . map ( ( child ) => child . data ) ;
395+ expect ( searchPosts . length ) . toBeGreaterThan ( 0 ) ;
396+
397+ let downloadedFromRegular = false ;
398+ let downloadedFromSearch = false ;
399+
400+ // Download at least one file from regular subreddit (e.g. image)
401+ const imageFromRegular = regularPosts . find (
402+ ( p ) =>
403+ p . url &&
404+ ( p . url . endsWith ( '.jpg' ) || p . url . endsWith ( '.png' ) || p . url . endsWith ( '.jpeg' ) ) ,
405+ ) ;
406+ if ( imageFromRegular ) {
407+ const ext = imageFromRegular . url . split ( '.' ) . pop ( ) . split ( '?' ) [ 0 ] ;
408+ const filePath = path . join ( TEST_DOWNLOAD_DIR , `multi_subreddit_pics.${ ext } ` ) ;
409+ await downloadFile ( imageFromRegular . url , filePath ) ;
410+ expect ( fs . existsSync ( filePath ) ) . toBe ( true ) ;
411+ expect ( fs . statSync ( filePath ) . size ) . toBeGreaterThan ( 0 ) ;
412+ downloadedFromRegular = true ;
413+ }
414+
415+ // Download at least one file from search results (image or text)
416+ const imageFromSearch = searchPosts . find (
417+ ( p ) =>
418+ p . url &&
419+ ( p . url . endsWith ( '.jpg' ) || p . url . endsWith ( '.png' ) || p . url . endsWith ( '.jpeg' ) ) ,
420+ ) ;
421+ if ( imageFromSearch ) {
422+ const ext = imageFromSearch . url . split ( '.' ) . pop ( ) . split ( '?' ) [ 0 ] ;
423+ const filePath = path . join ( TEST_DOWNLOAD_DIR , `multi_search_aww.${ ext } ` ) ;
424+ await downloadFile ( imageFromSearch . url , filePath ) ;
425+ expect ( fs . existsSync ( filePath ) ) . toBe ( true ) ;
426+ expect ( fs . statSync ( filePath ) . size ) . toBeGreaterThan ( 0 ) ;
427+ downloadedFromSearch = true ;
428+ }
429+ if ( ! downloadedFromSearch ) {
430+ const selfPost = searchPosts . find ( ( p ) => getPostType ( p ) === 0 ) ;
431+ if ( selfPost ) {
432+ const filePath = path . join ( TEST_DOWNLOAD_DIR , 'multi_search_aww.txt' ) ;
433+ const content = `${ selfPost . title } \n\n${ selfPost . selftext || '' } ` ;
434+ fs . writeFileSync ( filePath , content ) ;
435+ expect ( fs . existsSync ( filePath ) ) . toBe ( true ) ;
436+ downloadedFromSearch = true ;
437+ }
438+ }
439+
440+ expect ( downloadedFromRegular ) . toBe ( true ) ;
441+ expect ( downloadedFromSearch ) . toBe ( true ) ;
442+ } ) ;
443+ } ) ;
444+
341445describe ( 'Gallery Post Detection' , ( ) => {
342446 test ( 'can identify gallery posts' , async ( ) => {
343447 const posts = await fetchRedditPosts ( 'itookapicture' , 20 , 'top' , 'month' ) ;
@@ -362,21 +466,29 @@ describe('Error Handling', () => {
362466 const invalidUrl =
363467 'https://www.reddit.com/r/thisdefinitelydoesnotexist12345/top/.json' ;
364468
365- await expect (
366- axios . get ( invalidUrl , {
469+ try {
470+ await axios . get ( invalidUrl , {
367471 timeout : DEFAULT_REQUEST_TIMEOUT ,
368472 headers : { 'User-Agent' : 'RedditDownloaderTest/1.0' } ,
369- } ) ,
370- ) . rejects . toThrow ( ) ;
473+ } ) ;
474+ expect ( true ) . toBe ( false ) ;
475+ } catch ( err ) {
476+ expect ( err ) . toBeDefined ( ) ;
477+ expect ( err . response ?. status === 404 || err . message ) . toBeTruthy ( ) ;
478+ }
371479 } ) ;
372480
373481 test ( 'handles timeout appropriately' , async ( ) => {
374- await expect (
375- axios . get ( 'https://www.reddit.com/r/pics/top/.json' , {
482+ try {
483+ await axios . get ( 'https://www.reddit.com/r/pics/top/.json' , {
376484 timeout : 1 ,
377485 headers : { 'User-Agent' : 'RedditDownloaderTest/1.0' } ,
378- } ) ,
379- ) . rejects . toThrow ( ) ;
486+ } ) ;
487+ expect ( true ) . toBe ( false ) ;
488+ } catch ( err ) {
489+ expect ( err ) . toBeDefined ( ) ;
490+ expect ( err . code === 'ECONNABORTED' || err . message ) . toBeTruthy ( ) ;
491+ }
380492 } ) ;
381493} ) ;
382494
0 commit comments