<reponame>donaldacmartin/anjou
from anjou.model import MetroException
from unittest import TestCase
from unittest.mock import MagicMock, patch

from requests import RequestException

from anjou.metro import get_metro_status

URL = "http://abc.def"

GREEN_STATUS = "abc123"
ORANGE_STATUS = "def456"
YELLOW_STATUS = "ghi789"
BLUE_STATUS = "jkl321"

INVALID_HTML = "abc123"
HTML = """
<html>
    <body>
        <div id='status-metro'>
            <div class='block'>
                <h2>Ligne verte</h2>
                <p>%s</p>
            </div>
            <div class='block'>
                <h2>Ligne orange</h2>
                <p>%s</p>
            </div>
            <div class='block'>
                <h2>Ligne jaune</h2>
                <p>%s</p>
            </div>
            <div class='block'>
                <h2>Ligne bleue</h2>
                <p>%s</p>
            </div>
            <div class='block'>
                <h2>Unknown name</h2>
                <p>Unexpected status</p>
            </div>
        </div>
    </body>
</html>
""" % (
    GREEN_STATUS,
    ORANGE_STATUS,
    YELLOW_STATUS,
    BLUE_STATUS,
)

EXPECTED_RESULT = {
    "green": GREEN_STATUS,
    "orange": ORANGE_STATUS,
    "yellow": YELLOW_STATUS,
    "blue": BLUE_STATUS,
    "Unknown name": "Unexpected status",
}

REQUEST_ERROR = "Failed to connect to %s" % URL
NOT_OK_ERROR = "STM response not OK: 404"


class MockResponse:
    def __init__(self, content: str):
        self.ok = content is not None
        self.status_code = 200 if content is not None else 404
        self.content = content


class TestMetro(TestCase):
    @patch("anjou.metro.get")
    def test_get_metro_status_req_error(self, requests_mock: MagicMock):
        requests_mock.side_effect = RequestException()

        with self.assertRaises(MetroException) as context:
            get_metro_status(URL)
            self.assertEquals(REQUEST_ERROR, str(context.exception))

        requests_mock.assert_called_once_with(URL)

    @patch("anjou.metro.get")
    def test_get_metro_status_http_not_ok(self, requests_mock: MagicMock):
        requests_mock.return_value = MockResponse(None)

        with self.assertRaises(MetroException) as context:
            get_metro_status(URL)
            self.assertEquals(NOT_OK_ERROR, str(context.exception))

        requests_mock.assert_called_once_with(URL)

    @patch("anjou.metro.get")
    def test_get_metro_status_invalid_html(self, requests_mock: MagicMock):
        requests_mock.return_value = MockResponse(INVALID_HTML)

        with self.assertRaises(MetroException) as context:
            get_metro_status(URL)
            self.assertEquals(REQUEST_ERROR, str(context.exception))

        requests_mock.assert_called_once_with(URL)

    @patch("anjou.metro.get")
    def test_get_metro_status_ok(self, requests_mock: MagicMock):
        requests_mock.return_value = MockResponse(HTML)
        self.assertEqual(EXPECTED_RESULT, get_metro_status(URL))
        requests_mock.assert_called_once_with(URL)

from anjou.model import MetroException
from unittest import TestCase
from unittest.mock import MagicMock, patch

from requests import RequestException

from anjou.metro import get_metro_status

URL = "http://abc.def"

GREEN_STATUS = "abc123"
ORANGE_STATUS = "def456"
YELLOW_STATUS = "ghi789"
BLUE_STATUS = "jkl321"

INVALID_HTML = "abc123"
HTML = """
<html>
    <body>
        <div id='status-metro'>
            <div class='block'>
                <h2>Ligne verte</h2>
                <p>%s</p>
            </div>
            <div class='block'>
                <h2>Ligne orange</h2>
                <p>%s</p>
            </div>
            <div class='block'>
                <h2>Ligne jaune</h2>
                <p>%s</p>
            </div>
            <div class='block'>
                <h2>Ligne bleue</h2>
                <p>%s</p>
            </div>
            <div class='block'>
                <h2>Unknown name</h2>
                <p>Unexpected status</p>
            </div>
        </div>
    </body>
</html>
""" % (
    GREEN_STATUS,
    ORANGE_STATUS,
    YELLOW_STATUS,
    BLUE_STATUS,
)

EXPECTED_RESULT = {
    "green": GREEN_STATUS,
    "orange": ORANGE_STATUS,
    "yellow": YELLOW_STATUS,
    "blue": BLUE_STATUS,
    "Unknown name": "Unexpected status",
}

REQUEST_ERROR = "Failed to connect to %s" % URL
NOT_OK_ERROR = "STM response not OK: 404"


class MockResponse:
    def __init__(self, content: str):
        self.ok = content is not None
        self.status_code = 200 if content is not None else 404
        self.content = content


class TestMetro(TestCase):
    @patch("anjou.metro.get")
    def test_get_metro_status_req_error(self, requests_mock: MagicMock):
        requests_mock.side_effect = RequestException()

        with self.assertRaises(MetroException) as context:
            get_metro_status(URL)
            self.assertEquals(REQUEST_ERROR, str(context.exception))

        requests_mock.assert_called_once_with(URL)

    @patch("anjou.metro.get")
    def test_get_metro_status_http_not_ok(self, requests_mock: MagicMock):
        requests_mock.return_value = MockResponse(None)

        with self.assertRaises(MetroException) as context:
            get_metro_status(URL)
            self.assertEquals(NOT_OK_ERROR, str(context.exception))

        requests_mock.assert_called_once_with(URL)

    @patch("anjou.metro.get")
    def test_get_metro_status_invalid_html(self, requests_mock: MagicMock):
        requests_mock.return_value = MockResponse(INVALID_HTML)

        with self.assertRaises(MetroException) as context:
            get_metro_status(URL)
            self.assertEquals(REQUEST_ERROR, str(context.exception))

        requests_mock.assert_called_once_with(URL)

    @patch("anjou.metro.get")
    def test_get_metro_status_ok(self, requests_mock: MagicMock):
        requests_mock.return_value = MockResponse(HTML)
        self.assertEqual(EXPECTED_RESULT, get_metro_status(URL))
        requests_mock.assert_called_once_with(URL)
<html>     <body>         <div id='status-metro'>             <div class='block'>                 <h2>Ligne verte</h2>                 <p>%s</p>             </div>             <div class='block'>                 <h2>Ligne orange</h2>                 <p>%s</p>             </div>             <div class='block'>                 <h2>Ligne jaune</h2>                 <p>%s</p>             </div>             <div class='block'>                 <h2>Ligne bleue</h2>                 <p>%s</p>             </div>             <div class='block'>                 <h2>Unknown name</h2>                 <p>Unexpected status</p>             </div>         </div>     </body> </html>