def _create_test_form_searches(n=100): """Create n form searches with various properties. A testing ground for searches! """ users = h.get_users() contributor = [u for u in users if u.role == u'contributor'][0] for i in range(1, n + 1): fs = model.FormSearch() fs.enterer_id = contributor.id fs.search = unicode( json.dumps({ 'query': { 'filter': ['Form', 'transcription', 'regex', '%d' % i] } })) if i % 2 == 0: fs.name = u'Form Search %d' % i else: fs.name = u'form search %d' % i if i > 50: fs.description = u'I really like this search and my favourite number is %d' % i if i > 20: fs.datetime_modified = today_timestamp else: fs.datetime_modified = yesterday_timestamp Session.add(fs) Session.commit()
def _create_test_form_searches(n=100): """Create n form searches with various properties. A testing ground for searches! """ users = h.get_users() contributor = [u for u in users if u.role == u'contributor'][0] for i in range(1, n + 1): fs = model.FormSearch() fs.enterer_id = contributor.id fs.search = unicode(json.dumps( {'query': {'filter': ['Form', 'transcription', 'regex', '%d' % i]}})) if i % 2 == 0: fs.name = u'Form Search %d' % i else: fs.name = u'form search %d' % i if i > 50: fs.description = u'I really like this search and my favourite number is %d' % i if i > 20: fs.datetime_modified = today_timestamp else: fs.datetime_modified = yesterday_timestamp Session.add(fs) Session.commit()
def test_index(self): """Tests that GET & SEARCH /formbackups behave correctly. """ # Add some test data to the database. application_settings = h.generate_default_application_settings() source = h.generate_default_source() restricted_tag = h.generate_restricted_tag() file1 = h.generate_default_file() file1.name = u'file1' file2 = h.generate_default_file() file2.name = u'file2' speaker = h.generate_default_speaker() Session.add_all([application_settings, source, restricted_tag, file1, file2, speaker]) Session.commit() speaker_id = speaker.id restricted_tag_id = restricted_tag.id tag_ids = [restricted_tag_id] file1_id = file1.id file2_id = file2.id file_ids = [file1_id, file2_id] # Create a restricted form (via request) as the default contributor users = h.get_users() administrator_id = [u for u in users if u.role==u'administrator'][0].id # Define some extra_environs view = {'test.authentication.role': u'viewer', 'test.application_settings': True} contrib = {'test.authentication.role': u'contributor', 'test.application_settings': True} admin = {'test.authentication.role': u'administrator', 'test.application_settings': True} params = self.form_create_params.copy() params.update({ 'transcription': u'Created by the Contributor', 'translations': [{'transcription': u'test', 'grammaticality': u''}], 'tags': [restricted_tag_id] }) params = json.dumps(params) response = self.app.post(url('forms'), params, self.json_headers, contrib) form_count = Session.query(model.Form).count() resp = json.loads(response.body) form_id = resp['id'] assert form_count == 1 # Update our form (via request) as the default administrator; this # will create one form backup. params = self.form_create_params.copy() params.update({ 'translations': [{'transcription': u'test', 'grammaticality': u''}], 'transcription': u'Updated by the Administrator', 'speaker': speaker_id, 'tags': tag_ids + [None, u''], # None and u'' ('') will be ignored by forms.update_form 'enterer': administrator_id # This should change nothing. }) params = json.dumps(params) response = self.app.put(url('form', id=form_id), params, self.json_headers, admin) resp = json.loads(response.body) form_count = Session.query(model.Form).count() assert form_count == 1 # Finally, update our form (via request) as the default contributor. # Now we will have two form backups. params = self.form_create_params.copy() params.update({ 'transcription': u'Updated by the Contributor', 'translations': [{'transcription': u'test', 'grammaticality': u''}], 'speaker': speaker_id, 'tags': tag_ids, 'files': file_ids }) params = json.dumps(params) response = self.app.put(url('form', id=form_id), params, self.json_headers, contrib) resp = json.loads(response.body) form_count = Session.query(model.Form).count() assert form_count == 1 # Now GET the form backups as the restricted enterer of the original # form and expect to get them all. response = self.app.get(url('formbackups'), headers=self.json_headers, extra_environ=contrib) resp = json.loads(response.body) assert len(resp) == 2 assert response.content_type == 'application/json' # The admin should get them all too. response = self.app.get(url('formbackups'), headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) assert len(resp) == 2 # The viewer should get none because they're all restricted. response = self.app.get(url('formbackups'), headers=self.json_headers, extra_environ=view) resp = json.loads(response.body) assert len(resp) == 0 # Now update the form and de-restrict it. params = self.form_create_params.copy() params.update({ 'transcription': u'Updated and de-restricted by the Contributor', 'translations': [{'transcription': u'test', 'grammaticality': u''}], 'speaker': speaker_id, 'tags': [], 'files': file_ids }) params = json.dumps(params) response = self.app.put(url('form', id=form_id), params, self.json_headers, contrib) resp = json.loads(response.body) form_count = Session.query(model.Form).count() assert form_count == 1 # Now GET the form backups. Admin and contrib should see 3 but the # viewer should still see none. response = self.app.get(url('formbackups'), headers=self.json_headers, extra_environ=contrib) resp = json.loads(response.body) assert len(resp) == 3 response = self.app.get(url('formbackups'), headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) assert len(resp) == 3 response = self.app.get(url('formbackups'), headers=self.json_headers, extra_environ=view) resp = json.loads(response.body) assert len(resp) == 0 # Finally, update our form in some trivial way. params = self.form_create_params.copy() params.update({ 'transcription': u'Updated by the Contributor *again*', 'translations': [{'transcription': u'test', 'grammaticality': u''}], 'speaker': speaker_id, 'tags': [], 'files': file_ids }) params = json.dumps(params) response = self.app.put(url('form', id=form_id), params, self.json_headers, contrib) resp = json.loads(response.body) form_count = Session.query(model.Form).count() assert form_count == 1 # Now GET the form backups. Admin and contrib should see 4 and the # viewer should see 1 response = self.app.get(url('formbackups'), headers=self.json_headers, extra_environ=contrib) resp = json.loads(response.body) assert len(resp) == 4 response = self.app.get(url('formbackups'), headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) all_form_backups = resp assert len(resp) == 4 response = self.app.get(url('formbackups'), headers=self.json_headers, extra_environ=view) resp = json.loads(response.body) unrestricted_form_backup = resp[0] assert len(resp) == 1 assert resp[0]['transcription'] == u'Updated and de-restricted by the Contributor' restricted_form_backups = [cb for cb in all_form_backups if cb != unrestricted_form_backup] assert len(restricted_form_backups) == 3 # Test the paginator GET params. paginator = {'items_per_page': 1, 'page': 2} response = self.app.get(url('formbackups'), paginator, headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) assert len(resp['items']) == 1 assert resp['items'][0]['transcription'] == all_form_backups[1]['transcription'] assert response.content_type == 'application/json' # Test the order_by GET params. order_by_params = {'order_by_model': 'FormBackup', 'order_by_attribute': 'datetime_modified', 'order_by_direction': 'desc'} response = self.app.get(url('formbackups'), order_by_params, headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) result_set = sorted(all_form_backups, key=lambda cb: cb['datetime_modified'], reverse=True) assert [cb['id'] for cb in resp] == [cb['id'] for cb in result_set] # Test the order_by *with* paginator. params = {'order_by_model': 'FormBackup', 'order_by_attribute': 'datetime_modified', 'order_by_direction': 'desc', 'items_per_page': 1, 'page': 3} response = self.app.get(url('formbackups'), params, headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) assert result_set[2]['transcription'] == resp['items'][0]['transcription'] # Now test the show action: # Admin should be able to GET a particular restricted form backup response = self.app.get(url('formbackup', id=restricted_form_backups[0]['id']), headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) assert resp['transcription'] == restricted_form_backups[0]['transcription'] assert response.content_type == 'application/json' # Viewer should receive a 403 error when attempting to do so. response = self.app.get(url('formbackup', id=restricted_form_backups[0]['id']), headers=self.json_headers, extra_environ=view, status=403) resp = json.loads(response.body) assert resp['error'] == u'You are not authorized to access this resource.' assert response.content_type == 'application/json' # Viewer should be able to GET the unrestricted form backup response = self.app.get(url('formbackup', id=unrestricted_form_backup['id']), headers=self.json_headers, extra_environ=view) resp = json.loads(response.body) assert resp['transcription'] == unrestricted_form_backup['transcription'] # A nonexistent cb id will return a 404 error response = self.app.get(url('formbackup', id=100987), headers=self.json_headers, extra_environ=view, status=404) resp = json.loads(response.body) assert resp['error'] == u'There is no form backup with id 100987' assert response.content_type == 'application/json' # Test the search action self._add_SEARCH_to_web_test_valid_methods() # A search on form backup transcriptions using POST /formbackups/search json_query = json.dumps({'query': {'filter': ['FormBackup', 'transcription', 'like', u'%Contributor%']}}) response = self.app.post(url('/formbackups/search'), json_query, self.json_headers, admin) resp = json.loads(response.body) result_set = [cb for cb in all_form_backups if u'Contributor' in cb['transcription']] assert len(resp) == len(result_set) == 3 assert set([cb['id'] for cb in resp]) == set([cb['id'] for cb in result_set]) assert response.content_type == 'application/json' # A search on form backup transcriptions using SEARCH /formbackups json_query = json.dumps({'query': {'filter': ['FormBackup', 'transcription', 'like', u'%Administrator%']}}) response = self.app.request(url('formbackups'), method='SEARCH', body=json_query, headers=self.json_headers, environ=admin) resp = json.loads(response.body) result_set = [cb for cb in all_form_backups if u'Administrator' in cb['transcription']] assert len(resp) == len(result_set) == 1 assert set([cb['id'] for cb in resp]) == set([cb['id'] for cb in result_set]) # Perform the two previous searches as a restricted viewer to show that # the restricted tag is working correctly. json_query = json.dumps({'query': {'filter': ['FormBackup', 'transcription', 'like', u'%Contributor%']}}) response = self.app.post(url('/formbackups/search'), json_query, self.json_headers, view) resp = json.loads(response.body) result_set = [cb for cb in [unrestricted_form_backup] if u'Contributor' in cb['transcription']] assert len(resp) == len(result_set) == 1 assert set([cb['id'] for cb in resp]) == set([cb['id'] for cb in result_set]) assert response.content_type == 'application/json' json_query = json.dumps({'query': {'filter': ['FormBackup', 'transcription', 'like', u'%Administrator%']}}) response = self.app.request(url('formbackups'), method='SEARCH', body=json_query, headers=self.json_headers, environ=view) resp = json.loads(response.body) result_set = [cb for cb in [unrestricted_form_backup] if u'Administrator' in cb['transcription']] assert len(resp) == len(result_set) == 0 # I'm just going to assume that the order by and pagination functions are # working correctly since the implementation is essentially equivalent # to that in the index action already tested above. # Attempting to call edit/new/create/delete/update on a read-only resource # will return a 404 response response = self.app.get(url('edit_formbackup', id=2232), status=404) assert json.loads(response.body)['error'] == u'This resource is read-only.' response = self.app.get(url('new_formbackup', id=2232), status=404) assert json.loads(response.body)['error'] == u'This resource is read-only.' response = self.app.post(url('formbackups'), status=404) assert json.loads(response.body)['error'] == u'This resource is read-only.' response = self.app.put(url('formbackup', id=2232), status=404) assert json.loads(response.body)['error'] == u'This resource is read-only.' response = self.app.delete(url('formbackup', id=2232), status=404) assert json.loads(response.body)['error'] == u'This resource is read-only.' assert response.content_type == 'application/json'
def get_users(): users = h.get_users() viewer = [u for u in users if u.role == u'viewer'][0] contributor = [u for u in users if u.role == u'contributor'][0] administrator = [u for u in users if u.role == u'administrator'][0] return viewer, contributor, administrator
def test_index(self): """Tests that GET & SEARCH /collectionbackups behave correctly. """ # Add some test data to the database. application_settings = h.generate_default_application_settings() source = h.generate_default_source() restricted_tag = h.generate_restricted_tag() file1 = h.generate_default_file() file1.name = u'file1' file2 = h.generate_default_file() file2.name = u'file2' speaker = h.generate_default_speaker() Session.add_all([ application_settings, source, restricted_tag, file1, file2, speaker ]) Session.commit() speaker_id = speaker.id restricted_tag_id = restricted_tag.id tag_ids = [restricted_tag_id] file1_id = file1.id file2_id = file2.id file_ids = [file1_id, file2_id] # Create a restricted collection (via request) as the default contributor users = h.get_users() contributor_id = [u for u in users if u.role == u'contributor'][0].id administrator_id = [u for u in users if u.role == u'administrator'][0].id # Define some extra_environs view = { 'test.authentication.role': u'viewer', 'test.application_settings': True } contrib = { 'test.authentication.role': u'contributor', 'test.application_settings': True } admin = { 'test.authentication.role': u'administrator', 'test.application_settings': True } params = self.collection_create_params.copy() params.update({ 'title': u'Created by the Contributor', 'elicitor': contributor_id, 'tags': [restricted_tag_id] }) params = json.dumps(params) response = self.app.post(url('collections'), params, self.json_headers, contrib) collection_count = Session.query(model.Collection).count() resp = json.loads(response.body) collection_id = resp['id'] assert response.content_type == 'application/json' assert collection_count == 1 # Update our collection (via request) as the default administrator; this # will create one collection backup. params = self.collection_create_params.copy() params.update({ 'url': u'find/me/here', 'title': u'Updated by the Administrator', 'speaker': speaker_id, 'tags': tag_ids + [ None, u'' ], # None and u'' ('') will be ignored by collections.update_collection 'enterer': administrator_id # This should change nothing. }) params = json.dumps(params) response = self.app.put(url('collection', id=collection_id), params, self.json_headers, admin) resp = json.loads(response.body) collection_count = Session.query(model.Collection).count() assert response.content_type == 'application/json' assert collection_count == 1 # Finally, update our collection (via request) as the default contributor. # Now we will have two collection backups. params = self.collection_create_params.copy() params.update({ 'title': u'Updated by the Contributor', 'speaker': speaker_id, 'tags': tag_ids, 'files': file_ids }) params = json.dumps(params) response = self.app.put(url('collection', id=collection_id), params, self.json_headers, contrib) resp = json.loads(response.body) collection_count = Session.query(model.Collection).count() assert collection_count == 1 # Now GET the collection backups as the restricted enterer of the original # collection and expect to get them all. response = self.app.get(url('collectionbackups'), headers=self.json_headers, extra_environ=contrib) resp = json.loads(response.body) assert len(resp) == 2 assert response.content_type == 'application/json' # The admin should get them all too. response = self.app.get(url('collectionbackups'), headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) assert len(resp) == 2 # The viewer should get none because they're all restricted. response = self.app.get(url('collectionbackups'), headers=self.json_headers, extra_environ=view) resp = json.loads(response.body) assert len(resp) == 0 # Now update the collection and de-restrict it. params = self.collection_create_params.copy() params.update({ 'title': u'Updated and de-restricted by the Contributor', 'speaker': speaker_id, 'tags': [], 'files': file_ids }) params = json.dumps(params) response = self.app.put(url('collection', id=collection_id), params, self.json_headers, contrib) resp = json.loads(response.body) collection_count = Session.query(model.Collection).count() assert collection_count == 1 # Now GET the collection backups. Admin and contrib should see 3 but the # viewer should still see none. response = self.app.get(url('collectionbackups'), headers=self.json_headers, extra_environ=contrib) resp = json.loads(response.body) assert len(resp) == 3 response = self.app.get(url('collectionbackups'), headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) assert len(resp) == 3 response = self.app.get(url('collectionbackups'), headers=self.json_headers, extra_environ=view) resp = json.loads(response.body) assert len(resp) == 0 assert response.content_type == 'application/json' # Finally, update our collection in some trivial way. params = self.collection_create_params.copy() params.update({ 'title': u'Updated by the Contributor *again*', 'speaker': speaker_id, 'tags': [], 'files': file_ids }) params = json.dumps(params) response = self.app.put(url('collection', id=collection_id), params, self.json_headers, contrib) resp = json.loads(response.body) collection_count = Session.query(model.Collection).count() assert collection_count == 1 # Now GET the collection backups. Admin and contrib should see 4 and the # viewer should see 1 response = self.app.get(url('collectionbackups'), headers=self.json_headers, extra_environ=contrib) resp = json.loads(response.body) assert len(resp) == 4 response = self.app.get(url('collectionbackups'), headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) all_collection_backups = resp assert len(resp) == 4 response = self.app.get(url('collectionbackups'), headers=self.json_headers, extra_environ=view) resp = json.loads(response.body) unrestricted_collection_backup = resp[0] assert len(resp) == 1 assert resp[0][ 'title'] == u'Updated and de-restricted by the Contributor' restricted_collection_backups = [ cb for cb in all_collection_backups if cb != unrestricted_collection_backup ] assert len(restricted_collection_backups) == 3 # Test the paginator GET params. paginator = {'items_per_page': 1, 'page': 2} response = self.app.get(url('collectionbackups'), paginator, headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) assert len(resp['items']) == 1 assert resp['items'][0]['title'] == all_collection_backups[1]['title'] assert response.content_type == 'application/json' # Test the order_by GET params. order_by_params = { 'order_by_model': 'CollectionBackup', 'order_by_attribute': 'id', 'order_by_direction': 'desc' } response = self.app.get(url('collectionbackups'), order_by_params, headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) result_set = sorted(all_collection_backups, key=lambda cb: cb['id'], reverse=True) assert [cb['id'] for cb in resp] == [cb['id'] for cb in result_set] # Test the order_by *with* paginator. params = { 'order_by_model': 'CollectionBackup', 'order_by_attribute': 'id', 'order_by_direction': 'desc', 'items_per_page': 1, 'page': 3 } response = self.app.get(url('collectionbackups'), params, headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) assert result_set[2]['title'] == resp['items'][0]['title'] # Now test the show action: # Admin should be able to GET a particular restricted collection backup response = self.app.get(url('collectionbackup', id=restricted_collection_backups[0]['id']), headers=self.json_headers, extra_environ=admin) resp = json.loads(response.body) assert resp['title'] == restricted_collection_backups[0]['title'] assert response.content_type == 'application/json' # Viewer should receive a 403 error when attempting to do so. response = self.app.get(url('collectionbackup', id=restricted_collection_backups[0]['id']), headers=self.json_headers, extra_environ=view, status=403) resp = json.loads(response.body) assert resp[ 'error'] == u'You are not authorized to access this resource.' assert response.content_type == 'application/json' # Viewer should be able to GET the unrestricted collection backup response = self.app.get(url('collectionbackup', id=unrestricted_collection_backup['id']), headers=self.json_headers, extra_environ=view) resp = json.loads(response.body) assert resp['title'] == unrestricted_collection_backup['title'] # A nonexistent cb id will return a 404 error response = self.app.get(url('collectionbackup', id=100987), headers=self.json_headers, extra_environ=view, status=404) resp = json.loads(response.body) assert resp['error'] == u'There is no collection backup with id 100987' assert response.content_type == 'application/json' # Test the search action self._add_SEARCH_to_web_test_valid_methods() # A search on collection backup titles using POST /collectionbackups/search json_query = json.dumps({ 'query': { 'filter': ['CollectionBackup', 'title', 'like', u'%Contributor%'] } }) response = self.app.post(url('/collectionbackups/search'), json_query, self.json_headers, admin) resp = json.loads(response.body) result_set = [ cb for cb in all_collection_backups if u'Contributor' in cb['title'] ] assert len(resp) == len(result_set) == 3 assert set([cb['id'] for cb in resp]) == set([cb['id'] for cb in result_set]) assert response.content_type == 'application/json' # A search on collection backup titles using SEARCH /collectionbackups json_query = json.dumps({ 'query': { 'filter': ['CollectionBackup', 'title', 'like', u'%Administrator%'] } }) response = self.app.request(url('collectionbackups'), method='SEARCH', body=json_query, headers=self.json_headers, environ=admin) resp = json.loads(response.body) result_set = [ cb for cb in all_collection_backups if u'Administrator' in cb['title'] ] assert len(resp) == len(result_set) == 1 assert set([cb['id'] for cb in resp]) == set([cb['id'] for cb in result_set]) # Perform the two previous searches as a restricted viewer to show that # the restricted tag is working correctly. json_query = json.dumps({ 'query': { 'filter': ['CollectionBackup', 'title', 'like', u'%Contributor%'] } }) response = self.app.post(url('/collectionbackups/search'), json_query, self.json_headers, view) resp = json.loads(response.body) result_set = [ cb for cb in [unrestricted_collection_backup] if u'Contributor' in cb['title'] ] assert len(resp) == len(result_set) == 1 assert set([cb['id'] for cb in resp]) == set([cb['id'] for cb in result_set]) json_query = json.dumps({ 'query': { 'filter': ['CollectionBackup', 'title', 'like', u'%Administrator%'] } }) response = self.app.request(url('collectionbackups'), method='SEARCH', body=json_query, headers=self.json_headers, environ=view) resp = json.loads(response.body) result_set = [ cb for cb in [unrestricted_collection_backup] if u'Administrator' in cb['title'] ] assert len(resp) == len(result_set) == 0 # I'm just going to assume that the order by and pagination functions are # working correctly since the implementation is essentially equivalent # to that in the index action already tested above. # Attempting to call edit/new/create/delete/update on a read-only resource # will return a 404 response response = self.app.get(url('edit_collectionbackup', id=2232), status=404) assert json.loads( response.body)['error'] == u'This resource is read-only.' response = self.app.get(url('new_collectionbackup', id=2232), status=404) assert json.loads( response.body)['error'] == u'This resource is read-only.' response = self.app.post(url('collectionbackups'), status=404) assert json.loads( response.body)['error'] == u'This resource is read-only.' response = self.app.put(url('collectionbackup', id=2232), status=404) assert json.loads( response.body)['error'] == u'This resource is read-only.' response = self.app.delete(url('collectionbackup', id=2232), status=404) assert json.loads( response.body)['error'] == u'This resource is read-only.' assert response.content_type == 'application/json'