|
9 | 9 | import { getRepository } from '@server/datasource'; |
10 | 10 | import Media from '@server/entity/Media'; |
11 | 11 | import { MediaRequest } from '@server/entity/MediaRequest'; |
| 12 | +import Season from '@server/entity/Season'; |
12 | 13 | import SeasonRequest from '@server/entity/SeasonRequest'; |
13 | 14 | import { User } from '@server/entity/User'; |
14 | 15 | import { getSettings } from '@server/lib/settings'; |
@@ -243,6 +244,19 @@ async function seedTvMedia(tmdbId: number) { |
243 | 244 | ); |
244 | 245 | } |
245 | 246 |
|
| 247 | +async function seedMediaSeasons( |
| 248 | + tmdbId: number, |
| 249 | + seasons: { seasonNumber: number; status: MediaStatus }[] |
| 250 | +) { |
| 251 | + const media = await seedTvMedia(tmdbId); |
| 252 | + media.seasons = seasons.map( |
| 253 | + ({ seasonNumber, status }) => |
| 254 | + new Season({ seasonNumber, status, status4k: MediaStatus.UNKNOWN }) |
| 255 | + ); |
| 256 | + |
| 257 | + return getRepository(Media).save(media); |
| 258 | +} |
| 259 | + |
246 | 260 | async function seedTvRequest( |
247 | 261 | requestedBy: User, |
248 | 262 | seasons: number[], |
@@ -303,6 +317,102 @@ describe('PUT /request/:requestId (tv)', () => { |
303 | 317 | }); |
304 | 318 | }); |
305 | 319 |
|
| 320 | +describe('PUT /request/:requestId (season availability)', () => { |
| 321 | + it('does not add a season the media already has', async () => { |
| 322 | + const requestRepo = getRepository(MediaRequest); |
| 323 | + const owner = await seedUser('friend@seerr.dev'); |
| 324 | + const mediaRequest = await seedTvRequest(owner, [1]); |
| 325 | + await seedMediaSeasons(67890, [ |
| 326 | + { seasonNumber: 2, status: MediaStatus.AVAILABLE }, |
| 327 | + ]); |
| 328 | + |
| 329 | + const agent = await loginAs('friend@seerr.dev', 'test1234'); |
| 330 | + const res = await agent.put(`/request/${mediaRequest.id}`).send({ |
| 331 | + mediaType: MediaType.TV, |
| 332 | + seasons: [1, 2, 3], |
| 333 | + }); |
| 334 | + |
| 335 | + assert.strictEqual(res.status, 200); |
| 336 | + |
| 337 | + const saved = await requestRepo.findOneOrFail({ |
| 338 | + where: { id: mediaRequest.id }, |
| 339 | + }); |
| 340 | + assert.deepStrictEqual( |
| 341 | + saved.seasons.map((s) => s.seasonNumber).sort(), |
| 342 | + [1, 3] |
| 343 | + ); |
| 344 | + }); |
| 345 | + |
| 346 | + it('returns 202 when every requested season is already covered', async () => { |
| 347 | + const owner = await seedUser('friend@seerr.dev'); |
| 348 | + const mediaRequest = await seedTvRequest(owner, [1]); |
| 349 | + await seedMediaSeasons(67890, [ |
| 350 | + { seasonNumber: 2, status: MediaStatus.AVAILABLE }, |
| 351 | + ]); |
| 352 | + |
| 353 | + const agent = await loginAs('friend@seerr.dev', 'test1234'); |
| 354 | + const res = await agent.put(`/request/${mediaRequest.id}`).send({ |
| 355 | + mediaType: MediaType.TV, |
| 356 | + seasons: [2], |
| 357 | + }); |
| 358 | + |
| 359 | + assert.strictEqual(res.status, 202); |
| 360 | + }); |
| 361 | + |
| 362 | + it('keeps the seasons it already holds once they are available', async () => { |
| 363 | + const requestRepo = getRepository(MediaRequest); |
| 364 | + const owner = await seedUser('friend@seerr.dev'); |
| 365 | + const mediaRequest = await seedTvRequest(owner, [1, 2]); |
| 366 | + await seedMediaSeasons(67890, [ |
| 367 | + { seasonNumber: 1, status: MediaStatus.AVAILABLE }, |
| 368 | + { seasonNumber: 2, status: MediaStatus.PROCESSING }, |
| 369 | + ]); |
| 370 | + |
| 371 | + const agent = await loginAs('friend@seerr.dev', 'test1234'); |
| 372 | + const res = await agent.put(`/request/${mediaRequest.id}`).send({ |
| 373 | + mediaType: MediaType.TV, |
| 374 | + seasons: [1, 2], |
| 375 | + serverId: 3, |
| 376 | + }); |
| 377 | + |
| 378 | + assert.strictEqual(res.status, 200); |
| 379 | + |
| 380 | + const saved = await requestRepo.findOneOrFail({ |
| 381 | + where: { id: mediaRequest.id }, |
| 382 | + }); |
| 383 | + assert.deepStrictEqual( |
| 384 | + saved.seasons.map((s) => s.seasonNumber).sort(), |
| 385 | + [1, 2] |
| 386 | + ); |
| 387 | + assert.strictEqual(saved.serverId, 3); |
| 388 | + }); |
| 389 | + |
| 390 | + it('does not charge quota for a season the media already has', async () => { |
| 391 | + const requestRepo = getRepository(MediaRequest); |
| 392 | + const owner = await seedUser('friend@seerr.dev', { tvQuotaLimit: 1 }); |
| 393 | + const mediaRequest = await seedTvRequest(owner, [1]); |
| 394 | + await seedMediaSeasons(67890, [ |
| 395 | + { seasonNumber: 2, status: MediaStatus.AVAILABLE }, |
| 396 | + ]); |
| 397 | + |
| 398 | + const agent = await loginAs('friend@seerr.dev', 'test1234'); |
| 399 | + const res = await agent.put(`/request/${mediaRequest.id}`).send({ |
| 400 | + mediaType: MediaType.TV, |
| 401 | + seasons: [1, 2], |
| 402 | + }); |
| 403 | + |
| 404 | + assert.strictEqual(res.status, 200); |
| 405 | + |
| 406 | + const saved = await requestRepo.findOneOrFail({ |
| 407 | + where: { id: mediaRequest.id }, |
| 408 | + }); |
| 409 | + assert.deepStrictEqual( |
| 410 | + saved.seasons.map((s) => s.seasonNumber), |
| 411 | + [1] |
| 412 | + ); |
| 413 | + }); |
| 414 | +}); |
| 415 | + |
306 | 416 | describe('PUT /request/:requestId (quota)', () => { |
307 | 417 | it('rejects adding seasons beyond the season limit', async () => { |
308 | 418 | const requestRepo = getRepository(MediaRequest); |
|
0 commit comments