Skip to content

Commit 24e3eee

Browse files
committed
test: add unit tests for SongWebhookService methods
1 parent d7e94e4 commit 24e3eee

File tree

1 file changed

+260
-0
lines changed

1 file changed

+260
-0
lines changed
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
import { ConfigModule, ConfigService } from '@nestjs/config';
2+
import { getModelToken } from '@nestjs/mongoose';
3+
import { Test, TestingModule } from '@nestjs/testing';
4+
import { Model } from 'mongoose';
5+
6+
import { SongWebhookService } from './song-webhook.service';
7+
import { Song as SongEntity, SongWithUser } from '../entity/song.entity';
8+
import { getUploadDiscordEmbed } from '../song.util';
9+
10+
jest.mock('../song.util', () => ({
11+
getUploadDiscordEmbed: jest.fn(),
12+
}));
13+
14+
const mockSongModel = {
15+
find: jest.fn().mockReturnThis(),
16+
sort: jest.fn().mockReturnThis(),
17+
populate: jest.fn().mockReturnThis(),
18+
save: jest.fn(),
19+
};
20+
21+
describe('SongWebhookService', () => {
22+
let service: SongWebhookService;
23+
let _songModel: Model<SongEntity>;
24+
let _configService: ConfigService;
25+
26+
beforeEach(async () => {
27+
const module: TestingModule = await Test.createTestingModule({
28+
imports: [ConfigModule.forRoot()],
29+
providers: [
30+
SongWebhookService,
31+
{
32+
provide: getModelToken(SongEntity.name),
33+
useValue: mockSongModel,
34+
},
35+
{
36+
provide: 'DISCORD_WEBHOOK_URL',
37+
useValue: 'http://localhost/webhook',
38+
},
39+
],
40+
}).compile();
41+
42+
service = module.get<SongWebhookService>(SongWebhookService);
43+
_songModel = module.get<Model<SongEntity>>(getModelToken(SongEntity.name));
44+
_configService = module.get<ConfigService>(ConfigService);
45+
});
46+
47+
it('should be defined', () => {
48+
expect(service).toBeDefined();
49+
});
50+
51+
describe('postSongWebhook', () => {
52+
it('should post a new webhook message for a song', async () => {
53+
const song: SongWithUser = {
54+
publicId: '123',
55+
uploader: { username: 'testuser', profileImage: 'testimage' },
56+
} as SongWithUser;
57+
58+
(getUploadDiscordEmbed as jest.Mock).mockReturnValue({});
59+
60+
global.fetch = jest.fn().mockResolvedValue({
61+
json: jest.fn().mockResolvedValue({ id: 'message-id' }),
62+
});
63+
64+
const result = await service.postSongWebhook(song);
65+
66+
expect(result).toBe('message-id');
67+
expect(fetch).toHaveBeenCalledWith('http://localhost/webhook?wait=true', {
68+
method: 'POST',
69+
headers: {
70+
'Content-Type': 'application/json',
71+
},
72+
body: JSON.stringify({}),
73+
});
74+
});
75+
76+
it('should return null if there is an error', async () => {
77+
const song: SongWithUser = {
78+
publicId: '123',
79+
uploader: { username: 'testuser', profileImage: 'testimage' },
80+
} as SongWithUser;
81+
82+
(getUploadDiscordEmbed as jest.Mock).mockReturnValue({});
83+
84+
global.fetch = jest.fn().mockRejectedValue(new Error('Error'));
85+
86+
const result = await service.postSongWebhook(song);
87+
88+
expect(result).toBeNull();
89+
});
90+
});
91+
92+
describe('updateSongWebhook', () => {
93+
it('should update the webhook message for a song', async () => {
94+
const song: SongWithUser = {
95+
publicId: '123',
96+
webhookMessageId: 'message-id',
97+
uploader: { username: 'testuser', profileImage: 'testimage' },
98+
} as SongWithUser;
99+
100+
(getUploadDiscordEmbed as jest.Mock).mockReturnValue({});
101+
102+
global.fetch = jest.fn().mockResolvedValue({});
103+
104+
await service.updateSongWebhook(song);
105+
106+
expect(fetch).toHaveBeenCalledWith(
107+
'http://localhost/webhook/messages/message-id',
108+
{
109+
method: 'PATCH',
110+
headers: {
111+
'Content-Type': 'application/json',
112+
},
113+
body: JSON.stringify({}),
114+
},
115+
);
116+
});
117+
118+
it('should log an error if there is an error', async () => {
119+
const song: SongWithUser = {
120+
publicId: '123',
121+
webhookMessageId: 'message-id',
122+
uploader: { username: 'testuser', profileImage: 'testimage' },
123+
} as SongWithUser;
124+
125+
(getUploadDiscordEmbed as jest.Mock).mockReturnValue({});
126+
127+
global.fetch = jest.fn().mockRejectedValue(new Error('Error'));
128+
129+
const loggerSpy = jest.spyOn(service['logger'], 'error');
130+
131+
await service.updateSongWebhook(song);
132+
133+
expect(loggerSpy).toHaveBeenCalledWith(
134+
'Error updating Discord webhook',
135+
expect.any(Error),
136+
);
137+
});
138+
});
139+
140+
describe('deleteSongWebhook', () => {
141+
it('should delete the webhook message for a song', async () => {
142+
const song: SongWithUser = {
143+
publicId: '123',
144+
webhookMessageId: 'message-id',
145+
uploader: { username: 'testuser', profileImage: 'testimage' },
146+
} as SongWithUser;
147+
148+
global.fetch = jest.fn().mockResolvedValue({});
149+
150+
await service.deleteSongWebhook(song);
151+
152+
expect(fetch).toHaveBeenCalledWith(
153+
'http://localhost/webhook/messages/message-id',
154+
{
155+
method: 'DELETE',
156+
},
157+
);
158+
});
159+
160+
it('should log an error if there is an error', async () => {
161+
const song: SongWithUser = {
162+
publicId: '123',
163+
webhookMessageId: 'message-id',
164+
uploader: { username: 'testuser', profileImage: 'testimage' },
165+
} as SongWithUser;
166+
167+
global.fetch = jest.fn().mockRejectedValue(new Error('Error'));
168+
169+
const loggerSpy = jest.spyOn(service['logger'], 'error');
170+
171+
await service.deleteSongWebhook(song);
172+
173+
expect(loggerSpy).toHaveBeenCalledWith(
174+
'Error deleting Discord webhook',
175+
expect.any(Error),
176+
);
177+
});
178+
});
179+
180+
describe('syncSongWebhook', () => {
181+
it('should update the webhook message if the song is public', async () => {
182+
const song: SongWithUser = {
183+
publicId: '123',
184+
webhookMessageId: 'message-id',
185+
visibility: 'public',
186+
uploader: { username: 'testuser', profileImage: 'testimage' },
187+
} as SongWithUser;
188+
189+
const updateSpy = jest.spyOn(service, 'updateSongWebhook');
190+
191+
await service.syncSongWebhook(song);
192+
193+
expect(updateSpy).toHaveBeenCalledWith(song);
194+
});
195+
196+
it('should delete the webhook message if the song is not public', async () => {
197+
const song: SongWithUser = {
198+
publicId: '123',
199+
webhookMessageId: 'message-id',
200+
visibility: 'private',
201+
uploader: { username: 'testuser', profileImage: 'testimage' },
202+
} as SongWithUser;
203+
204+
const deleteSpy = jest.spyOn(service, 'deleteSongWebhook');
205+
206+
await service.syncSongWebhook(song);
207+
208+
expect(deleteSpy).toHaveBeenCalledWith(song);
209+
});
210+
211+
it('should post a new webhook message if the song is public and does not have a message', async () => {
212+
const song: SongWithUser = {
213+
publicId: '123',
214+
visibility: 'public',
215+
uploader: { username: 'testuser', profileImage: 'testimage' },
216+
} as SongWithUser;
217+
218+
const postSpy = jest.spyOn(service, 'postSongWebhook');
219+
220+
await service.syncSongWebhook(song);
221+
222+
expect(postSpy).toHaveBeenCalledWith(song);
223+
});
224+
225+
it('should return null if the song is not public and does not have a message', async () => {
226+
const song: SongWithUser = {
227+
publicId: '123',
228+
visibility: 'private',
229+
uploader: { username: 'testuser', profileImage: 'testimage' },
230+
} as SongWithUser;
231+
232+
const result = await service.syncSongWebhook(song);
233+
234+
expect(result).toBeNull();
235+
});
236+
});
237+
238+
describe('syncAllSongsWebhook', () => {
239+
it('should synchronize the webhook messages for all songs', async () => {
240+
const songs: SongWithUser[] = [
241+
{
242+
publicId: '123',
243+
uploader: { username: 'testuser', profileImage: 'testimage' },
244+
save: jest.fn(),
245+
} as unknown as SongWithUser,
246+
];
247+
248+
mockSongModel.find.mockReturnValue({
249+
sort: jest.fn().mockReturnThis(),
250+
populate: jest.fn().mockResolvedValue(songs),
251+
});
252+
253+
const syncSpy = jest.spyOn(service, 'syncSongWebhook');
254+
255+
await (service as any).syncAllSongsWebhook();
256+
257+
expect(syncSpy).toHaveBeenCalledWith(songs[0]);
258+
});
259+
});
260+
});

0 commit comments

Comments
 (0)