1
1
import type { UserDocument } from '@nbw/database' ;
2
- import {
3
- PageQueryDTO ,
4
- SongPreviewDto ,
5
- SongViewDto ,
6
- UploadSongDto ,
7
- UploadSongResponseDto ,
8
- } from '@nbw/database' ;
2
+ import { PageQueryDTO , SongPreviewDto , SongViewDto , UploadSongDto , UploadSongResponseDto , } from '@nbw/database' ;
9
3
import { HttpStatus , UnauthorizedException } from '@nestjs/common' ;
10
4
import { AuthGuard } from '@nestjs/passport' ;
11
5
import { Test , TestingModule } from '@nestjs/testing' ;
12
6
import { Response } from 'express' ;
13
7
14
- import { FileService } from '@server /file/file.service' ;
8
+ import { FileService } from '.. /file/file.service' ;
15
9
10
+ import { SongBrowserService } from './song-browser/song-browser.service' ;
16
11
import { SongController } from './song.controller' ;
17
12
import { SongService } from './song.service' ;
18
13
19
14
const mockSongService = {
20
15
getSongByPage : jest . fn ( ) ,
16
+ searchSongs : jest . fn ( ) ,
21
17
getSong : jest . fn ( ) ,
22
18
getSongEdit : jest . fn ( ) ,
23
19
patchSong : jest . fn ( ) ,
@@ -28,9 +24,17 @@ const mockSongService = {
28
24
29
25
const mockFileService = { } ;
30
26
27
+ const mockSongBrowserService = {
28
+ getRecentSongs : jest . fn ( ) ,
29
+ getCategories : jest . fn ( ) ,
30
+ getSongsByCategory : jest . fn ( ) ,
31
+ getRandomSongs : jest . fn ( ) ,
32
+ } ;
33
+
31
34
describe ( 'SongController' , ( ) => {
32
35
let songController : SongController ;
33
36
let songService : SongService ;
37
+ let songBrowserService : SongBrowserService ;
34
38
35
39
beforeEach ( async ( ) => {
36
40
const module : TestingModule = await Test . createTestingModule ( {
@@ -44,6 +48,10 @@ describe('SongController', () => {
44
48
provide : FileService ,
45
49
useValue : mockFileService ,
46
50
} ,
51
+ {
52
+ provide : SongBrowserService ,
53
+ useValue : mockSongBrowserService ,
54
+ } ,
47
55
] ,
48
56
} )
49
57
. overrideGuard ( AuthGuard ( 'jwt-refresh' ) )
@@ -52,6 +60,10 @@ describe('SongController', () => {
52
60
53
61
songController = module . get < SongController > ( SongController ) ;
54
62
songService = module . get < SongService > ( SongService ) ;
63
+ songBrowserService = module . get < SongBrowserService > ( SongBrowserService ) ;
64
+
65
+ // Clear all mocks
66
+ jest . clearAllMocks ( ) ;
55
67
} ) ;
56
68
57
69
it ( 'should be defined' , ( ) => {
@@ -71,6 +83,96 @@ describe('SongController', () => {
71
83
expect ( songService . getSongByPage ) . toHaveBeenCalledWith ( query ) ;
72
84
} ) ;
73
85
86
+ it ( 'should handle featured songs' , async ( ) => {
87
+ const query : PageQueryDTO = { page : 1 , limit : 10 } ;
88
+ const songList : SongPreviewDto [ ] = [ ] ;
89
+
90
+ mockSongBrowserService . getRecentSongs . mockResolvedValueOnce ( songList ) ;
91
+
92
+ const result = await songController . getSongList ( query , 'featured' ) ;
93
+
94
+ expect ( result ) . toEqual ( songList ) ;
95
+ expect ( mockSongBrowserService . getRecentSongs ) . toHaveBeenCalledWith ( query ) ;
96
+ } ) ;
97
+
98
+ it ( 'should handle recent songs' , async ( ) => {
99
+ const query : PageQueryDTO = { page : 1 , limit : 10 } ;
100
+ const songList : SongPreviewDto [ ] = [ ] ;
101
+
102
+ mockSongBrowserService . getRecentSongs . mockResolvedValueOnce ( songList ) ;
103
+
104
+ const result = await songController . getSongList ( query , 'recent' ) ;
105
+
106
+ expect ( result ) . toEqual ( songList ) ;
107
+ expect ( mockSongBrowserService . getRecentSongs ) . toHaveBeenCalledWith ( query ) ;
108
+ } ) ;
109
+
110
+ it ( 'should return categories when q=categories without id' , async ( ) => {
111
+ const query : PageQueryDTO = { page : 1 , limit : 10 } ;
112
+ const categories = { pop : 42 , rock : 38 } ;
113
+
114
+ mockSongBrowserService . getCategories . mockResolvedValueOnce ( categories ) ;
115
+
116
+ const result = await songController . getSongList ( query , 'categories' ) ;
117
+
118
+ expect ( result ) . toEqual ( categories ) ;
119
+ expect ( mockSongBrowserService . getCategories ) . toHaveBeenCalled ( ) ;
120
+ } ) ;
121
+
122
+ it ( 'should return songs by category when q=categories with id' , async ( ) => {
123
+ const query : PageQueryDTO = { page : 1 , limit : 10 } ;
124
+ const songList : SongPreviewDto [ ] = [ ] ;
125
+ const categoryId = 'pop' ;
126
+
127
+ mockSongBrowserService . getSongsByCategory . mockResolvedValueOnce ( songList ) ;
128
+
129
+ const result = await songController . getSongList ( query , 'categories' , categoryId ) ;
130
+
131
+ expect ( result ) . toEqual ( songList ) ;
132
+ expect ( mockSongBrowserService . getSongsByCategory ) . toHaveBeenCalledWith ( categoryId , query ) ;
133
+ } ) ;
134
+
135
+ it ( 'should return random songs' , async ( ) => {
136
+ const query : PageQueryDTO = { page : 1 , limit : 5 } ;
137
+ const songList : SongPreviewDto [ ] = [ ] ;
138
+ const category = 'electronic' ;
139
+
140
+ mockSongBrowserService . getRandomSongs . mockResolvedValueOnce ( songList ) ;
141
+
142
+ const result = await songController . getSongList ( query , 'random' , undefined , category ) ;
143
+
144
+ expect ( result ) . toEqual ( songList ) ;
145
+ expect ( mockSongBrowserService . getRandomSongs ) . toHaveBeenCalledWith ( 5 , category ) ;
146
+ } ) ;
147
+
148
+ it ( 'should throw error for invalid random count' , async ( ) => {
149
+ const query : PageQueryDTO = { page : 1 , limit : 15 } ; // Invalid limit > 10
150
+
151
+ await expect (
152
+ songController . getSongList ( query , 'random' )
153
+ ) . rejects . toThrow ( 'Invalid query parameters' ) ;
154
+ } ) ;
155
+
156
+ it ( 'should handle zero limit for random (uses default)' , async ( ) => {
157
+ const query : PageQueryDTO = { page : 1 , limit : 0 } ; // limit 0 is falsy, so uses default
158
+ const songList : SongPreviewDto [ ] = [ ] ;
159
+
160
+ mockSongBrowserService . getRandomSongs . mockResolvedValueOnce ( songList ) ;
161
+
162
+ const result = await songController . getSongList ( query , 'random' ) ;
163
+
164
+ expect ( result ) . toEqual ( songList ) ;
165
+ expect ( mockSongBrowserService . getRandomSongs ) . toHaveBeenCalledWith ( 0 , undefined ) ; // Passes 0 (nullish coalescing doesn't apply to 0)
166
+ } ) ;
167
+
168
+ it ( 'should throw error for invalid query mode' , async ( ) => {
169
+ const query : PageQueryDTO = { page : 1 , limit : 10 } ;
170
+
171
+ await expect (
172
+ songController . getSongList ( query , 'invalid' as any )
173
+ ) . rejects . toThrow ( 'Invalid query parameters' ) ;
174
+ } ) ;
175
+
74
176
it ( 'should handle errors' , async ( ) => {
75
177
const query : PageQueryDTO = { page : 1 , limit : 10 } ;
76
178
0 commit comments