from unittest.mock import Mock

from django.test import TestCase

from newsreader.news.collection.exceptions import (
    StreamDeniedException,
    StreamException,
    StreamNotFoundException,
    StreamTimeOutException,
)
from newsreader.news.collection.favicon import FaviconClient
from newsreader.news.collection.tests.factories import CollectionRuleFactory
from newsreader.news.collection.tests.favicon.client.mocks import simple_mock


class FaviconClientTestCase(TestCase):
    def setUp(self):
        self.maxDiff = None

    def test_simple(self):
        rule = CollectionRuleFactory()
        stream = Mock(url="https://www.bbc.com", rule=rule)
        stream.read.return_value = (simple_mock, stream)

        with FaviconClient([stream]) as client:
            for payload, stream in client:
                self.assertEquals(stream.rule.pk, rule.pk)
                self.assertEquals(payload, simple_mock)

        stream.read.assert_called_once_with()

    def test_client_catches_stream_exception(self):
        rule = CollectionRuleFactory(error=None, succeeded=True)
        stream = Mock(url="https://www.bbc.com", rule=rule)
        stream.read.side_effect = StreamException

        with FaviconClient([stream]) as client:
            for rule, data in client:
                pass

        stream.read.assert_called_once_with()

        # The favicon client does not set CollectionRule errors
        self.assertEquals(rule.succeeded, True)
        self.assertEquals(rule.error, None)

    def test_client_catches_stream_not_found_exception(self):
        rule = CollectionRuleFactory(error=None, succeeded=True)
        stream = Mock(url="https://www.bbc.com", rule=rule)
        stream.read.side_effect = StreamNotFoundException

        with FaviconClient([stream]) as client:
            for rule, data in client:
                pass

        stream.read.assert_called_once_with()

        # The favicon client does not set CollectionRule errors
        self.assertEquals(rule.succeeded, True)
        self.assertEquals(rule.error, None)

    def test_client_catches_stream_denied_exception(self):
        rule = CollectionRuleFactory(error=None, succeeded=True)
        stream = Mock(url="https://www.bbc.com", rule=rule)
        stream.read.side_effect = StreamDeniedException

        with FaviconClient([stream]) as client:
            for rule, data in client:
                pass

        stream.read.assert_called_once_with()

        # The favicon client does not set CollectionRule errors
        self.assertEquals(rule.succeeded, True)
        self.assertEquals(rule.error, None)

    def test_client_catches_stream_timed_out(self):
        rule = CollectionRuleFactory(error=None, succeeded=True)
        stream = Mock(url="https://www.bbc.com", rule=rule)
        stream.read.side_effect = StreamTimeOutException

        with FaviconClient([stream]) as client:
            for rule, data in client:
                pass

        stream.read.assert_called_once_with()

        # The favicon client does not set CollectionRule errors
        self.assertEquals(rule.succeeded, True)
        self.assertEquals(rule.error, None)
