diff --git a/.gitignore b/.gitignore index b8c6d657..980ae2ce 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ venv *.log *.log.* .env +.pytest_cache \ No newline at end of file diff --git a/README.adoc b/README.adoc index 37137e1d..a8a74271 100644 --- a/README.adoc +++ b/README.adoc @@ -43,6 +43,9 @@ For more install options type: Python 3.6 or above is required. +== Running unit tests + +`$ pytest` == External resources diff --git a/agrirouter/clients/__init__.py b/agrirouter/clients/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/agrirouter/clients/clients.py b/agrirouter/clients/clients.py deleted file mode 100644 index f42483ae..00000000 --- a/agrirouter/clients/clients.py +++ /dev/null @@ -1,29 +0,0 @@ -from agrirouter.environments.environments import ProductionEnvironment, QAEnvironment - - -class InvalidEnvironmentSetup(Exception): - def __init__(self, message=None, env=None): - if not message: - message = "Invalid value of env parameter. [QA] or [Production] values are allowed" - self.message = message - self.env = env - - -class ARClient: - - def __init__(self, env): - self._set_env(env) - - def authenticate(self): - auth_link = self._create_auth_link() - - def _create_auth_link(self): - return "" - - def _set_env(self, env): - if env == "QA": - self._environment = QAEnvironment - if env == "Production": - return ProductionEnvironment - else: - raise InvalidEnvironmentSetup(env=env) diff --git a/conftest.py b/conftest.py new file mode 100644 index 00000000..c36194f0 --- /dev/null +++ b/conftest.py @@ -0,0 +1,13 @@ +import pytest +from tests.constants import public_key, private_key, auth_result_url + + +@pytest.fixture(scope="session") +def authorization(): + from agrirouter.auth.auth import Authorization + + auth_client = Authorization("QA", public_key=public_key, private_key=private_key) + auth_response = auth_client.extract_auth_response(auth_result_url) + auth_client.verify_auth_response(auth_response) + auth_data = auth_response.get_auth_result() + return auth_data diff --git a/requirements.txt b/requirements.txt index 458446b3..9cd51d4f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,7 @@ protobuf==3.18.0 pycparser==2.20 requests==2.26.0 urllib3==1.26.7 +pytest==6.2.5 +black==21.9b0 +flake8==3.9.2 +pyflakes==2.3.1 diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/auth_test/test_response.py b/tests/auth_test/test_response.py new file mode 100644 index 00000000..75d0f679 --- /dev/null +++ b/tests/auth_test/test_response.py @@ -0,0 +1,22 @@ +"""Tests agrirouter/auth/response.py""" + +import re +from agrirouter.auth.response import AuthResponse + + +def test_decode_token(): + token = ( + "eyJhY2NvdW50IjoiMGJhMjRlZWUtYzMwYi00N2U1LWJkYzktNzcwM" + "2NmYjEzNmEwIiwicmVnY29kZSI6IjhlYWNiMTk4ZmMiLCJleHBpcm" + "VzIjoiMjAyMS0wOS0yM1QxNjowODo0My44ODhaIn0=" + ) + decoded_token = AuthResponse.decode_token(token) + assert isinstance(decoded_token["account"], str) + assert isinstance(decoded_token["expires"], str) + assert re.search(r"[\w]", decoded_token["regcode"]) + assert re.search(r"[\w]", decoded_token["account"]) + + +def test_get_auth_result(authorization): + assert isinstance(AuthResponse(authorization).get_auth_result(), dict) + assert AuthResponse(authorization).get_auth_result()["credentials"] diff --git a/tests/constants.py b/tests/constants.py new file mode 100644 index 00000000..c07044eb --- /dev/null +++ b/tests/constants.py @@ -0,0 +1,60 @@ +application_id = "8c947a45-c57d-42d2-affc-206e21d63a50" +ENV = "QA" +auth_result_url = ( + "http://fuf.me/?state=46c81f94-d117-4658-9a38-a85692448219&token=eyJhY2NvdW50IjoiMGJhMjRlZWUtYzMwY" + "i00N2U1LWJkYzktNzcwM2NmYjEzNmEwIiwicmVnY29kZSI6IjhlYWNiMTk4ZmMiLCJleHBpcmVzIjoiMjAyMS0wOS0yM1QxNj" + "owODo0My44ODhaIn0%3D&signature=SUL9SQMWAfG4%2FEyT0rejkRfAyioxJIOs4sxI5wxeB8TkIiv0MR6YFKw1tPIkM4ll" + "uZKHEIgr5WvM3b3SvII9TtEbzZf995R8GIlNP6yyP51TF%2F4vZMbkMjq%2B2g1o0qw%2FyuDQcGz1RpOJWCuBOjMXu9quzGO" + "8xvDW7LjrN%2BMA9rzJZYb1toNf51O0eO4BDWL5L1oLvrKrqvaErKcIoRJtTVJ51awOWMARDkGZahcRdWrZbdGUbQwIyKJQu4" + "vH8%2B4ytlyXPSWEYwKE2VFoAjhzWsKODdRRxDbNNLWsW8sxKamdXjSOC8inHUFsFNoxLbwZEnKROm2s3OfKGYuibXOpXw%3D%3D" +) +private_key = ( + "-----BEGIN PRIVATE KEY-----\n" + "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC8WVUWBhEiQYvo\n" + "DL9q/Z5LbIhqDtcdFYWBUV7A96AXJaNRA9J7m3a6es05S7pRynv9yT8i+bhz/qDf\n" + "18MPOaqLglTw58ylVtTGmIlIZr85KJecO5aQnKN1pz8LyKnQSk4IWMBZ0T6mcaEO\n" + "fLVcDCmLi3T9a07xT4g5i2PGnLI6nd1pf3sLuKEzUjp455xU3oJrP0HfwSc+DXZQ\n" + "YDk2Rk6mfPgEczBhRmqDFp44+WHgyq4CcXl92M5XdOSYVaRs/W6fcEmRTqjBxp1u\n" + "M3kNAIaOC4XNfxVV8kSCfZW0gVtuGqxGK+80OZay3Vc1nQZGm+IUVBHKbPVauhXS\n" + "UH0/28qbAgMBAAECggEANVX8vMBaEL/L/RnDCOqp7UTeOl5adx91j2G5+d4FhRiA\n" + "73usGpmzHOqSe/OgXvH+e6cGDIL3w00rREgGsiSL0XbGU/PoJTf6CAUA9zI1W1vN\n" + "1w2evPPGbBZAybb4s4WfJEjxq12QJrUNvRr+hoLhLuV+axb8o2P4uQbqab9Mz0ER\n" + "lczCbHi4VDs1fwmNR3o47T1J4Qffzv1nMlor3pSrDzRDebic7/DC5JFkYZNGUtHk\n" + "jKDF5Uv7Vzxgb4Of+i3JA5mRMqvG33pdenvvetwl9X69WOiC29bVlymSHyybBE4A\n" + "ItfCAHIiY3nUL7UqzoIXpsyPs3ftkiy3Hn7isVSpLQKBgQDjadkGlqIgXCKZ8RS6\n" + "a4iLTTTlh8Ur+vMrejBLPul1oxz2dRWZy8zykfNN2MPz7q2xT8wXGuxgj+jei/fi\n" + "Gk08+UudMhV5Dtshb3fFq0NFCBe1ZUEX/wAcKC4Ed9xuuHpe7HOKAG0AsnzS8MPC\n" + "lcMiL1/vz0GuRbsiyMY6hXweZQKBgQDUBmQNqOBWDTQkO/8MFHopo6Ju9iNvZ4fC\n" + "u4SWqL+5BO3nnQHAQyslsj8FNilqhgMI+zaFFbZMZPv5opBSaAR0CQanKxMe3c9I\n" + "XYkAJH2+M0fpp80LtxwShD411UDhIypzumfKe8vUXRW/8TWfl6VidfEVjxw6Rc2D\n" + "g9btI4k0/wKBgQC42plnGZq/4yTdLXJD9pUPZrrQuQQ1M8/mT3RiNclfri8kxxe/\n" + "5EG8C5dSeBkQd7sInmyve1sZQuFvxSbBy89s+NfV95gsxz6odwtMymHsAyACe0Pm\n" + "VYmpWZ/OUgAEoEAYWOuyCZaRMoT0knEOAt6TMx8wt7AUEOqE497+QvMZYQKBgQC6\n" + "ARlJenvEQjUaDKBFYrmBShK4MasIktThG0zINyZrFE35wR3GI6b4nRT4Z3mSABst\n" + "h+Vef5u8DWOYrurZwHMXsMtrYDiX/ZNZMuV7gIfnkmlmLFWQD4XLIMTKyVjvqcAW\n" + "YtOnKU+58CeiieO3LHxkkn97oF7tKEuRMtock+5M1QKBgC2fquqxXMrBEIoMGCZs\n" + "ooU5V9gOjFVKC52VWnTNgmOWTqgZuqxPJtCTN5wPvhOSggQuHPwBHa9ioshJ0dGE\n" + "6jdxGaJjAc82q2KZu9VEqoH/Xa2aS8dPEHwfJtzUVTia6WkrFtMFNaDMFd6byWDQ\n" + "ai+T4i2J3/SDL0BfsFWdQuje\n" + "-----END PRIVATE KEY-----" +) + +public_key = ( + "-----BEGIN PUBLIC KEY-----\n" + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvFlVFgYRIkGL6Ay/av2e\n" + "S2yIag7XHRWFgVFewPegFyWjUQPSe5t2unrNOUu6Ucp7/ck/Ivm4c/6g39fDDzmq\n" + "i4JU8OfMpVbUxpiJSGa/OSiXnDuWkJyjdac/C8ip0EpOCFjAWdE+pnGhDny1XAwp\n" + "i4t0/WtO8U+IOYtjxpyyOp3daX97C7ihM1I6eOecVN6Caz9B38EnPg12UGA5NkZO\n" + "pnz4BHMwYUZqgxaeOPlh4MquAnF5fdjOV3TkmFWkbP1un3BJkU6owcadbjN5DQCG\n" + "jguFzX8VVfJEgn2VtIFbbhqsRivvNDmWst1XNZ0GRpviFFQRymz1WroV0lB9P9vK\n" + "mwIDAQAB\n" + "-----END PUBLIC KEY-----" +) + +AR_PUBLIC_KEY = ( + "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy8xF9661acn+iS+QS+9Y\n3HvTfUV" + "cismzbuvxHgHA7YeoOUFxyj3lkaTnXm7hzQe4wDEDgwpJSGAzxIIYSUXe\n8EsWLorg5O0tRexx5SP3+kj1i83DATBJCXP7k+bAF4" + "u2FVJphC1m2BfLxelGLjzx\nVAS/v6+EwvYaT1AI9FFqW/a2o92IsVPOh9oM9eds3lBOAbH/8XrmVIeHofw+XbTH\n1/7MLD6IE2+" + "HbEeY0F96nioXArdQWXcjUQsTch+p0p9eqh23Ak4ef5oGcZhNd4yp\nY8M6ppvIMiXkgWSPJevCJjhxRJRmndY+ajYGx7CLePx7wN" + "vxXWtkng3yh+7WiZ/Y\nqwIDAQAB\n-----END PUBLIC KEY-----" +) diff --git a/tests/enviroments_test/test_environmental_services.py b/tests/enviroments_test/test_environmental_services.py new file mode 100644 index 00000000..611e3172 --- /dev/null +++ b/tests/enviroments_test/test_environmental_services.py @@ -0,0 +1,11 @@ +"""Test agrirouter/environments/environmental_services.py""" + +import pytest +from agrirouter.environments.exceptions import InvalidEnvironmentSetup +from agrirouter.environments.environmental_services import EnvironmentalService +from tests.constants import ENV + + +def test_arclient_set_env(): + with pytest.raises(InvalidEnvironmentSetup): + assert EnvironmentalService("WRONG")._set_env("WRONG") diff --git a/tests/enviroments_test/test_environments.py b/tests/enviroments_test/test_environments.py new file mode 100644 index 00000000..8619bdc4 --- /dev/null +++ b/tests/enviroments_test/test_environments.py @@ -0,0 +1,213 @@ +"""Test agrirouter/environments/environments.py""" + +import pytest +from agrirouter.environments.environments import ProductionEnvironment, QAEnvironment +from tests.constants import application_id, auth_result_url + + +class TestProductionEnvironment: + def test_get_base_url(self): + assert ( + ProductionEnvironment().get_base_url() + == ProductionEnvironment._ENV_BASE_URL + ) + + def test_get_api_prefix(self): + assert ( + ProductionEnvironment().get_api_prefix() + == ProductionEnvironment._API_PREFIX + ) + + def test_get_registration_service_url(self): + assert ( + ProductionEnvironment().get_registration_service_url() + == ProductionEnvironment._REGISTRATION_SERVICE_URL + ) + + def test_get_onboard_url(self): + assert ( + ProductionEnvironment().get_onboard_url() + == ProductionEnvironment._REGISTRATION_SERVICE_URL + + ProductionEnvironment._API_PREFIX + + "/registration/onboard" + ) + + def test_get_secured_onboard_url(self): + assert ( + ProductionEnvironment().get_secured_onboard_url() + == ProductionEnvironment._REGISTRATION_SERVICE_URL + + ProductionEnvironment._API_PREFIX + + "/registration/onboard/request" + ) + + def test_get_verify_onboard_request_url(self): + assert ( + ProductionEnvironment().get_verify_onboard_request_url() + == ProductionEnvironment._REGISTRATION_SERVICE_URL + + ProductionEnvironment._API_PREFIX + + "/registration/onboard/verify" + ) + + def test_get_revoke_url(self): + assert ( + ProductionEnvironment().get_revoke_url() + == ProductionEnvironment._REGISTRATION_SERVICE_URL + + ProductionEnvironment._API_PREFIX + + "/registration/onboard/revoke" + ) + + def test_get_agrirouter_login_url(self): + assert ( + ProductionEnvironment().get_agrirouter_login_url() + == ProductionEnvironment._ENV_BASE_URL + + ProductionEnvironment._AGRIROUTER_LOGIN_URL + ) + + def test_get_secured_onboarding_authorization_url(self): + assert ProductionEnvironment().get_secured_onboarding_authorization_url( + application_id, str, "state", auth_result_url + ) == ProductionEnvironment._ENV_BASE_URL + ProductionEnvironment._SECURED_ONBOARDING_AUTHORIZATION_LINK_TEMPLATE.format( + application_id=application_id, + response_type=str, + state="state", + redirect_uri=auth_result_url, + ) + with pytest.raises(AssertionError): + assert ProductionEnvironment().get_secured_onboarding_authorization_url( + application_id, str, "state", auth_result_url + ) == ProductionEnvironment._ENV_BASE_URL + ProductionEnvironment._SECURED_ONBOARDING_AUTHORIZATION_LINK_TEMPLATE.format( + application_id=application_id, + response_type=str, + state="123", + redirect_uri=auth_result_url, + ) + with pytest.raises(AssertionError): + assert ProductionEnvironment().get_secured_onboarding_authorization_url( + application_id, dict, "state", auth_result_url + ) == ProductionEnvironment._ENV_BASE_URL + ProductionEnvironment._SECURED_ONBOARDING_AUTHORIZATION_LINK_TEMPLATE.format( + application_id=application_id, + response_type=str, + state="state", + redirect_uri=auth_result_url, + ) + + def test_get_mqtt_server_url(self): + assert ProductionEnvironment().get_mqtt_server_url( + "localhost", "5000" + ) == ProductionEnvironment._MQTT_URL_TEMPLATE.format( + host="localhost", port="5000" + ) + with pytest.raises(AssertionError): + assert ProductionEnvironment().get_mqtt_server_url( + "localhost", "5000" + ) == ProductionEnvironment._MQTT_URL_TEMPLATE.format( + host="127.0.0.1", port="5000" + ) + with pytest.raises(AssertionError): + assert ProductionEnvironment().get_mqtt_server_url( + "localhost", "5000" + ) == ProductionEnvironment._MQTT_URL_TEMPLATE.format( + host="localhost", port="80" + ) + + def test_get_env_public_key(self): + assert ( + ProductionEnvironment().get_env_public_key() + == ProductionEnvironment.AR_PUBLIC_KEY + ) + + +class TestQAEnvironment: + def test_get_base_url(self): + assert QAEnvironment().get_base_url() == QAEnvironment._ENV_BASE_URL + + def test_get_api_prefix(self): + assert QAEnvironment().get_api_prefix() == QAEnvironment._API_PREFIX + + def test_get_registration_service_url(self): + assert ( + QAEnvironment().get_registration_service_url() + == QAEnvironment._REGISTRATION_SERVICE_URL + ) + + def test_get_onboard_url(self): + assert ( + QAEnvironment().get_onboard_url() + == QAEnvironment._REGISTRATION_SERVICE_URL + + QAEnvironment._API_PREFIX + + "/registration/onboard" + ) + + def test_get_secured_onboard_url(self): + assert ( + QAEnvironment().get_secured_onboard_url() + == QAEnvironment._REGISTRATION_SERVICE_URL + + QAEnvironment._API_PREFIX + + "/registration/onboard/request" + ) + + def test_get_verify_onboard_request_url(self): + assert ( + QAEnvironment().get_verify_onboard_request_url() + == QAEnvironment._REGISTRATION_SERVICE_URL + + QAEnvironment._API_PREFIX + + "/registration/onboard/verify" + ) + + def test_get_revoke_url(self): + assert ( + QAEnvironment().get_revoke_url() + == QAEnvironment._REGISTRATION_SERVICE_URL + + QAEnvironment._API_PREFIX + + "/registration/onboard/revoke" + ) + + def test_get_agrirouter_login_url(self): + assert ( + QAEnvironment().get_agrirouter_login_url() + == QAEnvironment._ENV_BASE_URL + QAEnvironment._AGRIROUTER_LOGIN_URL + ) + + def test_get_secured_onboarding_authorization_url(self): + assert QAEnvironment().get_secured_onboarding_authorization_url( + application_id, str, "state", auth_result_url + ) == QAEnvironment._ENV_BASE_URL + QAEnvironment._SECURED_ONBOARDING_AUTHORIZATION_LINK_TEMPLATE.format( + application_id=application_id, + response_type=str, + state="state", + redirect_uri=auth_result_url, + ) + with pytest.raises(AssertionError): + assert QAEnvironment().get_secured_onboarding_authorization_url( + application_id, str, "state", auth_result_url + ) == QAEnvironment._ENV_BASE_URL + QAEnvironment._SECURED_ONBOARDING_AUTHORIZATION_LINK_TEMPLATE.format( + application_id=application_id, + response_type=str, + state="123", + redirect_uri=auth_result_url, + ) + with pytest.raises(AssertionError): + assert QAEnvironment().get_secured_onboarding_authorization_url( + application_id, dict, "state", auth_result_url + ) == QAEnvironment._ENV_BASE_URL + QAEnvironment._SECURED_ONBOARDING_AUTHORIZATION_LINK_TEMPLATE.format( + application_id=application_id, + response_type=str, + state="state", + redirect_uri=auth_result_url, + ) + + def test_get_mqtt_server_url(self): + assert QAEnvironment().get_mqtt_server_url( + "localhost", "5000" + ) == QAEnvironment._MQTT_URL_TEMPLATE.format(host="localhost", port="5000") + with pytest.raises(AssertionError): + assert QAEnvironment().get_mqtt_server_url( + "localhost", "5000" + ) == QAEnvironment._MQTT_URL_TEMPLATE.format(host="127.0.0.1", port="5000") + with pytest.raises(AssertionError): + assert QAEnvironment().get_mqtt_server_url( + "localhost", "5000" + ) == QAEnvironment._MQTT_URL_TEMPLATE.format(host="localhost", port="80") + + def test_get_env_public_key(self): + assert QAEnvironment().get_env_public_key() == QAEnvironment.AR_PUBLIC_KEY diff --git a/tests/messaging_test/test_request.py b/tests/messaging_test/test_request.py new file mode 100644 index 00000000..5b978ec6 --- /dev/null +++ b/tests/messaging_test/test_request.py @@ -0,0 +1,15 @@ +"""Test agrirouter/messaging/request.py""" + +from agrirouter.messaging.messages import Message +from agrirouter.messaging.request import MessageRequest + + +def test_json_serialize(): + message_request = MessageRequest( + sensor_alternate_id="1", + capability_alternate_id="1", + messages=[Message(content="content")], + ).json_serialize() + assert isinstance(message_request, dict) + assert message_request["capabilityAlternateId"] == "1" + assert message_request["sensorAlternateId"] == "1" diff --git a/tests/onboarding_test/test_headers.py b/tests/onboarding_test/test_headers.py new file mode 100644 index 00000000..4a412082 --- /dev/null +++ b/tests/onboarding_test/test_headers.py @@ -0,0 +1,23 @@ +"""Test agrirouter/onboarding/headers.py""" +from agrirouter.constants.media_types import ContentTypes +from agrirouter.onboarding.headers import SoftwareOnboardingHeader + + +class TestSoftwareOnboardingHeader: + reg_code = "1AC2cs21W" + test_object = SoftwareOnboardingHeader(reg_code=reg_code, application_id=1) + test_object_1 = SoftwareOnboardingHeader( + reg_code=reg_code, application_id=1, content_type="json" + ) + + def test_get_header(self): + assert isinstance(self.test_object.get_header(), dict) + assert ( + self.test_object.get_header()["Authorization"] == "Bearer " + self.reg_code + ) + assert ( + self.test_object.get_header()["Content-Type"] + == ContentTypes.APPLICATION_JSON.value + ) + + assert self.test_object_1.get_header()["Content-Type"] == "json" diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..2aae4364 --- /dev/null +++ b/tox.ini @@ -0,0 +1,16 @@ +[flake8] +ignore = D203 +exclude = + .git, + __pycache__, + .pytest_cache + agrirouter_sdk_python.egg-info, + assets, + old, + build, + dist, + venv, + conftest.py, + *_pb2.py +max-line-length = 120 +max-complexity = 10