Example #1
0
 def setUp(self):
     self.spam = TVProgram(
         {
             'title': 'Paid Programming',
             'category_type': 'series'
         },
         translator=Mock())
     self.notSpam = TVProgram(
         {
             'title': 'I am not spam',
             'category_type': 'series'
         },
         translator=Mock())
     self.next = Mock()
     self.provider = SpamSkippingFanartProvider(nextProvider=self.next)
Example #2
0
 def test_getPosters_When_program_is_movie_Then_returns_empty_list(self):
     program = TVProgram({
         'title': 'Departed',
         'category_type': 'movie'
     },
                         translator=Mock())
     self.assertListEqual([], self.getProvider().getPosters(program))
Example #3
0
    def test_getPosters_When_pounded_by_many_threads_looking_up_same_program_Then_doesnt_fail_miserably(
            self):

        programs = []
        for i in xrange(10):  #@UnusedVariable
            programs.append(
                TVProgram({
                    'title': 'Seinfeld',
                    'category_type': 'series'
                },
                          translator=Mock()))
        provider = self.getProvider()

        @run_async
        def work(p):
            posters = provider.getPosters(p)
            if len(posters) == 0:
                self.fail = True
            for poster in posters:
                log.debug('%s - %s' % (p.title(), poster))

        self.fail = False
        threads = []
        for p in programs:
            threads.append(work(p))
        for t in threads:
            t.join()

        self.assertFalse(self.fail)
Example #4
0
    def test_cache_consistent_across_sessions(self):
        sandbox = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, sandbox, ignore_errors=True)
        nextProvider = Mock()
        platform = Mock()
        when(platform).getCacheDir().thenReturn(sandbox)
        when(nextProvider).getPosters(any(Program)).thenReturn([
            'http://a.com/a.gif', 'http://b.com/b.gif', 'http://c.com/c.gif',
            'http://d.com/d.gif'
        ])
        provider = SuperFastFanartProvider(platform, nextProvider)

        programs = []
        for i in xrange(1000):
            program = TVProgram({
                'title': 'P%d' % i,
                'category_type': 'series'
            },
                                translator=Mock())
            httpUrls = provider.getPosters(program)
            self.assertTrue(4, len(httpUrls))
            programs.append(program)
        provider.close()

        nextProvider = Mock()
        provider2 = SuperFastFanartProvider(platform, nextProvider)
        for p in programs:
            httpUrls = provider2.getPosters(p)
            self.assertTrue(4, len(httpUrls))
        provider2.close()
Example #5
0
 def getMovies(self):
     return map(
         lambda t: TVProgram({
             'title': t,
             'category_type': 'movie'
         },
                             translator=Mock()), self.movies)
Example #6
0
 def getTvShows(self):
     return map(
         lambda t: TVProgram({
             'title': t,
             'category_type': 'series'
         },
                             translator=Mock()), self.tvShows)
Example #7
0
 def setUp(self):
     self.nextProvider = Mock()
     self.dir = tempfile.mkdtemp()
     self.addCleanup(shutil.rmtree, self.dir, ignore_errors=True)
     self.httpCache = FileCache(self.dir, HttpResolver())
     self.program = TVProgram({'title': 'Not Important', 'category_type':'series'}, translator=Mock())
     self.provider = HttpCachingFanartProvider(self.httpCache, self.nextProvider)
     self.addCleanup(self.provider.close)
Example #8
0
 def test_getPosters_When_program_is_movie_Then_returns_empty_list(self):
     program = TVProgram({
         'title': 'Departed',
         'category_type': 'movie'
     },
                         translator=Mock())
     provider = TvdbFanartProvider(self.platform, nextProvider=None)
     self.assertListEqual([], provider.getPosters(program))
Example #9
0
 def test_getPosters_When_program_is_not_movie_Then_returns_empty_list(
         self):
     program = TVProgram({
         'title': 'Seinfeld',
         'category_type': 'series'
     },
                         translator=Mock())
     provider = TheMovieDbFanartProvider()
     self.assertListEqual([], provider.getPosters(program))
