Skip to content
Snippets Groups Projects
Commit 4c987278 authored by Remco Tukker's avatar Remco Tukker
Browse files

add tests and fix build

parent 2279dd1a
No related branches found
No related tags found
1 merge request!57Feature/survey locking system
import logging import logging
from enum import Enum from enum import Enum
from typing import Any from typing import Any, Tuple
from uuid import uuid4 from uuid import uuid4
from flask import Blueprint, request from flask import Blueprint, request
...@@ -99,7 +99,7 @@ def try_survey(year) -> Any: ...@@ -99,7 +99,7 @@ def try_survey(year) -> Any:
response will either a 400 range code with a descriptive message or a 200 code with the following format: response will either a 400 range code with a descriptive message or a 200 code with the following format:
.. asjson:: .. asjson::
compendium_v2.routes.survey.SURVEY_RESPONSE_SCHEMA compendium_v2.routes.response.SURVEY_RESPONSE_SCHEMA
""" """
survey = db.session.scalar(select(Survey).where(Survey.year == year)) survey = db.session.scalar(select(Survey).where(Survey.year == year))
...@@ -128,7 +128,7 @@ def inspect_survey(year) -> Any: ...@@ -128,7 +128,7 @@ def inspect_survey(year) -> Any:
response will either a 400 range code with a descriptive message or a 200 code with the following format: response will either a 400 range code with a descriptive message or a 200 code with the following format:
.. asjson:: .. asjson::
compendium_v2.routes.survey.SURVEY_RESPONSE_SCHEMA compendium_v2.routes.response.SURVEY_RESPONSE_SCHEMA
""" """
survey = db.session.scalar(select(Survey).where(Survey.year == year)) survey = db.session.scalar(select(Survey).where(Survey.year == year))
...@@ -158,7 +158,7 @@ def inspect_survey(year) -> Any: ...@@ -158,7 +158,7 @@ def inspect_survey(year) -> Any:
} }
def get_response_data(response, year, nren_id): def get_response_data(response, year, nren_id) -> Tuple[dict, int, dict, str]:
data = {} data = {}
page = 0 page = 0
verification_status = {} verification_status = {}
...@@ -194,7 +194,7 @@ def load_survey(year, nren_name) -> Any: ...@@ -194,7 +194,7 @@ def load_survey(year, nren_name) -> Any:
response will either a 400 range code with a descriptive message or a 200 code with the following format: response will either a 400 range code with a descriptive message or a 200 code with the following format:
.. asjson:: .. asjson::
compendium_v2.routes.survey.SURVEY_RESPONSE_SCHEMA compendium_v2.routes.response.SURVEY_RESPONSE_SCHEMA
""" """
nren = db.session.scalar(select(NREN).filter(NREN.name == nren_name)) nren = db.session.scalar(select(NREN).filter(NREN.name == nren_name))
...@@ -236,7 +236,7 @@ def lock_survey(year, nren_name) -> Any: ...@@ -236,7 +236,7 @@ def lock_survey(year, nren_name) -> Any:
response will either a 400 range code with a descriptive message or a 200 code with the following format: response will either a 400 range code with a descriptive message or a 200 code with the following format:
.. asjson:: .. asjson::
compendium_v2.routes.survey.SURVEY_LOCK_SCHEMA compendium_v2.routes.response.SURVEY_LOCK_SCHEMA
""" """
nren = db.session.scalar(select(NREN).filter(NREN.name == nren_name)) nren = db.session.scalar(select(NREN).filter(NREN.name == nren_name))
...@@ -299,7 +299,8 @@ def save_survey(year, nren_name) -> Any: ...@@ -299,7 +299,8 @@ def save_survey(year, nren_name) -> Any:
response will either a 400 range code with a descriptive message or a 200 code with the following format: response will either a 400 range code with a descriptive message or a 200 code with the following format:
.. asjson:: .. asjson::
compendium_v2.routes.survey.SURVEY_STATUS_RESPONSE_SCHEMA compendium_v2.routes.response.SURVEY_STATUS_RESPONSE_SCHEMA
""" """
class NewState(str, Enum): class NewState(str, Enum):
...@@ -367,7 +368,8 @@ def unlock_survey(year, nren_name) -> Any: ...@@ -367,7 +368,8 @@ def unlock_survey(year, nren_name) -> Any:
response will either a 400 range code with a descriptive message or a 200 code with the following format: response will either a 400 range code with a descriptive message or a 200 code with the following format:
.. asjson:: .. asjson::
compendium_v2.routes.survey.SURVEY_STATUS_RESPONSE_SCHEMA compendium_v2.routes.response.SURVEY_STATUS_RESPONSE_SCHEMA
""" """
nren = db.session.scalar(select(NREN).filter(NREN.name == nren_name)) nren = db.session.scalar(select(NREN).filter(NREN.name == nren_name))
if nren is None: if nren is None:
......
...@@ -113,12 +113,13 @@ def update_user_view(user_id) -> Any: ...@@ -113,12 +113,13 @@ def update_user_view(user_id) -> Any:
Request data should be in JSON format with the fields you want to update. Request data should be in JSON format with the fields you want to update.
The response will be formatted the same way as in the current_user_view. The response will be formatted the same way as in the current_user_view.
Example JSON request data: Example JSON request data::
{
"role": "admin", {
"active": False, "role": "admin",
"nren": "1" "active": False,
} "nren": "1"
}
:return: :return:
""" """
......
import React, { useEffect, useRef, useState, useCallback } from "react"; import React, { useEffect, useRef, useState, useCallback } from "react";
import { Container, Row } from "react-bootstrap"; import { Container } from "react-bootstrap";
import toast, { Toaster } from "react-hot-toast"; import toast, { Toaster } from "react-hot-toast";
import { Model, Serializer } from "survey-core"; import { Model, Serializer } from "survey-core";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
......
import json import json
import jsonschema import jsonschema
from compendium_v2.routes.response import SURVEY_RESPONSE_SCHEMA, VerificationStatus from compendium_v2.db.auth_model import User
from compendium_v2.db.survey_model import ResponseStatus
from compendium_v2.routes.response import SURVEY_RESPONSE_SCHEMA, VerificationStatus, SURVEY_LOCK_SCHEMA
def test_response_route_try_response(client, test_survey_data): def test_response_route_try_response(client, test_survey_data):
rv = client.get( rv = client.get('/api/response/try/2022', headers={'Accept': ['application/json']})
'/api/response/try/2022',
headers={'Accept': ['application/json']})
assert rv.status_code == 200 assert rv.status_code == 200
result = json.loads(rv.data.decode('utf-8')) result = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA) jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA)
...@@ -14,16 +14,14 @@ def test_response_route_try_response(client, test_survey_data): ...@@ -14,16 +14,14 @@ def test_response_route_try_response(client, test_survey_data):
def test_response_route_inspect_response(client, test_survey_data): def test_response_route_inspect_response(client, test_survey_data):
rv = client.get( rv = client.get('/api/response/inspect/2022', headers={'Accept': ['application/json']})
'/api/response/inspect/2022',
headers={'Accept': ['application/json']})
assert rv.status_code == 200 assert rv.status_code == 200
result = json.loads(rv.data.decode('utf-8')) result = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA) jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA)
assert result assert result
def test_response_route_save_load_response(client, test_survey_data, mocked_user): def test_response_route_load_save_closed_survey(client, test_survey_data, mocked_user):
rv = client.post( rv = client.post(
'/api/response/save/2021/nren2', '/api/response/save/2021/nren2',
headers={'Accept': ['application/json']}, headers={'Accept': ['application/json']},
...@@ -37,9 +35,7 @@ def test_response_route_save_load_response(client, test_survey_data, mocked_user ...@@ -37,9 +35,7 @@ def test_response_route_save_load_response(client, test_survey_data, mocked_user
assert not result.get('success') assert not result.get('success')
assert result.get('message') == 'Survey is closed' assert result.get('message') == 'Survey is closed'
rv = client.get( rv = client.get('/api/response/load/2021/nren2', headers={'Accept': ['application/json']})
'/api/survey/load/2021/nren2',
headers={'Accept': ['application/json']})
assert rv.status_code == 200 assert rv.status_code == 200
result = json.loads(rv.data.decode('utf-8')) result = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA) jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA)
...@@ -47,24 +43,115 @@ def test_response_route_save_load_response(client, test_survey_data, mocked_user ...@@ -47,24 +43,115 @@ def test_response_route_save_load_response(client, test_survey_data, mocked_user
assert result['data'] == {} assert result['data'] == {}
assert result['verification_status'] == {} assert result['verification_status'] == {}
def test_response_route_load_lock_save_response(client, test_survey_data, mocked_user):
rv = client.post( rv = client.post(
'/api/survey/save/2022/nren2', '/api/response/save/2022/nren2',
headers={'Accept': ['application/json']}, headers={'Accept': ['application/json']},
json={ json={
'data': {'q1': 'yes', 'q2': ['no']}, 'data': {'q1': 'yes', 'q2': ['no']},
'page': 3, 'page': 3,
'verification_status': {'q1': VerificationStatus.Verified} '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/2022/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/2022/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/2022/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/2022/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 assert rv.status_code == 200
result = json.loads(rv.data.decode('utf-8')) result = json.loads(rv.data.decode('utf-8'))
assert result.get('success') assert result.get('mode') == 'display'
rv = client.get( rv = client.get('/api/response/load/2022/nren2', headers={'Accept': ['application/json']})
'/api/survey/load/2022/nren2',
headers={'Accept': ['application/json']})
assert rv.status_code == 200 assert rv.status_code == 200
result = json.loads(rv.data.decode('utf-8')) result = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA) jsonschema.validate(result, SURVEY_RESPONSE_SCHEMA)
assert result['page'] == 3 assert result['page'] == 3
assert result['data'] == {'q1': 'yes', 'q2': ['no']} assert result['data'] == {'q1': 'yes', 'q2': ['no']}
assert result['verification_status'] == {'q1': VerificationStatus.Verified} 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/2022/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/2022/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/2022/nren2', headers={'Accept': ['application/json']})
assert rv.status_code == 200
result = json.loads(rv.data.decode('utf-8'))
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/2022/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/2022/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.'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment