Skip to content
Snippets Groups Projects
test_response.py 7.63 KiB
import json
import jsonschema
from compendium_v2.db.auth_model import User
from compendium_v2.db.survey_models import ResponseStatus
from compendium_v2.routes.response import SURVEY_RESPONSE_SCHEMA, VerificationStatus, SURVEY_LOCK_SCHEMA, \
    SURVEY_STATUS_RESPONSE_SCHEMA


def test_response_route_try_response(client, test_survey_data):
    rv = client.get('/api/response/try/2022', headers={'Accept': ['application/json']})
    assert rv.status_code == 200
    result = json.loads(rv.data.decode('utf-8'))
    jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA)
    assert result


def test_response_route_inspect_response(client, test_survey_data):
    rv = client.get('/api/response/inspect/2022', headers={'Accept': ['application/json']})
    assert rv.status_code == 200
    result = json.loads(rv.data.decode('utf-8'))
    jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA)
    assert result


def test_response_route_load_save_closed_survey(client, test_survey_data, mocked_user):
    rv = client.post(
        '/api/response/save/2021/nren2',
        headers={'Accept': ['application/json']},
        json={
            'data': {'q1': 'yes', 'q2': ['no']},
            'page': 3,
            'verification_status': {'q1': VerificationStatus.Verified}
        })
    assert rv.status_code == 400
    result = json.loads(rv.data.decode('utf-8'))
    assert not result.get('success')
    assert result.get('message') == 'Survey is closed'

    rv = client.get('/api/response/load/2021/nren2', headers={'Accept': ['application/json']})
    assert rv.status_code == 200
    result = json.loads(rv.data.decode('utf-8'))
    jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA)
    assert result['page'] == 0
    assert result['data'] == {}
    assert result['verification_status'] == {}


def test_response_route_load_lock_save_response(client, test_survey_data, mocked_user):
    rv = client.post(
        '/api/response/save/2023/nren2',
        headers={'Accept': ['application/json']},
        json={
            'data': {'q1': 'yes', 'q2': ['no']},
            'page': 3,
            'verification_status': {'q1': VerificationStatus.Verified}
        })
    assert rv.status_code == 400
    result = json.loads(rv.data.decode('utf-8'))
    assert result.get('message') == 'Survey response not found'

    rv = client.get('/api/response/load/2023/nren2', headers={'Accept': ['application/json']})
    assert rv.status_code == 200
    result = json.loads(rv.data.decode('utf-8'))
    jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA)
    assert result['page'] == 0
    assert result['data'] == {}
    assert result['verification_status'] == {}

    rv = client.post('/api/response/lock/2023/nren2', headers={'Accept': ['application/json']})
    assert rv.status_code == 200
    result = json.loads(rv.data.decode('utf-8'))
    jsonschema.validate(result, SURVEY_LOCK_SCHEMA)
    lock_uuid = result.get('lock_uuid')
    assert lock_uuid
    assert result.get('locked_by') == mocked_user.fullname
    assert result.get('status') == ResponseStatus.started.value

    rv = client.post(
        '/api/response/save/2023/nren2',
        headers={'Accept': ['application/json']},
        json={
            'data': {'q1': 'yes', 'q2': ['no']},
            'page': 3,
            'verification_status': {'q1': VerificationStatus.Verified},
            'lock_uuid': 'incorrect_uuid',
            'new_state': 'completed'
        })
    assert rv.status_code == 403
    result = json.loads(rv.data.decode('utf-8'))
    assert result.get('message') == 'Somebody else is currently editing this survey.'

    rv = client.post(
        '/api/response/save/2023/nren2',
        headers={'Accept': ['application/json']},
        json={
            'data': {'q1': 'yes', 'q2': ['no']},
            'page': 3,
            'verification_status': {'q1': VerificationStatus.Verified},
            'lock_uuid': lock_uuid,
            'new_state': 'completed'
        })
    assert rv.status_code == 200
    result = json.loads(rv.data.decode('utf-8'))
    jsonschema.validate(result, SURVEY_STATUS_RESPONSE_SCHEMA)
    assert result.get('mode') == 'display'

    rv = client.get('/api/response/load/2023/nren2', headers={'Accept': ['application/json']})
    assert rv.status_code == 200
    result = json.loads(rv.data.decode('utf-8'))
    jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA)
    assert result['page'] == 3
    assert result['data'] == {'q1': 'yes', 'q2': ['no']}
    assert result['verification_status'] == {'q1': VerificationStatus.Verified}
    assert result['locked_by'] == ''
    assert result['mode'] == 'display'
    assert result['status'] == ResponseStatus.completed.value


