Пример #1
0
    def test_show(self):
        """Tests that GET /applicationsettings/id returns the JSON application settings object with id=id
        or a 404 status code depending on whether the id is valid or
        invalid/unspecified, respectively.
        """

        # Invalid id
        id = 100000000000
        response = self.app.get(url('applicationsetting', id=id),
                            extra_environ=self.extra_environ_admin, status=404)
        assert json.loads(response.body)['error'] == u'There is no application settings with id %s' % id
        assert response.content_type == 'application/json'

        # No id
        response = self.app.get(url('applicationsetting', id=''), status=404,
                                extra_environ=self.extra_environ_admin)
        assert json.loads(response.body)['error'] == \
            'The resource could not be found.'

        # Add the default application settings.
        application_settings = add_default_application_settings()
        application_settings = h.get_application_settings()
        application_settings_id = application_settings.id

        # Valid id
        response = self.app.get(url('applicationsetting', id=application_settings_id),
                                extra_environ=self.extra_environ_admin)
        resp = json.loads(response.body)
        assert response.content_type == 'application/json'
        assert type(resp) == type({})
        assert resp['object_language_name'] == \
            application_settings.object_language_name
        assert resp['storage_orthography']['name'] == \
            application_settings.storage_orthography.name
Пример #2
0
    def delete(self, id):
        """Delete an existing orthography and return it.

        :URL: ``DELETE /orthographies/id``
        :param str id: the ``id`` value of the orthography to be deleted.
        :returns: the deleted orthography model.

        .. note::
        
            Contributors can only delete orthographies that are not used in the
            active application settings.

        """
        orthography = Session.query(Orthography).get(id)
        if orthography:
            app_set = h.get_application_settings()
            if session['user'].role == u'administrator' or orthography not in (
            app_set.storage_orthography, app_set.input_orthography, app_set.output_orthography):
                Session.delete(orthography)
                Session.commit()
                return orthography
            else:
                response.status = 403
                return {'error': u'Only administrators are permitted to delete orthographies that are used in the active application settings.'}
        else:
            response.status_int = 404
            return {'error': 'There is no orthography with id %s' % id}
Пример #3
0
    def delete(self, id):
        """Delete an existing orthography and return it.

        :URL: ``DELETE /orthographies/id``
        :param str id: the ``id`` value of the orthography to be deleted.
        :returns: the deleted orthography model.

        .. note::
        
            Contributors can only delete orthographies that are not used in the
            active application settings.

        """
        orthography = Session.query(Orthography).get(id)
        if orthography:
            app_set = h.get_application_settings()
            if session['user'].role == u'administrator' or orthography not in (
                    app_set.storage_orthography, app_set.input_orthography,
                    app_set.output_orthography):
                Session.delete(orthography)
                Session.commit()
                return orthography
            else:
                response.status = 403
                return {
                    'error':
                    u'Only administrators are permitted to delete orthographies that are used in the active application settings.'
                }
        else:
            response.status_int = 404
            return {'error': 'There is no orthography with id %s' % id}
Пример #4
0
    def update(self, id):
        """Update an orthography and return it.
        
        :URL: ``PUT /orthographies/id``
        :Request body: JSON object representing the orthography with updated attribute values.
        :param str id: the ``id`` value of the orthography to be updated.
        :returns: the updated orthography model.

        .. note::
        
            Contributors can only update orthographies that are not used in the
            active application settings.

        """
        orthography = Session.query(Orthography).get(int(id))
        user = session['user']
        if orthography:
            app_set = h.get_application_settings()
            if user.role == u'administrator' or orthography not in (
                    app_set.storage_orthography, app_set.input_orthography,
                    app_set.output_orthography):
                try:
                    schema = OrthographySchema()
                    values = json.loads(unicode(request.body, request.charset))
                    state = h.get_state_object(values)
                    state.id = id
                    result = schema.to_python(values, state)
                    orthography = update_orthography(orthography, result)
                    # orthography will be False if there are no changes (cf. update_orthography).
                    if orthography:
                        Session.add(orthography)
                        Session.commit()
                        return orthography
                    else:
                        response.status_int = 400
                        return {
                            'error':
                            u'The update request failed because the submitted data were not new.'
                        }
                except h.JSONDecodeError:
                    response.status_int = 400
                    return h.JSONDecodeErrorResponse
                except Invalid, e:
                    response.status_int = 400
                    return {'errors': e.unpack_errors()}
            else:
                response.status = 403
                return {
                    'error':
                    u'Only administrators are permitted to update orthographies that are used in the active application settings.'
                }
