def test_sort_by_publish_date(self): """Verify package API 'publish_date' sorting behavior. When this sort option is specified, the API should sort first by a package's upper bound, then by the precision of its range. """ # We already have four packages in the database, each of which are one # day long. We need to add two more here with > 1 day duration to test # the range precision sorting. package_factory( publish_date_lower=tz.localize(datetime(2015, 5, 2)), publish_date_upper=tz.localize(datetime(2015, 5, 5)), slug_key='test-pkg-api-sbpd1' ) package_factory( publish_date_lower=tz.localize(datetime(2015, 5, 3)), publish_date_upper=tz.localize(datetime(2015, 5, 5)), slug_key='test-pkg-api-sbpd2' ) response = self.client.get(PACKAGES_API_ENDPOINT, data={ 'format': 'json', 'ordering': 'publish_date'}) # Get the publish dates of the returned packages and make sure they # align with what we expect returned_dates = [ x['publishDate'] for x in json.loads(response.content)['results'] ] expected_dates = [ [ get_timestamp_for_date('2015-05-06'), get_timestamp_for_date('2015-05-07'), ], [ get_timestamp_for_date('2015-05-05'), get_timestamp_for_date('2015-05-06'), ], [ get_timestamp_for_date('2015-05-04'), get_timestamp_for_date('2015-05-05'), ], [ get_timestamp_for_date('2015-05-03'), get_timestamp_for_date('2015-05-05'), ], [ get_timestamp_for_date('2015-05-02'), get_timestamp_for_date('2015-05-05'), ], [ get_timestamp_for_date('2015-05-03'), get_timestamp_for_date('2015-05-04'), ], [ get_timestamp_for_date('2015-05-02'), get_timestamp_for_date('2015-05-03'), ] ] self.assertListEqual(returned_dates, expected_dates)
def setUpTestData(cls): package_one = package_factory(slug_key='test-items-api-base') item_factory(primary_for=package_one) item_factory(additional_for=package_one, slug_key='addl1') # item_factory(additional_for=package_one) for _ in range(5): slug_key = 'test-items-api-{}'.format(_) item_factory(primary_for=package_factory(slug_key=slug_key))
def test_has_primary_filter_invalid(self): """Verify has_primary filter behavior. Such filtering should return an empty queryset when passed an invalid value. """ package_factory(slug_key='test-pkg-api-hpf-inv') response = self.client.get(PACKAGES_API_ENDPOINT, { 'format': 'json', 'has_primary': 'x' }) json_response = json.loads(response.content) self.assertEqual(json_response['count'], 0)
def test_has_primary_filter_off(self): """Verify has_primary filter behavior. Such filtering should only include packages without primary content items when the search value is 0. """ package_factory(slug_key='test-pkg-api-hpf-off') response = self.client.get(PACKAGES_API_ENDPOINT, { 'format': 'json', 'has_primary': '1' }) json_response = json.loads(response.content) # Should only return the 5 items setup in setUpTestData self.assertEqual(json_response['count'], 5)
def test_write_invalid_date_bounds_to_daterange_field(self): """Verify date-range part ordering behavior. Passing a date range where the lower is greater than the upper raises an error. """ package = package_factory(slug_key='test-daterng-write-4') package_url = '%s%s/?format=json' % ( PACKAGES_API_ENDPOINT, package.pk,) update = { 'publishDate': [ get_timestamp_for_date('2015-05-03'), get_timestamp_for_date('2015-05-02'), ] } response = self.client.patch(package_url, update, format='json') self.assertEqual(response.status_code, 400) error = { 'publishDate': [ 'The upper date bound must be greater than the lower bound.' ] } self.assertJSONEqual(response.content, error)
def test_searches_slug_keys(self): """Verify search query behavior. Searches should find packages based on both primary & additional content slug keys. """ package = package_factory(slug_key='test-pkg-api-ssk') item_factory(primary_for=package) item_factory(additional_for=package, slug_key='klmnopqrst') response = self.client.get(PACKAGES_API_ENDPOINT, data={ 'format': 'json', 'search': 'test-pkg-api-ssk' }) json_response = json.loads(response.content) self.assertEqual(json_response['count'], 1) self.assertEqual(json_response['results'][0]['id'], package.pk) response = self.client.get(PACKAGES_API_ENDPOINT, data={ 'format': 'json', 'search': 'klmnopqrst' }) json_response = json.loads(response.content) self.assertEqual(json_response['count'], 1) self.assertEqual(json_response['results'][0]['id'], package.pk)
def test_duplicate_additional_item_slug(self): """Verify protection against duplicate additional-item slugs. Model should throw an IntegrityError when saving multiple additional items with the same slug key to a package. """ slug_key = 'my-test-content' package = package_factory(slug_key='test-item-dais') item_factory( additional_for=package, slug_key=slug_key ) self.assertEqual(package.additional_content.count(), 1) self.assertEqual( package.additional_content.all()[0].slug_key, slug_key ) with self.assertRaises(ValidationError): next_item = Item( slug_key=slug_key, type='text', editors=[{'email': '*****@*****.**'}], authors=[{'email': '*****@*****.**'}], budget_line='Budget line', primary_for_package=None, additional_for_package=package ) next_item.validate_unique()
def test_created_by_user_none(self): """Verify 'created_by_user' behavior when user is null. In this case, the property should return AnonymousUser. """ package = package_factory(slug_key='test-cr-trl-cbun') self.assertEqual(package.created_by_user, AnonymousUser)
def test_person_filter(self): """Person filter should search both author & editor fields.""" item_factory( author='*****@*****.**', primary_for=package_factory(slug_key='test-items-api-p1') ) item_factory( editor='*****@*****.**', primary_for=package_factory(slug_key='test-items-api-p2') ) response = self.client.get(ITEMS_API_ENDPOINT, data={ 'format': 'json', 'person': '*****@*****.**' }) self.assertEqual(response.status_code, 200) self.assertEqual(json.loads(response.content)['count'], 2)
def test_user_saved_on_item_create(self): """Verify user info is stored on item save. Item created via the API should have their created_by attribute set to the currently-authed user. """ package = package_factory(slug_key='test-audit-usoic') response = self.client.post( '%s?format=json' % ITEMS_API_ENDPOINT, json.dumps({ 'hub': 'hub', 'slugKey': 'slug', 'budgetLine': 'Budget line', 'authors': [{'name': 'Name'}], 'primaryForPackage': package.pk }), content_type='application/json' ) json_response = json.loads(response.content) self.assertEqual(response.status_code, 201) item = Item.objects.get(pk=json_response['id']) self.assertEqual(item.created_by, self.creator.pk) self.assertEqual(item.created_by_user, self.creator)
def test_change_created_on_addl_item_update(self): """Verify creation of Change instance on additional item update. When an additional content item is updated via the API, a change model should be created to reflect this modification. """ package = package_factory(slug_key='test-audit-ccoaiu') item_factory(primary_for=package) additional_item = item_factory(additional_for=package) response = self.client.patch( '%s%s/?format=json' % (ITEMS_API_ENDPOINT, additional_item.pk,), json.dumps({ 'budgetLine': 'Updated budget line', }), content_type='application/json' ) self.assertEqual(response.status_code, 200) change = Change.objects.get( item_id=additional_item.pk, item_content_type='item' ) self.assertEqual(change.package, package) self.assertEqual(change.by, self.creator.pk)
def test_str(self): """Verify string method for Package model. The method should return generated slug information. """ slug_key = 'my-test' package = package_factory(slug_key=slug_key) self.assertEqual(str(package), 'hub.{}.050115'.format(slug_key))
def test_primary_and_additional_raise_error(self): """Verify mutual exclusivity of primary- & additional-type FKs. Raise ValidationError if an item has simultaneous values set for both primary and additional package. """ with six.assertRaisesRegex( self, ValidationError, "Items cannot be connected to a package as both" ): package_one = package_factory(slug_key='test-item-tpaare1') package_two = package_factory(slug_key='test-item-tpaare2') item = Item(slug_key='sluggy-slug', type='text', budget_line='Budget line', primary_for_package=package_one, additional_for_package=package_two) item.clean()
def test_get_by_slug(self): """The package detail view should allow GETing by slug""" package = package_factory(slug_key='test-pkg-api-gbs') url = '%s%s/' % (PACKAGES_API_ENDPOINT, package.full_slug) response = self.client.get(url, data={'format': 'json'}) self.assertEqual(response.status_code, 200) json_response = json.loads(response.content) self.assertEqual(json_response['id'], package.id)
def test_created_by_user_missing(self): """Verify 'created_by_user' behavior when user does not exist. In this case, the property should return a value of None. """ package = package_factory(slug_key='test-cr-trl-cbum') package.created_by = 5000 package.save() self.assertEqual(package.created_by_user, None)
def test_generate_date_slug_with_day(self): """Verify precise-date date-range formatting behavior. If publish_date is day- / datetime-precise, generate a date slug with format 'MMDDYY'. """ day_resolution = package_factory( publish_date_lower=make_aware(datetime(2015, 5, 1)), publish_date_upper=make_aware(datetime(2015, 5, 2)), slug_key='test-item-gdswd' ) self.assertEqual(day_resolution.slugified_date, '050115') time_resolution = package_factory( publish_date_lower=make_aware(datetime(2015, 5, 1, 11)), publish_date_upper=make_aware(datetime(2015, 5, 2, 11, 1)), slug_key='test-item-gdswdat' ) self.assertEqual(time_resolution.slugified_date, '050115')
def test_str(self): """Verify string method for Headline model. The method should return the headline's text. """ hed = Headline( package=package_factory(slug_key='test-hed-str'), text='A headline' ) self.assertEqual(str(hed), 'A headline')
def setUpTestData(cls): cls.item = item_factory( primary_for=package_factory(slug_key='test-change') ) cls.user = User.objects.create_user('user') cls.change = Change.objects.create( by=cls.user.pk, package=cls.item.primary_for_package, item_content_type='item', item_id=cls.item.pk )
def test_package_slug_creation(self): """Verify behavior of Package's 'full_slug' model property. This property should return a Package's 'slug_key'. """ slug_key = 'test-key-one' package = package_factory(slug_key=slug_key) self.assertEqual( package.full_slug, 'hub.{}.050115'.format(slug_key) )
def test_str(self): """Verify string method for HeadlineVote model. The method should include voter and vote information. """ hed = Headline( package=package_factory(slug_key='test-hedvote-str'), text='A headline' ) vote = HeadlineVote(headline=hed, voter='*****@*****.**') self.assertEqual(str(vote), '[email protected] for A headline')
def test_author_filter(self): """Author field should return items based on author's e-mail.""" item_factory( author='*****@*****.**', primary_for=package_factory(slug_key='test-items-api-p3') ) response = self.client.get(ITEMS_API_ENDPOINT, data={ 'format': 'json', 'author': '*****@*****.**' }) self.assertEqual(response.status_code, 200) self.assertEqual(json.loads(response.content)['count'], 1)
def test_created_by_user(self): """Verify behavior of 'created_by_user' model property. This property should load the user model from the database. """ user = User.objects.create_user('user') package = package_factory(slug_key='test-cr-trl-cbu') package.created_by = user.pk package.save() self.assertEqual(package.created_by_user, user)
def test_generate_date_slug_no_day(self): """Verify month and week date-range formatting behavior. If publish_date doesn't have at least day precision, day of month should be excluded from the date slug. """ week_resolution = package_factory( publish_date_lower=make_aware(datetime(2015, 5, 1)), publish_date_upper=make_aware(datetime(2015, 5, 8)), slug_key='test-item-gdsnd' ) self.assertEqual(week_resolution.slugified_date, '05--15')
def test_total_votes(self): """Verify total_votes() method behavior. The method should return latest total for headline votes. """ hed = Headline.objects.create( package=package_factory(slug_key='test-hed-tv'), text='A headline' ) for _ in range(5): HeadlineVote.objects.create(headline=hed, voter='*****@*****.**' % _) self.assertEqual(hed.total_votes(), 5)
def setUpTestData(cls): # Generate packages on 5 consecutive days, so we can run date-bound # filtered queries for offset in range(5): days_to_add = offset + 1 lower = tz.localize(datetime(2015, 5, 1)) + timedelta( days=days_to_add ) upper = lower + timedelta(days=1) package = package_factory( publish_date_lower=lower, publish_date_upper=upper) item_factory(primary_for=package)
def test_get_by_id(self): """Verify package API get-by-ID behavior. This is the traditional GET behavior for API detail views. """ package = package_factory(slug_key='test-pkg-api-gbid') url = '%s%s/' % (PACKAGES_API_ENDPOINT, package.pk) response = self.client.get(url, data={'format': 'json'}) self.assertEqual(response.status_code, 200) json_response = json.loads(response.content) self.assertEqual(json_response['id'], package.id)
def test_has_primary_filter_on(self): """Verify has_primary filter behavior. Such filtering should exclude packages that don't have primary content items when the search value is 1. """ package = package_factory(slug_key='test-pkg-api-hpf-on') response = self.client.get(PACKAGES_API_ENDPOINT, { 'format': 'json', 'has_primary': '0' }) json_response = json.loads(response.content) self.assertEqual(json_response['count'], 1) self.assertEqual(json_response['results'][0]['id'], package.pk)
def test_default_sort(self): """By default, packages API should order by 'publish_date'.""" # Add additional packages with > 1 day duration to test range precision package_factory( publish_date_lower=datetime(2015, 5, 1), publish_date_upper=datetime(2015, 5, 4), slug_key='test-pkg-api-dst1' ) package_factory( publish_date_lower=datetime(2015, 5, 2), publish_date_upper=datetime(2015, 5, 4), slug_key='test-pkg-api-dst2' ) response_with_sort = self.client.get( PACKAGES_API_ENDPOINT, data={ 'format': 'json', 'ordering': 'publish_date', } ) response_no_sort = self.client.get( PACKAGES_API_ENDPOINT, data={'format': 'json'} ) ids_with_sort = ','.join([ str(_['id']) for _ in json.loads(response_with_sort.content)['results'] ]) ids_no_sort = ','.join([ str(_['id']) for _ in json.loads(response_no_sort.content)['results'] ]) self.assertEqual(ids_with_sort, ids_no_sort)
def test_read_from_daterange_field(self): """Verify range-field serialization behavior. Range field should serialize as two ISO-8601 dates in an array. """ package = package_factory(slug_key='test-daterng-read') package_url = '%s%s/' % (PACKAGES_API_ENDPOINT, package.pk,) response = self.client.get(package_url, data={'format': 'json'}) json_response = json.loads(response.content) expect = [ get_timestamp_for_date('2015-05-01'), get_timestamp_for_date('2015-05-02'), ] self.assertEqual(json_response['publishDate'], expect)
def test_additional_item_slug(self): """Verify additional-item slug behavior. An additional item's slug should be the concatenation of its parent package's slug and the individual item's slug key. """ slug_key = 'my-test-content' package = package_factory(slug_key='test-item-ais') additional_item = item_factory( additional_for=package, slug_key=slug_key ) self.assertEqual( additional_item.full_slug, '{}.{}'.format(package.full_slug, slug_key) )