def test_parsing_attributes(self): """Test parsing different attributes of the vehicle. Just make sure parsing that no exception is raised. """ backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): backend_mock.setup_default_vehicles() account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) account.update_vehicle_states() for vehicle in account.vehicles: print('testing vehicle {}'.format(vehicle.name)) state = vehicle.state self.assertIsNotNone(state.lids) self.assertIsNotNone(state.is_vehicle_tracking_enabled) self.assertIsNotNone(state.windows) self.assertIsNotNone(state.condition_based_services) self.assertIsNotNone(state.door_lock_state) self.assertIsNotNone(state.timestamp) self.assertGreater(state.mileage, 0) self.assertGreater(state.remaining_range_total, 0) self.assertIsNotNone(state.remaining_fuel) self.assertIsNotNone(state.all_windows_closed) self.assertEqual(0, len(state.check_control_messages)) self.assertFalse(state.has_check_control_messages) for attrib in vehicle.drive_train_attributes: print(attrib, getattr(state, attrib)) # charging_time is only set when charging if attrib != 'charging_time_remaining': self.assertIsNotNone(getattr(state, attrib), attrib)
def test_parsing_attributes(self): """Test parsing different attributes of the vehicle. Just make sure parsing that no exception is raised. """ backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): backend_mock.setup_default_vehicles() account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_COUNTRY) account.update_vehicle_states() for vehicle in account.vehicles: print('testing vehicle {}'.format(vehicle.name)) state = vehicle.state self.assertIsNotNone(state.lids) self.assertIsNotNone(state.is_vehicle_tracking_enabled) self.assertIsNotNone(state.windows) self.assertIsNotNone(state.condition_based_services) if vehicle.vin != F32_VIN: # these values are not available in the F32 self.assertIsNotNone(state.door_lock_state) self.assertIsNotNone(state.timestamp) self.assertIsNotNone(state.mileage) self.assertIsNotNone(state.remaining_fuel) self.assertIsNotNone(state.all_windows_closed)
def test_update_data(self): """Test update_data method.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) vehicle = account.get_vehicle(G31_VIN) with self.assertRaises(IOError): vehicle.state.update_data() backend_mock.setup_default_vehicles() vehicle.state.update_data() self.assertEqual(4126, vehicle.state.mileage)
def test_get_remote_service_status(self): """Test get_remove_service_status method.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) vehicle = account.get_vehicle(G31_VIN) with self.assertRaises(IOError): vehicle.remote_services._get_remote_service_status(remote_services._Services.REMOTE_LIGHT_FLASH) backend_mock.add_response( r'https://.+/webapi/v1/user/vehicles/{vin}/serviceExecutionStatus\?.+'.format(vin=G31_VIN), data_files=['G31_NBTevo/flash_executed.json']) status = vehicle.remote_services._get_remote_service_status(remote_services._Services.REMOTE_LIGHT_FLASH) self.assertEqual(ExecutionState.EXECUTED, status.state)
def test_update_data(self): """Test update_data method.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_COUNTRY) vehicle = account.get_vehicle(G31_VIN) with self.assertRaises(IOError): vehicle.state.update_data() backend_mock.add_response( '.*/api/vehicle/dynamic/v1/{vin}'.format(vin=G31_VIN), data_files=['G31_NBTevo/dynamic.json']) vehicle.state.update_data() self.assertEqual(2201, vehicle.state.mileage)
def test_update_data(self): """Test update_data method.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) vehicle = account.get_vehicle(G31_VIN) vehicle.state.update_data() self.assertEqual(vehicle.state._attributes[SERVICE_STATUS], {}) backend_mock.setup_default_vehicles() vehicle.state.update_data() self.assertEqual(4126, vehicle.state.vehicle_status.mileage)
def test_invalid_send_response(self): """Test parsing the results of an invalid request""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, Regions.REST_OF_WORLD) with self.assertRaises(IOError): account.send_request('invalid_url')
def test_update_data(self): """Test with proper data.""" backend_mock = BackendMock() backend_mock.setup_default_vehicles() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_COUNTRY) vehicle = account.get_vehicle(G31_VIN) self.assertAlmostEqual(68.0, float(vehicle.specs.TANK_CAPACITY)) vehicle = account.get_vehicle(F48_VIN) self.assertAlmostEqual(36.0, float(vehicle.specs.TANK_CAPACITY)) vehicle = account.get_vehicle(F32_VIN) self.assertIsNone(vehicle.specs.TANK_CAPACITY)
def test_us_header(self): """Test if the host is set correctly in the request.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, Regions.NORTH_AMERICA) request = [r for r in backend_mock.last_request if 'oauth' in r.url][0] self.assertEqual('b2vapi.bmwgroup.us', request.headers['Host'])
def test_available_state_services(self): """Check that available_attributes returns exactly the arguments we have in our test data.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) vehicles = load_response_json('vehicles.json') for test_vehicle in vehicles['vehicles']: vehicle = account.get_vehicle(test_vehicle['vin']) print(vehicle.name) services_to_check = { k: v for k, v in test_vehicle.items() if k in list(AVAILABLE_STATES_MAPPING) } available_services = ['STATUS'] for key, value in services_to_check.items(): if AVAILABLE_STATES_MAPPING[key].get(value): available_services += AVAILABLE_STATES_MAPPING[key][value] if vehicle.drive_train != DriveTrainType.CONVENTIONAL: available_services += ['EFFICIENCY', 'NAVIGATION'] self.assertListEqual(sorted(vehicle.available_state_services), sorted(available_services))
def test_get_remote_service_status(self): """Test get_remove_service_status method.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_COUNTRY) vehicle = account.get_vehicle(G31_VIN) with self.assertRaises(IOError): vehicle.remote_services._get_remote_service_status() backend_mock.add_response( '.*/api/vehicle/remoteservices/v1/{vin}/state/execution'. format(vin=G31_VIN), data_files=['G31_NBTevo/RLF_EXECUTED.json']) status = vehicle.remote_services._get_remote_service_status() self.assertEqual(ExecutionState.EXECUTED, status.state)
def test_parsing_attributes(self): """Test parsing different attributes of the vehicle. Just make sure parsing that no exception is raised and we get not-None values. """ backend_mock = BackendMock() # list of attributes that are ignored at the moment ignored_attributes = [ATTRIBUTE_MAPPING.get(a, a) for a in MISSING_ATTRIBUTES] with mock.patch('bimmer_connected.account.requests', new=backend_mock): backend_mock.setup_default_vehicles() account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) account.update_vehicle_states() for vehicle in account.vehicles: print(vehicle.name) for attribute in (a for a in vehicle.available_attributes if a not in ignored_attributes): self.assertIsNotNone(getattr(vehicle.state, attribute), attribute)
def test_check_control_messages(self): """Test handling of check control messages. F48 is the only vehicle with active Check Control Messages, so we only expect to get something there. """ backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): backend_mock.setup_default_vehicles() account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) account.update_vehicle_states() for vehicle in account.vehicles: print(vehicle.name, vehicle.vin) if vehicle.vin == F48_VIN: self.assertTrue(vehicle.state.has_check_control_messages) else: self.assertFalse(vehicle.state.has_check_control_messages)
def test_parsing_of_lsc_type(self): """Test parsing the lsc type field.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) for vehicle in account.vehicles: self.assertIsNotNone(vehicle.lsc_type)
def test_update_data_error(self): """Test with server returning an error.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_COUNTRY) vehicle = account.get_vehicle(G31_VIN) with self.assertRaises(IOError): vehicle.update_state()
def test_vehicle_search_case(self): """Check if the search for the vehicle by VIN is NOT case sensitive.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) vin = account.vehicles[1].vin self.assertEqual(vin, account.get_vehicle(vin).vin) self.assertEqual(vin, account.get_vehicle(vin.lower()).vin) self.assertEqual(vin, account.get_vehicle(vin.upper()).vin)
def test_set_observer_value(self): """Test set_observer_position with valid arguments.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, Regions.REST_OF_WORLD) account.set_observer_position(1.0, 2.0) for vehicle in account.vehicles: self.assertEqual(vehicle.observer_latitude, 1.0) self.assertEqual(vehicle.observer_longitude, 2.0)
def test_token_vehicles(self): """Test getting backend token and vehicle list.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_COUNTRY) self.assertIsNotNone(account._oauth_token) self.assertEqual(5, len(account.vehicles)) vin = 'G31_NBTEvo_VIN' vehicle = account.get_vehicle(vin) self.assertEqual(vehicle.vin, vin)
def test_statistics_available(self): """Test parsing the statistics_available field.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) g31 = account.get_vehicle(G31_VIN) f45 = account.get_vehicle(F45_VIN) self.assertFalse(g31.statistics_available) self.assertTrue(f45.statistics_available)
def test_invalid_auth(self): """Test if the host is set correctly in the request.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): with mock.patch('bimmer_connected.account.get_gcdm_oauth_endpoint' ) as mocked_endpoint: mocked_endpoint( ).return_value = 'customer.bmwgroup.com/gcdm/invalid' with self.assertRaises(OSError): ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, Regions.REST_OF_WORLD)
def test_token_vehicles(self): """Test getting backend token and vehicle list.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, Regions.REST_OF_WORLD) self.assertIsNotNone(account._oauth_token) self.assertEqual(5, len(account.vehicles)) vehicle = account.get_vehicle(G31_VIN) self.assertEqual(G31_VIN, vehicle.vin) self.assertIsNone(account.get_vehicle('invalid_vin'))
def test_set_observer_some_none(self): """Test set_observer_position with invalid arguments.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, Regions.REST_OF_WORLD) with self.assertRaises(ValueError): account.set_observer_position(None, 2.0) with self.assertRaises(ValueError): account.set_observer_position(1.0, None)
def test_parsing_attributes(self): """Test parsing different attributes of the vehicle.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_COUNTRY) for vehicle in account.vehicles: self.assertIsNotNone(vehicle.drive_train) self.assertIsNotNone(vehicle.name) self.assertIsNotNone(vehicle.has_rex)
def test_drive_train_attributes(self): """Test parsing different attributes of the vehicle.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) for vehicle in account.vehicles: print(vehicle.name) self.assertEqual(vehicle.vin in [G31_VIN, F48_VIN, F15_VIN, I01_VIN, F45_VIN], vehicle.has_internal_combustion_engine) self.assertEqual(vehicle.vin in [I01_VIN, I01_NOREX_VIN, F45_VIN], vehicle.has_hv_battery)
def test_parsing_attributes(self): """Test parsing different attributes of the vehicle.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) for vehicle in account.vehicles: print(vehicle.name) self.assertIsNotNone(vehicle.drive_train) self.assertIsNotNone(vehicle.name) self.assertIsNotNone(vehicle.has_internal_combustion_engine) self.assertIsNotNone(vehicle.has_hv_battery) self.assertIsNotNone(vehicle.drive_train_attributes) self.assertIsNotNone(vehicle.statistics_available)
def test_available_attributes(self): """Check that available_attributes returns exactly the arguments we have in our test data.""" backend_mock = BackendMock() with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) for vin, dirname in TEST_VEHICLE_DATA.items(): vehicle = account.get_vehicle(vin) print(vehicle.name) status_data = load_response_json('{}/status.json'.format(dirname)) existing_attributes = status_data['vehicleStatus'].keys() existing_attributes = sorted([ATTRIBUTE_MAPPING.get(a, a) for a in existing_attributes if a not in MISSING_ATTRIBUTES]) expected_attributes = sorted([a for a in vehicle.available_attributes if a not in ADDITIONAL_ATTRIBUTES]) self.assertListEqual(existing_attributes, expected_attributes)
def test_trigger_remote_services(self): """Test executing a remote light flash.""" remote_services._POLLING_CYCLE = 0 remote_services._UPDATE_AFTER_REMOTE_SERVICE_DELAY = 0 services = [('RLF', 'trigger_remote_light_flash', False), ('RDL', 'trigger_remote_door_lock', True), ('RDU', 'trigger_remote_door_unlock', True), ('RCN', 'trigger_remote_air_conditioning', True), ('RHB', 'trigger_remote_horn', False)] for service, call, triggers_update in services: backend_mock = BackendMock() backend_mock.setup_default_vehicles() backend_mock.add_response( r'.*/api/vehicle/remoteservices/v1/{vin}/{service}'.format( vin=G31_VIN, service=service), data_files=['G31_NBTevo/RLF_INITIAL_RESPONSE.json']) backend_mock.add_response( '.*/api/vehicle/remoteservices/v1/{vin}/state/execution'. format(vin=G31_VIN), data_files=[ 'G31_NBTevo/RLF_PENDING.json', 'G31_NBTevo/RLF_DELIVERED.json', 'G31_NBTevo/RLF_EXECUTED.json' ]) with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_COUNTRY) mock_listener = mock.Mock(return_value=None) account.add_update_listener(mock_listener) vehicle = account.get_vehicle(G31_VIN) response = getattr(vehicle.remote_services, call)() self.assertEqual(ExecutionState.EXECUTED, response.state) if triggers_update: mock_listener.assert_called_once_with() else: mock_listener.assert_not_called()
def test_trigger_remote_services(self): """Test executing a remote light flash.""" remote_services._POLLING_CYCLE = 0 remote_services._UPDATE_AFTER_REMOTE_SERVICE_DELAY = 0 services = [ ('LIGHT_FLASH', 'trigger_remote_light_flash', False), ('DOOR_LOCK', 'trigger_remote_door_lock', True), ('DOOR_UNLOCK', 'trigger_remote_door_unlock', True), ('CLIMATE_NOW', 'trigger_remote_air_conditioning', True), ('HORN_BLOW', 'trigger_remote_horn', False) ] for service, call, triggers_update in services: backend_mock = BackendMock() backend_mock.setup_default_vehicles() backend_mock.add_response('https://.+/webapi/v1/user/vehicles/{vin}/executeService'.format(vin=G31_VIN), data_files=[_RESPONSE_INITIATED]) backend_mock.add_response( r'https://.+/webapi/v1/user/vehicles/{vin}/serviceExecutionStatus\?serviceType={service_type}'.format( vin=G31_VIN, service_type=service), data_files=[ _RESPONSE_PENDING, _RESPONSE_PENDING, _RESPONSE_DELIVERED, _RESPONSE_DELIVERED, _RESPONSE_EXECUTED]) with mock.patch('bimmer_connected.account.requests', new=backend_mock): account = ConnectedDriveAccount(TEST_USERNAME, TEST_PASSWORD, TEST_REGION) mock_listener = mock.Mock(return_value=None) account.add_update_listener(mock_listener) vehicle = account.get_vehicle(G31_VIN) response = getattr(vehicle.remote_services, call)() self.assertEqual(ExecutionState.EXECUTED, response.state) if triggers_update: mock_listener.assert_called_once_with() else: mock_listener.assert_not_called()