Skip to content

Commit

Permalink
Add tests for setting roles/active per student. Tighten routes a bit,…
Browse files Browse the repository at this point in the history
… too.
  • Loading branch information
liffiton committed Jun 22, 2024
1 parent bebe0ba commit dca0866
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/gened/instructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def set_user_class_setting() -> Response:


@bp.route("/role/set_active", methods=["POST"]) # just for url_for in the Javascript code
@bp.route("/role/set_active/<int:role_id>/<int:bool_active>", methods=["POST"])
@bp.route("/role/set_active/<int:role_id>/<int(min=0, max=1):bool_active>", methods=["POST"])
@instructor_required
def set_role_active(role_id: int, bool_active: int) -> str:
db = get_db()
Expand All @@ -181,7 +181,7 @@ def set_role_active(role_id: int, bool_active: int) -> str:


@bp.route("/role/set_instructor", methods=["POST"]) # just for url_for in the Javascript code
@bp.route("/role/set_instructor/<int:role_id>/<int:bool_instructor>", methods=["POST"])
@bp.route("/role/set_instructor/<int:role_id>/<int(min=0, max=1):bool_instructor>", methods=["POST"])
@instructor_required
def set_role_instructor(role_id: int, bool_instructor: int) -> str:
db = get_db()
Expand Down
6 changes: 5 additions & 1 deletion tests/test_data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ INSERT INTO roles (id, user_id, class_id, role)
VALUES
(1, 21, 1, 'student'), -- ltiuser1
(2, 22, 1, 'student'), -- ltiuser2
(3, 23, 1, 'instructor'); -- ltiuser3 is an instructor
(3, 23, 1, 'instructor'), -- ltiuser3 is an instructor
-- testuser, testadmin, and testinstructor are in class 2 -- but not testuser2
(4, 11, 2, 'instructor'), -- testuser created the class
(5, 12, 2, 'student'), -- testadmin is a student
(6, 13, 2, 'student'); -- testinstructor is a student

INSERT INTO queries (id, language, code, error, issue, response_json, response_text, helpful, user_id, role_id)
VALUES
Expand Down
109 changes: 109 additions & 0 deletions tests/test_instructor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# SPDX-FileCopyrightText: 2024 Mark Liffiton <[email protected]>
#
# SPDX-License-Identifier: AGPL-3.0-only

from gened.db import get_db


def test_set_role_active(app, client, auth):
auth.login() # as testuser, who created and is instructor in class id 2

response = client.get('/classes/switch/2') # switch to class 2
assert response.status_code == 302
assert response.location == "/profile/"

# Test successful deactivation (deactivating testadmint in the course)
response = client.post('/instructor/role/set_active/5/0')
assert response.status_code == 200
assert response.data == b'okay'

# Verify database update
with app.app_context():
db = get_db()
active_status = db.execute('SELECT active FROM roles JOIN users ON roles.user_id=users.id WHERE users.auth_name="testadmin"').fetchone()['active']
assert active_status == 0

# Test successful activation
response = client.post('/instructor/role/set_active/5/1')
assert response.status_code == 200
assert response.data == b'okay'

# Verify database update
with app.app_context():
db = get_db()
active_status = db.execute('SELECT active FROM roles JOIN users ON roles.user_id=users.id WHERE users.auth_name="testadmin"').fetchone()['active']
assert active_status == 1

# Test class instructor (testuser, role 4) trying to deactivate themselves
response = client.post('/instructor/role/set_active/4/0')
assert response.status_code == 200
assert b'okay' not in response.data
assert response.data == b'You cannot make yourself inactive.'

# Test invalid role_id
response = client.post('/instructor/role/set_active/999/0')
assert response.status_code == 200
assert response.data == b'okay' # It doesn't fail, just doesn't update anything

# Test invalid bool_active value
response = client.post('/instructor/role/set_active/4/2')
assert response.status_code == 404 # Not Found, as it doesn't match the route (0 or 1 only for the new state)

# Test non-instructor access
auth.logout()
auth.login('testuser2', 'testuser2password')
response = client.post('/instructor/role/set_active/5/0')
assert response.status_code == 302 # Redirect to login
assert response.location.startswith('/auth/login?')


def test_set_role_instructor(app, client, auth):
auth.login() # as testuser, who created and is instructor in class id 2

response = client.get('/classes/switch/2') # switch to class 2
assert response.status_code == 302
assert response.location == "/profile/"

# Test successful change to instructor for testadmin (starts as student)
response = client.post('/instructor/role/set_instructor/5/1')
assert response.status_code == 200
assert response.data == b'okay'

# Verify database update
with app.app_context():
db = get_db()
role = db.execute('SELECT role FROM roles JOIN users ON roles.user_id=users.id WHERE users.auth_name="testadmin"').fetchone()['role']
assert role == 'instructor'

# Test successful change back to student
response = client.post('/instructor/role/set_instructor/5/0')
assert response.status_code == 200
assert response.data == b'okay'

# Verify database update
with app.app_context():
db = get_db()
role = db.execute('SELECT role FROM roles JOIN users ON roles.user_id=users.id WHERE users.auth_name="testadmin"').fetchone()['role']
assert role == 'student'

# Test instructor trying to change their own role
response = client.post('/instructor/role/set_instructor/4/0')
assert response.status_code == 200
assert b'okay' not in response.data
assert response.data == b'You cannot change your own role.'

# Test invalid role_id
response = client.post('/instructor/role/set_instructor/999/1')
assert response.status_code == 200
assert response.data == b'okay' # It doesn't fail, just doesn't update anything

# Test invalid bool_instructor value
response = client.post('/instructor/role/set_instructor/4/2')
assert response.status_code == 404 # Not Found, as it doesn't match the route

# Test non-instructor access
auth.logout()
auth.login('testuser2', 'testuser2password')
response = client.post('/instructor/role/set_instructor/5/1')
assert response.status_code == 302 # Redirect to login
assert response.location.startswith('/auth/login?')
2 changes: 1 addition & 1 deletion tests/test_user_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def _test_user_class_link(client, link_name, status, result):
('reg_enabled', 302, '/'),
])
def test_user_class_link(auth, client, link_name, status, result):
auth.login()
auth.login('testuser2', 'testuser2password') # log in a testuser2, not connected to any existing classes
_test_user_class_link(client, link_name, status, result)


Expand Down

0 comments on commit dca0866

Please sign in to comment.