def test_sort_by_time_added(self): # create a tap for a second beer in between the two other_beer = BeerFactory() TapFactory( beer=other_beer, time_added=now() - relativedelta(hours=5, minutes=2), ) # create another beer on tap with no time added, so therefore it's now third_beer = TapFactory(beer=BeerFactory()).beer # create two taps for the first beer TapFactory(beer=self.beer, time_added=now() - relativedelta(hours=1)) TapFactory(beer=self.beer, time_added=now() - relativedelta(hours=16)) # 5 queries: # 1. count of results # 2. beers # 3. taps # 4. alt names # 5. prices with self.assertNumQueries(5): response = self.client.get(f'{self.url}?o=-most_recently_added') eq_(response.status_code, 200) # expected order is third_beer, self.beer, other_beer eq_(len(response.data['results']), 3, response.data) eq_(response.data['results'][0]['name'], third_beer.name, response.data) eq_(response.data['results'][1]['name'], self.beer.name, response.data) eq_(response.data['results'][2]['name'], other_beer.name, response.data)
def test_merge(self): manufacturer = ManufacturerFactory() new_time = UTC.localize(datetime.datetime(2018, 4, 3, 6, 2)) other_time = new_time + datetime.timedelta(days=30) beer1 = BeerFactory( manufacturer=manufacturer, untappd_url='http://localhost/123456', color_srm=None, time_first_seen=other_time, ) beer2 = BeerFactory( manufacturer=manufacturer, color_srm=55, stem_and_stein_pk=551, time_first_seen=new_time, ) tap = TapFactory(beer=beer2) beer1.merge_from(beer2) self.assertEqual(beer1.color_srm, beer2.color_srm) tap.refresh_from_db() self.assertEqual(tap.beer, beer1) self.assertFalse(Beer.objects.filter(id=beer2.id).exists()) self.assertTrue( BeerAlternateName.objects.filter( name=beer2.name, beer=beer1, ).exists()) self.assertEqual(tap.beer.time_first_seen, new_time) self.assertEqual(tap.beer.stem_and_stein_pk, 551)
def test_on_tap_no_dupes(self): # create two taps for the beer TapFactory(beer=self.beer) TapFactory(beer=self.beer) # create another beer that isn't on tap BeerFactory() response = self.client.get(f'{self.url}?on_tap=True') eq_(response.status_code, 200) eq_(len(response.data['results']), 1, response.data) eq_(response.data['results'][0]['name'], self.beer.name, response.data)
def test_on_tap_no_dupes(self): # create two taps for the beer TapFactory(beer=self.beer) TapFactory(beer=self.beer) # create another beer that isn't on tap BeerFactory() response = self.client.get(f"{self.url}?on_tap=True") self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data["results"]), 1, response.data) self.assertEqual(response.data["results"][0]["name"], self.beer.name, response.data)
def test_filter_by_venue_slug(self): wanted_venue = VenueFactory(slug="slug-1") other_venue = VenueFactory(slug="not-this") mfg = ManufacturerFactory() style = StyleFactory() beers = Beer.objects.bulk_create( BeerFactory.build(style=style, manufacturer=mfg) for _ in range(3)) # set up 3 beers on tap, two at the one we want to look for, one at # the other Tap.objects.bulk_create( TapFactory.build(beer=beer, venue=venue) for beer, venue in zip( beers, [wanted_venue, wanted_venue, other_venue], )) url = f"{self.url}?taps__venue__slug__icontains=SLUG&on_tap=True" with self.assertNumQueries(5): # 1. count # 2. beer + style # 3. style alt names # 4. prices # 5. taps response = self.client.get(url) self.assertEqual(response.status_code, 200, response.data) self.assertEqual(len(response.data["results"]), 2, json.dumps(response.data, indent=2)) self.assertEqual( set(i["id"] for i in response.data["results"]), set(i.id for i in beers[:-1]), )
def test_sort_abv_descending(self): venue = VenueFactory() mfg = ManufacturerFactory() style = StyleFactory() beers = Beer.objects.bulk_create([ BeerFactory.build(manufacturer=mfg, abv=None, style=style), BeerFactory.build(manufacturer=mfg, abv=Decimal("3.2"), style=style), ]) Tap.objects.bulk_create( TapFactory.build(beer=beer, venue=venue) for beer in beers) url = f"{self.url}?o=-abv&on_tap=True" with self.assertNumQueries(5): # 1. count # 2. beer + style # 3. style alt names # 4. prices # 5. taps response = self.client.get(url) self.assertEqual(response.status_code, 200, response.data) self.assertEqual(len(response.data["results"]), 2, json.dumps(response.data, indent=2)) self.assertEqual( list(i["id"] for i in response.data["results"]), [i.id for i in reversed(beers)], )
def test_beers(self): tap = TapFactory(venue=self.venue, beer=BeerFactory()) BeerFactory() url = f"{self.url}beers/" response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(len(response.data["results"]), 1, response.data) self.assertEqual(response.data["results"][0]["id"], tap.beer_id)
def test_beers(self): tap = TapFactory(venue=self.venue, beer=BeerFactory()) BeerFactory() url = f'{self.url}beers/' response = self.client.get(url) eq_(response.status_code, status.HTTP_200_OK, response.data) eq_(len(response.data['results']), 1, response.data) eq_(response.data['results'][0]['id'], tap.beer_id)
def test_venues_at(self): # two where it's attached and one where it isn't taps = [ TapFactory(beer=self.beer), TapFactory(beer=self.beer), TapFactory(), ] url = f'{self.url}placesavailable/' response = self.client.get(url) eq_(response.status_code, 200) eq_(len(response.data['results']), 2, response.data) venues = [i.venue for i in taps if i.beer == self.beer] eq_( {i.name for i in venues}, {i['name'] for i in response.data['results']}, response.data, )
def test_venues_at(self): # two where it's attached and one where it isn't taps = [ TapFactory(beer=self.beer), TapFactory(beer=self.beer), TapFactory(), ] url = f"{self.url}placesavailable/" response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data["results"]), 2, response.data) venues = [i.venue for i in taps if i.beer == self.beer] self.assertEqual( {i.name for i in venues}, {i["name"] for i in response.data["results"]}, response.data, )
def test_filtering(self): beer = BeerFactory() venue = VenueFactory() TapFactory(venue=venue, beer=beer) url = f'{self.url}?taps__beer__name__istartswith={beer.name.lower()[:5]}' response = self.client.get(url) self.assertEqual(len(response.data['results']), 1) self.assertEqual(response.data['results'][0]['id'], venue.id, response.data) url = f'{self.url}?taps__beer__name={beer.name.lower()}aaaaa' response = self.client.get(url) self.assertEqual(len(response.data['results']), 0, response.data)
def test_single_beer_no_creds(self, mock_retry, mock_api): beer = BeerFactory() TapFactory(venue=self.venue, beer=beer) with self.settings( TWITTER_CONSUMER_KEY="", TWITTER_CONSUMER_SECRET="", TWITTER_ACCESS_TOKEN_KEY="", TWITTER_ACCESS_TOKEN_SECRET="", ): tweet_about_beers([beer.id]) # pylint: disable=no-value-for-parameter mock_retry.assert_not_called() mock_api.assert_not_called()
def test_styles(self): style = BeerStyleFactory() tap = TapFactory(venue=self.venue, beer=BeerFactory(style=style)) BeerStyleFactory() url = f'{self.url}styles/' response = self.client.get(url) eq_(response.status_code, status.HTTP_200_OK, response.data) eq_(len(response.data['results']), 1, response.data) eq_(response.data['results'][0]['id'], style.id) beers = response.data['results'][0]['beers'] eq_(len(beers), 1, beers) eq_(beers[0]['id'], tap.beer_id, beers[0])
def setUp(self): self.manufacturer = ManufacturerFactory() self.new_time = UTC.localize(datetime.datetime(2018, 4, 3, 6, 2)) self.other_time = self.new_time + datetime.timedelta(days=30) self.beer1 = BeerFactory( manufacturer=self.manufacturer, untappd_url="http://localhost/123456", color_srm=None, time_first_seen=self.other_time, ) self.beer2 = BeerFactory( manufacturer=self.manufacturer, color_srm=55, stem_and_stein_pk=551, time_first_seen=self.new_time, ) self.tap = TapFactory(beer=self.beer2) self.venue2 = self.tap.venue self.venue1 = VenueFactory() self.serving_size = ServingSize.objects.create(name="foo", volume_oz=12)
def test_single_beer_no_creds(self, mock_retry, mock_api): beer = BeerFactory() TapFactory(venue=self.venue, beer=beer) with self.settings( TWITTER_CONSUMER_KEY='', TWITTER_CONSUMER_SECRET='', TWITTER_ACCESS_TOKEN_KEY='', TWITTER_ACCESS_TOKEN_SECRET='', ): tweet_about_beers([beer.id]) mock_retry.assert_not_called() mock_api.assert_not_called()
def test_merge(self): manufacturer = ManufacturerFactory() beer1 = BeerFactory( manufacturer=manufacturer, untappd_url='http://localhost/123456', color_srm=None, ) beer2 = BeerFactory( manufacturer=manufacturer, color_srm=55, ) tap = TapFactory(beer=beer2) beer1.merge_from(beer2) self.assertEqual(beer1.color_srm, beer2.color_srm) tap.refresh_from_db() self.assertEqual(tap.beer, beer1) self.assertFalse(Beer.objects.filter(id=beer2.id).exists()) self.assertTrue( BeerAlternateName.objects.filter( name=beer2.name, beer=beer1, ).exists())
def test_filter_match(self): BeerFactory(name=f"aaaaaaa{self.beer.name[:10]}") tap = TapFactory(beer=self.beer) response = self.client.get( f"{self.url}?name__istartswith={self.beer.name[:5].lower()}") eq_(response.status_code, 200) eq_(len(response.data["results"]), 1, response.data) eq_(response.data["results"][0]["name"], self.beer.name, response.data) eq_( response.data["results"][0]["venues"][0]["id"], tap.venue.id, response.data, ) eq_(len(response.data["results"][0]["venues"]), 1, response.data)
def test_filter_match(self): BeerFactory(name=f'aaaaaaa{self.beer.name[:10]}') tap = TapFactory(beer=self.beer) response = self.client.get( f'{self.url}?name__istartswith={self.beer.name[:5].lower()}') eq_(response.status_code, 200) eq_(len(response.data['results']), 1, response.data) eq_(response.data['results'][0]['name'], self.beer.name, response.data) eq_( response.data['results'][0]['venues'][0]['id'], tap.venue.id, response.data, ) eq_(len(response.data['results'][0]['venues']), 1, response.data)
def test_single_beer_already_tweeted(self, mock_retry, mock_api): beer = BeerFactory(tweeted_about=True) TapFactory(venue=self.venue, beer=beer) with self.settings_context_manager(): tweet_about_beers([beer.id]) mock_retry.assert_not_called() mock_api.assert_called_once_with( consumer_key=self.consumer_key, consumer_secret=self.consumer_secret, access_token_key=self.api_key, access_token_secret=self.api_secret, ) mock_api.return_value.PostUpdate.assert_not_called() mock_api.return_value.PostUpdates.assert_not_called()
def test_compound_match(self): """Test that searching for part of the beer name and mfg name works""" query_string = f'{self.beer.name[:10]}+{self.beer.manufacturer.name[:5]}' tap = TapFactory(beer=self.beer) response = self.client.get( f'{self.url}?search={query_string.upper()}', ) eq_(response.status_code, 200) eq_(len(response.data['results']), 1, response.data) eq_(response.data['results'][0]['name'], self.beer.name, response.data) eq_( response.data['results'][0]['venues'][0]['id'], tap.venue.id, response.data, ) eq_(len(response.data['results'][0]['venues']), 1, response.data)
def test_sort_abv_descending(self): venue = VenueFactory() mfg = ManufacturerFactory() beers = Beer.objects.bulk_create([ BeerFactory.build(manufacturer=mfg, abv=None), BeerFactory.build(manufacturer=mfg, abv=Decimal('3.2')) ]) Tap.objects.bulk_create( TapFactory.build(beer=beer, venue=venue) for beer in beers) url = f'{self.url}?o=-abv&on_tap=True' with self.assertNumQueries(4): response = self.client.get(url) eq_(response.status_code, 200, response.data) eq_(len(response.data['results']), 2, json.dumps(response.data, indent=2)) eq_(list(i['id'] for i in response.data['results']), [i.id for i in reversed(beers)])
def test_compound_match(self): """Test that searching for part of the beer name and mfg name works""" query_string = f"{self.beer.name[:10]}+{self.beer.manufacturer.name[:5]}" tap = TapFactory(beer=self.beer) response = self.client.get( f"{self.url}?search={query_string.upper()}", ) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data["results"]), 1, response.data) self.assertEqual(response.data["results"][0]["name"], self.beer.name, response.data) self.assertEqual( response.data["results"][0]["venues"][0]["id"], tap.venue.id, response.data, ) self.assertEqual(len(response.data["results"][0]["venues"]), 1, response.data)
def setUpTestData(cls): super().setUpTestData() cls.venue = VenueFactory() cls.normal_user = UserFactory() cls.styles = Style.objects.bulk_create(StyleFactory.build_batch(50)) cls.manufacturer = ManufacturerFactory() cls.beers = Beer.objects.bulk_create( BeerFactory.build(style=style, manufacturer=cls.manufacturer) for style in cls.styles) cls.taps = Tap.objects.bulk_create( TapFactory.build( beer=beer, venue=cls.venue, tap_number=index, ) for index, beer in enumerate(cls.beers)) VenueTapManager.objects.create( user=cls.normal_user, venue=cls.venue, )
def test_single_beer(self, mock_retry, mock_api): beer = BeerFactory() TapFactory(venue=self.venue, beer=beer) with self.settings_context_manager(): tweet_about_beers([beer.id]) # pylint: disable=no-value-for-parameter mock_retry.assert_not_called() mock_api.assert_called_once_with( consumer_key=self.consumer_key, consumer_secret=self.consumer_secret, access_token_key=self.api_key, access_token_secret=self.api_secret, ) mock_api.return_value.PostUpdate.assert_called_once_with( SINGLE_BEER_TEMPLATE.format( beer.name, "@" + beer.manufacturer.twitter_handle, beer.style.name, self.venue.name, )) mock_api.return_value.PostUpdates.assert_not_called()
def test_filter_by_venue_slug(self): wanted_venue = VenueFactory(slug='slug-1') other_venue = VenueFactory(slug='not-this') mfg = ManufacturerFactory() beers = Beer.objects.bulk_create( BeerFactory.build(manufacturer=mfg) for dummy in range(3)) # set up 3 beers on tap, two at the one we want to look for, one at # the other Tap.objects.bulk_create( TapFactory.build(beer=beer, venue=venue) for beer, venue in zip( beers, [wanted_venue, wanted_venue, other_venue], )) url = f'{self.url}?taps__venue__slug__icontains=SLUG&on_tap=True' with self.assertNumQueries(4): response = self.client.get(url) eq_(response.status_code, 200, response.data) eq_(len(response.data['results']), 2, json.dumps(response.data, indent=2)) eq_(set(i['id'] for i in response.data['results']), set(i.id for i in beers[:-1]))
def setUp(self): manufacturer = ManufacturerFactory() venue = VenueFactory() style = StyleFactory() self.beers = Beer.objects.bulk_create( BeerFactory.build( manufacturer=manufacturer, style=style, ) for _ in range(20)) self.prices = BeerPrice.objects.bulk_create( BeerPrice( # pint serving_size_id=1, price=index * 2.1, beer=beer, venue=venue, ) for index, beer in enumerate(self.beers)) self.taps = Tap.objects.bulk_create( # only for half of them TapFactory.build(beer=beer, venue=venue) for beer in self.beers[:10])
def test_multi_beer_more_to_come(self, mock_retry, mock_api): mfg = ManufacturerFactory() beers = Beer.objects.bulk_create( BeerFactory.build(manufacturer=mfg, style=None) for dummy in range(20)) Tap.objects.bulk_create( TapFactory.build(venue=self.venue, beer=beer) for beer in beers) with self.settings_context_manager(): tweet_about_beers([i.id for i in beers]) # pylint: disable=no-value-for-parameter beers = beers[:10] mock_retry.assert_not_called() mock_api.assert_called_once_with( consumer_key=self.consumer_key, consumer_secret=self.consumer_secret, access_token_key=self.api_key, access_token_secret=self.api_secret, ) mock_api.return_value.PostUpdates.assert_called_once() mock_api.return_value.PostUpdate.assert_not_called() call_args = mock_api.return_value.PostUpdates.call_args self.assertEqual(call_args[1], {"continuation": "…", "threaded": True}) self.assertEqual(len(call_args[0]), 1) tweet = call_args[0][0] self.assertIn( MULTI_BEER_OUTER.format(len(beers), "(10 still to come!)").strip(), tweet, ) lines = tweet.splitlines() self.assertEqual(len(lines), 1 + len(beers)) for beer, line in zip(beers, lines[1:]): self.assertIn( MULTI_BEER_INNER.format( beer.name, "@" + beer.manufacturer.twitter_handle, "unknown", self.venue.name, ), line, )
def test_multi_beer(self, mock_retry, mock_api): mfg = ManufacturerFactory() beers = Beer.objects.bulk_create( BeerFactory.build(manufacturer=mfg, style=None) for dummy in range(10) ) Tap.objects.bulk_create( TapFactory.build(venue=self.venue, beer=beer) for beer in beers ) with self.settings_context_manager(): tweet_about_beers([i.id for i in beers]) mock_retry.assert_not_called() mock_api.assert_called_once_with( consumer_key=self.consumer_key, consumer_secret=self.consumer_secret, access_token_key=self.api_key, access_token_secret=self.api_secret, ) mock_api.return_value.PostUpdates.assert_called_once() mock_api.return_value.PostUpdate.assert_not_called() call_args = mock_api.return_value.PostUpdates.call_args self.assertEqual(call_args[1], {'continuation': '…', 'threaded': True}) self.assertEqual(len(call_args[0]), 1) tweet = call_args[0][0] self.assertIn( MULTI_BEER_OUTER.format(len(beers), '').strip(), tweet, ) lines = tweet.splitlines() self.assertEqual(len(lines), 1 + len(beers)) for beer, line in zip(beers, lines[1:]): self.assertIn(MULTI_BEER_INNER.format( beer.name, '@' + beer.manufacturer.twitter_handle, 'unknown', self.venue.name, ), line)
def setUpTestData(cls) -> None: cls.normal_user = UserFactory() cls.venue = VenueFactory() cls.existing_tap = TapFactory(venue=cls.venue) cls.manufacturers = Manufacturer.objects.bulk_create( ManufacturerFactory.build_batch(2))
class BeerTestCase(TestCase): def setUp(self): self.manufacturer = ManufacturerFactory() self.new_time = UTC.localize(datetime.datetime(2018, 4, 3, 6, 2)) self.other_time = self.new_time + datetime.timedelta(days=30) self.beer1 = BeerFactory( manufacturer=self.manufacturer, untappd_url="http://localhost/123456", color_srm=None, time_first_seen=self.other_time, ) self.beer2 = BeerFactory( manufacturer=self.manufacturer, color_srm=55, stem_and_stein_pk=551, time_first_seen=self.new_time, ) self.tap = TapFactory(beer=self.beer2) self.venue2 = self.tap.venue self.venue1 = VenueFactory() self.serving_size = ServingSize.objects.create(name="foo", volume_oz=12) def test_merge(self): self.beer1.merge_from(self.beer2) self.assertEqual(self.beer1.color_srm, self.beer2.color_srm) self.tap.refresh_from_db() self.assertEqual(self.tap.beer, self.beer1) self.assertFalse(Beer.objects.filter(id=self.beer2.id).exists()) self.assertTrue( BeerAlternateName.objects.filter( name=self.beer2.name, beer=self.beer1, ).exists()) self.assertEqual(self.tap.beer.time_first_seen, self.new_time) self.assertEqual(self.tap.beer.stem_and_stein_pk, 551) def test_preserve_prices_no_overlap(self): BeerPrice.objects.create( beer=self.beer1, venue=self.venue1, price=15, serving_size=self.serving_size, ) BeerPrice.objects.create( beer=self.beer2, venue=self.venue2, price=10, serving_size=self.serving_size, ) self.beer1.merge_from(self.beer2) self.assertEqual(BeerPrice.objects.filter(beer=self.beer1).count(), 2) def test_preserve_prices_overlap(self): BeerPrice.objects.create( beer=self.beer1, venue=self.venue2, price=15, serving_size=self.serving_size, ) BeerPrice.objects.create( beer=self.beer2, venue=self.venue2, price=10, serving_size=self.serving_size, ) other_size = ServingSize.objects.create(name="bar", volume_oz=16) BeerPrice.objects.create( beer=self.beer2, venue=self.venue2, price=20, serving_size=other_size, ) self.beer1.merge_from(self.beer2) # Because we have an overlap in one unique condition (beer + venue + size), # we are going to take the safest route possible and ignore both of the # prices from beer2 for venue2. self.assertEqual(BeerPrice.objects.filter(beer=self.beer1).count(), 1)