from micawber import *
from micawber.test_utils import test_pr, test_cache, test_pr_cache, TestProvider, BaseTestCase


class ProviderTestCase(BaseTestCase):
    def test_register_unregister(self):
        pr = ProviderRegistry()
        provider1 = TestProvider('link')
        provider2 = TestProvider('link')
        pr.register('1', provider1)
        pr.register('2', provider1)
        pr.register('3', provider2)
        pr.unregister('2')
        self.assertEqual(len(pr._registry), 2)

        # Multiple calls to remove() are OK.
        self.assertRaises(KeyError, pr.unregister, '2')

        self.assertEqual(pr.provider_for_url('1'), provider1)
        self.assertEqual(pr.provider_for_url('2'), None)
        self.assertEqual(pr.provider_for_url('3'), provider2)

        pr.unregister('1')
        pr.unregister('3')
        self.assertEqual(len(pr._registry), 0)
        for test_regex in ['1', '2', '3']:
            self.assertEqual(pr.provider_for_url(test_regex), None)

    def test_multiple_matches(self):
        pr = ProviderRegistry()
        provider1 = TestProvider('link')
        provider2 = TestProvider('link')
        pr.register('1(\d+)', provider1)
        pr.register('1\d+', provider2)
        self.assertEqual(pr.provider_for_url('11'), provider2)
        pr.unregister('1\d+')
        self.assertEqual(pr.provider_for_url('11'), provider1)

    def test_provider_matching(self):
        provider = test_pr.provider_for_url('http://link-test1')
        self.assertFalse(provider is None)
        self.assertEqual(provider.endpoint, 'link')

        provider = test_pr.provider_for_url('http://photo-test1')
        self.assertFalse(provider is None)
        self.assertEqual(provider.endpoint, 'photo')

        provider = test_pr.provider_for_url('http://video-test1')
        self.assertFalse(provider is None)
        self.assertEqual(provider.endpoint, 'video')

        provider = test_pr.provider_for_url('http://rich-test1')
        self.assertFalse(provider is None)
        self.assertEqual(provider.endpoint, 'rich')

        provider = test_pr.provider_for_url('http://none-test1')
        self.assertTrue(provider is None)

    def test_provider(self):
        resp = test_pr.request('http://link-test1')
        self.assertEqual(resp, {'title': 'test1', 'type': 'link', 'url': 'http://link-test1'})

        resp = test_pr.request('http://photo-test2')
        self.assertEqual(resp, {'title': 'ptest2', 'type': 'photo', 'url': 'test2.jpg'})

        resp = test_pr.request('http://video-test1')
        self.assertEqual(resp, {'title': 'vtest1', 'type': 'video', 'html': '<test1>video</test1>', 'url': 'http://video-test1'})

        resp = test_pr.request('http://link-test1', width=100)
        self.assertEqual(resp, {'title': 'test1', 'type': 'link', 'url': 'http://link-test1', 'width': 99})

        self.assertRaises(ProviderException, test_pr.request, 'http://not-here')
        self.assertRaises(ProviderException, test_pr.request, 'http://link-test3')

    def test_caching(self):
        resp = test_pr_cache.request('http://link-test1')
        self.assertCached('http://link-test1', resp)

        # check that its the same as what we tested in the previous case
        resp2 = test_pr.request('http://link-test1')
        self.assertEqual(resp, resp2)

        resp = test_pr_cache.request('http://photo-test2')
        self.assertCached('http://photo-test2', resp)

        resp = test_pr_cache.request('http://video-test1')
        self.assertCached('http://video-test1', resp)

        self.assertEqual(len(test_cache._cache), 3)

    def test_caching_params(self):
        resp = test_pr_cache.request('http://link-test1')
        self.assertCached('http://link-test1', resp)

        resp_p = test_pr_cache.request('http://link-test1', width=100)
        self.assertCached('http://link-test1', resp_p, width=100)

        self.assertFalse(resp == resp_p)

    def test_invalid_json(self):
        pr = ProviderRegistry()
        class BadProvider(Provider):
            def fetch(self, url):
                return 'bad'
        pr.register('http://bad', BadProvider('link'))
        self.assertRaises(InvalidResponseException, pr.request, 'http://bad')


class ParserTestCase(BaseTestCase):
    def test_parse_text_full(self):
        for url, expected in self.full_pairs.items():
            parsed = parse_text_full(url, test_pr)
            self.assertHTMLEqual(parsed, expected)