Example #10
0
 def setUp(self):
     self.delegate = Mock()
     self.nextProvider = Mock()
     self.platform = Mock()
     self.sandbox = tempfile.mkdtemp()
     self.addCleanup(shutil.rmtree, self.sandbox)
     when(self.platform).getCacheDir().thenReturn(self.sandbox)
     self.program = TVProgram(
         {
             'title': 'Two Fat Ladies',
             'category_type': 'series',
             'channum': '5.1',
             'starttime': datetime.datetime.now(),
             'endtime': datetime.datetime.now(),
             'subtitle': 'blah',
             'description': 'blah'
         },
         translator=Mock())
Example #11
0
 def test_createKey_When_program_title_contains_unicode_chars_Then_dont_blow_up(
         self):
     program = TVProgram(
         {
             'title': u'madeleine (Grabación Manual)',
             'category_type': 'series'
         },
         translator=Mock())
     key = self.provider.createKey('getPosters', program)
     self.assertGreater(len(key), 0)
Example #12
0
 def test_getPosters_When_title_has_override_Then_returns_posters_for_override(
         self):
     # 'Conan' is mapped to 'Conan (2010)' as TVDB's official title
     program = TVProgram({
         'title': u'Conan',
         'category_type': u'series'
     },
                         translator=Mock())
     urls = self.getProvider().getPosters(program)
     self.assertTrue(len(urls) > 0)
Example #13
0
 def test_getPosters_When_program_is_not_movie_Then_returns_posters(self):
     # Setup
     program = TVProgram({'title':'Seinfeld', 'category_type':'series'}, translator=Mock())
     
     # Test
     posterUrls = self.getProvider().getPosters(program)
     
     # Verify
     log.debug('Poster URLs = %s' % posterUrls)
     for posterUrl in posterUrls:
         self.assertEqual("http", posterUrl[0:4])
Example #14
0
 def test_getPosters_When_title_has_funny_chars_Then_dont_fail_miserably(self):
     # Setup
     program = TVProgram({'title': u'Königreich der Himmel', 'category_type':'series'}, translator=Mock())
     
     # Test
     posters = self.getProvider().getPosters(program)
     
     # Verify
     log.debug('Posters = %s' % posters)
     for p in posters:
         self.assertEqual('http', p[0:4])
Example #15
0
 def test_eq_Make_sure_bidirectional_equivalence_to_RecordedProgram_works(self):
     tv = TVProgram(self.data, self.translator)
     recorded = RecordedProgram(pdata({'channum':'23','starttime': socketDateTime(2008, 11, 21, 14, 0, 0)}), Mock(), Mock(), Mock(), self.protocol, Mock())
     
     self.assertTrue(tv == recorded)
     self.assertTrue(recorded == tv)
     
     self.assertTrue(tv in [recorded])
     self.assertTrue(recorded in [tv])
     
     self.assertTrue({tv:tv}.has_key(recorded))
     self.assertTrue({recorded:recorded}.has_key(tv))
Example #16
0
 def test_getBackgrounds_When_program_is_not_movie_Then_returns_backgrounds(self):
     # Setup
     program = TVProgram({'title':'Seinfeld', 'category_type':'series'}, translator=Mock())
     
     # Test
     urls = self.getProvider().getBackgrounds(program)
     
     # Verify
     [log.debug('Background = %s' % url) for url in urls]
     self.assertTrue(len(urls) > 0)
     for url in urls:
         self.assertEqual("http", url[0:4])
Example #17
0
 def test_getPosters_When_program_is_movie_Then_returns_posters(self):
     # Setup
     program = TVProgram({'title': 'Ghostbusters', 'category_type':'movie'}, translator=Mock())
     provider = TheMovieDbFanartProvider()
     
     # Test
     posters = provider.getPosters(program)
     
     # Verify
     log.debug('Posters = %s' % posters)
     for p in posters:
         self.assertEqual('http', p[0:4])
