242 lines
8.6 KiB
Python
242 lines
8.6 KiB
Python
"""Test the automatic device tracker platform."""
|
|
|
|
import logging
|
|
import requests
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from homeassistant.components.device_tracker.automatic import (
|
|
URL_AUTHORIZE, URL_VEHICLES, URL_TRIPS, setup_scanner)
|
|
|
|
from tests.common import get_test_home_assistant
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
INVALID_USERNAME = 'bob'
|
|
VALID_USERNAME = 'jim'
|
|
PASSWORD = 'password'
|
|
CLIENT_ID = '12345'
|
|
CLIENT_SECRET = '54321'
|
|
FUEL_LEVEL = 77.2
|
|
LATITUDE = 32.82336
|
|
LONGITUDE = -117.23743
|
|
ACCURACY = 8
|
|
DISPLAY_NAME = 'My Vehicle'
|
|
|
|
|
|
def mocked_requests(*args, **kwargs):
|
|
"""Mock requests.get invocations."""
|
|
class MockResponse:
|
|
"""Class to represent a mocked response."""
|
|
|
|
def __init__(self, json_data, status_code):
|
|
"""Initialize the mock response class."""
|
|
self.json_data = json_data
|
|
self.status_code = status_code
|
|
|
|
def json(self):
|
|
"""Return the json of the response."""
|
|
return self.json_data
|
|
|
|
@property
|
|
def content(self):
|
|
"""Return the content of the response."""
|
|
return self.json()
|
|
|
|
def raise_for_status(self):
|
|
"""Raise an HTTPError if status is not 200."""
|
|
if self.status_code != 200:
|
|
raise requests.HTTPError(self.status_code)
|
|
|
|
data = kwargs.get('data')
|
|
|
|
if data and data.get('username', None) == INVALID_USERNAME:
|
|
return MockResponse({
|
|
"error": "invalid_credentials"
|
|
}, 401)
|
|
elif str(args[0]).startswith(URL_AUTHORIZE):
|
|
return MockResponse({
|
|
"user": {
|
|
"sid": "sid",
|
|
"id": "id"
|
|
},
|
|
"token_type": "Bearer",
|
|
"access_token": "accesstoken",
|
|
"refresh_token": "refreshtoken",
|
|
"expires_in": 31521669,
|
|
"scope": ""
|
|
}, 200)
|
|
elif str(args[0]).startswith(URL_VEHICLES):
|
|
return MockResponse({
|
|
"_metadata": {
|
|
"count": 2,
|
|
"next": None,
|
|
"previous": None
|
|
},
|
|
"results": [
|
|
{
|
|
"url": "https://api.automatic.com/vehicle/vid/",
|
|
"id": "vid",
|
|
"created_at": "2016-03-05T20:05:16.240000Z",
|
|
"updated_at": "2016-08-29T01:52:59.597898Z",
|
|
"make": "Honda",
|
|
"model": "Element",
|
|
"year": 2007,
|
|
"submodel": "EX",
|
|
"display_name": DISPLAY_NAME,
|
|
"fuel_grade": "regular",
|
|
"fuel_level_percent": FUEL_LEVEL,
|
|
"active_dtcs": []
|
|
}]
|
|
}, 200)
|
|
elif str(args[0]).startswith(URL_TRIPS):
|
|
return MockResponse({
|
|
"_metadata": {
|
|
"count": 1594,
|
|
"next": "https://api.automatic.com/trip/?page=2",
|
|
"previous": None
|
|
},
|
|
"results": [
|
|
{
|
|
"url": "https://api.automatic.com/trip/tid1/",
|
|
"id": "tid1",
|
|
"driver": "https://api.automatic.com/user/uid/",
|
|
"user": "https://api.automatic.com/user/uid/",
|
|
"started_at": "2016-08-28T19:37:23.986000Z",
|
|
"ended_at": "2016-08-28T19:43:22.500000Z",
|
|
"distance_m": 3931.6,
|
|
"duration_s": 358.5,
|
|
"vehicle": "https://api.automatic.com/vehicle/vid/",
|
|
"start_location": {
|
|
"lat": 32.87336,
|
|
"lon": -117.22743,
|
|
"accuracy_m": 10
|
|
},
|
|
"start_address": {
|
|
"name": "123 Fake St, Nowhere, NV 12345",
|
|
"display_name": "123 Fake St, Nowhere, NV",
|
|
"street_number": "Unknown",
|
|
"street_name": "Fake St",
|
|
"city": "Nowhere",
|
|
"state": "NV",
|
|
"country": "US"
|
|
},
|
|
"end_location": {
|
|
"lat": LATITUDE,
|
|
"lon": LONGITUDE,
|
|
"accuracy_m": ACCURACY
|
|
},
|
|
"end_address": {
|
|
"name": "321 Fake St, Nowhere, NV 12345",
|
|
"display_name": "321 Fake St, Nowhere, NV",
|
|
"street_number": "Unknown",
|
|
"street_name": "Fake St",
|
|
"city": "Nowhere",
|
|
"state": "NV",
|
|
"country": "US"
|
|
},
|
|
"path": "path",
|
|
"vehicle_events": [],
|
|
"start_timezone": "America/Denver",
|
|
"end_timezone": "America/Denver",
|
|
"idling_time_s": 0,
|
|
"tags": []
|
|
},
|
|
{
|
|
"url": "https://api.automatic.com/trip/tid2/",
|
|
"id": "tid2",
|
|
"driver": "https://api.automatic.com/user/uid/",
|
|
"user": "https://api.automatic.com/user/uid/",
|
|
"started_at": "2016-08-28T18:48:00.727000Z",
|
|
"ended_at": "2016-08-28T18:55:25.800000Z",
|
|
"distance_m": 3969.1,
|
|
"duration_s": 445.1,
|
|
"vehicle": "https://api.automatic.com/vehicle/vid/",
|
|
"start_location": {
|
|
"lat": 32.87336,
|
|
"lon": -117.22743,
|
|
"accuracy_m": 11
|
|
},
|
|
"start_address": {
|
|
"name": "123 Fake St, Nowhere, NV, USA",
|
|
"display_name": "Fake St, Nowhere, NV",
|
|
"street_number": "123",
|
|
"street_name": "Fake St",
|
|
"city": "Nowhere",
|
|
"state": "NV",
|
|
"country": "US"
|
|
},
|
|
"end_location": {
|
|
"lat": 32.82336,
|
|
"lon": -117.23743,
|
|
"accuracy_m": 10
|
|
},
|
|
"end_address": {
|
|
"name": "321 Fake St, Nowhere, NV, USA",
|
|
"display_name": "Fake St, Nowhere, NV",
|
|
"street_number": "Unknown",
|
|
"street_name": "Fake St",
|
|
"city": "Nowhere",
|
|
"state": "NV",
|
|
"country": "US"
|
|
},
|
|
"path": "path",
|
|
"vehicle_events": [],
|
|
"start_timezone": "America/Denver",
|
|
"end_timezone": "America/Denver",
|
|
"idling_time_s": 0,
|
|
"tags": []
|
|
}
|
|
]
|
|
}, 200)
|
|
else:
|
|
_LOGGER.debug('UNKNOWN ROUTE')
|
|
|
|
|
|
class TestAutomatic(unittest.TestCase):
|
|
"""Test cases around the automatic device scanner."""
|
|
|
|
def see_mock(self, **kwargs):
|
|
"""Mock see function."""
|
|
self.assertEqual('vid', kwargs.get('dev_id'))
|
|
self.assertEqual(FUEL_LEVEL,
|
|
kwargs.get('attributes', {}).get('fuel_level'))
|
|
self.assertEqual((LATITUDE, LONGITUDE), kwargs.get('gps'))
|
|
self.assertEqual(ACCURACY, kwargs.get('gps_accuracy'))
|
|
|
|
def setUp(self):
|
|
"""Set up test data."""
|
|
self.hass = get_test_home_assistant()
|
|
|
|
def tearDown(self):
|
|
"""Tear down test data."""
|
|
self.hass.stop()
|
|
|
|
@patch('requests.get', side_effect=mocked_requests)
|
|
@patch('requests.post', side_effect=mocked_requests)
|
|
def test_invalid_credentials(self, mock_get, mock_post):
|
|
"""Test error is raised with invalid credentials."""
|
|
config = {
|
|
'platform': 'automatic',
|
|
'username': INVALID_USERNAME,
|
|
'password': PASSWORD,
|
|
'client_id': CLIENT_ID,
|
|
'secret': CLIENT_SECRET
|
|
}
|
|
|
|
self.assertFalse(setup_scanner(self.hass, config, self.see_mock))
|
|
|
|
@patch('requests.get', side_effect=mocked_requests)
|
|
@patch('requests.post', side_effect=mocked_requests)
|
|
def test_valid_credentials(self, mock_get, mock_post):
|
|
"""Test error is raised with invalid credentials."""
|
|
config = {
|
|
'platform': 'automatic',
|
|
'username': VALID_USERNAME,
|
|
'password': PASSWORD,
|
|
'client_id': CLIENT_ID,
|
|
'secret': CLIENT_SECRET
|
|
}
|
|
|
|
self.assertTrue(setup_scanner(self.hass, config, self.see_mock))
|