diff --git a/pizzapi/address.py b/pizzapi/address.py index 6785cec..910b2d0 100755 --- a/pizzapi/address.py +++ b/pizzapi/address.py @@ -45,8 +45,22 @@ def nearby_stores(self, service='Delivery'): nearby_stores will filter the information we receive from the API to exclude stores that are not currently online (!['IsOnlineNow']), and stores that are not currently in service (!['ServiceIsOpen']). + + (city and region) or (postalcode) is required to get a result from + the API. This is enforced in the tests, but not in these methods, + since the API might change in the future. """ - data = request_json(self.urls.find_url(), line1=self.line1, line2=self.line2, type=service) + data = request_json( + self.urls.find_url(), + line1=self.line1, + line2=self.line2, + type=service + ) + + if data['Status'] == -1: + # This is an error from the Domino's API. + raise Exception(data['StatusItems']) + return [Store(x, self.country) for x in data['Stores'] if x['IsOnlineNow'] and x['ServiceIsOpen'][service]] diff --git a/tests/fixtures/stores_failure.json b/tests/fixtures/stores_failure.json new file mode 100644 index 0000000..fa8ae94 --- /dev/null +++ b/tests/fixtures/stores_failure.json @@ -0,0 +1 @@ +{"Status": -1, "StatusItems": [{"Code": "MissingCityRegionOrPostalCode"}], "Address": {"City": "", "Region": "MN", "UnitType": "", "UnitNumber": "", "StreetNumber": "", "PostalCode": "", "StreetName": "", "Street": ""}, "Stores": [], "Granularity": "Unknown"} diff --git a/tests/test_address.py b/tests/test_address.py index 5b44690..948f81a 100644 --- a/tests/test_address.py +++ b/tests/test_address.py @@ -9,31 +9,84 @@ from pizzapi.urls import Urls, COUNTRY_USA -fixture_path = os.path.join('tests', 'fixtures', 'stores.json') -with open(fixture_path) as fp: +# TODO: Is there a cleaner way to load fixtures? +store_fixture_path = os.path.join('tests', 'fixtures', 'stores.json') +with open(store_fixture_path) as fp: stores_fixture = json.load(fp) +failure_fixture_path = os.path.join('tests', 'fixtures', 'stores_failure.json') +with open(failure_fixture_path) as fp: + failure_fixture = json.load(fp) + address_params = mark.parametrize( argnames=('street', 'city', 'region', 'zip'), argvalues=[ ('700 Pennsylvania Avenue NW', 'Washington', 'DC', '20408'), ('700 Pennsylvania Avenue NW ', ' Washington ', ' DC ', ' 20408 '), - ('700 Pennsylvania Avenue NW', 'Washington', 'DC', 20408) + ('700 Pennsylvania Avenue NW', 'Washington', 'DC', 20408), ] ) +# TODO: Does pytest offer a combinatorics plugin? This is messy. +missing_address_params = mark.parametrize( + argnames=('street', 'city', 'region', 'zip'), + argvalues=[ + # All values are present, but commented ones should pass. + # AKA, anything with a ZIP, or with enough info to get stores. + ('', '', '', ''), + ('700 Pennsylvania Avenue NW', '', '', ''), + ('', 'Washington', '', ''), + ('', '', 'DC', ''), + # ('', '', '', '20408'), + ('700 Pennsylvania Avenue NW', 'Washington', '', ''), + ('700 Pennsylvania Avenue NW', '', 'DC', ''), + # ('700 Pennsylvania Avenue NW', '', '', '20408'), + # ('', 'Washington', 'DC', ''), + # ('', 'Washington', '', '20408'), + # ('', '', 'DC', '20408'), + # ('', 'Washington', 'DC', '20408'), + # ('700 Pennsylvania Avenue NW', '', 'DC', '20408'), + # ('700 Pennsylvania Avenue NW', 'Washington', '', '20408'), + # ('700 Pennsylvania Avenue NW', 'Washington', 'DC', ''), + # ('700 Pennsylvania Avenue NW', 'Washington', 'DC', '20408'), + ] +) def mocked_request_json(url, **kwargs): - - assert_that(url, equal_to(Urls(COUNTRY_USA).find_url())) - assert_that(kwargs, has_entries( - line1='700 Pennsylvania Avenue NW', - line2='Washington, DC, 20408', - type='Delivery' - )) - return stores_fixture - + # We have to have the API rejection logic in here, since we're not + # actually going to query the API. Determining whether or not the + # API would reject a paramter set was an experiment, and may not + # reflect the current state of the API. + # This would be sweet to automate - programmatically determine the + # behavior of a foreign API, and reflect that in test fixtures. + + # This mock isn't great, has built-in assumptions about kwargs. + street_address = str(kwargs['line1']) + city = str(kwargs['line2'].split(',')[0]) + region = str(kwargs['line2'].split(',')[1]) + postalcode = str(kwargs['line2'].split(',')[2]) + + print(street_address, city, region, postalcode) + # return stores_fixture + + # if city and region are present, pass no matter what + if (len(city) > 2) and (len(region) > 2): + return stores_fixture + + # if ZIP is present, pass + if len(postalcode) > 3: + return stores_fixture + + # if street address, only pass if city and region are present + if (len(street_address) > 2): + if (len(city) > 2) and (len(region) > 2): + return stores_fixture + # or if zip is present + elif len(postalcode) > 3: + return stores_fixture + else: + return failure_fixture @address_params def test_address_init(street, city, region, zip): @@ -111,6 +164,11 @@ def test_address_nearby_stores(mocked, street, city, region, zip): assert_that(stores, has_length(12)) assert_that([x.data for x in stores], equal_to(stores_fixture['Stores'])) +@missing_address_params +@patch('pizzapi.address.request_json', side_effect=mocked_request_json) +def test_address_nearby_stores_failure(mocked, street, city, region, zip): + address = Address(street, city, region, zip) + assert_that(calling(address.nearby_stores), raises(Exception)) # print 'Creating Order...' # order = Order(store, customer)