Example #18
0
 def programs(cnt):
     for i in xrange(cnt): #@UnusedVariable
         yield TVProgram({
             'starttime': '20081121140000',
             'endtime'  : '20081121140000',
             'chanid'   : random.randint(1,9999999),
             'channum'  : str(random.randint(1,10)),
             'title'    : 'Two Fat Ladies %d' % random.randint(1,999999),
             'subtitle' : 'Away we go....', 
             'description' : 'blah blah blah', 
             'category_type':'series'}, 
             translator=Mock())
Example #19
0
 def test_getPosters_works(self):
     # Setup
     program = TVProgram({'title': 'Top Chef', 'category_type':'series'}, translator=Mock())
     provider = GoogleImageSearchProvider()
     
     # Test
     posters = provider.getPosters(program)
     
     # Verify
     log.debug('Posters = %s' % posters)
     self.assertTrue(len(posters) > 0)
     for p in posters:
         self.assertEqual('http', p[0:4])
Example #20
0
 def setUp(self):
     self.sandbox = tempfile.mkdtemp()
     self.addCleanup(shutil.rmtree, self.sandbox, ignore_errors=True)
     self.nextProvider = Mock()
     self.platform = Mock()
     when(self.platform).getCacheDir().thenReturn(self.sandbox)
     self.program = TVProgram(
         {
             'title': 'Two Fat Ladies',
             'category_type': 'series'
         },
         translator=Mock())
     self.provider = SuperFastFanartProvider(self.platform,
                                             self.nextProvider)
Example #21
0
 def test_works_with_TVProgram_not_just_RecordedProgram(self):
     data = {
         'title': u'Love and HipHop',
         'subtitle': u'',
         'category_type': 'series',
         'originalairdate': u'2011-11-21',
         'starttime': datetime.datetime(2011, 12, 8, 22),
         'endtime': datetime.datetime(2011, 12, 8, 23),
     }
     tvProgram = TVProgram(data, translator=Mock())
     tvRage = TvRageProvider(self.platform)
     season, episode = tvRage.getSeasonAndEpisode(tvProgram)
     self.assertEqual('2', season)
     self.assertEqual('2', episode)
Example #22
0
    def test_getPosters_When_program_is_a_movie_Then_returns_fanart(self):
        # Setup
        program = TVProgram({
            'title': 'Fargo',
            'category_type': 'movie'
        },
                            translator=Mock())
        provider = ImdbFanartProvider(nextProvider=None)

        # Test
        posters = provider.getPosters(program)

        # Verify
        log.debug('Poster URLs = %s' % posters)
        for p in posters:
            self.assertEqual('http', p[0:4])
Example #23
0
    def testConstructor(self):
        
        fanArt = Mock()
        when(fanArt).pickPoster(any()).thenReturn(None)
        
        kwargs = {}
        kwargs['settings'] = Mock()
        kwargs['translator'] = Mock()
        kwargs['mythChannelIconCache'] = Mock()
        kwargs['platform'] = Mock()
        kwargs['fanArt'] = fanArt
        args = ()
        win = LiveTvWindow(*args, **kwargs)
        
        channels = []
        for i in range(10):
            c = Channel({
                'chanid':i, 
                'channum': '%d' % (i*2), 
                'name': 'name%d' % i, 
                'callsign':'callsign%d'%i
            })
            channels.append(c)
        
        db = Mock()
        when(db).getChannels().thenReturn(channels)
        
        programs = []
        for i in range(10):
            p = TVProgram({
                'title': 'title%d' % i, 
                'chanid':i,
                'description':'desc%d'%i,
                'category':'cat%d'%i}, 
                translator=Mock()) 
            programs.append(p)
            
        when(db).getTVGuideDataFlattened(any(), any(), any()).thenReturn(programs)
        
        dbFactory = Mock()
        when(dbFactory).create().thenReturn(db)

        from mythbox import pool    
        pool.pools['dbPool'] = pool.Pool(dbFactory)
        
        win.onInit()
        win.onClick(self, 600)