Пример #5
0
    def update(self, id):
        """Update an orthography and return it.
        
        :URL: ``PUT /orthographies/id``
        :Request body: JSON object representing the orthography with updated attribute values.
        :param str id: the ``id`` value of the orthography to be updated.
        :returns: the updated orthography model.

        .. note::
        
            Contributors can only update orthographies that are not used in the
            active application settings.

        """
        orthography = Session.query(Orthography).get(int(id))
        user = session['user']
        if orthography:
            app_set = h.get_application_settings()
            if user.role == u'administrator' or orthography not in (
            app_set.storage_orthography, app_set.input_orthography, app_set.output_orthography):
                try:
                    schema = OrthographySchema()
                    values = json.loads(unicode(request.body, request.charset))
                    state = h.get_state_object(values)
                    state.id = id
                    result = schema.to_python(values, state)
                    orthography = update_orthography(orthography, result)
                    # orthography will be False if there are no changes (cf. update_orthography).
                    if orthography:
                        Session.add(orthography)
                        Session.commit()
                        return orthography
                    else:
                        response.status_int = 400
                        return {'error':
                            u'The update request failed because the submitted data were not new.'}
                except h.JSONDecodeError:
                    response.status_int = 400
                    return h.JSONDecodeErrorResponse
                except Invalid, e:
                    response.status_int = 400
                    return {'errors': e.unpack_errors()}
            else:
                response.status = 403
                return {'error': u'Only administrators are permitted to update orthographies that are used in the active application settings.'}
Пример #6
0
    def delete(self, id):
        """Delete an existing application settings and return it.

        :URL: ``DELETE /applicationsettings/id``
        :param str id: the ``id`` value of the application settings to be deleted.
        :returns: the deleted application settings model.

        """
        application_settings = h.eagerload_application_settings(
            Session.query(ApplicationSettings)).get(id)
        if application_settings:
            active_application_settings_id = getattr(h.get_application_settings(), 'id', None)
            to_be_deleted_application_settings_id = application_settings.id
            Session.delete(application_settings)
            Session.commit()
            if active_application_settings_id == to_be_deleted_application_settings_id:
                app_globals.application_settings = h.ApplicationSettings()
            return application_settings
        else:
            response.status_int = 404
            return {'error': 'There is no application settings with id %s' % id}
Пример #7
0
    def delete(self, id):
        """Delete an existing application settings and return it.

        :URL: ``DELETE /applicationsettings/id``
        :param str id: the ``id`` value of the application settings to be deleted.
        :returns: the deleted application settings model.

        """
        application_settings = h.eagerload_application_settings(
            Session.query(ApplicationSettings)).get(id)
        if application_settings:
            active_application_settings_id = getattr(
                h.get_application_settings(), 'id', None)
            to_be_deleted_application_settings_id = application_settings.id
            Session.delete(application_settings)
            Session.commit()
            if active_application_settings_id == to_be_deleted_application_settings_id:
                app_globals.application_settings = h.ApplicationSettings()
            return application_settings
        else:
            response.status_int = 404
            return {
                'error': 'There is no application settings with id %s' % id
            }
