def test_a_initialize(self): """Initialize the database for /rememberedforms tests.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) self.create_db() db.clear_all_models() administrator = omb.generate_default_administrator( settings=self.settings) contributor = omb.generate_default_contributor(settings=self.settings) viewer = omb.generate_default_viewer(settings=self.settings) dbsession.add_all([administrator, contributor, viewer]) dbsession.commit() _create_test_data(dbsession, db, self.n) add_SEARCH_to_web_test_valid_methods() # Create an application settings where the contributor is unrestricted viewer, contributor, administrator = get_users(db) application_settings = omb.generate_default_application_settings() application_settings.unrestricted_users = [contributor] dbsession.add(application_settings) dbsession.commit()
def test_zzz_cleanup(self): """Clean up after the tests.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Destruction db.clear_all_tables() h.destroy_all_directories('users', self.settings) h.destroy_all_directories('corpora', self.settings) dbsession.commit() self.create_db()
def test_e_cleanup(self): """Clean up the database after /rememberedforms tests.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) db.clear_all_models() administrator = omb.generate_default_administrator( settings=self.settings) contributor = omb.generate_default_contributor(settings=self.settings) viewer = omb.generate_default_viewer(settings=self.settings) dbsession.add_all([administrator, contributor, viewer]) dbsession.commit()
def tearDown(self, **kwargs): """Clean up after a test.""" db = DBUtils(self.dbsession, self.settings) clear_all_tables = kwargs.get('clear_all_tables', False) dirs_to_clear = kwargs.get('dirs_to_clear', []) dirs_to_destroy = kwargs.get('dirs_to_destroy', []) if clear_all_tables: db.clear_all_tables(['language']) else: self.clear_all_models(self.dbsession) for dir_path in dirs_to_clear: h.clear_directory_of_files(getattr(self, dir_path)) for dir_name in dirs_to_destroy: h.destroy_all_directories(self.inflect_p.plural(dir_name), self.settings) if self.Session2: db = DBUtils(self.dbsession, self.settings2) clear_all_tables = kwargs.get('clear_all_tables', False) dirs_to_clear = kwargs.get('dirs_to_clear', []) dirs_to_destroy = kwargs.get('dirs_to_destroy', []) if clear_all_tables: db.clear_all_tables(['language']) else: self.clear_all_models(self.dbsession2) for attr_name in dirs_to_clear: dir_name = attr_name.replace('_path', '') dir_path = h.get_old_directory_path(dir_name, settings=self.settings2) h.clear_directory_of_files(dir_path) for dir_name in dirs_to_destroy: h.destroy_all_directories(self.inflect_p.plural(dir_name), self.settings2) self.tear_down_dbsession()
def test_edit(self): """Tests that GET /orthographies/id/edit returns a JSON object of data necessary to edit the orthography with id=id. The JSON object is of the form {'orthography': {...}, 'data': {...}} or {'error': '...'} (with a 404 status code) depending on whether the id is valid or invalid/unspecified, respectively. """ dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create an orthography to edit. params = self.orthography_create_params.copy() params.update({'name': 'orthography', 'orthography': 'a, b, c'}) params = json.dumps(params) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body assert resp['name'] == 'orthography' assert resp['orthography'] == 'a, b, c' assert resp[ 'lowercase'] is False # default value from model/orthography.py assert resp[ 'initial_glottal_stops'] is True # default value from model/orthography.py orthography_id = resp['id'] # Not logged in: expect 401 Unauthorized response = self.app.get(url('edit', id=orthography_id), status=401) resp = response.json_body assert resp[ 'error'] == 'Authentication is required to access this resource.' assert response.content_type == 'application/json' # Invalid id id = 9876544 response = self.app.get(url('edit', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) assert 'There is no orthography with id %s' % id in response.json_body[ 'error'] assert response.content_type == 'application/json' # No id response = self.app.get(url('edit', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body[ 'error'] == 'The resource could not be found.' # Valid id response = self.app.get(url('edit', id=orthography_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body assert resp['orthography']['name'] == 'orthography' assert resp['orthography']['orthography'] == 'a, b, c' assert resp['data'] == {} assert response.content_type == 'application/json'
def test_show(self): """Tests that GET /syntacticcategories/id returns the syntactic category with id=id or an appropriate error.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create an syntactic category to show. params = json.dumps({'name': 'name', 'type': 'lexical', 'description': 'description'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body syntactic_category_id = resp['id'] # Try to get a syntactic_category using an invalid id id = 100000000000 response = self.app.get(url('show', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) resp = response.json_body assert 'There is no syntactic category with id %s' % id in response.json_body['error'] assert response.content_type == 'application/json' # No id response = self.app.get(url('show', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body['error'] == 'The resource could not be found.' assert response.content_type == 'application/json' # Valid id response = self.app.get(url('show', id=syntactic_category_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body assert resp['name'] == 'name' assert resp['description'] == 'description' assert response.content_type == 'application/json'
def test_new(self): """Tests that GET /elicitationmethods/new returns an empty JSON object.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) response = self.app.get(url('new'), headers=self.json_headers, extra_environ=self.extra_environ_contrib) resp = response.json_body assert resp == {} assert response.content_type == 'application/json'
def test_new(self): """Tests that GET /syntacticcategories/new returns an empty JSON object.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) response = self.app.get(url('new'), headers=self.json_headers, extra_environ=self.extra_environ_contrib) resp = response.json_body assert resp['syntactic_category_types'] == list(oldc.SYNTACTIC_CATEGORY_TYPES) assert response.content_type == 'application/json'
def test_delete(self): """Tests that DELETE /formsearches/id deletes the form search with id=id.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create a form search to delete. query = {'filter': ['Form', 'transcription', 'regex', '[a-g]{3,}']} params = self.form_search_create_params.copy() params.update({ 'name': 'form search', 'description': 'This one\'s worth saving!', 'search': query }) params = json.dumps(params) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body form_search_count = dbsession.query(FormSearch).count() form_search_id = resp['id'] assert resp['name'] == 'form search' assert resp['description'] == "This one's worth saving!" assert resp['search'] == query # Now delete the form_search response = self.app.delete(url('delete', id=form_search_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body new_form_search_count = dbsession.query(FormSearch).count() assert new_form_search_count == form_search_count - 1 assert resp['id'] == form_search_id assert response.content_type == 'application/json' # Trying to get the deleted form_search from the db should return None deleted_form_search = dbsession.query(FormSearch).get(form_search_id) assert deleted_form_search is None # Delete with an invalid id id = 9999999999999 response = self.app.delete(url('delete', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) assert 'There is no form search with id %s' % id in response.json_body[ 'error'] assert response.content_type == 'application/json' # Delete without an id response = self.app.delete(url('delete', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body[ 'error'] == 'The resource could not be found.'
def test_new(self): """Tests that GET /speakers/new returns an empty JSON object.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) response = self.app.get(url('new'), headers=self.json_headers, extra_environ=self.extra_environ_contrib) resp = response.json_body assert resp == {'markup_languages': list(oldc.MARKUP_LANGUAGES)} assert response.content_type == 'application/json'
def test_delete(self): """Tests that DELETE /speakers/id deletes the speaker with id=id.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create a speaker to delete. params = self.speaker_create_params.copy() params.update({ 'first_name': 'first_name', 'last_name': 'last_name', 'page_content': 'page_content', 'dialect': 'dialect' }) params = json.dumps(params) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body speaker_count = dbsession.query(Speaker).count() speaker_id = resp['id'] # Now delete the speaker response = self.app.delete(url('delete', id=speaker_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body new_speaker_count = dbsession.query(Speaker).count() assert new_speaker_count == speaker_count - 1 assert resp['id'] == speaker_id assert response.content_type == 'application/json' # Trying to get the deleted speaker from the db should return None deleted_speaker = dbsession.query(Speaker).get(speaker_id) assert deleted_speaker is None assert response.content_type == 'application/json' # Delete with an invalid id id = 9999999999999 response = self.app.delete(url('delete', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) assert 'There is no speaker with id %s' % id in response.json_body[ 'error'] assert response.content_type == 'application/json' # Delete without an id response = self.app.delete(url('delete', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body[ 'error'] == 'The resource could not be found.' assert response.content_type == 'application/json'
def test_new(self): """Tests that GET /formsearches/new returns the data necessary to create a new form search.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) response = self.app.get(url('new'), headers=self.json_headers, extra_environ=self.extra_environ_contrib) resp = response.json_body assert 'attributes' in resp['search_parameters'] assert 'relations' in resp['search_parameters'] assert response.content_type == 'application/json'
def test_new_search(self): """Tests that GET /languages/new_search returns the search parameters for searching the languages resource.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) query_builder = SQLAQueryBuilder( dbsession, model_name='Language', settings=self.settings) response = self.app.get( url('new_search'), headers=self.json_headers, extra_environ=self.extra_environ_view) resp = response.json_body assert resp['search_parameters'] == query_builder.get_search_parameters()
def test_show(self): """Tests that GET /formsearches/id returns the formsearch with id=id or an appropriate error.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create a form search to show. query = {'filter': ['Form', 'transcription', 'regex', '[a-g]{3,}']} params = self.form_search_create_params.copy() params.update({ 'name': 'form search', 'description': 'This one\'s worth saving!', 'search': query }) params = json.dumps(params) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body form_search_id = resp['id'] assert resp['name'] == 'form search' assert resp['description'] == "This one's worth saving!" assert resp['search'] == query # Try to get a form search using an invalid id id = 100000000000 response = self.app.get(url('show', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) resp = response.json_body assert 'There is no form search with id %s' % id in response.json_body[ 'error'] assert response.content_type == 'application/json' # No id response = self.app.get(url('show', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body[ 'error'] == 'The resource could not be found.' # Valid id response = self.app.get(url('show', id=form_search_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body assert resp['name'] == 'form search' assert resp['description'] == "This one's worth saving!" assert response.content_type == 'application/json'
def test_new_search(self): """Tests that GET /collectionbackups/new_search returns the search parameters for searching the collection backups resource.""" db = DBUtils(self.dbsession, self.settings) query_builder = SQLAQueryBuilder(self.dbsession, 'CollectionBackup', settings=self.settings) response = self.app.get(url('new_search'), headers=self.json_headers, extra_environ=self.extra_environ_view) resp = response.json_body assert resp[ 'search_parameters'] == query_builder.get_search_parameters()
def test_show(self): """Tests that GET /orthographies/id returns the orthography with id=id or an appropriate error.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create an orthography to show. params = self.orthography_create_params.copy() params.update({'name': 'orthography', 'orthography': 'a, b, c'}) params = json.dumps(params) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body assert resp['name'] == 'orthography' assert resp['orthography'] == 'a, b, c' assert resp[ 'lowercase'] is False # default value from model/orthography.py assert resp[ 'initial_glottal_stops'] is True # default value from model/orthography.py orthography_id = resp['id'] # Try to get an orthography using an invalid id id = 100000000000 response = self.app.get(url('show', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) resp = response.json_body assert 'There is no orthography with id %s' % id in response.json_body[ 'error'] assert response.content_type == 'application/json' # No id response = self.app.get(url('show', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body[ 'error'] == 'The resource could not be found.' assert response.content_type == 'application/json' # Valid id response = self.app.get(url('show', id=orthography_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body assert resp['name'] == 'orthography' assert resp['orthography'] == 'a, b, c' assert response.content_type == 'application/json'
def test_new_search(self): """Tests that GET /formbackups/new_search returns the search parameters for searching the form backups resource.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) query_builder = SQLAQueryBuilder(dbsession, 'FormBackup', settings=self.settings) response = self.app.get('/{}/formbackups/new_search'.format( self.old_name), headers=self.json_headers, extra_environ=self.extra_environ_view) resp = response.json_body assert resp[ 'search_parameters'] == query_builder.get_search_parameters()
def test_show(self): """Tests that GET /speakers/id returns the speaker with id=id or an appropriate error.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create a speaker to show. params = self.speaker_create_params.copy() params.update({ 'first_name': 'first_name', 'last_name': 'last_name', 'page_content': 'page_content', 'dialect': 'dialect' }) params = json.dumps(params) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body speaker_id = resp['id'] # Try to get a speaker using an invalid id id = 100000000000 response = self.app.get(url('show', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) resp = response.json_body assert 'There is no speaker with id %s' % id in response.json_body[ 'error'] assert response.content_type == 'application/json' # No id response = self.app.get(url('show', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body[ 'error'] == 'The resource could not be found.' assert response.content_type == 'application/json' # Valid id response = self.app.get(url('show', id=speaker_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body assert resp['first_name'] == 'first_name' assert resp['dialect'] == 'dialect' assert response.content_type == 'application/json'
def test_create(self): """Tests that POST /speakers creates a new speaker or returns an appropriate error if the input is invalid. """ dbsession = self.dbsession db = DBUtils(dbsession, self.settings) original_speaker_count = dbsession.query(Speaker).count() # Create a valid one params = self.speaker_create_params.copy() params.update({ 'first_name': 'John', 'last_name': 'Doe', 'page_content': 'page_content', 'dialect': 'dialect' }) params = json.dumps(params) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body new_speaker_count = dbsession.query(Speaker).count() assert new_speaker_count == original_speaker_count + 1 assert resp['first_name'] == 'John' assert resp['dialect'] == 'dialect' assert response.content_type == 'application/json' # Invalid because first_name is too long params = self.speaker_create_params.copy() params.update({ 'first_name': 'John' * 400, 'last_name': 'Doe', 'page_content': 'page_content', 'dialect': 'dialect' }) params = json.dumps(params) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body assert resp['errors'][ 'first_name'] == 'Enter a value not more than 255 characters long' assert response.content_type == 'application/json'
def test_create(self): """Tests that POST /syntacticcategories creates a new syntactic category or returns an appropriate error if the input is invalid. """ dbsession = self.dbsession db = DBUtils(dbsession, self.settings) original_SC_count = dbsession.query(SyntacticCategory).count() # Create a valid one params = json.dumps({'name': 'sc', 'type': 'lexical', 'description': 'Described.'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body new_SC_count = dbsession.query(SyntacticCategory).count() assert new_SC_count == original_SC_count + 1 assert resp['name'] == 'sc' assert resp['description'] == 'Described.' assert resp['type'] == 'lexical' assert response.content_type == 'application/json' # Invalid because name is not unique params = json.dumps({'name': 'sc', 'type': 'lexical', 'description': 'Described.'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body assert resp['errors']['name'] == 'The submitted value for SyntacticCategory.name is not unique.' assert response.content_type == 'application/json' # Invalid because name is empty params = json.dumps({'name': '', 'type': 'lexical', 'description': 'Described.'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body assert resp['errors']['name'] == 'Please enter a value' # Invalid because name is too long params = json.dumps({'name': 'name' * 400, 'type': 'lexical', 'description': 'Described.'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body assert resp['errors']['name'] == 'Enter a value not more than 255 characters long' # Invalid because type is not in oldc.SYNTACTIC_CATEGORY_TYPES params = json.dumps({'name': 'name' * 400, 'type': 'spatial', 'description': 'Described.'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body assert resp['errors']['type'] == "Value must be one of: lexical; phrasal; sentential (not 'spatial')" assert response.content_type == 'application/json'
def test_edit(self): """Tests that GET /syntacticcategories/id/edit returns a JSON object of data necessary to edit the syntactic category with id=id. The JSON object is of the form {'syntactic_category': {...}, 'data': {...}} or {'error': '...'} (with a 404 status code) depending on whether the id is valid or invalid/unspecified, respectively. """ dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create an syntactic category to edit. params = json.dumps({'name': 'name', 'type': 'lexical', 'description': 'description'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body syntactic_category_id = resp['id'] # Not logged in: expect 401 Unauthorized response = self.app.get(url('edit', id=syntactic_category_id), status=401) resp = response.json_body assert resp['error'] == 'Authentication is required to access this resource.' assert response.content_type == 'application/json' # Invalid id id = 9876544 response = self.app.get(url('edit', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) assert 'There is no syntactic category with id %s' % id in response.json_body['error'] assert response.content_type == 'application/json' # No id response = self.app.get(url('edit', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body['error'] == 'The resource could not be found.' assert response.content_type == 'application/json' # Valid id response = self.app.get(url('edit', id=syntactic_category_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body assert resp['syntactic_category']['name'] == 'name' assert resp['data']['syntactic_category_types'] == list(oldc.SYNTACTIC_CATEGORY_TYPES) assert response.content_type == 'application/json'
def test_delete(self): """Tests that DELETE /syntacticcategories/id deletes the syntactic_category with id=id.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create an syntactic category to delete. params = json.dumps({'name': 'name', 'type': 'lexical', 'description': 'description'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body syntactic_category_count = dbsession.query(SyntacticCategory).count() syntactic_category_id = resp['id'] # Now delete the syntactic category response = self.app.delete(url('delete', id=syntactic_category_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body new_syntactic_category_count = dbsession.query(SyntacticCategory).count() assert new_syntactic_category_count == syntactic_category_count - 1 assert resp['id'] == syntactic_category_id assert response.content_type == 'application/json' # Trying to get the deleted syntactic category from the db should return None deleted_syntactic_category = dbsession.query(SyntacticCategory).get(syntactic_category_id) assert deleted_syntactic_category is None # Delete with an invalid id id = 9999999999999 response = self.app.delete(url('delete', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) assert 'There is no syntactic category with id %s' % id in response.json_body['error'] assert response.content_type == 'application/json' # Delete without an id response = self.app.delete(url('delete', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body['error'] == 'The resource could not be found.' assert response.content_type == 'application/json'
def test_delete(self): """Tests that DELETE /elicitationmethods/id deletes the elicitation_method with id=id.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create an elicitation method to delete. params = json.dumps({'name': 'name', 'description': 'description'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body elicitation_method_count = dbsession.query(ElicitationMethod).count() elicitation_method_id = resp['id'] # Now delete the elicitation method response = self.app.delete(url('delete', id=elicitation_method_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body new_elicitation_method_count = dbsession.query(ElicitationMethod).count() assert new_elicitation_method_count == elicitation_method_count - 1 assert resp['id'] == elicitation_method_id assert response.content_type == 'application/json' # Trying to get the deleted elicitation method from the db should return None deleted_elicitation_method = dbsession.query(ElicitationMethod).get(elicitation_method_id) assert deleted_elicitation_method is None # Delete with an invalid id id = 9999999999999 response = self.app.delete(url('delete', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) assert 'There is no elicitation method with id %s' % id in response.json_body['error'] assert response.content_type == 'application/json' # Delete without an id response = self.app.delete(url('delete', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body['error'] == 'The resource could not be found.'
def test_update(self): """Tests that PUT /syntacticcategories/id updates the syntacticcategory with id=id.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create an syntactic category to update. params = json.dumps({'name': 'name', 'type': 'lexical', 'description': 'description'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body syntactic_category_count = dbsession.query(SyntacticCategory).count() syntactic_category_id = resp['id'] original_datetime_modified = resp['datetime_modified'] # Update the syntactic category sleep(1) # sleep for a second to ensure that MySQL registers a different datetime_modified for the update params = json.dumps({'name': 'name', 'type': 'lexical', 'description': 'More content-ful description.'}) response = self.app.put(url('update', id=syntactic_category_id), params, self.json_headers, self.extra_environ_admin) resp = response.json_body datetime_modified = resp['datetime_modified'] new_syntactic_category_count = dbsession.query(SyntacticCategory).count() assert syntactic_category_count == new_syntactic_category_count assert datetime_modified != original_datetime_modified assert response.content_type == 'application/json' # Attempt an update with no new input and expect to fail sleep(1) # sleep for a second to ensure that MySQL could register a different datetime_modified for the update response = self.app.put(url('update', id=syntactic_category_id), params, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body syntactic_category_count = new_syntactic_category_count new_syntactic_category_count = dbsession.query(SyntacticCategory).count() our_SC_datetime_modified = dbsession.query(SyntacticCategory).get(syntactic_category_id).datetime_modified assert our_SC_datetime_modified.isoformat() == datetime_modified assert syntactic_category_count == new_syntactic_category_count assert resp['error'] == 'The update request failed because the submitted data were not new.' assert response.content_type == 'application/json'
def test_create(self): """Tests that POST /elicitationmethods creates a new elicitation method or returns an appropriate error if the input is invalid. """ dbsession = self.dbsession db = DBUtils(dbsession, self.settings) original_EM_count = dbsession.query(ElicitationMethod).count() # Create a valid one params = json.dumps({'name': 'em', 'description': 'Described.'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body new_EM_count = dbsession.query(ElicitationMethod).count() assert new_EM_count == original_EM_count + 1 assert resp['name'] == 'em' assert resp['description'] == 'Described.' assert response.content_type == 'application/json' # Invalid because name is not unique params = json.dumps({'name': 'em', 'description': 'Described.'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body assert resp['errors']['name'] == 'The submitted value for ElicitationMethod.name is not unique.' assert response.content_type == 'application/json' # Invalid because name is empty params = json.dumps({'name': '', 'description': 'Described.'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body assert resp['errors']['name'] == 'Please enter a value' # Invalid because name is too long params = json.dumps({'name': 'name' * 400, 'description': 'Described.'}) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body assert resp['errors']['name'] == 'Enter a value not more than 255 characters long'
def test_update(self): """Tests that PUT /speakers/id updates the speaker with id=id.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create a speaker to update. params = self.speaker_create_params.copy() params.update({ 'first_name': 'first_name', 'last_name': 'last_name', 'page_content': 'page_content', 'dialect': 'dialect' }) params = json.dumps(params) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body speaker_count = dbsession.query(Speaker).count() speaker_id = resp['id'] original_datetime_modified = resp['datetime_modified'] # Update the speaker sleep( 1 ) # sleep for a second to ensure that MySQL registers a different datetime_modified for the update params = self.speaker_create_params.copy() params.update({ 'first_name': 'first_name', 'last_name': 'last_name', 'page_content': 'page_content', 'dialect': 'updated dialect.' }) params = json.dumps(params) response = self.app.put(url('update', id=speaker_id), params, self.json_headers, self.extra_environ_admin) resp = response.json_body datetime_modified = resp['datetime_modified'] new_speaker_count = dbsession.query(Speaker).count() assert speaker_count == new_speaker_count assert datetime_modified != original_datetime_modified assert response.content_type == 'application/json' # Attempt an update with no new input and expect to fail sleep( 1 ) # sleep for a second to ensure that MySQL could register a different datetime_modified for the update response = self.app.put(url('update', id=speaker_id), params, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body speaker_count = new_speaker_count new_speaker_count = dbsession.query(Speaker).count() our_speaker_datetime_modified = dbsession.query(Speaker).get( speaker_id).datetime_modified assert our_speaker_datetime_modified.isoformat() == datetime_modified assert speaker_count == new_speaker_count assert resp[ 'error'] == 'The update request failed because the submitted data were not new.' assert response.content_type == 'application/json'
def test_writetofile_content_specified(self): """Tests file writing/retrieval of a corpus whose forms are specified in the ``content`` attribute. """ dbsession = self.dbsession db = DBUtils(dbsession, self.settings) tgrep2_installed = h.command_line_program_installed('tgrep2') # Get ids of all sentences. sentences = dbsession.query(old_models.Form).\ filter(old_models.Form.syntactic_category.\ has(old_models.SyntacticCategory.name=='S')).all() len_sentences = len(sentences) sentences = ','.join(map(str, map(lambda f: f.id, sentences))) # Get ids of all sentences with more than 5 words. long_sentences = dbsession.query(old_models.Form).\ filter(and_( old_models.Form.syntactic_category.has(old_models.SyntacticCategory.name=='S'), old_models.Form.transcription.op('regexp')(u'^([^ ]+ ){5}[^ ]+'))).all() len_long_sentences = len(long_sentences) long_sentences = ','.join(map(str, map(lambda f: f.id, long_sentences))) content = ','.join( [sentences, long_sentences, long_sentences, long_sentences]) anticipated_length = len_sentences + (3 * len_long_sentences) name = 'Corpus of sentences with 6+ word sentences repeated' description = 'Ordered by content field; duplicates of words with more than 6 words.' # Generate some valid corpus creation input parameters. params = self.corpus_create_params.copy() params.update({ 'name': name, 'description': description, 'content': content }) params = json.dumps(params) # Create the corpus original_corpus_count = dbsession.query(Corpus).count() response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body corpus_id = resp['id'] new_corpus_count = dbsession.query(Corpus).count() corpus = dbsession.query(Corpus).get(corpus_id) corpus_dir = os.path.join(self.corpora_path, 'corpus_%d' % corpus_id) corpus_dir_contents = os.listdir(corpus_dir) assert new_corpus_count == original_corpus_count + 1 assert resp['name'] == name assert resp['description'] == description assert corpus_dir_contents == [] assert response.content_type == 'application/json' assert resp['content'] == content # The ``forms`` attribute is a collection, no repeats, that's why the following is true: assert len(corpus.forms) == len_sentences # Write the corpus to file as a treebank sleep(1) params = json.dumps({u'format': 'treebank'}) response = self.app.put('/%s/corpora/%d/writetofile' % (self.old_name, corpus_id), params, headers=self.json_headers, extra_environ=self.extra_environ_admin) resp2 = response.json_body corpus_dir_contents = os.listdir(corpus_dir) corpus_tbk_path = os.path.join(corpus_dir, 'corpus_%d.tbk' % corpus_id) corpus_tbk_gzipped_path = '%s.gz' % corpus_tbk_path corpus_tbk_gzipped_size = get_file_size(corpus_tbk_gzipped_path) corpus_tbk_file_length = h.get_file_length(corpus_tbk_path) corpus_tbk_t2c_path = os.path.join(corpus_dir, 'corpus_%d.tbk.t2c' % corpus_id) corpus_file_id = resp2['files'][0]['id'] assert resp['id'] == resp2['id'] assert resp['name'] == resp2['name'] assert resp2['datetime_modified'] > resp['datetime_modified'] assert os.path.exists(corpus_tbk_path) if tgrep2_installed: assert os.path.exists(corpus_tbk_t2c_path) else: assert not os.path.exists(corpus_tbk_t2c_path) assert os.path.exists(corpus_tbk_gzipped_path) assert get_file_size(corpus_tbk_path) > corpus_tbk_gzipped_size assert anticipated_length == corpus_tbk_file_length # Retrieve the corpus file directly from the filesystem. with open(corpus_tbk_path, 'rb') as filei: corpus_file_object = filei corpus_file_content = corpus_file_object.read() # Attempt to retrieve the gzipped corpus file via request as a restricted # user and expect to fail. response = self.app.get('/%s/corpora/%d/servefile/%d' % (self.old_name, corpus_id, corpus_file_id), status=403, headers=self.json_headers, extra_environ=self.extra_environ_contrib) resp = response.json_body assert resp == UNAUTHORIZED_MSG # Retrieve the gzipped corpus file via request. response = self.app.get('/%s/corpora/%d/servefile/%d' % (self.old_name, corpus_id, corpus_file_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) assert len(response.body) < len(corpus_file_content) unzipped_corpus_file_content = decompress_gzip_string(response.body) assert unzipped_corpus_file_content == corpus_file_content # Write the corpus to file as a list of transcriptions, one per line. sleep(1) params = json.dumps({u'format': 'transcriptions only'}) response = self.app.put('/%s/corpora/%d/writetofile' % (self.old_name, corpus_id), params, headers=self.json_headers, extra_environ=self.extra_environ_admin) old_resp2 = resp2 resp2 = response.json_body corpus_dir_contents = os.listdir(corpus_dir) corpus_TO_path = os.path.join( corpus_dir, 'corpus_%d_transcriptions.txt' % corpus_id) corpus_TO_gzipped_path = '%s.gz' % corpus_TO_path corpus_TO_gzipped_size = get_file_size(corpus_TO_gzipped_path) corpus_TO_file_length = h.get_file_length(corpus_TO_path) if tgrep2_installed: # Five files should be present: tbk, tbk.gz, tbk.t2c, txt and txt.gz assert len(corpus_dir_contents) == 5 else: # Four files should be present: tbk, tbk.gz, txt and txt.gz assert len(corpus_dir_contents) == 4 assert resp2['datetime_modified'] > old_resp2['datetime_modified'] assert os.path.exists(corpus_TO_path) assert os.path.exists(corpus_TO_gzipped_path) assert get_file_size(corpus_TO_path) > corpus_TO_gzipped_size assert anticipated_length == corpus_TO_file_length # Finally delete the corpus and expect it, its file data and corpus file # objects to have been deleted. dbsession.expire(corpus) assert os.path.exists(corpus_TO_path) assert os.path.exists(corpus_TO_gzipped_path) assert os.path.exists(corpus_tbk_path) assert os.path.exists(corpus_tbk_gzipped_path) if tgrep2_installed: assert os.path.exists(corpus_tbk_t2c_path) else: assert not os.path.exists(corpus_tbk_t2c_path) corpus_file_ids = [cf['id'] for cf in resp2['files']] self.app.delete(url('delete', id=corpus_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) assert dbsession.query(old_models.Corpus).get(corpus_id) is None for corpus_file_id in corpus_file_ids: assert dbsession.query(CorpusFile).get(corpus_file_id) is None assert not os.path.exists(corpus_TO_path) assert not os.path.exists(corpus_TO_gzipped_path) assert not os.path.exists(corpus_tbk_path) assert not os.path.exists(corpus_tbk_t2c_path) assert not os.path.exists(corpus_tbk_gzipped_path)
def test_index(self): """Tests that GET /speakers returns an array of all speakers and that order_by and pagination parameters work correctly.""" dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Add 100 speakers. def create_speaker_from_index(index): speaker = old_models.Speaker() speaker.first_name = 'John%d' % index speaker.last_name = 'Doe%d' % index speaker.dialect = 'dialect %d' % index speaker.page_content = 'page content %d' % index return speaker speakers = [create_speaker_from_index(i) for i in range(1, 101)] dbsession.add_all(speakers) dbsession.commit() speakers = db.get_speakers(True) speakers_count = len(speakers) # Test that GET /speakers gives us all of the speakers. response = self.app.get(url('index'), headers=self.json_headers, extra_environ=self.extra_environ_view) resp = response.json_body assert len(resp) == speakers_count assert resp[0]['first_name'] == 'John1' assert resp[0]['id'] == speakers[0].id assert response.content_type == 'application/json' # Test the paginator GET params. paginator = {'items_per_page': 23, 'page': 3} response = self.app.get(url('index'), paginator, headers=self.json_headers, extra_environ=self.extra_environ_view) resp = response.json_body assert len(resp['items']) == 23 assert resp['items'][0]['first_name'] == speakers[46].first_name # Test the order_by GET params. order_by_params = { 'order_by_model': 'Speaker', 'order_by_attribute': 'first_name', 'order_by_direction': 'desc' } response = self.app.get(url('index'), order_by_params, headers=self.json_headers, extra_environ=self.extra_environ_view) resp = response.json_body result_set = sorted([s.first_name for s in speakers], reverse=True) assert result_set == [s['first_name'] for s in resp] # Test the order_by *with* paginator. params = { 'order_by_model': 'Speaker', 'order_by_attribute': 'first_name', 'order_by_direction': 'desc', 'items_per_page': 23, 'page': 3 } response = self.app.get(url('index'), params, headers=self.json_headers, extra_environ=self.extra_environ_view) resp = response.json_body assert result_set[46] == resp['items'][0]['first_name'] # Expect a 400 error when the order_by_direction param is invalid order_by_params = { 'order_by_model': 'Speaker', 'order_by_attribute': 'first_name', 'order_by_direction': 'descending' } response = self.app.get(url('index'), order_by_params, status=400, headers=self.json_headers, extra_environ=self.extra_environ_view) resp = response.json_body assert resp['errors'][ 'order_by_direction'] == "Value must be one of: asc; desc (not 'descending')" assert response.content_type == 'application/json' # Expect the default BY id ASCENDING ordering when the order_by_model/Attribute # param is invalid. order_by_params = { 'order_by_model': 'Speakerist', 'order_by_attribute': 'prenom', 'order_by_direction': 'desc' } response = self.app.get(url('index'), order_by_params, headers=self.json_headers, extra_environ=self.extra_environ_view) resp = response.json_body assert resp[0]['id'] == speakers[0].id # Expect a 400 error when the paginator GET params are empty # or are integers less than 1 paginator = {'items_per_page': 'a', 'page': ''} response = self.app.get(url('index'), paginator, headers=self.json_headers, extra_environ=self.extra_environ_view, status=400) resp = response.json_body assert resp['errors'][ 'items_per_page'] == 'Please enter an integer value' assert resp['errors']['page'] == 'Please enter a value' assert response.content_type == 'application/json' paginator = {'items_per_page': 0, 'page': -1} response = self.app.get(url('index'), paginator, headers=self.json_headers, extra_environ=self.extra_environ_view, status=400) resp = response.json_body assert resp['errors'][ 'items_per_page'] == 'Please enter a number that is 1 or greater' assert resp['errors'][ 'page'] == 'Please enter a number that is 1 or greater' assert response.content_type == 'application/json'
def test_edit(self): """Tests that GET /speakers/id/edit returns a JSON object of data necessary to edit the speaker with id=id. The JSON object is of the form {'speaker': {...}, 'data': {...}} or {'error': '...'} (with a 404 status code) depending on whether the id is valid or invalid/unspecified, respectively. """ dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create a speaker to edit. params = self.speaker_create_params.copy() params.update({ 'first_name': 'first_name', 'last_name': 'last_name', 'page_content': 'page_content', 'dialect': 'dialect' }) params = json.dumps(params) response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body speaker_id = resp['id'] # Not logged in: expect 401 Unauthorized response = self.app.get(url('edit', id=speaker_id), status=401) resp = response.json_body assert resp[ 'error'] == 'Authentication is required to access this resource.' assert response.content_type == 'application/json' # Invalid id id = 9876544 response = self.app.get(url('edit', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) assert 'There is no speaker with id %s' % id in response.json_body[ 'error'] assert response.content_type == 'application/json' # No id response = self.app.get(url('edit', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert response.json_body[ 'error'] == 'The resource could not be found.' assert response.content_type == 'application/json' # Valid id response = self.app.get(url('edit', id=speaker_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body assert resp['speaker']['first_name'] == 'first_name' assert resp['data'] == { 'markup_languages': list(oldc.MARKUP_LANGUAGES) } assert response.content_type == 'application/json'
def test_search(self): """Tests that corpora search works correctly. """ dbsession = self.dbsession db = DBUtils(dbsession, self.settings) # Create a corpus defined by ``content`` that contains all sentences # with five or more words. # Get ids of all sentences with more than 5 words. long_sentences = dbsession.query(old_models.Form).\ filter(and_( old_models.Form.syntactic_category.has(old_models.SyntacticCategory.name=='S'), old_models.Form.transcription.op('regexp')(u'^([^ ]+ ){5}[^ ]+'))).all() long_sentence = long_sentences[0] len_long_sentences = len(long_sentences) long_sentence_ids = [f.id for f in long_sentences] long_sentences = ','.join(map(str, long_sentence_ids)) # Restrict one of the forms that will be in the corpus. restricted_tag = db.get_restricted_tag() long_sentence.tags.append(restricted_tag) dbsession.add(long_sentence) dbsession.commit() # Create the corpus name = 'Sentences with 6 or more words.' params = self.corpus_create_params.copy() params.update({'name': name, 'content': long_sentences}) params = json.dumps(params) original_corpus_count = dbsession.query(Corpus).count() response = self.app.post(url('create'), params, self.json_headers, self.extra_environ_admin) resp = response.json_body corpus_id = resp['id'] new_corpus_count = dbsession.query(Corpus).count() corpus = dbsession.query(Corpus).get(corpus_id) corpus_dir = os.path.join(self.corpora_path, 'corpus_%d' % corpus_id) corpus_dir_contents = os.listdir(corpus_dir) assert new_corpus_count == original_corpus_count + 1 assert resp['name'] == name assert corpus_dir_contents == [] assert response.content_type == 'application/json' assert resp['content'] == long_sentences # The ``forms`` attribute is a collection, no repeats, that's why the following is true: assert len(corpus.forms) == len_long_sentences # Search the corpus for forms beginning in vowels. query = json.dumps({ "query": { "filter": ['Form', 'transcription', 'regex', '^[AEIOUaeiou]'] }, "paginator": { 'page': 1, 'items_per_page': 10 } }) response = self.app.post( '/%s/corpora/%d/search' % (self.old_name, corpus_id), query, self.json_headers, self.extra_environ_admin) resp = response.json_body matches = resp['items'] assert not set([f['id'] for f in matches]) - set(long_sentence_ids) assert len( list( filter( lambda f: f['transcription'][0].lower() not in ['a', 'e', 'i', 'o', 'u'], matches))) == 0 assert len( list( filter(lambda f: len(f['transcription'].split(' ')) < 6, matches))) == 0 # Vacuous search of the corpus returns everything. query = json.dumps( {"query": { "filter": ['Form', 'transcription', 'like', '%'] }}) response = self.app.post( '/%s/corpora/%d/search' % (self.old_name, corpus_id), query, self.json_headers, self.extra_environ_admin) resp = response.json_body assert set([f['id'] for f in resp]) == set(long_sentence_ids) # Vacuous search as the viewer returns everything that is not restricted. query = json.dumps( {"query": { "filter": ['Form', 'transcription', 'like', '%'] }}) response = self.app.post( '/%s/corpora/%d/search' % (self.old_name, corpus_id), query, self.json_headers, self.extra_environ_view) resp2 = response.json_body # Viewer will get 1 or 2 forms fewer (2 are restricted, 1 assuredly a long sentence.) assert len(resp) > len(resp2) # Failed search with an invalid corpus id query = json.dumps( {"query": { "filter": ['Form', 'transcription', 'like', '%'] }}) response = self.app.post('/%s/corpora/123456789/search' % self.old_name, query, self.json_headers, self.extra_environ_admin, status=404) resp = response.json_body assert resp['error'] == 'There is no corpus with id 123456789' # Failed search with an invalid query query = json.dumps( {"query": { "filter": ['Form', 'thingamafracasicle', 'like', '%'] }}) response = self.app.post('/%s/corpora/%d/search' % (self.old_name, corpus_id), query, self.json_headers, self.extra_environ_admin, status=400) resp = response.json_body assert resp['errors'][ 'Form.thingamafracasicle'] == 'There is no attribute thingamafracasicle of Form' # Request GET /corpora/new_search response = self.app.get(url('new_search'), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = response.json_body query_builder = SQLAQueryBuilder(dbsession, 'Form', settings=self.settings) assert resp == { 'search_parameters': query_builder.get_search_parameters() }