def test_response_route_unlock(client, test_survey_data, mocked_user):
    rv = client.post('/api/response/unlock/2023/nren2', headers={'Accept': ['application/json']})
    assert rv.status_code == 404
    result = json.loads(rv.data.decode('utf-8'))
    assert result.get('message') == 'Survey response not found'

    rv = client.post('/api/response/lock/2023/nren2', headers={'Accept': ['application/json']})
    assert rv.status_code == 200
    result = json.loads(rv.data.decode('utf-8'))
    jsonschema.validate(result, SURVEY_LOCK_SCHEMA)
    lock_uuid = result.get('lock_uuid')
    assert lock_uuid
    assert result.get('locked_by') == mocked_user.fullname
    assert result.get('status') == ResponseStatus.started.value

    rv = client.post('/api/response/unlock/2023/nren2', headers={'Accept': ['application/json']})
    assert rv.status_code == 200
    result = json.loads(rv.data.decode('utf-8'))
    jsonschema.validate(result, SURVEY_STATUS_RESPONSE_SCHEMA)
    assert result.get('locked_by') == ''


def test_response_route_lock_prevents_other_edits(app, mocker, client, test_survey_data, mocked_user):
    rv = client.post('/api/response/lock/2023/nren2', headers={'Accept': ['application/json']})
    assert rv.status_code == 200
    result = json.loads(rv.data.decode('utf-8'))
    jsonschema.validate(result, SURVEY_LOCK_SCHEMA)
    lock_uuid = result.get('lock_uuid')
    assert lock_uuid
    assert result.get('locked_by') == mocked_user.fullname
    assert result.get('status') == ResponseStatus.started.value

    def user_loader(*args):
        user2 = User(email='otheruser@email.local', fullname='otheruser', oidc_sub='fakesub2', roles='user')
        user2.nrens = [mocked_user.nren]
        return user2
    mocker.patch('flask_login.utils._get_user', user_loader)

    rv = client.post('/api/response/lock/2023/nren2', headers={'Accept': ['application/json']})
    assert rv.status_code == 403
    result = json.loads(rv.data.decode('utf-8'))
    assert result.get('message') == 'This survey is already locked.'


def test_response_routes_observer(app, client, test_survey_data, mocked_observer_user):
    # observers should not be able to modify surveys, but should be able to view all of them

    rv = client.get(
        '/api/survey/list',
        headers={'Accept': ['application/json']})
    assert rv.status_code == 200

    surveys = json.loads(rv.data.decode('utf-8'))
    assert surveys

    # load the first survey and check that the observer can view it
    rv = client.get(
        f'/api/response/load/{surveys[0]["year"]}/nren1',
        headers={'Accept': ['application/json']})
    assert rv.status_code == 200

    # try to lock the first survey and check that the observer can't
    rv = client.post(
        f'/api/response/lock/{surveys[0]["year"]}/nren1',
        headers={'Accept': ['application/json']})
    assert rv.status_code == 403

    # try to save the first survey and check that the observer can't
    rv = client.post(
        f'/api/response/save/{surveys[0]["year"]}/nren1',
        headers={'Accept': ['application/json']})
    assert rv.status_code == 403