# SPDX-License-Identifier: GPL-3.0-or-later
import datetime
import os
import unittest

from . channeltest import ChannelTest


class TestTv4Channel(ChannelTest):
    # noinspection PyPep8Naming
    def __init__(self, methodName):  # NOSONAR
        super(TestTv4Channel, self).__init__(methodName, "channel.se.tv4se", "tv4segroup")

    def test_channel_exists(self):
        self.assertIsNotNone(self.channel)

    def test_main_list(self):
        items = self.channel.process_folder_list(None)
        self.assertGreaterEqual(len(items), 5, "Incorrect number of items in mainlist")

    def test_program_list(self):
        url = "https://client-gateway.tv4.a2d.tv/graphql?operationName=MediaIndex&query=query%20MediaIndex%28%24input%3A%20MediaIndexListInput%21%2C%20%24genres%3A%20%5BString%21%5D%29%20%7B%20mediaIndex%28genres%3A%20%24genres%29%20%7B%20overview%20%7B%20letterIndex%20%7B%20letter%20totalCount%20%7D%20%7D%20contentList%28input%3A%20%24input%29%20%7B%20__typename%20items%20%7B%20...%20on%20MediaIndexSeriesItem%20%7B%20__typename%20letter%20series%20%7B%20...SeriesFieldsLight%20__typename%20%7D%20%7D%20...%20on%20MediaIndexMovieItem%20%7B%20__typename%20letter%20movie%20%7B%20...MovieFieldsLight%20__typename%20%7D%20%7D%20%7D%20pageInfo%20%7B%20hasMoreForLastLetter%20totalCount%20lastLetter%20nextPageOffset%20%7D%20%7D%20%7D%20%7D%20fragment%20SeriesFieldsLight%20on%20Series%20%7B%20id%20slug%20title%20genres%20mediaClassification%20numberOfAvailableSeasons%20label%20%7B%20...LabelFields%20%7D%20images%20%7B%20cover2x3%20%7B%20...ImageFieldsFull%20%7D%20main16x9Annotated%20%7B%20...ImageFieldsLight%20%7D%20%7D%20parentalRating%20%7B%20...ParentalRatingFields%20%7D%20trailers%20%7B%20mp4%20webm%20%7D%20upsell%20%7B%20tierId%20%7D%20%7D%20fragment%20MovieFieldsLight%20on%20Movie%20%7B%20id%20slug%20title%20genres%20productionYear%20isLiveContent%20productionCountries%20%7B%20name%20%7D%20parentalRating%20%7B%20...ParentalRatingFields%20%7D%20liveEventEnd%20%7B%20isoString%20%7D%20label%20%7B%20...LabelFields%20%7D%20images%20%7B%20cover2x3%20%7B%20...ImageFieldsFull%20%7D%20main16x9Annotated%20%7B%20...ImageFieldsLight%20%7D%20%7D%20playableUntil%20%7B%20readableDistance%28type%3A%20DAYS_LEFT%29%20%7D%20playableFrom%20%7B%20isoString%20humanDateTime%20readableDate%20%7D%20trailers%20%7B%20mp4%20webm%20%7D%20upsell%20%7B%20tierId%20%7D%20%7D%20fragment%20LabelFields%20on%20Label%20%7B%20id%20airtime%20announcement%20recurringBroadcast%20%7D%20fragment%20ImageFieldsFull%20on%20Image%20%7B%20sourceEncoded%20meta%20%7B%20muteBgColor%20%7B%20hex%20%7D%20%7D%20%7D%20fragment%20ImageFieldsLight%20on%20Image%20%7B%20sourceEncoded%20isFallback%20%7D%20fragment%20ParentalRatingFields%20on%20ParentalRating%20%7B%20finland%20%7B%20ageRestriction%20reason%20%7D%20sweden%20%7B%20ageRecommendation%20suitableForChildren%20%7D%20%7D&variables=%7B%22input%22%3A%20%7B%22letterFilters%22%3A%20%5B%22A%22%2C%20%22B%22%2C%20%22C%22%2C%20%22D%22%2C%20%22E%22%2C%20%22F%22%2C%20%22G%22%2C%20%22H%22%2C%20%22I%22%2C%20%22J%22%2C%20%22K%22%2C%20%22L%22%2C%20%22M%22%2C%20%22N%22%2C%20%22O%22%2C%20%22P%22%2C%20%22Q%22%2C%20%22R%22%2C%20%22S%22%2C%20%22T%22%2C%20%22U%22%2C%20%22V%22%2C%20%22W%22%2C%20%22X%22%2C%20%22Y%22%2C%20%22Z%22%5D%2C%20%22limit%22%3A%20100%2C%20%22offset%22%3A%200%7D%7D"
        self._test_folder_url(url, expected_results=1000)

    def test_lastest_news(self):
        url = "https://client-gateway.tv4.a2d.tv/graphql?operationName=Panel&"
        data = {"operationName": "Panel", "query": "query Panel($panelId: ID!, $offset: Int!, $limit: Int!) { panel(id: $panelId) { ... on ContinueWatchingPanel { id } ... on PagePanel { id content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { ... on PagePanelPageItem { page { ...PageListFields } } } } } ... on SportEventPanel { id content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { sportEvent { ...SportEventFieldsLight } } } } ... on ClipsPanel { id title content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { __typename clip { __typename ...ClipFieldsLight } } } } ... on EpisodesPanel { id title content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { episode { ...EpisodeFields } labelText } } } ... on MediaPanel { __typename id slug title content(input: {offset: $offset, limit: $limit}) { __typename pageInfo { ...PageInfoFields } items { ... on MediaPanelMovieItem { __typename movie { ...MovieFieldsLight __typename } } ... on MediaPanelSeriesItem { __typename series { ...SeriesFieldsLight __typename} } } } } ... on ChannelPanel { id title type content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { channel { ...ChannelFields } } } } } } fragment ImageFieldsFull on Image { sourceEncoded meta { muteBgColor { hex } } } fragment ParentalRatingFields on ParentalRating { finland { ageRestriction reason } sweden { ageRecommendation suitableForChildren } } fragment ImageFieldsLight on Image { sourceEncoded isFallback } fragment VideoFields on Video { id duration { readableShort readableMinutes seconds } isLiveContent access { hasAccess } isDrmProtected } fragment EpisodeFields on Episode { id slug title isLiveContent isStartOverEnabled series { id title slug } images { main16x9 { ...ImageFieldsLight } } liveEventEnd { isoString } playableUntil { readableDistance(type: DAYS_LEFT) humanDateTime } playableFrom { humanDateTime isoString } video { ...VideoFields } upsell { tierId } } fragment LabelFields on Label { id airtime announcement recurringBroadcast } fragment MovieFieldsLight on Movie { id slug title genres productionYear isLiveContent productionCountries { name } parentalRating { ...ParentalRatingFields } liveEventEnd { isoString } label { ...LabelFields } images { cover2x3 { ...ImageFieldsFull } main16x9Annotated { ...ImageFieldsLight } } playableUntil { readableDistance(type: DAYS_LEFT) } playableFrom { isoString humanDateTime readableDate } trailers { mp4 webm } upsell { tierId } } fragment SportEventFieldsLight on SportEvent { title slug id league round images { main16x9 { ...ImageFieldsLight } brandLogo { ...ImageFieldsLight } } playableFrom { humanDateTime isoString } liveEventEnd { isoString } isLiveContent upsell { tierId } }  fragment SeriesFieldsLight on Series { id slug title genres mediaClassification numberOfAvailableSeasons label { ...LabelFields } images { cover2x3 { ...ImageFieldsFull } main16x9Annotated { ...ImageFieldsLight } } parentalRating { ...ParentalRatingFields } trailers { mp4 webm } upsell { tierId } } fragment ClipFieldsLight on Clip { id slug title clipVideo: video { ...VideoFields } images { main16x9 { ...ImageFieldsLight } } playableFrom { readableDistance } mediaClassification parent { ... on ClipParentSeriesLink { id title } ... on ClipParentMovieLink { id title } } } fragment ChannelFields on Channel { __typename id title description tagline slug type images { logo { ...ImageFieldsLight } main16x9 { ...ImageFieldsLight } } access { hasAccess } epg { end start title } }  fragment PageListFields on PageReference { id title images { image16x9 { ...ImageFieldsFull } image4x3 { ...ImageFieldsFull } logo { ...ImageFieldsLight isFallback } } } fragment PageInfoFields on PageInfo { hasNextPage nextPageOffset totalCount }", "variables": {"panelId": "5Rqb0w0SN16A6YHt5Mx8BU", "limit": 100, "offset": 0}}
        self._test_folder_url(url, expected_results=10, json=data)

    def test_recent(self):
        url = "https://client-gateway.tv4.a2d.tv/graphql?operationName=Panel&"
        data = {"operationName": "Panel", "query": "query Panel($panelId: ID!, $offset: Int!, $limit: Int!) { panel(id: $panelId) { ... on ContinueWatchingPanel { id } ... on PagePanel { id content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { ... on PagePanelPageItem { page { ...PageListFields } } } } } ... on SportEventPanel { id content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { sportEvent { ...SportEventFieldsLight } } } } ... on ClipsPanel { id title content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { __typename clip { __typename ...ClipFieldsLight } } } } ... on EpisodesPanel { id title content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { episode { ...EpisodeFields } labelText } } } ... on MediaPanel { __typename id slug title content(input: {offset: $offset, limit: $limit}) { __typename pageInfo { ...PageInfoFields } items { ... on MediaPanelMovieItem { __typename movie { ...MovieFieldsLight __typename } } ... on MediaPanelSeriesItem { __typename series { ...SeriesFieldsLight __typename} } } } } ... on ChannelPanel { id title type content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { channel { ...ChannelFields } } } } } } fragment ImageFieldsFull on Image { sourceEncoded meta { muteBgColor { hex } } } fragment ParentalRatingFields on ParentalRating { finland { ageRestriction reason } sweden { ageRecommendation suitableForChildren } } fragment ImageFieldsLight on Image { sourceEncoded isFallback } fragment VideoFields on Video { id duration { readableShort readableMinutes seconds } isLiveContent access { hasAccess } isDrmProtected } fragment EpisodeFields on Episode { id slug title isLiveContent isStartOverEnabled series { id title slug } images { main16x9 { ...ImageFieldsLight } } liveEventEnd { isoString } playableUntil { readableDistance(type: DAYS_LEFT) humanDateTime } playableFrom { humanDateTime isoString } video { ...VideoFields } upsell { tierId } } fragment LabelFields on Label { id airtime announcement recurringBroadcast } fragment MovieFieldsLight on Movie { id slug title genres productionYear isLiveContent productionCountries { name } parentalRating { ...ParentalRatingFields } liveEventEnd { isoString } label { ...LabelFields } images { cover2x3 { ...ImageFieldsFull } main16x9Annotated { ...ImageFieldsLight } } playableUntil { readableDistance(type: DAYS_LEFT) } playableFrom { isoString humanDateTime readableDate } trailers { mp4 webm } upsell { tierId } } fragment SportEventFieldsLight on SportEvent { title slug id league round images { main16x9 { ...ImageFieldsLight } brandLogo { ...ImageFieldsLight } } playableFrom { humanDateTime isoString } liveEventEnd { isoString } isLiveContent upsell { tierId } }  fragment SeriesFieldsLight on Series { id slug title genres mediaClassification numberOfAvailableSeasons label { ...LabelFields } images { cover2x3 { ...ImageFieldsFull } main16x9Annotated { ...ImageFieldsLight } } parentalRating { ...ParentalRatingFields } trailers { mp4 webm } upsell { tierId } } fragment ClipFieldsLight on Clip { id slug title clipVideo: video { ...VideoFields } images { main16x9 { ...ImageFieldsLight } } playableFrom { readableDistance } mediaClassification parent { ... on ClipParentSeriesLink { id title } ... on ClipParentMovieLink { id title } } } fragment ChannelFields on Channel { __typename id title description tagline slug type images { logo { ...ImageFieldsLight } main16x9 { ...ImageFieldsLight } } access { hasAccess } epg { end start title } }  fragment PageListFields on PageReference { id title images { image16x9 { ...ImageFieldsFull } image4x3 { ...ImageFieldsFull } logo { ...ImageFieldsLight isFallback } } } fragment PageInfoFields on PageInfo { hasNextPage nextPageOffset totalCount }", "variables": {"panelId": "2K0BCBpDDfhpW1NRLY0jET", "limit": 100, "offset": 0}}
        self._test_folder_url(url, expected_results=10, json=data)

    def test_popular(self):
        url = "https://client-gateway.tv4.a2d.tv/graphql?operationName=Panel&"
        data = {"operationName": "Panel", "query": "query Panel($panelId: ID!, $offset: Int!, $limit: Int!) { panel(id: $panelId) { ... on ContinueWatchingPanel { id } ... on PagePanel { id content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { ... on PagePanelPageItem { page { ...PageListFields } } } } } ... on SportEventPanel { id content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { sportEvent { ...SportEventFieldsLight } } } } ... on ClipsPanel { id title content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { __typename clip { __typename ...ClipFieldsLight } } } } ... on EpisodesPanel { id title content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { episode { ...EpisodeFields } labelText } } } ... on MediaPanel { __typename id slug title content(input: {offset: $offset, limit: $limit}) { __typename pageInfo { ...PageInfoFields } items { ... on MediaPanelMovieItem { __typename movie { ...MovieFieldsLight __typename } } ... on MediaPanelSeriesItem { __typename series { ...SeriesFieldsLight __typename} } } } } ... on ChannelPanel { id title type content(input: {offset: $offset, limit: $limit}) { pageInfo { ...PageInfoFields } items { channel { ...ChannelFields } } } } } } fragment ImageFieldsFull on Image { sourceEncoded meta { muteBgColor { hex } } } fragment ParentalRatingFields on ParentalRating { finland { ageRestriction reason } sweden { ageRecommendation suitableForChildren } } fragment ImageFieldsLight on Image { sourceEncoded isFallback } fragment VideoFields on Video { id duration { readableShort readableMinutes seconds } isLiveContent access { hasAccess } isDrmProtected } fragment EpisodeFields on Episode { id slug title isLiveContent isStartOverEnabled series { id title slug } images { main16x9 { ...ImageFieldsLight } } liveEventEnd { isoString } playableUntil { readableDistance(type: DAYS_LEFT) humanDateTime } playableFrom { humanDateTime isoString } video { ...VideoFields } upsell { tierId } } fragment LabelFields on Label { id airtime announcement recurringBroadcast } fragment MovieFieldsLight on Movie { id slug title genres productionYear isLiveContent productionCountries { name } parentalRating { ...ParentalRatingFields } liveEventEnd { isoString } label { ...LabelFields } images { cover2x3 { ...ImageFieldsFull } main16x9Annotated { ...ImageFieldsLight } } playableUntil { readableDistance(type: DAYS_LEFT) } playableFrom { isoString humanDateTime readableDate } trailers { mp4 webm } upsell { tierId } } fragment SportEventFieldsLight on SportEvent { title slug id league round images { main16x9 { ...ImageFieldsLight } brandLogo { ...ImageFieldsLight } } playableFrom { humanDateTime isoString } liveEventEnd { isoString } isLiveContent upsell { tierId } }  fragment SeriesFieldsLight on Series { id slug title genres mediaClassification numberOfAvailableSeasons label { ...LabelFields } images { cover2x3 { ...ImageFieldsFull } main16x9Annotated { ...ImageFieldsLight } } parentalRating { ...ParentalRatingFields } trailers { mp4 webm } upsell { tierId } } fragment ClipFieldsLight on Clip { id slug title clipVideo: video { ...VideoFields } images { main16x9 { ...ImageFieldsLight } } playableFrom { readableDistance } mediaClassification parent { ... on ClipParentSeriesLink { id title } ... on ClipParentMovieLink { id title } } } fragment ChannelFields on Channel { __typename id title description tagline slug type images { logo { ...ImageFieldsLight } main16x9 { ...ImageFieldsLight } } access { hasAccess } epg { end start title } }  fragment PageListFields on PageReference { id title images { image16x9 { ...ImageFieldsFull } image4x3 { ...ImageFieldsFull } logo { ...ImageFieldsLight isFallback } } } fragment PageInfoFields on PageInfo { hasNextPage nextPageOffset totalCount }", "variables": {"panelId": "4nNp00Z12bjEiNboaW2uxB", "limit": 100, "offset": 0}}
        self._test_folder_url(url, expected_results=10, json=data)

    def test_categories(self):
        # url = "https://client-gateway.tv4.a2d.tv/graphql?operationName=PageList&variables=%7B%22pageListId%22%3A%20%22categories%22%7D&extensions=%7B%22persistedQuery%22%3A%20%7B%22version%22%3A%201%2C%20%22sha256Hash%22%3A%20%2258da321b8e31df2b746f1d1f374151a450a4c24bda6415182fe81551c90e7d25%22%7D%7D"
        url = "https://client-gateway.tv4.a2d.tv/graphql?operationName=PageList&"
        data = {"operationName": "PageList", "query": "query PageList($pageListId: ID!) { pageList(id: $pageListId) { id content { ... on PageReferenceItem { pageReference { ...PageListFields __typename } __typename } ... on StaticPageItem { staticPage { id title type images { image4x3 { ...ImageFieldsFull __typename } __typename } __typename } __typename } __typename } __typename }} fragment PageListFields on PageReference { id title images { image16x9 { ...ImageFieldsFull } image4x3 { ...ImageFieldsFull } logo { ...ImageFieldsLight isFallback } } } fragment ImageFieldsFull on Image { sourceEncoded meta { muteBgColor { hex } } } fragment ImageFieldsLight on Image { sourceEncoded isFallback }", "variables": {"pageListId": "categories"}}
        self._test_folder_url(url, expected_results=10, json=data)

    @unittest.skip("Requires login")
    def test_seasons(self):
        url = "https://client-gateway.tv4.a2d.tv/graphql?operationName=ContentDetailsPage&query=query%20ContentDetailsPage%28%24mediaId%3A%20ID%21%2C%20%24panelsInput%3A%20CdpPanelsInput%21%29%20%7B%20media%28id%3A%20%24mediaId%29%20%7B%20...%20on%20SportEvent%20%7B%20__typename%20id%20slug%20title%20league%20arena%20commentators%20country%20round%20season%20inStudio%20isLiveContent%20isStartOverEnabled%20humanCallToAction%20editorialInfoText%20synopsis%20%7B%20brief%20long%20%7D%20trailers%20%7B%20...TrailerFields%20%7D%20playableFrom%20%7B%20humanDateTime%20isoString%20readableDate%20%7D%20playableUntil%20%7B%20readableDate%20%7D%20liveEventEnd%20%7B%20isoString%20%7D%20images%20%7B%20poster2x3%20%7B%20...ImageFieldsFull%20%7D%20main16x9%20%7B%20...ImageFieldsFull%20%7D%20logo%20%7B%20...ImageFieldsLight%20%7D%20brandLogo%20%7B%20...ImageFieldsLight%20%7D%20%7D%20upsell%20%7B%20tierId%20%7D%20%7D%20...%20on%20Movie%20%7B%20__typename%20id%20slug%20title%20genres%20humanCallToAction%20isPollFeatureEnabled%20productionYear%20isLiveContent%20isStartOverEnabled%20liveEventEnd%20%7B%20isoString%20%7D%20productionCountries%20%7B%20countryCode%20name%20%7D%20playableFrom%20%7B%20isoString%20readableDate%20humanDateTime%20readableDistance%20%7D%20playableUntil%20%7B%20isoString%20readableDate%20%7D%20video%20%7B%20...VideoFields%20%7D%20parentalRating%20%7B%20...ParentalRatingFields%20%7D%20credits%20%7B%20...MovieCreditsFields%20%7D%20images%20%7B%20poster2x3%20%7B%20...ImageFieldsFull%20%7D%20main16x9%20%7B%20...ImageFieldsFull%20%7D%20logo%20%7B%20...ImageFieldsLight%20%7D%20brandLogo%20%7B%20...ImageFieldsLight%20%7D%20%7D%20synopsis%20%7B%20brief%20long%20%7D%20trailers%20%7B%20...TrailerFields%20%7D%20label%20%7B%20...LabelFields%20%7D%20panels%28input%3A%20%24panelsInput%29%20%7B%20...CdpPanelsFields%20%7D%20hasPanels%20editorialInfoText%20upsell%20%7B%20tierId%20%7D%20%7D%20...%20on%20Series%20%7B%20__typename%20id%20slug%20title%20numberOfAvailableSeasons%20genres%20isPollFeatureEnabled%20upcomingEpisode%20%7B%20...UpcomingEpisodeFields%20%7D%20trailers%20%7B%20...TrailerFields%20%7D%20parentalRating%20%7B%20...ParentalRatingFields%20%7D%20credits%20%7B%20...SeriesCreditsFields%20%7D%20images%20%7B%20poster2x3%20%7B%20...ImageFieldsFull%20%7D%20main16x9%20%7B%20...ImageFieldsFull%20%7D%20logo%20%7B%20...ImageFieldsLight%20%7D%20brandLogo%20%7B%20...ImageFieldsLight%20%7D%20%7D%20synopsis%20%7B%20brief%20long%20%7D%20allSeasonLinks%20%7B%20__typename%20seasonId%20title%20numberOfEpisodes%20%7D%20label%20%7B%20...LabelFields%20%7D%20panels%28input%3A%20%24panelsInput%29%20%7B%20...CdpPanelsFields%20%7D%20hasPanels%20editorialInfoText%20upsell%20%7B%20tierId%20%7D%20%7D%20%7D%20%7D%20fragment%20TrailerFields%20on%20Trailers%20%7B%20mp4%20webm%20%7D%20fragment%20ImageFieldsFull%20on%20Image%20%7B%20sourceEncoded%20meta%20%7B%20muteBgColor%20%7B%20hex%20%7D%20%7D%20%7D%20fragment%20ImageFieldsLight%20on%20Image%20%7B%20sourceEncoded%20isFallback%20%7D%20fragment%20VideoFields%20on%20Video%20%7B%20id%20duration%20%7B%20readableShort%20readableMinutes%20seconds%20%7D%20isLiveContent%20access%20%7B%20hasAccess%20%7D%20isDrmProtected%20%7D%20fragment%20ParentalRatingFields%20on%20ParentalRating%20%7B%20finland%20%7B%20ageRestriction%20reason%20%7D%20sweden%20%7B%20ageRecommendation%20suitableForChildren%20%7D%20%7D%20fragment%20MovieCreditsFields%20on%20MovieCredits%20%7B%20actors%20%7B%20characterName%20name%20type%20%7D%20directors%20%7B%20name%20type%20%7D%20%7D%20fragment%20LabelFields%20on%20Label%20%7B%20id%20airtime%20announcement%20recurringBroadcast%20%7D%20fragment%20CdpPanelsFields%20on%20CdpPanels%20%7B%20items%20%7B%20...%20on%20ClipsPanel%20%7B%20id%20title%20%7D%20%7D%20%7D%20fragment%20UpcomingEpisodeFields%20on%20UpcomingEpisode%20%7B%20id%20title%20seasonTitle%20playableFrom%20%7B%20humanDateTime%20isoString%20readableDateShort%20%7D%20image%20%7B%20main16x9%20%7B%20...ImageFieldsLight%20%7D%20%7D%20upsell%20%7B%20tierId%20%7D%20%7D%20%20fragment%20SeriesCreditsFields%20on%20SeriesCredits%20%7B%20directors%20%7B%20name%20type%20%7D%20hosts%20%7B%20name%20type%20%7D%20actors%20%7B%20characterName%20name%20type%20%7D%20%7D&variables=%7B%22mediaId%22%3A%20%22fbe386fc49d06efd7ee1%22%2C%20%22panelsInput%22%3A%20%7B%22offset%22%3A%200%2C%20%22limit%22%3A%2020%7D%7D"
        self._test_folder_url(url, expected_results=4)

    def test_season_content_listing(self):
        url = "https://client-gateway.tv4.a2d.tv/graphql?operationName=SeasonEpisodes&"
        data = {"operationName": "SeasonEpisodes", "query": "query SeasonEpisodes($input: SeasonEpisodesInput!, $seasonId: ID!) { season(id: $seasonId) { id numberOfEpisodes episodes(input: $input) { initialSortOrder pageInfo { ...PageInfoFields } items { __typename ...EpisodeFieldsFull } } } } fragment PageInfoFields on PageInfo { hasNextPage nextPageOffset totalCount } fragment EpisodeFieldsFull on Episode { ...EpisodeFields synopsis { medium } parentalRating { ...ParentalRatingFields } upsell { tierId } } fragment EpisodeFields on Episode { id slug title isLiveContent isStartOverEnabled series { id title slug } images { main16x9 { ...ImageFieldsLight } } liveEventEnd { isoString } playableUntil { readableDistance(type: DAYS_LEFT) humanDateTime } playableFrom { humanDateTime isoString } video { ...VideoFields } upsell { tierId } } fragment ParentalRatingFields on ParentalRating { finland { ageRestriction reason } sweden { ageRecommendation suitableForChildren } } fragment ImageFieldsLight on Image { sourceEncoded isFallback } fragment VideoFields on Video { id duration { readableShort readableMinutes seconds } isLiveContent access { hasAccess } isDrmProtected }", "variables": {"seasonId": "c0a98773088605ce81da", "input": {"limit": 100, "offset": 0}}}
        self._test_folder_url(url, expected_results=5, json=data)

    @unittest.skip(reason="Requires Login")
    def test_list_category_content(self):
        url = "https://client-gateway.tv4.a2d.tv/graphql?operationName=Page&"
        data = {"operationName": "Page", "query": "query Page($pageId: ID!, $input: PageContentInput!) { page(id: $pageId) { id title content(input: $input) { pageInfo { ...PageInfoFields } panels { __typename ... on TiersPanel { __typename id title detailed } ... on ContinueWatchingPanel { __typename id title } ... on MediaPanel { __typename id slug title displayHint { mediaPanelImageRatio } } ... on SportEventPanel { __typename id title } ... on ClipsPanel { __typename id title } ... on EpisodesPanel { __typename id title } ... on LivePanel { __typename id title } ... on PagePanel { __typename id title } ... on ChannelPanel { __typename id title type } ... on ThemePanel { __typename ...ThemePanelFields } ... on SinglePanel { __typename ...SinglePanelFields } ... on TiersPanel { __typename id title } } } } } fragment PageInfoFields on PageInfo { hasNextPage nextPageOffset totalCount } fragment ThemePanelFields on ThemePanel { id title pitch hexColor images { image16x9 { ...ImageFieldsFull } } link { ... on ThemePanelSeriesLink { series { id slug genres numberOfAvailableSeasons parentalRating { ...ParentalRatingFields } images { brandLogo { ...ImageFieldsLight } } upsell { tierId } } } ... on ThemePanelMovieLink { movie { id slug genres productionCountries { countryCode name } productionYear parentalRating { ...ParentalRatingFields } images { brandLogo { ...ImageFieldsLight } } upsell { tierId } } } ... on ThemePanelEpisodeLink { episode { id slug upsell { tierId } } } ... on ThemePanelClipLink { clip { id slug } } ... on ThemePanelPageLink { page { id } } ... on ThemePanelUrlsLink { webUrl } ... on ThemePanelSportEventLink { sportEvent { id slug arena league round playableFrom { humanDateTime isoString readableDate } images { brandLogo { ...ImageFieldsLight } } upsell { tierId } } } } themePanelLinkText: linkText showMetadataForLink subtitle trailers { ...TrailerFields } showUpsellLabel } fragment SinglePanelFields on SinglePanel { id secondaryLinkText images { image16x9 { ...ImageFieldsFull } image2x3 { ...ImageFieldsFull } brandLogo { ...ImageFieldsLight } } link { __typename ... on SinglePanelPageLink { page { id } } ... on SinglePanelSportEventLink { sportEvent { ...SportEventFieldsLight } } ... on SinglePanelSeriesLink { series { ...SeriesFieldsLight } } ... on SinglePanelMovieLink { movie { ...MovieFieldsLight } } ... on SinglePanelEpisodeLink { episode { ...EpisodeFields } } ... on SinglePanelClipLink { clip { ...ClipFieldsLight } } ... on SinglePanelChannelLink { channel { ...ChannelFields } } } trailers { ...TrailerFields } linkText title pitch shortPitch } fragment ImageFieldsFull on Image { sourceEncoded meta { muteBgColor { hex } } } fragment ParentalRatingFields on ParentalRating { finland { ageRestriction reason } sweden { ageRecommendation suitableForChildren } } fragment ImageFieldsLight on Image { sourceEncoded isFallback } fragment TrailerFields on Trailers { mp4 webm } fragment SportEventFieldsLight on SportEvent { title slug id league round images { main16x9 { ...ImageFieldsLight } brandLogo { ...ImageFieldsLight } } playableFrom { humanDateTime isoString } liveEventEnd { isoString } isLiveContent upsell { tierId } }  fragment SeriesFieldsLight on Series { id slug title genres mediaClassification numberOfAvailableSeasons label { ...LabelFields } images { cover2x3 { ...ImageFieldsFull } main16x9Annotated { ...ImageFieldsLight } } parentalRating { ...ParentalRatingFields } trailers { mp4 webm } upsell { tierId } } fragment MovieFieldsLight on Movie { id slug title genres productionYear isLiveContent productionCountries { name } parentalRating { ...ParentalRatingFields } liveEventEnd { isoString } label { ...LabelFields } images { cover2x3 { ...ImageFieldsFull } main16x9Annotated { ...ImageFieldsLight } } playableUntil { readableDistance(type: DAYS_LEFT) } playableFrom { isoString humanDateTime readableDate } trailers { mp4 webm } upsell { tierId } } fragment EpisodeFields on Episode { id slug title isLiveContent isStartOverEnabled series { id title slug } images { main16x9 { ...ImageFieldsLight } } liveEventEnd { isoString } playableUntil { readableDistance(type: DAYS_LEFT) humanDateTime } playableFrom { humanDateTime isoString } video { ...VideoFields } upsell { tierId } } fragment ClipFieldsLight on Clip { id slug title clipVideo: video { ...VideoFields } images { main16x9 { ...ImageFieldsLight } } playableFrom { readableDistance } mediaClassification parent { ... on ClipParentSeriesLink { id title } ... on ClipParentMovieLink { id title } } } fragment ChannelFields on Channel { __typename id title description tagline slug type images { logo { ...ImageFieldsLight } main16x9 { ...ImageFieldsLight } } access { hasAccess } epg { end start title } }  fragment LabelFields on Label { id airtime announcement recurringBroadcast } fragment VideoFields on Video { id duration { readableShort readableMinutes seconds } isLiveContent access { hasAccess } isDrmProtected }", "variables": {"pageId": "sport", "input": {"limit": 100, "offset": 0}}}
        self._test_folder_url(url, expected_results=5, json=data)

    @unittest.skip(reason="Requires Login")
    def test_video_playback(self):
        url = "https://playback2.a2d.tv/play/5deba52e58a8ebba316d?service=tv4play&device=browser&browser=GoogleChrome&protocol=hls%2Cdash&drm=widevine&capabilities=live-drm-adstitch-2%2Cexpired_assets"
        self._test_video_url(url)