diff --git a/.circleci/config.yml b/.circleci/config.yml index 365f9bb..887d776 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,7 +20,7 @@ jobs: name: 'Unit Tests' command: | source /usr/local/share/virtualenvs/tap-recharge/bin/activate - pip install nose coverage + pip install nose coverage parameterized nosetests --with-coverage --cover-erase --cover-package=tap_recharge --cover-html-dir=htmlcov tests/unittests coverage html - store_test_results: diff --git a/tap_recharge/schemas/addresses.json b/tap_recharge/schemas/addresses.json index 3880aac..a5ec9cc 100644 --- a/tap_recharge/schemas/addresses.json +++ b/tap_recharge/schemas/addresses.json @@ -145,6 +145,59 @@ }, "zip": { "type": ["null", "string"] + }, + "payment_method_id": { + "type": ["null", "integer"] + }, + "country_code": { + "type": ["null", "string"] + }, + "discounts": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": ["null", "integer"] + } + } + } + }, + { + "type": "null" + } + ] + }, + "order_attributes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] + }, + "order_note": { + "type": ["null", "string"] + }, + "presentment_currency": { + "type": ["null", "string"] } } } diff --git a/tap_recharge/schemas/charges.json b/tap_recharge/schemas/charges.json index 54c8ef0..bcdf8aa 100644 --- a/tap_recharge/schemas/charges.json +++ b/tap_recharge/schemas/charges.json @@ -38,6 +38,9 @@ }, "zip": { "type": ["null", "string"] + }, + "country_code": { + "type": ["null", "string"] } } }, @@ -132,6 +135,9 @@ }, "small": { "type": ["null", "string"] + }, + "sort_order": { + "type": ["null", "integer"] } } }, @@ -180,6 +186,76 @@ }, "variant_title": { "type": ["null", "string"] + }, + "purchase_item_id": { + "type": ["null", "integer"] + }, + "external_product_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "external_variant_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "handle": { + "type": ["null", "string"] + }, + "purchase_item_type": { + "type": ["null", "string"] + }, + "tax_due": { + "type": ["null", "string"] + }, + "tax_lines": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "price": { + "type": ["null", "string"] + }, + "rate": { + "type": ["null", "string"] + }, + "title": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] + }, + "taxable": { + "type": ["null", "boolean"] + }, + "taxable_amount": { + "type": ["null", "string"] + }, + "total_price": { + "type": ["null", "string"] + }, + "unit_price": { + "type": ["null", "string"] + }, + "unit_price_includes_tax": { + "type": ["null", "boolean"] } } } @@ -261,6 +337,9 @@ }, "zip": { "type": ["null", "string"] + }, + "country_code": { + "type": ["null", "string"] } } }, @@ -280,6 +359,37 @@ }, "title": { "type": ["null", "string"] + }, + "source": { + "type": ["null", "string"] + }, + "taxable": { + "type": ["null", "string"] + }, + "tax_lines": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "price": { + "type": ["null", "string"] + }, + "rate": { + "type": ["null", "string"] + }, + "title": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] } } } @@ -358,6 +468,160 @@ "updated_at": { "type": ["null", "string"], "format": "date-time" + }, + "analytics_data": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "utm_params": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "utm_campaign": { + "type": ["null", "string"] + }, + "utm_content": { + "type": ["null", "string"] + }, + "utm_data_source": { + "type": ["null", "string"] + }, + "utm_source": { + "type": ["null", "string"] + }, + "utm_medium": { + "type": ["null", "string"] + }, + "utm_term": { + "type": ["null", "string"] + }, + "utm_timestamp": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] + } + } + }, + "currency": { + "type": ["null", "string"] + }, + "customer": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "id": { + "type": ["null", "integer"] + }, + "email": { + "type": ["null", "string"] + }, + "external_customer_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "hash": { + "type": ["null", "string"] + } + } + }, + "discounts": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": ["null", "integer"] + }, + "code": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "number"] + }, + "value_type": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] + }, + "external_order_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "external_transaction_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "payment_processor": { + "type": ["null", "string"] + } + } + }, + "order_attributes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] + }, + "orders_count": { + "type": ["null", "integer"] + }, + "payment_processor": { + "type": ["null", "string"] + }, + "retry_date": { + "type": ["null", "string"], + "format": "date-time" + }, + "taxable": { + "type": ["null", "boolean"] + }, + "total_weight_grams": { + "type": ["null", "integer"] } } } diff --git a/tap_recharge/schemas/customers.json b/tap_recharge/schemas/customers.json index 4eb441e..01c40cf 100644 --- a/tap_recharge/schemas/customers.json +++ b/tap_recharge/schemas/customers.json @@ -82,6 +82,67 @@ "first_charge_processed_at": { "type": ["null", "string"], "format": "date-time" + }, + "analytics_data": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "utm_params": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "utm_campaign": { + "type": ["null", "string"] + }, + "utm_content": { + "type": ["null", "string"] + }, + "utm_data_source": { + "type": ["null", "string"] + }, + "utm_source": { + "type": ["null", "string"] + }, + "utm_medium": { + "type": ["null", "string"] + }, + "utm_term": { + "type": ["null", "string"] + }, + "utm_timestamp": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] + } + } + }, + "external_customer_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "has_payment_method_in_dunning": { + "type": ["null", "boolean"] + }, + "subscriptions_active_count": { + "type": ["null", "integer"] + }, + "subscriptions_total_count": { + "type": ["null", "integer"] } } } diff --git a/tap_recharge/schemas/discounts.json b/tap_recharge/schemas/discounts.json index e85f8d1..4cb3763 100644 --- a/tap_recharge/schemas/discounts.json +++ b/tap_recharge/schemas/discounts.json @@ -53,6 +53,106 @@ }, "once_per_customer": { "type": ["null", "boolean"] + }, + "applies_to": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ids": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "integer" + } + }, + { + "type": "null" + } + ] + }, + "purchase_item_type": { + "type": ["null", "string"] + }, + "resource": { + "type": ["null", "string"] + } + } + }, + "channel_settings": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "api": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "can_apply": { + "type": ["null", "boolean"] + } + } + }, + "customer_portal": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "can_apply": { + "type": ["null", "boolean"] + } + } + }, + "merchant_portal": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "can_apply": { + "type": ["null", "boolean"] + } + } + }, + "checkout_page": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "can_apply": { + "type": ["null", "boolean"] + } + } + } + } + }, + "external_discount_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "first_time_customer_restriction": { + "type": ["null", "boolean"] + }, + "prerequisite_subtotal_min": { + "type": ["null", "string"] + }, + "usage_limits": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "max_subsequent_redemptions": { + "type": ["null", "integer"] + }, + "first_time_customer_restriction": { + "type": ["null", "boolean"] + }, + "one_application_per_customer": { + "type": ["null", "string"] + } + } + }, + "value_type": { + "type": ["null", "string"] } } } diff --git a/tap_recharge/schemas/onetimes.json b/tap_recharge/schemas/onetimes.json index b0a3acd..13c967d 100644 --- a/tap_recharge/schemas/onetimes.json +++ b/tap_recharge/schemas/onetimes.json @@ -72,6 +72,27 @@ }, "variant_title": { "type": ["null", "string"] + }, + "external_product_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "external_variant_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "sku_override": { + "type": ["null", "boolean"] } } } diff --git a/tap_recharge/schemas/orders.json b/tap_recharge/schemas/orders.json index d7c60a9..5a5ec73 100644 --- a/tap_recharge/schemas/orders.json +++ b/tap_recharge/schemas/orders.json @@ -41,6 +41,9 @@ }, "zip": { "type": ["null", "string"] + }, + "country_code": { + "type": ["null", "string"] } } }, @@ -126,6 +129,9 @@ }, "small": { "type": ["null", "string"] + }, + "sort_order": { + "type": ["null", "integer"] } } }, @@ -175,6 +181,79 @@ }, "variant_title": { "type": ["null", "string"] + }, + "purchase_item_id": { + "type": ["null", "integer"] + }, + "external_product_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "external_variant_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "handle": { + "type": ["null", "string"] + }, + "sort_order": { + "type": ["null", "integer"] + }, + "purchase_item_type": { + "type": ["null", "string"] + }, + "tax_due": { + "type": ["null", "string"] + }, + "tax_lines": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "price": { + "type": ["null", "string"] + }, + "rate": { + "type": ["null", "string"] + }, + "title": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] + }, + "taxable": { + "type": ["null", "boolean"] + }, + "taxable_amount": { + "type": ["null", "string"] + }, + "total_price": { + "type": ["null", "string"] + }, + "unit_price": { + "type": ["null", "string"] + }, + "unit_price_includes_tax": { + "type": ["null", "boolean"] } } } @@ -257,6 +336,9 @@ }, "zip": { "type": ["null", "string"] + }, + "country_code": { + "type": ["null", "string"] } } }, @@ -280,6 +362,37 @@ }, "title": { "type": ["null", "string"] + }, + "source": { + "type": ["null", "string"] + }, + "taxable": { + "type": ["null", "string"] + }, + "tax_lines": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "price": { + "type": ["null", "string"] + }, + "rate": { + "type": ["null", "string"] + }, + "title": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] } } } @@ -329,6 +442,9 @@ }, "title": { "type": ["null", "string"] + }, + "rate": { + "type": ["null", "string"] } } } @@ -369,6 +485,140 @@ "updated_at": { "type": ["null", "string"], "format": "date-time" + }, + "charge": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "id": { + "type": ["null", "integer"] + }, + "external_transaction_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "payment_processor": { + "type": ["null", "string"] + } + } + } + } + }, + "client_details": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "browser_ip": { + "type": ["null", "string"] + }, + "user_agent": { + "type": ["null", "string"] + } + } + }, + "currency": { + "type": ["null", "string"] + }, + "customer": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "id": { + "type": ["null", "integer"] + }, + "email": { + "type": ["null", "string"] + }, + "external_customer_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "hash": { + "type": ["null", "string"] + } + } + }, + "discounts": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": ["null", "integer"] + }, + "code": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "number"] + }, + "value_type": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] + }, + "external_cart_token": { + "type": ["null", "string"] + }, + "external_order_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "external_order_number": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "order_attributes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] + }, + "taxable": { + "type": ["null", "boolean"] + }, + "total_weight_grams": { + "type": ["null", "integer"] } } } diff --git a/tap_recharge/schemas/subscriptions.json b/tap_recharge/schemas/subscriptions.json index 610429a..ee629e6 100644 --- a/tap_recharge/schemas/subscriptions.json +++ b/tap_recharge/schemas/subscriptions.json @@ -115,6 +115,73 @@ }, "variant_title": { "type": ["null", "string"] + }, + "analytics_data": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "utm_params": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "utm_campaign": { + "type": ["null", "string"] + }, + "utm_content": { + "type": ["null", "string"] + }, + "utm_data_source": { + "type": ["null", "string"] + }, + "utm_medium": { + "type": ["null", "string"] + }, + "utm_source": { + "type": ["null", "string"] + }, + "utm_term": { + "type": ["null", "string"] + }, + "utm_timestamp": { + "type": ["null", "string"] + } + } + } + }, + { + "type": "null" + } + ] + } + } + }, + "external_product_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "external_variant_id": { + "type": ["null", "object"], + "additionalProperties": false, + "properties": { + "ecommerce": { + "type": ["null", "string"] + } + } + }, + "is_prepaid": { + "type": ["null", "boolean"] + }, + "presentment_currency": { + "type": ["null", "string"] } } } diff --git a/tests/unittests/test_request_timeout.py b/tests/unittests/test_request_timeout.py index 5764e15..09b259f 100644 --- a/tests/unittests/test_request_timeout.py +++ b/tests/unittests/test_request_timeout.py @@ -2,6 +2,7 @@ import unittest from unittest import mock from requests.exceptions import Timeout, ConnectionError +from parameterized import parameterized class TestBackoffError(unittest.TestCase): ''' @@ -87,64 +88,35 @@ def json(self): class TestRequestTimeoutValue(unittest.TestCase): ''' - Test that request timeout parameter works properly in various cases + Test that the request timeout parameter works properly in various cases ''' - @mock.patch('tap_recharge.client.requests.Session.request', return_value = MockResponse("", status_code=200)) - @mock.patch('tap_recharge.client.RechargeClient.check_access_token') - def test_config_provided_request_timeout(self, mock_get, mock_request): - """ - Unit tests to ensure that request timeout is set based on config value - """ - config = {"access_token": "dummy_at", "user_agent": "dummy_ua", "request_timeout": 100} - client = RechargeClient(**config) - client.request("GET", "dummy_path") - - mock_request.assert_called_with('GET', 'https://api.rechargeapps.com/dummy_path', stream=True, timeout=100.0, headers={'X-Recharge-Access-Token': 'dummy_at', 'Accept': 'application/json', 'X-Recharge-Version': '2021-11', 'User-Agent': 'dummy_ua'}) + expected_URL = 'https://api.rechargeapps.com/dummy_path' + expected_headers = {'X-Recharge-Access-Token': 'dummy_at', 'Accept': 'application/json', 'X-Recharge-Version': '2021-11', 'User-Agent': 'dummy_ua'} + @parameterized.expand([ + ['default_timeout', None, 600], + ['integer_timeout', 100, 100], + ['empty_string_timeout', '', 600], + ['string_timeout', '100', 100], + ['float_timeout', 100.8, 100.8] + ]) + @mock.patch('time.sleep') @mock.patch('tap_recharge.client.requests.Session.request', return_value = MockResponse("", status_code=200)) @mock.patch('tap_recharge.client.RechargeClient.check_access_token') - def test_default_value_request_timeout(self, mock_get, mock_request): + def test_timeout_value(self, test_case_name, test_value, expected_value, mock_get, mock_request, mocked_sleep): """ - Unit tests to ensure that request timeout is set based default value + Unit tests to ensure that request timeout is set based on config value """ config = {"access_token": "dummy_at", "user_agent": "dummy_ua"} - client = RechargeClient(**config) - client.request("GET", "dummy_path") - - mock_request.assert_called_with('GET', 'https://api.rechargeapps.com/dummy_path', stream=True, timeout=600, headers={'X-Recharge-Access-Token': 'dummy_at', 'Accept': 'application/json', 'X-Recharge-Version': '2021-11', 'User-Agent': 'dummy_ua'}) - @mock.patch('tap_recharge.client.requests.Session.request', return_value = MockResponse("", status_code=200)) - @mock.patch('tap_recharge.client.RechargeClient.check_access_token') - def test_config_provided_empty_request_timeout(self, mock_get, mock_request): - """ - Unit tests to ensure that request timeout is set based on default value if empty value is given in config - """ - config = {"access_token": "dummy_at", "user_agent": "dummy_ua", "request_timeout": ""} - client = RechargeClient(**config) - client.request("GET", "dummy_path") - - mock_request.assert_called_with('GET', 'https://api.rechargeapps.com/dummy_path', stream=True, timeout=600.0, headers={'X-Recharge-Access-Token': 'dummy_at', 'Accept': 'application/json', 'X-Recharge-Version': '2021-11', 'User-Agent': 'dummy_ua'}) + # set timeout in the config + config["request_timeout"] = test_value - @mock.patch('tap_recharge.client.requests.Session.request', return_value = MockResponse("", status_code=200)) - @mock.patch('tap_recharge.client.RechargeClient.check_access_token') - def test_config_provided_string_request_timeout(self, mock_get, mock_request): - """ - Unit tests to ensure that request timeout is set based on config string value - """ - config = {"access_token": "dummy_at", "user_agent": "dummy_ua", "request_timeout": "100"} - client = RechargeClient(**config) - client.request("GET", "dummy_path") - - mock_request.assert_called_with('GET', 'https://api.rechargeapps.com/dummy_path', stream=True, timeout=100.0, headers={'X-Recharge-Access-Token': 'dummy_at', 'Accept': 'application/json', 'X-Recharge-Version': '2021-11', 'User-Agent': 'dummy_ua'}) + # Remove "request_timeout" form config, if the value to be passed is "None" + if not test_value: + config.pop("request_timeout") - @mock.patch('tap_recharge.client.requests.Session.request', return_value = MockResponse("", status_code=200)) - @mock.patch('tap_recharge.client.RechargeClient.check_access_token') - def test_config_provided_float_request_timeout(self, mock_get, mock_request): - """ - Unit tests to ensure that request timeout is set based on config float value - """ - config = {"access_token": "dummy_at", "user_agent": "dummy_ua", "request_timeout": 100.8} client = RechargeClient(**config) client.request("GET", "dummy_path") - - mock_request.assert_called_with('GET', 'https://api.rechargeapps.com/dummy_path', stream=True, timeout=100.8, headers={'X-Recharge-Access-Token': 'dummy_at', 'Accept': 'application/json', 'X-Recharge-Version': '2021-11', 'User-Agent': 'dummy_ua'}) + + mock_request.assert_called_with('GET', self.expected_URL, stream=True, timeout=expected_value, headers=self.expected_headers)