Пример #8
0
    def test_delete(self):
        """Tests that DELETE /orthographies/id deletes the orthography with id=id."""

        # Create an orthography to delete.
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c'})
        params = json.dumps(params)
        response = self.app.post(url('orthographies'), params, self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        orthography_count = Session.query(Orthography).count()
        assert resp['name'] == u'orthography'
        assert resp['orthography'] == u'a, b, c'
        assert resp['lowercase'] == False   # default value from model/orthography.py
        assert resp['initial_glottal_stops'] == True    # default value from model/orthography.py
        orthography_id = resp['id']
        original_datetime_modified = resp['datetime_modified']

        # Now delete the orthography
        response = self.app.delete(url('orthography', id=orthography_id), headers=self.json_headers,
            extra_environ=self.extra_environ_admin)
        resp = json.loads(response.body)
        new_orthography_count = Session.query(Orthography).count()
        assert new_orthography_count == orthography_count - 1
        assert resp['id'] == orthography_id
        assert response.content_type == 'application/json'

        # Trying to get the deleted orthography from the db should return None
        deleted_orthography = Session.query(Orthography).get(orthography_id)
        assert deleted_orthography == None

        # Delete with an invalid id
        id = 9999999999999
        response = self.app.delete(url('orthography', id=id),
            headers=self.json_headers, extra_environ=self.extra_environ_admin,
            status=404)
        assert u'There is no orthography with id %s' % id in json.loads(response.body)['error']
        assert response.content_type == 'application/json'

        # Delete without an id
        response = self.app.delete(url('orthography', id=''), status=404,
            headers=self.json_headers, extra_environ=self.extra_environ_admin)
        assert json.loads(response.body)['error'] == 'The resource could not be found.'
        assert response.content_type == 'application/json'

        # Observe how deletions are restricted when an orthography is part of an
        # active application settings ...

        # Create an orthography to demonstrate.
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c'})
        params = json.dumps(params)
        response = self.app.post(url('orthographies'), params, self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        orthography_count = Session.query(Orthography).count()
        assert resp['name'] == u'orthography'
        assert resp['orthography'] == u'a, b, c'
        assert resp['lowercase'] == False   # default value from model/orthography.py
        assert resp['initial_glottal_stops'] == True    # default value from model/orthography.py
        orthography_id = resp['id']

        # Create an application settings with the above orthography as the storage orthography
        app_set = h.generate_default_application_settings()
        app_set.storage_orthography = Session.query(Orthography).get(orthography_id)
        Session.add(app_set)
        Session.commit()

        # Now attempting to delete as a contributor should fail
        response = self.app.delete(url('orthography', id=orthography_id),
                    headers=self.json_headers, extra_environ=self.extra_environ_contrib, status=403)
        resp = json.loads(response.body)
        assert resp['error'] == u'Only administrators are permitted to delete orthographies that are used in the active application settings.'
        assert response.content_type == 'application/json'

        # If we now remove the orthography from the application settings, the
        # contributor will be able to delete it.
        app_set = h.get_application_settings()
        app_set.storage_orthography = None
        Session.commit()
        response = self.app.delete(url('orthography', id=orthography_id),
                    headers=self.json_headers, extra_environ=self.extra_environ_contrib)
        resp = json.loads(response.body)
        assert response.content_type == 'application/json'
        assert resp['orthography'] == u'a, b, c'
Пример #9
0
    def test_update(self):
        """Tests that PUT /orthographies/id updates the orthography with id=id."""

        # Create an orthography to update.
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c'})
        params = json.dumps(params)
        response = self.app.post(url('orthographies'), params, self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        orthography_count = Session.query(Orthography).count()
        assert resp['name'] == u'orthography'
        assert resp['orthography'] == u'a, b, c'
        assert resp['lowercase'] == False   # default value from model/orthography.py
        assert resp['initial_glottal_stops'] == True    # default value from model/orthography.py
        assert response.content_type == 'application/json'
        orthography_id = resp['id']
        original_datetime_modified = resp['datetime_modified']

        # Update the orthography
        sleep(1)    # sleep for a second to ensure that MySQL registers a different datetime_modified for the update
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c, d'})
        params = json.dumps(params)
        response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        datetime_modified = resp['datetime_modified']
        new_orthography_count = Session.query(Orthography).count()
        assert orthography_count == new_orthography_count
        assert datetime_modified != original_datetime_modified
        assert resp['orthography'] == u'a, b, c, d'
        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('orthography', id=orthography_id), params, self.json_headers,
                                 self.extra_environ_admin, status=400)
        resp = json.loads(response.body)
        orthography_count = new_orthography_count
        new_orthography_count = Session.query(Orthography).count()
        our_orthography_datetime_modified = Session.query(Orthography).get(orthography_id).datetime_modified
        assert our_orthography_datetime_modified.isoformat() == datetime_modified
        assert orthography_count == new_orthography_count
        assert resp['error'] == u'The update request failed because the submitted data were not new.'
        assert response.content_type == 'application/json'

        # Observe how updates are restricted when an orthography is part of an
        # active application settings ...
        app_set = h.generate_default_application_settings()
        app_set.storage_orthography = Session.query(Orthography).get(orthography_id)
        Session.add(app_set)
        Session.commit()

        # Now attempting a valid update as a contributor should fail
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c, d, e'})
        params = json.dumps(params)
        response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers,
                                 self.extra_environ_contrib, status=403)
        resp = json.loads(response.body)
        assert resp['error'] == u'Only administrators are permitted to update orthographies that are used in the active application settings.'
        assert response.content_type == 'application/json'

        # The same update as an admin should succeed.
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c, d, e'})
        params = json.dumps(params)
        response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        assert resp['name'] == u'orthography'
        assert resp['orthography'] == u'a, b, c, d, e'
        assert response.content_type == 'application/json'

        # If we now remove the orthography from the application settings, the
        # contributor will be able to edit it.
        app_set = h.get_application_settings()
        app_set.storage_orthography = None
        Session.commit()
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c, d, e, f'})
        params = json.dumps(params)
        response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers,
                                 self.extra_environ_contrib)
        resp = json.loads(response.body)
        assert response.content_type == 'application/json'
        assert resp['name'] == u'orthography'
        assert resp['orthography'] == u'a, b, c, d, e, f'