Example #24
0
 def setUp(self):
     self.delegate = Mock()
     self.nextProvider = Mock()
     self.platform = Mock()
     self.sandbox = tempfile.mkdtemp()
     self.addCleanup(shutil.rmtree, self.sandbox)
     when(self.platform).getCacheDir().thenReturn(self.sandbox)
     self.program = TVProgram({
         'title': 'Two Fat Ladies', 
         'category_type':'series',
         'channum' : '5.1',
         'starttime' : datetime.datetime.now(),
         'endtime': datetime.datetime.now(),
         'subtitle': 'blah',
         'description': 'blah'
         },
         translator=Mock())
Example #25
0
    def test_getBanners_When_program_is_not_movie_Then_returns_banners(self):
        # Setup
        program = TVProgram({
            'title': 'Seinfeld',
            'category_type': 'series'
        },
                            translator=Mock())
        provider = TvdbFanartProvider(self.platform, nextProvider=None)

        # Test
        bannerUrls = provider.getBanners(program)

        # Verify
        [log.debug('Banner = %s' % banner) for banner in bannerUrls]
        self.assertTrue(len(bannerUrls) > 0)
        for bannerUrl in bannerUrls:
            self.assertEqual("http", bannerUrl[0:4])
Example #26
0
    def test_getPosters_When_title_has_funny_chars_Then_dont_fail_miserably(
            self):
        # Setup
        program = TVProgram(
            {
                'title': u'Königreich der Himmel',
                'category_type': 'series'
            },
            translator=Mock())
        provider = GoogleImageSearchProvider(nextProvider=None)

        # Test
        posters = provider.getPosters(program)

        # Verify
        log.debug('Posters = %s' % posters)
        self.assertTrue(len(posters) > 0)
        for p in posters:
            self.assertEqual('http', p[0:4])
Example #27
0
 def test_starttime_TypeInDataDictIsADateTime(self):
     p = TVProgram({'starttime': datetime.datetime(2008, 11, 21, 14)}, self.translator)
     self.assertEqual('20081121140000', p.starttime())
Example #28
0
 def test_starttimeAsTime(self):
     program = TVProgram(self.data, self.translator) 
     time = program.starttimeAsTime()
     log.debug('startTime = %s' % time)
     self.assertTrue(time)
Example #29
0
 def test_constructor(self):
     program = TVProgram(self.data, self.translator)
     self.assertTrue(program is not None)
     self.assertTrue(program.isHD())
Example #30
0
    def getTVGuideData(self, startTime, endTime, channels):
        """
        @type startTime: datetime.datetime 
        @type endTime: datetime.datetime
        @type channels: Channel[] 
        @rtype: dict(Channel, TVProgram[])
        """
        strStartTime = startTime.strftime("%Y%m%d%H%M%S")
        strEndTime = endTime.strftime("%Y%m%d%H%M%S")

        sql = """
            select
                c.chanid,
                c.channum,
                c.callsign,
                c.icon,
                c.name as channame,                
                p.starttime,
                p.endtime,
                p.title,
                p.subtitle,
                p.description,
                p.showtype,
                p.originalairdate,
                p.category,
                p.category_type,
                p.seriesid,
                p.programid,
                p.hdtv
            from 
                channel c, 
                program p
            where c.visible = 1
                and c.chanid in (%s)
                and c.chanid = p.chanid
                and p.starttime != p.endtime
                and 
                (   
                       (p.endtime   >  %s and p.endtime   <= %s) 
                    or (p.starttime >= %s and p.starttime <  %s) 
                    or (p.starttime <  %s and p.endtime   >  %s) 
                    or (p.starttime =  %s and p.endtime   =  %s)
                )
            order by 
                c.chanid, 
                p.starttime
                """ % (','.join(map(lambda c: str(c.getChannelId()), channels)),
                       strStartTime, strEndTime,
                       strStartTime, strEndTime,
                       strStartTime, strEndTime,
                       strStartTime, strEndTime)
        shows = []
        self.cursor.execute(sql)
        from mythbox.mythtv.domain import TVProgram
        for row in self.cursor.fetchall():
            shows.append(TVProgram(self.toDict(self.cursor, row), self.translator))

        channelById = odict.odict()  # dict(int, Channel)
        showsByChannel = {}          # dict(Channel, TVProgram[])
        for c in channels:
            channelById[c.getChannelId()] = c
            showsByChannel[c] = []
                    
        for s in shows:
            showsByChannel[channelById[s.getChannelId()]].append(s)
            
        for shows in showsByChannel.values():
            shows.sort(key=lambda x: x.starttimeAsTime())
            
        return showsByChannel
