def test_jwt_credential() -> None: """Test get/set with jwt credential.""" credential_store = CredentialStore() test_key = "test" # Try to get value from empty store assert test_key not in credential_store assert not credential_store.get(test_key) with pytest.raises(KeyError): credential_store[test_key] # Set value test_value = JWTCredential(get_jwt()) credential_store[test_key] = test_value # Try to get values from filled store assert test_key in credential_store assert credential_store.get(test_key) == test_value assert credential_store.get_value(test_key) == test_value.value assert credential_store[test_key] == test_value # Try again with expired expired_time = time.time() + 3600 with mock.patch("time.time", mock.MagicMock(return_value=expired_time)): assert test_key not in credential_store assert credential_store.get_value(test_key) is None assert not credential_store.get(test_key) with pytest.raises(KeyError): credential_store[test_key]
def test_file_store_expired_token() -> None: """Test loading expired token from credential store.""" with tempfile.TemporaryDirectory() as tmpdirname: # Prepare initial store expired_token = get_jwt(timedelta(seconds=-900)) old_filename = f"{tmpdirname}/.credentials/renault-api.json" old_credential_store = FileCredentialStore(old_filename) test_key = "key" test_value = Credential("value") test_jwt_key = "gigya_jwt" test_jwt_value = Credential(expired_token) # bypass JWTCredential old_credential_store[test_key] = test_value old_credential_store[test_jwt_key] = test_jwt_value assert test_key in old_credential_store assert old_credential_store.get(test_key) == test_value assert old_credential_store[test_key] == test_value assert test_jwt_key in old_credential_store assert old_credential_store.get(test_jwt_key) == test_jwt_value assert old_credential_store[test_jwt_key] == test_jwt_value # Copy the data into new file new_filename = f"{tmpdirname}/.credentials/renault-api-copy.json" copyfile(old_filename, new_filename) new_credential_store = FileCredentialStore(new_filename) # Check that the data is in the new store assert test_key in new_credential_store assert new_credential_store.get(test_key) == test_value assert new_credential_store[test_key] == test_value # Except the JWT token which was rejected on load assert test_jwt_key not in new_credential_store
def get_logged_in_credential_store() -> CredentialStore: """Get credential store initialised with Gigya credentials.""" credential_store = CredentialStore() credential_store[GIGYA_LOGIN_TOKEN] = Credential(TEST_LOGIN_TOKEN) credential_store[GIGYA_PERSON_ID] = Credential(TEST_PERSON_ID) credential_store[GIGYA_JWT] = JWTCredential(get_jwt()) return credential_store
async def test_set_vehicle_action(websession: aiohttp.ClientSession, mocked_responses: aioresponses) -> None: """Test set_vehicle_action.""" url = fixtures.inject_set_hvac_start(mocked_responses, "cancel") assert await kamereon.set_vehicle_action( websession=websession, root_url=TEST_KAMEREON_URL, api_key=TEST_KAMEREON_APIKEY, gigya_jwt=fixtures.get_jwt(), country=TEST_COUNTRY, account_id=TEST_ACCOUNT_ID, vin=TEST_VIN, endpoint="hvac-start", attributes={"action": "cancel"}, ) expected_json = { "data": { "type": "HvacStart", "attributes": { "action": "cancel" } } } request: RequestCall = mocked_responses.requests[("POST", URL(url))][0] assert expected_json == request.kwargs["json"]
def test_http_get(mocked_responses: aioresponses, cli_runner: CliRunner) -> None: """It exits with a status code of zero.""" credential_store = FileCredentialStore(os.path.expanduser(CREDENTIAL_PATH)) credential_store[CONF_LOCALE] = Credential(TEST_LOCALE) credential_store[CONF_ACCOUNT_ID] = Credential(TEST_ACCOUNT_ID) credential_store[CONF_VIN] = Credential(TEST_VIN) credential_store[GIGYA_LOGIN_TOKEN] = Credential(TEST_LOGIN_TOKEN) credential_store[GIGYA_PERSON_ID] = Credential(TEST_PERSON_ID) credential_store[GIGYA_JWT] = JWTCredential(fixtures.get_jwt()) fixtures.inject_get_charging_settings(mocked_responses, "single") endpoint = ("/commerce/v1/accounts/{account_id}" "/kamereon/kca/car-adapter" "/v1/cars/{vin}/charging-settings") result = cli_runner.invoke( __main__.main, f"http get {endpoint}", ) assert result.exit_code == 0, result.exception expected_output = ( "{'data': {'type': 'Car', 'id': 'VF1AAAAA555777999', 'attributes': {" "'mode': 'scheduled', 'schedules': [" "{'id': 1, 'activated': True, " "'monday': {'startTime': 'T12:00Z', 'duration': 15}, " "'tuesday': {'startTime': 'T04:30Z', 'duration': 420}, " "'wednesday': {'startTime': 'T22:30Z', 'duration': 420}, " "'thursday': {'startTime': 'T22:00Z', 'duration': 420}, " "'friday': {'startTime': 'T12:15Z', 'duration': 15}, " "'saturday': {'startTime': 'T12:30Z', 'duration': 30}, " "'sunday': {'startTime': 'T12:45Z', 'duration': 45}}" "]}}}\n") assert expected_output == result.output
def test_file_store() -> None: """Test file credential store.""" with tempfile.TemporaryDirectory() as tmpdirname: # Prepare initial store old_filename = f"{tmpdirname}/.credentials/renault-api.json" old_credential_store = FileCredentialStore(old_filename) test_key = "key" test_value = Credential("value") test_jwt_key = "gigya_jwt" test_jwt_value = JWTCredential(get_jwt()) old_credential_store[test_key] = test_value old_credential_store[test_jwt_key] = test_jwt_value assert test_key in old_credential_store assert old_credential_store.get(test_key) == test_value assert old_credential_store[test_key] == test_value assert test_jwt_key in old_credential_store assert old_credential_store.get(test_jwt_key) == test_jwt_value assert old_credential_store[test_jwt_key] == test_jwt_value # Copy the data into new file new_filename = f"{tmpdirname}/.credentials/renault-api-copy.json" copyfile(old_filename, new_filename) new_credential_store = FileCredentialStore(new_filename) # Check that the data is in the new store assert test_key in new_credential_store assert new_credential_store.get(test_key) == test_value assert new_credential_store[test_key] == test_value assert test_jwt_key in new_credential_store assert new_credential_store.get(test_jwt_key) == test_jwt_value assert new_credential_store[test_jwt_key] == test_jwt_value
def test_http_post_file(tmpdir: Any, mocked_responses: aioresponses, cli_runner: CliRunner) -> None: """It exits with a status code of zero.""" credential_store = FileCredentialStore(os.path.expanduser(CREDENTIAL_PATH)) credential_store[CONF_LOCALE] = Credential(TEST_LOCALE) credential_store[CONF_ACCOUNT_ID] = Credential(TEST_ACCOUNT_ID) credential_store[CONF_VIN] = Credential(TEST_VIN) credential_store[GIGYA_LOGIN_TOKEN] = Credential(TEST_LOGIN_TOKEN) credential_store[GIGYA_PERSON_ID] = Credential(TEST_PERSON_ID) credential_store[GIGYA_JWT] = JWTCredential(fixtures.get_jwt()) url = fixtures.inject_set_charge_schedule(mocked_responses, "schedules") endpoint = ("/commerce/v1/accounts/{account_id}" "/kamereon/kca/car-adapter" "/v2/cars/{vin}/actions/charge-schedule") body = { "data": { "type": "ChargeSchedule", "attributes": { "schedules": [] } } } json_file = tmpdir.mkdir("json").join("sample.json") json_file.write(json.dumps(body)) result = cli_runner.invoke( __main__.main, f"http post-file {endpoint} '{json_file}'", ) assert result.exit_code == 0, result.exception expected_output = ( "{'data': {'type': 'ChargeSchedule', 'id': 'guid', " "'attributes': {'schedules': [" "{'id': 1, 'activated': True, " "'tuesday': {'startTime': 'T04:30Z', 'duration': 420}, " "'wednesday': {'startTime': 'T22:30Z', 'duration': 420}, " "'thursday': {'startTime': 'T22:00Z', 'duration': 420}, " "'friday': {'startTime': 'T23:30Z', 'duration': 480}, " "'saturday': {'startTime': 'T18:30Z', 'duration': 120}, " "'sunday': {'startTime': 'T12:45Z', 'duration': 45}}]}}}\n") assert expected_output == result.output expected_json = { "data": { "type": "ChargeSchedule", "attributes": { "schedules": [] } } } request: RequestCall = mocked_responses.requests[("POST", URL(url))][0] assert expected_json == request.kwargs["json"]
def test_jwt() -> None: """Test for Credential class.""" jwt_token = get_jwt() credential = JWTCredential(jwt_token) assert credential.value == jwt_token assert not credential.has_expired() expired_time = time.time() + 3600 with mock.patch("time.time", mock.MagicMock(return_value=expired_time)): assert credential.has_expired()
async def test_get_account_vehicles(websession: aiohttp.ClientSession, mocked_responses: aioresponses) -> None: """Test get_account_vehicles.""" fixtures.inject_get_vehicles(mocked_responses, "zoe_40.1") await kamereon.get_account_vehicles( websession=websession, root_url=TEST_KAMEREON_URL, api_key=TEST_KAMEREON_APIKEY, gigya_jwt=fixtures.get_jwt(), country=TEST_COUNTRY, account_id=TEST_ACCOUNT_ID, )
async def test_get_person(websession: aiohttp.ClientSession, mocked_responses: aioresponses) -> None: """Test get_person.""" fixtures.inject_get_person(mocked_responses) person = await kamereon.get_person( websession=websession, root_url=TEST_KAMEREON_URL, api_key=TEST_KAMEREON_APIKEY, gigya_jwt=fixtures.get_jwt(), country=TEST_COUNTRY, person_id=TEST_PERSON_ID, ) assert len(person.accounts) == 2
def initialise_credential_store( include_account_id: Optional[bool] = None, include_vin: Optional[bool] = None, ) -> None: """Initialise CLI credential store.""" credential_store = FileCredentialStore(os.path.expanduser(CREDENTIAL_PATH)) credential_store[CONF_LOCALE] = Credential(TEST_LOCALE) credential_store[GIGYA_LOGIN_TOKEN] = Credential(TEST_LOGIN_TOKEN) credential_store[GIGYA_PERSON_ID] = Credential(TEST_PERSON_ID) credential_store[GIGYA_JWT] = JWTCredential(get_jwt()) if include_account_id: credential_store[CONF_ACCOUNT_ID] = Credential(TEST_ACCOUNT_ID) if include_vin: credential_store[CONF_VIN] = Credential(TEST_VIN)
async def test_get_vehicle_data(websession: aiohttp.ClientSession, mocked_responses: aioresponses) -> None: """Test get_vehicle_data.""" fixtures.inject_get_battery_status(mocked_responses) assert await kamereon.get_vehicle_data( websession=websession, root_url=TEST_KAMEREON_URL, api_key=TEST_KAMEREON_APIKEY, gigya_jwt=fixtures.get_jwt(), country=TEST_COUNTRY, account_id=TEST_ACCOUNT_ID, vin=TEST_VIN, endpoint="battery-status", )
def test_vehicle_status_no_prompt(mocked_responses: aioresponses, cli_runner: CliRunner) -> None: """It exits with a status code of zero.""" credential_store = FileCredentialStore(os.path.expanduser(CREDENTIAL_PATH)) credential_store[CONF_LOCALE] = Credential(TEST_LOCALE) credential_store[GIGYA_LOGIN_TOKEN] = Credential(TEST_LOGIN_TOKEN) credential_store[GIGYA_PERSON_ID] = Credential(TEST_PERSON_ID) credential_store[GIGYA_JWT] = JWTCredential(fixtures.get_jwt()) fixtures.inject_vehicle_status(mocked_responses) result = cli_runner.invoke( __main__.main, f"--account {TEST_ACCOUNT_ID} --vin {TEST_VIN} status") assert result.exit_code == 0, result.exception assert EXPECTED_BATTERY_STATUS == result.output
def test_list_vehicles_no_prompt(mocked_responses: aioresponses, cli_runner: CliRunner) -> None: """It exits with a status code of zero.""" credential_store = FileCredentialStore(os.path.expanduser(CREDENTIAL_PATH)) credential_store[CONF_LOCALE] = Credential(TEST_LOCALE) credential_store[GIGYA_LOGIN_TOKEN] = Credential(TEST_LOGIN_TOKEN) credential_store[GIGYA_PERSON_ID] = Credential(TEST_PERSON_ID) credential_store[GIGYA_JWT] = JWTCredential(fixtures.get_jwt()) fixtures.inject_get_vehicles(mocked_responses, "zoe_40.1.json") result = cli_runner.invoke(__main__.main, f"--account {TEST_ACCOUNT_ID} vehicles") assert result.exit_code == 0, result.exception expected_output = ("Registration Brand Model VIN\n" "-------------- ------- ------- -----------------\n" "REG-NUMBER RENAULT ZOE VF1AAAAA555777999\n") assert expected_output == result.output
def test_vehicle_status(mocked_responses: aioresponses, cli_runner: CliRunner, filename: str) -> None: """It exits with a status code of zero.""" filename = os.path.basename(filename) credential_store = FileCredentialStore(os.path.expanduser(CREDENTIAL_PATH)) credential_store[CONF_LOCALE] = Credential(TEST_LOCALE) credential_store[CONF_ACCOUNT_ID] = Credential(TEST_ACCOUNT_ID) credential_store[CONF_VIN] = Credential(TEST_VIN) credential_store[GIGYA_LOGIN_TOKEN] = Credential(TEST_LOGIN_TOKEN) credential_store[GIGYA_PERSON_ID] = Credential(TEST_PERSON_ID) credential_store[GIGYA_JWT] = JWTCredential(fixtures.get_jwt()) fixtures.inject_get_vehicle_details(mocked_responses, filename) fixtures.inject_get_vehicle_contracts(mocked_responses, "fr_FR.2.json") fixtures.inject_vehicle_status(mocked_responses) result = cli_runner.invoke(__main__.main, "status") assert result.exit_code == 0, result.exception assert EXPECTED_STATUS[filename] == result.output
def test_vehicle_contracts(mocked_responses: aioresponses, cli_runner: CliRunner) -> None: """It exits with a status code of zero.""" credential_store = FileCredentialStore(os.path.expanduser(CREDENTIAL_PATH)) credential_store[CONF_LOCALE] = Credential(TEST_LOCALE) credential_store[CONF_ACCOUNT_ID] = Credential(TEST_ACCOUNT_ID) credential_store[CONF_VIN] = Credential(TEST_VIN) credential_store[GIGYA_LOGIN_TOKEN] = Credential(TEST_LOGIN_TOKEN) credential_store[GIGYA_PERSON_ID] = Credential(TEST_PERSON_ID) credential_store[GIGYA_JWT] = JWTCredential(fixtures.get_jwt()) fixtures.inject_get_vehicle_contracts(mocked_responses, "fr_FR.1.json") result = cli_runner.invoke(__main__.main, "contracts") assert result.exit_code == 0, result.exception expected_output = ( "Type Code " "Description Start End Status\n" "------------------------------ -------------------- " "-------------------------------- ---------- ---------- " "------------------\n" "WARRANTY_MAINTENANCE_CONTRACTS 40 " "CONTRAT LOSANGE 2018-04-04 2022-04-03 Actif\n" "CONNECTED_SERVICES ZECONNECTP " "My Z.E. Connect en série 36 mois 2018-08-23 2021-08-23 Actif\n" "CONNECTED_SERVICES GBA " "Battery Services 2018-03-23 " "Echec d’activation\n" "WARRANTY ManufacturerWarranty " "Garantie fabricant 2020-04-03 Expiré\n" "WARRANTY PaintingWarranty " "Garantie peinture 2021-04-03 Actif\n" "WARRANTY CorrosionWarranty " "Garantie corrosion 2030-04-03 Actif\n" "WARRANTY GMPeWarranty " "Garantie GMPe 2020-04-03 Expiré\n" "WARRANTY AssistanceWarranty " "Garantie assistance 2020-04-03 Expiré\n") assert expected_output == result.output
def test_list_accounts_no_prompt( mocked_responses: aioresponses, cli_runner: CliRunner ) -> None: """It exits with a status code of zero.""" credential_store = FileCredentialStore(os.path.expanduser(CREDENTIAL_PATH)) credential_store[CONF_LOCALE] = Credential(TEST_LOCALE) credential_store[GIGYA_LOGIN_TOKEN] = Credential(TEST_LOGIN_TOKEN) credential_store[GIGYA_PERSON_ID] = Credential(TEST_PERSON_ID) credential_store[GIGYA_JWT] = JWTCredential(fixtures.get_jwt()) fixtures.inject_get_person(mocked_responses) result = cli_runner.invoke(__main__.main, "accounts") assert result.exit_code == 0, result.exception expected_output = ( "Type ID\n" "--------- ------------\n" "MYRENAULT account-id-1\n" "SFDC account-id-2\n" ) assert expected_output == result.output