Пример #10
0
    def test_delete(self):
        """Tests that DELETE /orthographies/id deletes the orthography with id=id."""

        # Create an orthography to delete.
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c'})
        params = json.dumps(params)
        response = self.app.post(url('orthographies'), params,
                                 self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        orthography_count = Session.query(Orthography).count()
        assert resp['name'] == u'orthography'
        assert resp['orthography'] == u'a, b, c'
        assert resp[
            'lowercase'] == False  # default value from model/orthography.py
        assert resp[
            'initial_glottal_stops'] == True  # default value from model/orthography.py
        orthography_id = resp['id']
        original_datetime_modified = resp['datetime_modified']

        # Now delete the orthography
        response = self.app.delete(url('orthography', id=orthography_id),
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin)
        resp = json.loads(response.body)
        new_orthography_count = Session.query(Orthography).count()
        assert new_orthography_count == orthography_count - 1
        assert resp['id'] == orthography_id
        assert response.content_type == 'application/json'

        # Trying to get the deleted orthography from the db should return None
        deleted_orthography = Session.query(Orthography).get(orthography_id)
        assert deleted_orthography == None

        # Delete with an invalid id
        id = 9999999999999
        response = self.app.delete(url('orthography', id=id),
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin,
                                   status=404)
        assert u'There is no orthography with id %s' % id in json.loads(
            response.body)['error']
        assert response.content_type == 'application/json'

        # Delete without an id
        response = self.app.delete(url('orthography', id=''),
                                   status=404,
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin)
        assert json.loads(
            response.body)['error'] == 'The resource could not be found.'
        assert response.content_type == 'application/json'

        # Observe how deletions are restricted when an orthography is part of an
        # active application settings ...

        # Create an orthography to demonstrate.
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c'})
        params = json.dumps(params)
        response = self.app.post(url('orthographies'), params,
                                 self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        orthography_count = Session.query(Orthography).count()
        assert resp['name'] == u'orthography'
        assert resp['orthography'] == u'a, b, c'
        assert resp[
            'lowercase'] == False  # default value from model/orthography.py
        assert resp[
            'initial_glottal_stops'] == True  # default value from model/orthography.py
        orthography_id = resp['id']

        # Create an application settings with the above orthography as the storage orthography
        app_set = h.generate_default_application_settings()
        app_set.storage_orthography = Session.query(Orthography).get(
            orthography_id)
        Session.add(app_set)
        Session.commit()

        # Now attempting to delete as a contributor should fail
        response = self.app.delete(url('orthography', id=orthography_id),
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_contrib,
                                   status=403)
        resp = json.loads(response.body)
        assert resp[
            'error'] == u'Only administrators are permitted to delete orthographies that are used in the active application settings.'
        assert response.content_type == 'application/json'

        # If we now remove the orthography from the application settings, the
        # contributor will be able to delete it.
        app_set = h.get_application_settings()
        app_set.storage_orthography = None
        Session.commit()
        response = self.app.delete(url('orthography', id=orthography_id),
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_contrib)
        resp = json.loads(response.body)
        assert response.content_type == 'application/json'
        assert resp['orthography'] == u'a, b, c'
Пример #11
0
    def test_update(self):
        """Tests that PUT /orthographies/id updates the orthography with id=id."""

        # Create an orthography to update.
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c'})
        params = json.dumps(params)
        response = self.app.post(url('orthographies'), params,
                                 self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        orthography_count = Session.query(Orthography).count()
        assert resp['name'] == u'orthography'
        assert resp['orthography'] == u'a, b, c'
        assert resp[
            'lowercase'] == False  # default value from model/orthography.py
        assert resp[
            'initial_glottal_stops'] == True  # default value from model/orthography.py
        assert response.content_type == 'application/json'
        orthography_id = resp['id']
        original_datetime_modified = resp['datetime_modified']

        # Update the orthography
        sleep(
            1
        )  # sleep for a second to ensure that MySQL registers a different datetime_modified for the update
        params = self.orthography_create_params.copy()
        params.update({'name': u'orthography', 'orthography': u'a, b, c, d'})
        params = json.dumps(params)
        response = self.app.put(url('orthography', id=orthography_id), params,
                                self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        datetime_modified = resp['datetime_modified']
        new_orthography_count = Session.query(Orthography).count()
        assert orthography_count == new_orthography_count
        assert datetime_modified != original_datetime_modified
        assert resp['orthography'] == u'a, b, c, d'
        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('orthography', id=orthography_id),
                                params,
                                self.json_headers,
                                self.extra_environ_admin,
                                status=400)
        resp = json.loads(response.body)
        orthography_count = new_orthography_count
        new_orthography_count = Session.query(Orthography).count()
        our_orthography_datetime_modified = Session.query(Orthography).get(
            orthography_id).datetime_modified
        assert our_orthography_datetime_modified.isoformat(
        ) == datetime_modified
        assert orthography_count == new_orthography_count
        assert resp[
            'error'] == u'The update request failed because the submitted data were not new.'
        assert response.content_type == 'application/json'

        # Observe how updates are restricted when an orthography is part of an
        # active application settings ...
        app_set = h.generate_default_application_settings()
        app_set.storage_orthography = Session.query(Orthography).get(
            orthography_id)
        Session.add(app_set)
        Session.commit()

        # Now attempting a valid update as a contributor should fail
        params = self.orthography_create_params.copy()
        params.update({
            'name': u'orthography',
            'orthography': u'a, b, c, d, e'
        })
        params = json.dumps(params)
        response = self.app.put(url('orthography', id=orthography_id),
                                params,
                                self.json_headers,
                                self.extra_environ_contrib,
                                status=403)
        resp = json.loads(response.body)
        assert resp[
            'error'] == u'Only administrators are permitted to update orthographies that are used in the active application settings.'
        assert response.content_type == 'application/json'

        # The same update as an admin should succeed.
        params = self.orthography_create_params.copy()
        params.update({
            'name': u'orthography',
            'orthography': u'a, b, c, d, e'
        })
        params = json.dumps(params)
        response = self.app.put(url('orthography', id=orthography_id), params,
                                self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        assert resp['name'] == u'orthography'
        assert resp['orthography'] == u'a, b, c, d, e'
        assert response.content_type == 'application/json'

        # If we now remove the orthography from the application settings, the
        # contributor will be able to edit it.
        app_set = h.get_application_settings()
        app_set.storage_orthography = None
        Session.commit()
        params = self.orthography_create_params.copy()
        params.update({
            'name': u'orthography',
            'orthography': u'a, b, c, d, e, f'
        })
        params = json.dumps(params)
        response = self.app.put(url('orthography', id=orthography_id), params,
                                self.json_headers, self.extra_environ_contrib)
        resp = json.loads(response.body)
        assert response.content_type == 'application/json'
        assert resp['name'] == u'orthography'
        assert resp['orthography'] == u'a, b, c, d, e, f'
Пример #12
0
    def test_edit(self):
        """Tests that GET /applicationsettings/id/edit returns a JSON object for editing an existing application settings.

        The JSON object is of the form {application_settings: {...}, data: {...}}
        or {'error': '...'} (and a 404 status code) depending on whether the id
        is valid or invalid/unspecified, respectively.
        """

        # Not logged in: expect 401 Unauthorized
        response = self.app.get(
            url('edit_applicationsetting', id=100000000000), status=401)
        resp = json.loads(response.body)
        assert resp['error'] == u'Authentication is required to access this resource.'
        assert response.content_type == 'application/json'

        # Invalid id: expect 404 Not Found
        id = 100000000000
        response = self.app.get(url('edit_applicationsetting', id=id),
                            extra_environ=self.extra_environ_admin, status=404)
        assert json.loads(response.body)['error'] == \
            u'There is no application settings with id %s' % id
        assert response.content_type == 'application/json'

        # No id: expect 404 Not Found
        response = self.app.get(url('edit_applicationsetting', id=''),
            status=404, extra_environ=self.extra_environ_admin)
        assert json.loads(response.body)['error'] == \
            'The resource could not be found.'

        # Add the default application settings.
        application_settings = add_default_application_settings()
        application_settings = h.get_application_settings()
        application_settings_id = application_settings.id

        # Valid id
        response = self.app.get(url('edit_applicationsetting', id=application_settings_id),
                                extra_environ=self.extra_environ_admin)
        resp = json.loads(response.body)
        assert response.content_type == 'application/json'
        assert type(resp) == type({})
        assert resp['application_settings']['object_language_name'] == \
            application_settings.object_language_name

        # Valid id with GET params.  Param values are treated as strings, not
        # JSON.  If any params are specified, the default is to return a JSON
        # array corresponding to store for the param.  There are three cases
        # that will result in an empty JSON array being returned:
        # 1. the param is not specified
        # 2. the value of the specified param is an empty string
        # 3. the value of the specified param is an ISO 8601 UTC datetime
        #    string that matches the most recent datetime_modified value of the
        #    store in question.

        # Get the data currently in the db (see websetup.py for the test data).
        data = {
            'languages': h.get_languages(),
            'users': h.get_mini_dicts_getter('User')(),
            'orthographies': h.get_mini_dicts_getter('Orthography')()
        }
        # JSON.stringify and then re-Python-ify the data.  This is what the data
        # should look like in the response to a simulated GET request.
        data = json.loads(json.dumps(data, cls=h.JSONOLDEncoder))

        params = {
            # Value is a non-empty string: 'users' will be in response.
            'users': 'give me some users!',
            # Value is empty string: 'languages' will not be in response.
            'languages': '',
            # Value is ISO 8601 UTC datetime string that does not match the most
            # recent Orthography.datetime_modified value: 'orthographies' *will*
            # be in the response.
            'orthographies': datetime.datetime.utcnow().isoformat(),
        }
        response = self.app.get(url('edit_applicationsetting', id=application_settings_id), params,
                                extra_environ=self.extra_environ_admin)
        resp = json.loads(response.body)
        assert resp['data']['users'] == data['users']
        assert resp['data']['languages'] == []
        assert resp['data']['orthographies'] == data['orthographies']

        # Invalid id with GET params.  It should still return a 404 Not Found.
        params = {
            # If id were valid, this would cause a users array to be returned also.
            'users': 'True',
        }
        response = self.app.get(
            url('edit_applicationsetting', id=id), params,
            extra_environ=self.extra_environ_admin, status=404)
        assert json.loads(response.body)['error'] == \
            u'There is no application settings with id %s' % id