Example #31
0
class OneStrikeAndYoureOutFanartProviderTest(unittest.TestCase):

    def setUp(self):
        self.delegate = Mock()
        self.nextProvider = Mock()
        self.platform = Mock()
        self.sandbox = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, self.sandbox)
        when(self.platform).getCacheDir().thenReturn(self.sandbox)
        self.program = TVProgram({
            'title': 'Two Fat Ladies', 
            'category_type':'series',
            'channum' : '5.1',
            'starttime' : datetime.datetime.now(),
            'endtime': datetime.datetime.now(),
            'subtitle': 'blah',
            'description': 'blah'
            },
            translator=Mock())
    
    def test_getPosters_When_not_struck_out_and_delegate_returns_empty_list_Then_strike_out_and_return_nextProviders_result(self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform, self.delegate, self.nextProvider)
        key = provider.createKey('getPosters', self.program)
        when(self.delegate).getPosters(any()).thenReturn([])
        when(self.nextProvider).getPosters(any()).thenReturn(['blah.png'])
        
        # Test
        posters = provider.getPosters(self.program)
        
        # Verify
        self.assertEqual('blah.png', posters[0])
        self.assertIn(self.program.title(), provider.struckOut[key].values())
        
    def test_getPosters_When_not_struck_out_and_delegate_returns_posters_Then_return_posters(self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform, self.delegate, self.nextProvider)
        when(self.delegate).getPosters(any()).thenReturn(['blah.png'])
        
        # Test
        posters = provider.getPosters(self.program)
        
        # Verify
        self.assertEqual('blah.png', posters[0])
        self.assertNotIn(self.program.title(), provider.struckOut.values())
        verifyZeroInteractions(self.nextProvider)

    def test_getPosters_When_struck_out_Then_skip_delegate_and_return_nextProviders_result(self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform, self.delegate, self.nextProvider)
        key = provider.createKey('getPosters', self.program)
        provider.strikeOut(key, self.program)
        when(self.nextProvider).getPosters(any()).thenReturn(['blah.png'])
        
        # Test
        posters = provider.getPosters(self.program)
        
        # Verify
        self.assertEqual('blah.png', posters[0])
        self.assertIn(self.program.title(), provider.struckOut[key].values())
        verifyZeroInteractions(self.delegate)

    def test_clear_When_struckout_not_empty_Then_empties_struckout_and_forwards_to_delegate(self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform, self.delegate, self.nextProvider)
        provider.struckOut[self.program.title()] = self.program.title()
        
        # Test
        provider.clear()
        
        # Verify
        self.assertFalse(len(provider.struckOut))
        verify(self.delegate, times=1).clear(any())
        
    def test_constructor_When_delegate_is_none_Then_raise_exception(self):
        try:
            OneStrikeAndYoureOutFanartProvider(self.platform, delegate=None, nextProvider=self.nextProvider)
            self.fail('Expected exception to be thrown when delegate is null')
        except Exception:
            log.debug('SUCCESS: got exception on null delegate')

    def test_getSeasonAndEpisode_When_not_struck_out_and_delegate_returns_empty_tuple_Then_strike_out_and_return_nextProviders_result(self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform, self.delegate, self.nextProvider)
        key = provider.createKey('getSeasonAndEpisode', self.program)
        when(self.delegate).getSeasonAndEpisode(any()).thenReturn((None,None,))
        when(self.nextProvider).getSeasonAndEpisode(any()).thenReturn(('1','2',))
        
        # Test
        season, episode = provider.getSeasonAndEpisode(self.program)
        
        # Verify
        self.assertEqual('1', season)
        self.assertEqual('2', episode)
        self.assertIn(self.program.title(), provider.struckOut[key].values())

    def test_getSeasonAndEpisode_When_struck_out_Then_skip_delegate_and_return_nextProviders_result(self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform, self.delegate, self.nextProvider)
        key = provider.createKey('getSeasonAndEpisode', self.program)
        provider.strikeOut(key, self.program)
        when(self.nextProvider).getSeasonAndEpisode(any()).thenReturn(('1','2'))
        
        # Test
        season, episode = provider.getSeasonAndEpisode(self.program)
        
        # Verify
        self.assertEqual('1', season)
        self.assertEqual('2', episode)
        self.assertIn(self.program.title(), provider.struckOut[key].values())
        verifyZeroInteractions(self.delegate)

    def test_getSeasonAndEpisode_When_not_struck_out_and_delegate_returns_season_and_episode_Then_return_season_and_episode(self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform, self.delegate, self.nextProvider)
        when(self.delegate).getSeasonAndEpisode(any()).thenReturn(('1','2',))
        
        # Test
        season, episode = provider.getSeasonAndEpisode(self.program)
        
        # Verify
        self.assertEqual('1', season)
        self.assertEqual('2', episode)
        self.assertNotIn(self.program.title(), provider.struckOut.values())
        verifyZeroInteractions(self.nextProvider)
