diff --git a/cypress/e2e/indexers/tvdb.cy.ts b/cypress/e2e/indexers/tvdb.cy.ts new file mode 100644 index 00000000..be8871b0 --- /dev/null +++ b/cypress/e2e/indexers/tvdb.cy.ts @@ -0,0 +1,91 @@ +describe('TVDB Integration', () => { + // Constants for routes and selectors + const ROUTES = { + home: '/', + tvdbSettings: '/settings/tvdb', + pokemonShow: '/tv/72879', + }; + + const SELECTORS = { + sidebarToggle: '[data-testid=sidebar-toggle]', + sidebarSettingsMobile: '[data-testid=sidebar-menu-settings-mobile]', + settingsNavDesktop: 'nav[data-testid="settings-nav-desktop"]', + tvdbEnable: 'input[data-testid="tvdb-enable"]', + tvdbSaveButton: '[data-testid=tvbd-save-button]', + heading: '.heading', + season1: 'Season 1', + season2: 'Season 2', + }; + + // Reusable commands + const toggleTVDBSetting = () => { + cy.intercept('/api/v1/settings/tvdb').as('tvdbRequest'); + cy.get(SELECTORS.tvdbSaveButton).click(); + return cy.wait('@tvdbRequest'); + }; + + const verifyTVDBResponse = (response, expectedUseValue) => { + expect(response.statusCode).to.equal(200); + expect(response.body.use).to.equal(expectedUseValue); + }; + + beforeEach(() => { + // Perform login + cy.login(Cypress.env('ADMIN_EMAIL'), Cypress.env('ADMIN_PASSWORD')); + + // Navigate to TVDB settings + cy.visit(ROUTES.home); + cy.get(SELECTORS.sidebarToggle).click(); + cy.get(SELECTORS.sidebarSettingsMobile).click(); + cy.get( + `${SELECTORS.settingsNavDesktop} a[href="${ROUTES.tvdbSettings}"]` + ).click(); + + // Verify heading + cy.get(SELECTORS.heading).should('contain', 'Tvdb'); + + // Configure TVDB settings + cy.get(SELECTORS.tvdbEnable).then(($checkbox) => { + const isChecked = $checkbox.is(':checked'); + + if (!isChecked) { + // If disabled, enable TVDB + cy.wrap($checkbox).click(); + toggleTVDBSetting().then(({ response }) => { + verifyTVDBResponse(response, true); + }); + } else { + // If enabled, disable then re-enable TVDB + cy.wrap($checkbox).click(); + toggleTVDBSetting().then(({ response }) => { + verifyTVDBResponse(response, false); + }); + + cy.wrap($checkbox).click(); + toggleTVDBSetting().then(({ response }) => { + verifyTVDBResponse(response, true); + }); + } + }); + }); + + it('should display "Tomorrow is Ours" show information correctly (1 season on TMDB >1 seasons on TVDB)', () => { + cy.visit(ROUTES.pokemonShow); + cy.contains(SELECTORS.season2) + .should('be.visible') + .scrollIntoView() + .click(); + }); + + it('Should display "Monster" show information correctly (Not existing on TVDB)', () => { + cy.visit('/tv/225634'); + cy.intercept('/api/v1/tv/225634/season/1').as('season1'); + cy.contains(SELECTORS.season1) + .should('be.visible') + .scrollIntoView() + .click(); + cy.wait('@season1'); + + cy.contains('9 - Hang Men').should('be.visible'); + }); +}); diff --git a/cypress/e2e/tv-details.cy.ts b/cypress/e2e/tv-details.cy.ts index 9d2dab42..5b4bd049 100644 --- a/cypress/e2e/tv-details.cy.ts +++ b/cypress/e2e/tv-details.cy.ts @@ -17,7 +17,7 @@ describe('TV Details', () => { cy.visit('/tv/66732'); // intercept request for season info - cy.intercept('/api/v1/tv/66732/season/4/163313').as('season4'); + cy.intercept('/api/v1/tv/66732/season/4').as('season4'); cy.contains('Season 4').should('be.visible').scrollIntoView().click(); diff --git a/jellyseerr-api.yml b/jellyseerr-api.yml index bf455367..ecc7f6d0 100644 --- a/jellyseerr-api.yml +++ b/jellyseerr-api.yml @@ -6532,7 +6532,7 @@ paths: application/json: schema: $ref: '#/components/schemas/TvDetails' - /tv/{tvId}/season/{seasonNumber}/{seasonId}: + /tv/{tvId}/season/{seasonNumber}: get: summary: Get season details and episode list description: Returns season details with a list of episodes in a JSON object. @@ -6545,12 +6545,6 @@ paths: schema: type: number example: 76479 - - in: path - name: seasonId - required: true - schema: - type: number - example: 1 - in: path name: seasonNumber required: true diff --git a/server/api/indexer/index.ts b/server/api/indexer/index.ts index 23321b63..0da0c914 100644 --- a/server/api/indexer/index.ts +++ b/server/api/indexer/index.ts @@ -13,12 +13,10 @@ export interface TvShowIndexer { }): Promise; getTvSeason({ tvId, - seasonId, seasonNumber, language, }: { tvId: number; - seasonId: number; seasonNumber: number; language?: string; }): Promise; diff --git a/server/routes/settings/tvdb.ts b/server/routes/settings/tvdb.ts index 3fe83d2b..db497be7 100644 --- a/server/routes/settings/tvdb.ts +++ b/server/routes/settings/tvdb.ts @@ -15,6 +15,12 @@ tvdbRoutes.get('/', (_req, res) => { tvdbRoutes.put('/', (req, res) => { const settings = getSettings(); + if (!settings.tvdb) { + settings.tvdb = { + use: false, + }; + } + const newTvdb = req.body as TvdbSettings; const tvdb = settings.tvdb; diff --git a/server/routes/tv.ts b/server/routes/tv.ts index 3b15e01b..3b98fe71 100644 --- a/server/routes/tv.ts +++ b/server/routes/tv.ts @@ -56,14 +56,12 @@ tvRoutes.get('/:id', async (req, res, next) => { } }); -tvRoutes.get('/:id/season/:seasonNumber/:seasonId', async (req, res, next) => { +tvRoutes.get('/:id/season/:seasonNumber', async (req, res, next) => { try { const indexer = getIndexer(); - const seasonIdentifier = indexer.getSeasonIdentifier(req); const season = await indexer.getTvSeason({ tvId: Number(req.params.id), - seasonId: seasonIdentifier, seasonNumber: Number(req.params.seasonNumber), }); diff --git a/src/components/Settings/SettingsTvdb.tsx b/src/components/Settings/SettingsTvdb.tsx index 6574288d..bf981c0f 100644 --- a/src/components/Settings/SettingsTvdb.tsx +++ b/src/components/Settings/SettingsTvdb.tsx @@ -118,6 +118,7 @@ const SettingsTvdb = () => {
{