Verified Commit 048f3ce0 authored by Peter Stanko's avatar Peter Stanko
Browse files

Fixed tests

parent 42e20272
Pipeline #12645 passed with stage
in 18 minutes and 47 seconds
......@@ -108,7 +108,7 @@ class DataFactory(object):
return entity
def create_component(self, name: str, secret: str = None, component_type: str = 'executor',
ip_addr: str = '0.0.0.0', notes: str = None) -> Component:
ip_addr: str = '127.0.0.1', notes: str = None) -> Component:
secret = secret or f"{name}_secret"
notes = notes or f"Component {name} of type {type}"
return self.__create_entity(Component, name=name, secret=secret,
......
......@@ -41,7 +41,7 @@ class ComponentList(Resource):
data = rest_helpers.parse_request_data(
component_schema, action='create', resource='component'
)
new_component = create_component(data)
new_component = create_component(**data)
return component_schema.dump(new_component)[0], 201
......
......@@ -92,7 +92,7 @@ class CourseList(Resource):
raise ForbiddenError(uid=client.id)
data = rest_helpers.parse_request_data(course_schema, resource='course', action='create')
new_course = create_course(data)
new_course = create_course(**data)
return course_schema.dump(new_course)[0], 201
......
......@@ -90,7 +90,7 @@ class GroupsList(Resource):
group_schema, action='create', resource='group'
)
new_group = create_group(course, data)
new_group = create_group(course, **data)
return group_schema.dump(new_group)[0], 201
......
......@@ -86,7 +86,7 @@ class RoleList(Resource):
data = rest_helpers.parse_request_data(
role_schema, action='create', resource='role'
)
new_role = create_role(course, data)
new_role = create_role(course, **data)
return role_schema.dump(new_role)[0], 201
......
......@@ -11,7 +11,16 @@ def __set_component_data(component: Component, data: dict) -> Component:
return general.update_entity(component, data, allowed=allowed)
def create_component(data: dict) -> Component:
def create_component(**data) -> Component:
"""Create component
Keyword Args:
name(str): Name of the submission
ip_address(str): IP Address
secret(str): Secret
type(str): Type of component
notes(str): Additional notes for the component
"""
component = Component()
__set_component_data(component=component, data=data)
log.info(f"[CREATE] Component({component.id}): {data}")
......
......@@ -65,11 +65,12 @@ def update_course(course: Course, data: dict) -> Course:
return course
def create_course(data: dict) -> Course:
def create_course(**data) -> Course:
"""Creates new course
Args:
data(dict): Course representation in dictionary
Keyword Args:
name(str): name of the course
codename(str): codename of the course
Returns(Course): Course instance
"""
......
import logging
from portal.service.errors import ResourceNotFoundError
from portal import db
from portal.database.models import Course, Group, Component, Project, Role, Submission, User
from portal.database.models import Component, Course, Group, Project, Role, Submission, User
from portal.database.utils import sql_get_count
from portal.service.errors import ResourceNotFoundError
log = logging.getLogger(__name__)
......@@ -219,3 +219,24 @@ def find_user(identifier: str, throws=True) -> User:
)
def get_new_name(source, target: Course, count_func=None) -> str:
"""Gets new name based on the count
Args:
source: Source entity
target(course): Target entity
count_func: Count func
Returns(str): New name with suffix
"""
def __count_general(target, name):
klass = source.__class__
query = klass.query.filter_by(course=target).filter(klass.name.like(name))
return sql_get_count(query)
count_func = count_func or __count_general
new_name = source.name
number = count_func(target=target, name=new_name)
if number > 0:
new_name += f"{number + 1}"
return new_name
import logging
from typing import List
from portal.database.models import Course, Group, User, Project
from portal.database.utils import sql_get_count
from portal.service import general, filters
from portal.service.errors import PortalAPIError, ForbiddenError
from portal.service.general import find_group, find_course, find_role
from portal.database.models import Course, Group, Project, User
from portal.service import filters, general
from portal.service.errors import ForbiddenError, PortalAPIError
from portal.service.general import find_course, find_group, find_role, get_new_name
from portal.service.permissions import check_client
from portal.service.users import find_users
log = logging.getLogger(__name__)
def __count_groups(target, name):
query = Group.query.filter_by(course=target).filter(
Group.name.like(name)
)
return sql_get_count(query)
def copy_group(source: Group, target: Course, with_users: str):
"""Copies group to a specified course
......@@ -30,9 +21,8 @@ def copy_group(source: Group, target: Course, with_users: str):
Returns: the new group
"""
new_name = source.name
number = __count_groups(target=target, name=new_name)
new_name += f"{number + 1}"
log.info(f"[COPY] Group: {source.id} to course {target.id} with config: {with_users}")
new_name = get_new_name(source, target)
new_group = Group(target, new_name)
if with_users == "with_users":
for user in source.users:
......@@ -67,12 +57,14 @@ def update_group(group: Group, data: dict) -> Group:
return __set_group_data(group, data)
def create_group(course: Course, data: dict) -> Course:
def create_group(course: Course, **data) -> Course:
"""Creates a new group
Args:
course(Course): Course instance
data(dict): Group data
Args:
course(Course): Course instance
Keyword Args:
name(str): Name of the group
Returns(Group): Created group instance
"""
......
import logging
from typing import List
from portal.database.models import Project, Course, User, Submission, ProjectConfig, SubmissionState
from portal.service import general, filters
from portal.database.models import Course, Project, ProjectConfig, Submission, SubmissionState, User
from portal.service import filters, general
from portal.service.errors import ForbiddenError
from portal.service.general import find_project
from portal.service.general import get_new_name
from portal.service.permissions import check_client
log = logging.getLogger(__name__)
......@@ -19,13 +19,7 @@ def copy_project(source: Project, target: Course) -> Project:
Returns(Project): Copied project
"""
new_name = source.name
count = 1
if find_project(target, source.name, throws=False):
new_name += "_copy0"
while find_project(target, new_name, throws=False):
new_name[-1] = count
count += 1
new_name = get_new_name(source, target)
new_project = Project(target, new_name, source.config.test_files_source)
new_project.set_config(**vars(source.config))
return new_project
......
import logging
from portal.database.models import Course, Role, RolePermissions, User
from portal.service.errors import ForbiddenError, PortalAPIError
from portal.service.filters import filter_roles_from_course
from portal.service.errors import PortalAPIError, ForbiddenError
from portal.service.general import find_role, delete_entity, write_entity, update_entity
from portal.service.general import delete_entity, get_new_name, update_entity, write_entity
from portal.service.permissions import check_client
from portal.service.users import find_users
......@@ -20,13 +20,7 @@ def copy_role(source: Role, target: Course, with_users: str) -> Role:
Returns(Role): Copied role
"""
log.info(f"[COPY] Role: {source.id} to course {target.id} with config: {with_users}")
new_name = source.name
count = 1
if find_role(target, source.name, throws=False):
new_name += "_copy0"
while find_role(target, new_name, throws=False):
new_name[-1] = count
count += 1
new_name = get_new_name(source, target)
new_role = Role(target, new_name)
new_role.set_permissions(**vars(source.permissions))
new_role.description = source.description
......@@ -60,11 +54,15 @@ def __set_role_data(role: Role, data: dict):
return update_entity(role, data, allowed=['name', 'description'])
def create_role(course: Course, data: dict) -> Role:
def create_role(course: Course, **data) -> Role:
"""Creates new role
Args:
course(Course): Course instance
data(dict): Role data
Keyword Args:
name(str): Name of the role
description(str): Description of the role
Returns(Role): New role instance
"""
new_role = Role(course=course)
......
......@@ -9,11 +9,11 @@ def test_list(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
data = str(response.get_data().decode("utf-8"))
components = json.loads(data)
components = utils.extract_data(response)
assert len(components) == 2
db_components = Component.query.all()
utils.assert_component_in(db_components, components[0])
utils.assert_component_in(db_components, components[1])
def test_create(client):
......@@ -22,7 +22,7 @@ def test_create(client):
ipaddr="127.0.0.1",
secret='new_exec_secret',
type='executor',
)
)
db_components_number = len(Component.query.all())
request_json = json.dumps(request_dict)
......@@ -33,7 +33,7 @@ def test_create(client):
assert response.status_code == 201
assert response.mimetype == 'application/json'
resp_new_component = json.loads(str(response.get_data().decode("utf-8")))
resp_new_component = utils.extract_data(response)
db_components = Component.query.all()
assert len(db_components) == db_components_number + 1
utils.assert_component_in(db_components, resp_new_component)
......@@ -45,8 +45,7 @@ def test_read(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
data = str(response.get_data().decode("utf-8"))
component = json.loads(data)
component = utils.extract_data(response)
utils.assert_component(c, component)
......@@ -55,7 +54,7 @@ def test_update(client):
c = Component.query.filter_by(name="executor").first()
request_dict = dict(
notes="Super executor",
)
)
request_json = json.dumps(request_dict)
response = utils.make_request(client, f'/components/{c.id}', data=request_json,
headers={"content-type": "application/json"}, method='put')
......
import json
from portal.database.models import Course, Project
from portal.service import courses, general
from . import utils
import json
def test_list(client):
......@@ -8,8 +10,7 @@ def test_list(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
data = str(response.get_data().decode("utf-8"))
courses = json.loads(data)
courses = utils.extract_data(response)
assert len(courses) == 2
db_courses = Course.query.all()
utils.assert_course_in(db_courses, courses[0])
......@@ -29,7 +30,7 @@ def test_create(client):
assert response.status_code == 201
assert response.mimetype == 'application/json'
resp_new_course = json.loads(str(response.get_data().decode("utf-8")))
resp_new_course = utils.extract_data(response)
db_courses = Course.query.all()
assert len(db_courses) == db_courses_number + 1
utils.assert_course_in(db_courses, resp_new_course)
......@@ -50,7 +51,7 @@ def test_create_extra_key(client):
assert response.status_code == 201
assert response.mimetype == 'application/json'
resp_new_course = json.loads(str(response.get_data().decode("utf-8")))
resp_new_course = utils.extract_data(response)
db_courses = Course.query.all()
assert len(db_courses) == db_courses_number + 1
utils.assert_course_in(db_courses, resp_new_course)
......@@ -93,8 +94,7 @@ def test_read(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
data = str(response.get_data().decode("utf-8"))
course = json.loads(data)
course = utils.extract_data(response)
utils.assert_course(c, course)
......@@ -135,7 +135,7 @@ def test_notes_token_read(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
data = json.loads(str(response.get_data().decode("utf-8")))
data = utils.extract_data(response)
assert data == "PB161_token"
......@@ -164,8 +164,8 @@ def test_notes_token_update(client):
def test_copy_from_course(client):
cpp = Course.query.filter_by(codename="PB161").first()
c = Course.query.filter_by(codename="PB071").first()
source: Course = general.find_course('PB161')
target = courses.create_course(name='test_course', codename='test')
request_dict = {
"source_course": "PB161",
"config": {
......@@ -176,19 +176,33 @@ def test_copy_from_course(client):
}
request_json = json.dumps(request_dict)
response = utils.make_request(client, f'/courses/{c.codename}/import', data=request_json,
headers={"content-type": "application/json"}, method='put')
response = utils.make_request(client, f'/courses/{target.codename}/import',
data=request_json,
headers={"content-type": "application/json"},
method='put')
assert response.status_code == 204
assert response.mimetype == "application/json"
new_c = Course.query.filter_by(codename="PB071").first()
cpp_project = Project.query.filter(Project.course == cpp).filter(Project.name == "p1").first()
c_project = Project.query.filter(Project.course == new_c).filter(Project.name == "p1").first()
updated_course: Course = general.find_course(target.codename)
print(f"CPP projects:{source.projects}\n Target projects:{updated_course.projects}\n\n")
print(f"CPP roles:{source.roles}\n Target roles:{updated_course.roles}\n\n")
print(f"CPP groups:{source.groups}\n Target groups:{updated_course.groups}\n\n")
assert_collections(source, updated_course, 'projects')
assert_collections(source, updated_course, 'roles')
assert_collections(source, updated_course, 'groups')
def assert_collections(expected: Course, actual: Course, collection: str):
def extract_names(obj, coll_name: str):
coll = getattr(obj, coll_name)
return [elem.name for elem in coll]
# TODO: asserts (... equals on id)
print(f"CPP projects:{cpp.projects}\n C projects:{new_c.projects}\n\n")
print(f"CPP roles:{cpp.roles}\n C roles:{new_c.roles}\n\n")
print(f"CPP groups:{cpp.groups}\n C groups:{new_c.groups}\n\n")
expected_names = extract_names(expected, collection)
actual_names = extract_names(actual, collection)
for elem in actual_names:
assert elem in expected_names
'''
......
......@@ -9,8 +9,7 @@ def test_list(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
data = str(response.get_data().decode("utf-8"))
groups = json.loads(data)
groups = utils.extract_data(response)
assert len(groups) == len(cpp.groups)
db_courses = Group.query.all()
utils.assert_group_in(db_courses, groups[0])
......@@ -28,7 +27,7 @@ def test_create(client):
headers={"content-type": "application/json"}, method='post')
assert response.status_code == 201
assert response.mimetype == "application/json"
resp_new_group = json.loads(str(response.get_data().decode("utf-8")))
resp_new_group = utils.extract_data(response)
cpp_updated = Course.query.filter_by(codename="PB161").first()
assert len(cpp_updated.groups) == groups_before + 1
......@@ -43,9 +42,7 @@ def test_read(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
data = str(response.get_data().decode("utf-8"))
group = json.loads(data)
group = utils.extract_data(response)
utils.assert_group(g, group)
......@@ -86,7 +83,7 @@ def test_list_users(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
users = json.loads(str(response.get_data().decode("utf-8")))
users = utils.extract_data(response)
assert len(users) == len(g.users)
for user in users:
utils.assert_user_in(g.users, user)
......@@ -101,7 +98,7 @@ def test_list_users_filter(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
users = json.loads(str(response.get_data().decode("utf-8")))
users = utils.extract_data(response)
assert len(users) == len(students)
for user in users:
utils.assert_user_in(students, user)
......
......@@ -2,6 +2,8 @@
import json
import pytest
from tests.rest import utils
@pytest.fixture
def tokens(client):
......@@ -9,11 +11,11 @@ def tokens(client):
"type": "user",
"username": "admin",
"password": "789789"
}
}
request_json = json.dumps(request_dict)
response = client.post("/api/v1.0/auth/login", data=request_json,
headers={"content-type": "application/json"})
data = json.loads(response.data)
data = utils.extract_data(response)
return data
......@@ -22,39 +24,36 @@ def test_login_user_valid(client):
"type": "user",
"username": "admin",
"password": "789789"
}
}
request_json = json.dumps(request_dict)
response = client.post("/api/v1.0/auth/login", data=request_json,
headers={"content-type": "application/json"})
assert response.status_code == 200
assert response.mimetype == "application/json"
tokens = json.loads(response.data)
tokens = utils.extract_data(response)
assert tokens.get('access_token')
assert tokens.get('refresh_token')
# TODO: Add sample components
"""
def test_login_component_valid(client):
request_dict = {
"type": "component",
"name": "test_component",
"secret": "11123552699"
}
"name": "executor",
"secret": "executor_secret"
}
request_json = json.dumps(request_dict)
response = client.post("/api/v1.0/auth/login", data=request_json,
headers={"content-type": "application/json"})
assert response.status_code == 200
assert response.mimetype == "application/json"
"""
def test_refresh_token(client, tokens: dict):
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer " + tokens['refresh_token']
}
}
response = client.post("/api/v1.0/auth/refresh", headers=headers)
assert response.status_code == 200
assert response.mimetype == "application/json"
......@@ -65,12 +64,7 @@ def test_user_logout(client, tokens):
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer " + tokens['access_token']
}
}
response = client.post("/api/v1.0/auth/logout", headers=headers)
assert response.status_code == 200
assert response.mimetype == "application/json"
......@@ -3,7 +3,7 @@ from datetime import timedelta
from flask_jwt_extended import create_access_token
from portal.database.models import Course, User, Project
from portal.tools.time import NOW, strip_seconds, portal_timezone
from portal.tools.time import NOW, strip_seconds
from . import utils
import json
......@@ -16,7 +16,7 @@ def test_list(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
projects = json.loads(str(response.get_data().decode("utf-8")))
projects = utils.extract_data(response)
assert len(projects) == cpp_projects
cpp_updated = Course.query.filter_by(codename="PB161").first()
for p in projects:
......@@ -40,7 +40,7 @@ def test_create(client):
assert response.status_code == 201
assert response.mimetype == 'application/json'
new_project = json.loads(str(response.get_data().decode("utf-8")))
new_project = utils.extract_data(response)
cpp_updated = Course.query.filter_by(codename="PB161").first()
assert len(cpp_updated.projects) == cpp_projects + 1
assert new_project['name'] == "new_project"
......@@ -57,7 +57,7 @@ def test_read(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
project = json.loads(str(response.get_data().decode("utf-8")))
project = utils.extract_data(response)
utils.assert_project(p, project)
......@@ -106,7 +106,7 @@ def test_config_read(client):
assert response.status_code == 200
assert response.mimetype == 'application/json'
data = json.loads(str(response.get_data().decode("utf-8")))
data = utils.extract_data(response)
utils.assert_project_config(p.config, data)
......@@ -145,7 +145,7 @@ def test_list_submissions(client):
headers={"Authorization": f"Bearer {access_token}"}, method='get')
assert response.status_code == 200
assert response.mimetype == 'application/json'
submissions = json.loads(str(response.get_data().decode("utf-8")))
submissions = utils.extract_data(response)
assert len(submissions) == len(p.submissions)
for s in submissions:
utils.assert_submission_in(p.submissions, s)
......@@ -164,7 +164,7 @@ def test_list_submissions_filter(client):
headers={"Authorization": f"Bearer {access_token}"}, method='get')