Example #32
0
 def test_constructor(self):
     program = TVProgram(self.data, self.translator)
     self.assertTrue(program is not None)
     self.assertTrue(program.isHD())
Example #33
0
 def test_starttimeAsTime(self):
     program = TVProgram(self.data, self.translator) 
     time = program.starttimeAsTime()
     log.debug('startTime = %s' % time)
     self.assertTrue(time)
Example #34
0
 def test_starttime_TypeInDataDictIsADateTime(self):
     p = TVProgram({'starttime': datetime.datetime(2008, 11, 21, 14)}, self.translator)
     self.assertEqual('20081121140000', p.starttime())
Example #35
0
class OneStrikeAndYoureOutFanartProviderTest(unittest.TestCase):
    def setUp(self):
        self.delegate = Mock()
        self.nextProvider = Mock()
        self.platform = Mock()
        self.sandbox = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, self.sandbox)
        when(self.platform).getCacheDir().thenReturn(self.sandbox)
        self.program = TVProgram(
            {
                'title': 'Two Fat Ladies',
                'category_type': 'series',
                'channum': '5.1',
                'originalairdate': '2001-01-01',
                'starttime': datetime.datetime.now(),
                'endtime': datetime.datetime.now(),
                'subtitle': 'blah',
                'description': 'blah'
            },
            translator=Mock())

    def test_getPosters_When_not_struck_out_and_delegate_returns_empty_list_Then_strike_out_and_return_nextProviders_result(
            self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform,
                                                      self.delegate,
                                                      self.nextProvider)
        key = provider.createKey('getPosters', self.program)
        when(self.delegate).getPosters(any()).thenReturn([])
        when(self.nextProvider).getPosters(any()).thenReturn(['blah.png'])

        # Test
        posters = provider.getPosters(self.program)

        # Verify
        self.assertEqual('blah.png', posters[0])
        self.assertIn(self.program.title(), provider.struckOut[key].values())

    def test_getPosters_When_not_struck_out_and_delegate_returns_posters_Then_return_posters(
            self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform,
                                                      self.delegate,
                                                      self.nextProvider)
        when(self.delegate).getPosters(any()).thenReturn(['blah.png'])

        # Test
        posters = provider.getPosters(self.program)

        # Verify
        self.assertEqual('blah.png', posters[0])
        self.assertNotIn(self.program.title(), provider.struckOut.values())
        verifyZeroInteractions(self.nextProvider)

    def test_getPosters_When_struck_out_Then_skip_delegate_and_return_nextProviders_result(
            self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform,
                                                      self.delegate,
                                                      self.nextProvider)
        key = provider.createKey('getPosters', self.program)
        provider.strikeOut(key, self.program)
        when(self.nextProvider).getPosters(any()).thenReturn(['blah.png'])

        # Test
        posters = provider.getPosters(self.program)

        # Verify
        self.assertEqual('blah.png', posters[0])
        self.assertIn(self.program.title(), provider.struckOut[key].values())
        verifyZeroInteractions(self.delegate)

    def test_clear_When_struckout_not_empty_Then_empties_struckout_and_forwards_to_delegate(
            self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform,
                                                      self.delegate,
                                                      self.nextProvider)
        provider.struckOut[self.program.title()] = self.program.title()

        # Test
        provider.clear()

        # Verify
        self.assertFalse(len(provider.struckOut))
        verify(self.delegate, times=1).clear(any())

    def test_constructor_When_delegate_is_none_Then_raise_exception(self):
        try:
            OneStrikeAndYoureOutFanartProvider(self.platform,
                                               delegate=None,
                                               nextProvider=self.nextProvider)
            self.fail('Expected exception to be thrown when delegate is null')
        except Exception:
            log.debug('SUCCESS: got exception on null delegate')

    def test_getSeasonAndEpisode_When_not_struck_out_and_delegate_returns_empty_tuple_Then_strike_out_and_return_nextProviders_result(
            self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform,
                                                      self.delegate,
                                                      self.nextProvider)
        key = provider.createKey('getSeasonAndEpisode', self.program)
        when(self.delegate).getSeasonAndEpisode(any()).thenReturn((
            None,
            None,
        ))
        when(self.nextProvider).getSeasonAndEpisode(any()).thenReturn((
            '1',
            '2',
        ))

        # Test
        season, episode = provider.getSeasonAndEpisode(self.program)

        # Verify
        self.assertEqual('1', season)
        self.assertEqual('2', episode)
        self.assertIn(self.program.title(), provider.struckOut[key].values())

    def test_getSeasonAndEpisode_When_struck_out_Then_skip_delegate_and_return_nextProviders_result(
            self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform,
                                                      self.delegate,
                                                      self.nextProvider)
        key = provider.createKey('getSeasonAndEpisode', self.program)
        provider.strikeOut(key, self.program)
        when(self.nextProvider).getSeasonAndEpisode(any()).thenReturn(
            ('1', '2'))

        # Test
        season, episode = provider.getSeasonAndEpisode(self.program)

        # Verify
        self.assertEqual('1', season)
        self.assertEqual('2', episode)
        self.assertIn(self.program.title(), provider.struckOut[key].values())
        verifyZeroInteractions(self.delegate)

    def test_getSeasonAndEpisode_When_not_struck_out_and_delegate_returns_season_and_episode_Then_return_season_and_episode(
            self):
        # Setup
        provider = OneStrikeAndYoureOutFanartProvider(self.platform,
                                                      self.delegate,
                                                      self.nextProvider)
        when(self.delegate).getSeasonAndEpisode(any()).thenReturn((
            '1',
            '2',
        ))

        # Test
        season, episode = provider.getSeasonAndEpisode(self.program)

        # Verify
        self.assertEqual('1', season)
        self.assertEqual('2', episode)
        self.assertNotIn(self.program.title(), provider.struckOut.values())
        verifyZeroInteractions(self.nextProvider)