add functional tests of group endpoints for coordinator view
This commit is contained in:
parent
57d0c9bd55
commit
ea39814b81
@ -8,7 +8,7 @@ from ..schemas import GroupEditSchema, GroupsPaginationSchema, GroupCreateSchema
|
|||||||
DetailGroupSchema
|
DetailGroupSchema
|
||||||
from ...dependencies import db
|
from ...dependencies import db
|
||||||
from ...base.utils import paginate_models
|
from ...base.utils import paginate_models
|
||||||
from ..utils import load_weight_for_project_grade_sheet, calculate_points_for_one_term
|
from ..utils import attach_points_for_first_and_second_term_to_group_models
|
||||||
|
|
||||||
bp = APIBlueprint("groups", __name__, url_prefix="/groups")
|
bp = APIBlueprint("groups", __name__, url_prefix="/groups")
|
||||||
|
|
||||||
@ -21,23 +21,11 @@ def list_groups(year_group_id: int, query: dict) -> dict:
|
|||||||
page = query.get('page')
|
page = query.get('page')
|
||||||
per_page = query.get('per_page')
|
per_page = query.get('per_page')
|
||||||
|
|
||||||
weights = load_weight_for_project_grade_sheet()
|
|
||||||
|
|
||||||
groups_query = Group.search_by_name(year_group_id, search_name)
|
groups_query = Group.search_by_name(year_group_id, search_name)
|
||||||
data = paginate_models(page, groups_query, per_page)
|
data = paginate_models(page, groups_query, per_page)
|
||||||
|
|
||||||
items = data['items']
|
items = data['items']
|
||||||
pgs = []
|
attach_points_for_first_and_second_term_to_group_models(items)
|
||||||
for g in items:
|
|
||||||
if len(g.project_grade_sheet) == 0:
|
|
||||||
pgs.append(None)
|
|
||||||
else:
|
|
||||||
pgs.append(g.project_grade_sheet[0])
|
|
||||||
calculated_points = calculate_points_for_one_term(weights, pgs)
|
|
||||||
|
|
||||||
for group, points in zip(items, calculated_points):
|
|
||||||
group.points_for_first_term = points[0]
|
|
||||||
group.points_for_second_term = points[1]
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"groups": items,
|
"groups": items,
|
||||||
@ -55,13 +43,13 @@ def create_group(year_group_id: int, data: dict) -> dict:
|
|||||||
|
|
||||||
yg = YearGroup.query.filter(YearGroup.id == year_group_id).first()
|
yg = YearGroup.query.filter(YearGroup.id == year_group_id).first()
|
||||||
if yg is None:
|
if yg is None:
|
||||||
abort(404, "YearGroup doesn't exist!")
|
abort(404, "Not found year group!")
|
||||||
|
|
||||||
project_supervisor = ProjectSupervisor.query.filter_by(id=project_supervisor_id).first()
|
project_supervisor = ProjectSupervisor.query.filter_by(id=project_supervisor_id).first()
|
||||||
|
|
||||||
limit_student_per_group = current_app.config.get('LIMIT_STUDENTS_PER_GROUP')
|
limit_student_per_group = current_app.config.get('LIMIT_STUDENTS_PER_GROUP')
|
||||||
if project_supervisor is None:
|
if project_supervisor is None:
|
||||||
abort(400, f"Project Supervisor with id {project_supervisor_id} doesnt exist")
|
abort(404, f"Not found project supervisor!")
|
||||||
elif limit_student_per_group is not None and limit_student_per_group < len(students_indexes):
|
elif limit_student_per_group is not None and limit_student_per_group < len(students_indexes):
|
||||||
abort(400, f"Too much students you want add to group, "
|
abort(400, f"Too much students you want add to group, "
|
||||||
f"The group can have only {limit_student_per_group} students")
|
f"The group can have only {limit_student_per_group} students")
|
||||||
@ -84,10 +72,13 @@ def create_group(year_group_id: int, data: dict) -> dict:
|
|||||||
if len(students_without_groups) > 0:
|
if len(students_without_groups) > 0:
|
||||||
abort(400, "One or more students have already belonged to group!")
|
abort(400, "One or more students have already belonged to group!")
|
||||||
|
|
||||||
|
students = db.session.query(Student).filter(Student.index.in_(students_indexes)).all()
|
||||||
|
if len(students) != len(students_indexes):
|
||||||
|
abort(404, "Not found students!")
|
||||||
|
|
||||||
db.session.add(group)
|
db.session.add(group)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
students = db.session.query(Student).filter(Student.index.in_(students_indexes)).all()
|
|
||||||
for student in students:
|
for student in students:
|
||||||
group.students.append(student)
|
group.students.append(student)
|
||||||
|
|
||||||
@ -135,10 +126,24 @@ def edit_group(id: int, data: dict) -> dict:
|
|||||||
if group is None:
|
if group is None:
|
||||||
abort(404, f"Not found group!")
|
abort(404, f"Not found group!")
|
||||||
|
|
||||||
students = db.session.query(Student).filter(Student.index.in_(data['students'])).all()
|
students_indexes = data.get('students')
|
||||||
group.students = students
|
name = data.get('name')
|
||||||
group.name = data['name']
|
project_supervisor_id = data.get('project_supervisor_id')
|
||||||
group.project_supervisor_id = data['project_supervisor_id']
|
|
||||||
|
if students_indexes is not None:
|
||||||
|
students = db.session.query(Student).filter(Student.index.in_(students_indexes)).all()
|
||||||
|
if len(students_indexes) != len(students):
|
||||||
|
abort(404, 'Not found students!')
|
||||||
|
group.students = students
|
||||||
|
|
||||||
|
if name is not None:
|
||||||
|
group.name = name
|
||||||
|
|
||||||
|
if project_supervisor_id is not None:
|
||||||
|
ps = ProjectSupervisor.query.filter(ProjectSupervisor.id == project_supervisor_id).first()
|
||||||
|
if ps is None:
|
||||||
|
abort(404, "Not found project supervisor!")
|
||||||
|
group.project_supervisor_id = project_supervisor_id
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return {"message": "Group was updated!"}
|
return {"message": "Group was updated!"}
|
||||||
|
@ -207,3 +207,18 @@ def calculate_points_for_one_term(weights: dict, project_grade_sheets: List[Proj
|
|||||||
terms.append((round(fp, 2) * 100, round(sp, 2) * 100))
|
terms.append((round(fp, 2) * 100, round(sp, 2) * 100))
|
||||||
|
|
||||||
return terms
|
return terms
|
||||||
|
|
||||||
|
|
||||||
|
def attach_points_for_first_and_second_term_to_group_models(items: List[Group]) -> None:
|
||||||
|
weights = load_weight_for_project_grade_sheet()
|
||||||
|
pgs = []
|
||||||
|
for g in items:
|
||||||
|
if len(g.project_grade_sheet) == 0:
|
||||||
|
pgs.append(None)
|
||||||
|
else:
|
||||||
|
pgs.append(g.project_grade_sheet[0])
|
||||||
|
calculated_points = calculate_points_for_one_term(weights, pgs)
|
||||||
|
|
||||||
|
for group, points in zip(items, calculated_points):
|
||||||
|
group.points_for_first_term = points[0]
|
||||||
|
group.points_for_second_term = points[1]
|
||||||
|
@ -50,5 +50,3 @@ class YearGroupStudentsFactory(alchemy.SQLAlchemyModelFactory):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = YearGroupStudents
|
model = YearGroupStudents
|
||||||
sqlalchemy_session = db.session
|
sqlalchemy_session = db.session
|
||||||
# year_group_id
|
|
||||||
# student_index
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from .factory import ProjectSupervisorFactory, YearGroupProjectSupervisorsFactory, \
|
from .factory import ProjectSupervisorFactory, YearGroupProjectSupervisorsFactory, \
|
||||||
StudentFactory, YearGroupStudentsFactory
|
StudentFactory, YearGroupStudentsFactory, GroupFactory
|
||||||
from ..app.dependencies import db
|
from ..app.dependencies import db
|
||||||
from ..app.project_supervisor.models import YearGroup, ProjectSupervisor
|
from ..app.project_supervisor.models import YearGroup, ProjectSupervisor
|
||||||
from ..app.students.models import Group, Student, YearGroupStudents
|
from ..app.students.models import Group, Student, YearGroupStudents
|
||||||
@ -58,3 +58,17 @@ def create_student(data: dict, year_group_id: int) -> Student:
|
|||||||
db.session.add(YearGroupStudents(year_group_id=year_group_id, student_index=st.index))
|
db.session.add(YearGroupStudents(year_group_id=year_group_id, student_index=st.index))
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return st
|
return st
|
||||||
|
|
||||||
|
|
||||||
|
def create_groups(yg: YearGroup, amount: int) -> List[Group]:
|
||||||
|
groups = [GroupFactory(year_group_id=yg.id) for _ in range(amount)]
|
||||||
|
db.session.add_all(groups)
|
||||||
|
db.session.commit()
|
||||||
|
return groups
|
||||||
|
|
||||||
|
|
||||||
|
def create_group(data: dict, yg: YearGroup) -> Group:
|
||||||
|
group = Group(**data, year_group_id=yg.id)
|
||||||
|
db.session.add(group)
|
||||||
|
db.session.commit()
|
||||||
|
return group
|
||||||
|
209
backend/tests/functional_tests/coordinator/test_groups.py
Normal file
209
backend/tests/functional_tests/coordinator/test_groups.py
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
import copy
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
from ...utils import _test_case_client, _test_case_client_without_response, assert_model_changes, _test_case_group
|
||||||
|
from ...fake_data import create_year_group, create_groups, create_group, create_students, create_project_supervisors
|
||||||
|
from ....app.dependencies import db
|
||||||
|
from ....app.students.models import Group
|
||||||
|
from ....app.project_supervisor.models import YearGroupProjectSupervisors
|
||||||
|
|
||||||
|
valid_data = {
|
||||||
|
'name': 'System Pri'
|
||||||
|
}
|
||||||
|
|
||||||
|
new_data = {
|
||||||
|
'name': 'Mobile app'
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid_data = {
|
||||||
|
'name': 'Mobile app v2',
|
||||||
|
'students': [123_344, 455_444],
|
||||||
|
'project_supervisor_id': 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_groups(test_app_with_context) -> None:
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
create_groups(yg, 33)
|
||||||
|
data = _test_case_client_without_response(client, f'/api/coordinator/groups/{yg.id}/?per_page=10', None, 200,
|
||||||
|
method='get')
|
||||||
|
assert data.get('max_pages') == 4
|
||||||
|
assert len(data.get('groups')) == 10
|
||||||
|
|
||||||
|
|
||||||
|
def test_detail_group(test_app_with_context) -> None:
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
group = create_group(valid_data, yg)
|
||||||
|
data = _test_case_client_without_response(client, f'/api/coordinator/groups/{group.id}/detail/', None, 200,
|
||||||
|
method='get')
|
||||||
|
assert_model_changes(group, data)
|
||||||
|
|
||||||
|
|
||||||
|
def test_detail_group_if_group_doesnt_exist(test_app_with_context) -> None:
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
_test_case_client(client, '/api/coordinator/groups/11/detail/', None, 'Not found group!', 404, method='get',
|
||||||
|
key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_delete_group(test_app_with_context) -> None:
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
group = create_group(valid_data, yg)
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{group.id}/', None, 'Group was deleted!', 202,
|
||||||
|
method='delete')
|
||||||
|
|
||||||
|
|
||||||
|
def test_delete_group_if_group_doesnt_exist(test_app_with_context) -> None:
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
_test_case_client(client, '/api/coordinator/groups/32/', None, 'Not found group!', 404, method='delete',
|
||||||
|
key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_group(test_app_with_context) -> None:
|
||||||
|
data = copy.copy(new_data)
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
students = create_students(yg, 3)
|
||||||
|
ps = create_project_supervisors(yg, 1)[0]
|
||||||
|
group = create_group(valid_data, yg)
|
||||||
|
data['students'] = [student.index for student in students]
|
||||||
|
data['project_supervisor_id'] = ps.id
|
||||||
|
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{group.id}/', data, 'Group was updated!', 200,
|
||||||
|
method='put')
|
||||||
|
_test_case_group(group, data)
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_group_with_invalid_project_supervisor_id(test_app_with_context) -> None:
|
||||||
|
data = copy.copy(new_data)
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
students = create_students(yg, 3)
|
||||||
|
group = create_group(valid_data, yg)
|
||||||
|
data['students'] = [student.index for student in students]
|
||||||
|
data['project_supervisor_id'] = 10
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{group.id}/', data, 'Not found project supervisor!', 404,
|
||||||
|
method='put', key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_group_with_invalid_data(test_app_with_context) -> None:
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
group = create_group(valid_data, yg)
|
||||||
|
data = {'students': [123_4356, 243_533, 434_343]}
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{group.id}/', data, 'Validation error', 400, method='put')
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_group_with_invalid_student_indexes(test_app_with_context) -> None:
|
||||||
|
data = copy.deepcopy(new_data)
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
group = create_group(valid_data, yg)
|
||||||
|
data['students'] = [123_456, 243_533, 434_343]
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{group.id}/', data, 'Not found students!', 404,
|
||||||
|
method='put', key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_group_if_group_doesnt_exist(test_app_with_context) -> None:
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
_test_case_client(client, '/api/coordinator/groups/333/', new_data, 'Not found group!', 404,
|
||||||
|
method='put', key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_group_if_you_pass_empty_data(test_app_with_context) -> None:
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
_test_case_client(client, '/api/coordinator/groups/333/', {}, 'You have passed empty data!', 400,
|
||||||
|
method='put', key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_group(test_app_with_context) -> None:
|
||||||
|
data = copy.deepcopy(new_data)
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
students = create_students(yg, 3)
|
||||||
|
ps = create_project_supervisors(yg, 1)[0]
|
||||||
|
data['students'] = [student.index for student in students]
|
||||||
|
data['project_supervisor_id'] = ps.id
|
||||||
|
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{yg.id}/', data, 'Group was created!', 201,
|
||||||
|
method='post')
|
||||||
|
assert Group.query.count() == 1
|
||||||
|
_test_case_group(Group.query.first(), data)
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_group_if_year_group_doesnt_exist(test_app_with_context) -> None:
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
_test_case_client(client, '/api/coordinator/groups/22/', invalid_data, 'Not found year group!', 404,
|
||||||
|
method='post', key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_group_if_project_supervisor_doesnt_exist(test_app_with_context) -> None:
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{yg.id}/', invalid_data, 'Not found project supervisor!',
|
||||||
|
404, method='post', key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_group_if_you_exceed_the_group_limit(test_app_with_context) -> None:
|
||||||
|
data = copy.deepcopy(invalid_data)
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
ps = create_project_supervisors(yg, 1)[0]
|
||||||
|
data['project_supervisor_id'] = ps.id
|
||||||
|
limit_group = current_app.config.get('LIMIT_STUDENTS_PER_GROUP')
|
||||||
|
|
||||||
|
data['students'].extend([999_000 + i for i in range(limit_group + 4)])
|
||||||
|
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{yg.id}/', data,
|
||||||
|
f"Too much students you want add to group, The group can have only {limit_group}"
|
||||||
|
" students", 400, method='post', key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_group_if_students_doesnt_exist(test_app_with_context) -> None:
|
||||||
|
data = copy.deepcopy(invalid_data)
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
ps = create_project_supervisors(yg, 1)[0]
|
||||||
|
data['project_supervisor_id'] = ps.id
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{yg.id}/', data, "Not found students!", 404, method='post',
|
||||||
|
key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_group_if_at_least_one_student_belong_to_other_group(test_app_with_context) -> None:
|
||||||
|
data = copy.deepcopy(invalid_data)
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
ps = create_project_supervisors(yg, 1)[0]
|
||||||
|
group = create_group(valid_data, yg)
|
||||||
|
data['project_supervisor_id'] = ps.id
|
||||||
|
student = create_students(yg, 1)[0]
|
||||||
|
group.students.append(student)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
data['students'].extend([student.index])
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{yg.id}/', data,
|
||||||
|
"One or more students have already belonged to group!", 400, method='post', key='error')
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_group_if_limit_of_group_was_exceed_for_project_supervisor(test_app_with_context) -> None:
|
||||||
|
data = copy.deepcopy(invalid_data)
|
||||||
|
with test_app_with_context.test_client() as client:
|
||||||
|
yg = create_year_group()
|
||||||
|
ps = create_project_supervisors(yg, 1)[0]
|
||||||
|
data['project_supervisor_id'] = ps.id
|
||||||
|
|
||||||
|
ygps = YearGroupProjectSupervisors.query.filter_by(project_supervisor_id=ps.id, year_group_id=yg.id). \
|
||||||
|
first()
|
||||||
|
limit_group = ygps.limit_group
|
||||||
|
|
||||||
|
groups = create_groups(yg, limit_group)
|
||||||
|
for group in groups:
|
||||||
|
group.project_supervisor_id = ps.id
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
_test_case_client(client, f'/api/coordinator/groups/{yg.id}/', data,
|
||||||
|
"Can't create new group, project supervisor achieved a limit of groups",
|
||||||
|
400, method='post', key='error')
|
@ -1,8 +1,7 @@
|
|||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ...utils import _test_case_client, _test_case_client_without_response, assert_model_changes
|
from ...utils import _test_case_client, _test_case_client_without_response, assert_model_changes
|
||||||
from ...fake_data import create_project_supervisors, create_year_group, create_students, create_student
|
from ...fake_data import create_year_group, create_students, create_student
|
||||||
from ....app.dependencies import db
|
|
||||||
|
|
||||||
valid_data = {
|
valid_data = {
|
||||||
'first_name': 'Albert',
|
'first_name': 'Albert',
|
||||||
|
@ -3,6 +3,7 @@ from typing import Union
|
|||||||
from flask.testing import FlaskClient
|
from flask.testing import FlaskClient
|
||||||
|
|
||||||
from ..app.dependencies import db
|
from ..app.dependencies import db
|
||||||
|
from ..app.students.models import Group
|
||||||
|
|
||||||
|
|
||||||
def assert_model_changes(model: db.Model, expected_data: dict) -> None:
|
def assert_model_changes(model: db.Model, expected_data: dict) -> None:
|
||||||
@ -27,3 +28,11 @@ def _test_case_client(test_client: FlaskClient, url: str, data: Union[dict, None
|
|||||||
response_data = _test_case_client_without_response(test_client, url, data, status_code, method)
|
response_data = _test_case_client_without_response(test_client, url, data, status_code, method)
|
||||||
assert key in response_data.keys()
|
assert key in response_data.keys()
|
||||||
assert response_data.get(key) == message
|
assert response_data.get(key) == message
|
||||||
|
|
||||||
|
|
||||||
|
def _test_case_group(group: Group, data: dict) -> None:
|
||||||
|
assert group.name == data['name']
|
||||||
|
assert group.project_supervisor_id == data['project_supervisor_id']
|
||||||
|
|
||||||
|
for st in group.students:
|
||||||
|
assert st.index in data['students']
|
||||||
|
Loading…
Reference in New Issue
Block a user