Skip to content

Commit a461cb7

Browse files
authored
Merge pull request #1272 from jhamrick/improve-coverage
Improve test coverage in auth folder
2 parents 9f9f3ba + b8241b1 commit a461cb7

File tree

4 files changed

+65
-20
lines changed

4 files changed

+65
-20
lines changed

nbgrader/auth/base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
class BaseAuthPlugin(LoggingConfigurable):
66

7-
def get_student_courses(self, student_id):
7+
def get_student_courses(self, student_id): # pragma: no cover
88
"""Gets the list of courses that the student is enrolled in.
99
1010
Arguments
@@ -22,7 +22,7 @@ def get_student_courses(self, student_id):
2222
"""
2323
raise NotImplementedError
2424

25-
def add_student_to_course(self, student_id, course_id):
25+
def add_student_to_course(self, student_id, course_id): # pragma: no cover
2626
"""Grants a student access to a given course.
2727
2828
Arguments
@@ -35,7 +35,7 @@ def add_student_to_course(self, student_id, course_id):
3535
"""
3636
raise NotImplementedError
3737

38-
def remove_student_from_course(self, student_id, course_id):
38+
def remove_student_from_course(self, student_id, course_id): # pragma: no cover
3939
"""Removes a student's access to a given course.
4040
4141
Arguments

nbgrader/auth/jupyterhub.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@ def get_jupyterhub_user():
1919
raise JupyterhubEnvironmentError("JUPYTERHUB_USER env is required to run the exchange features of nbgrader.")
2020

2121

22-
def get_jupyterhub_url():
23-
return os.environ.get('JUPYTERHUB_BASE_URL') or 'http://127.0.0.1:8000'
24-
25-
2622
def get_jupyterhub_api_url():
2723
return os.environ.get('JUPYTERHUB_API_URL') or 'http://127.0.0.1:8081/hub/api'
2824

@@ -89,13 +85,11 @@ def get_student_courses(self, student_id):
8985
self.log.error("Make sure you start your service with a valid admin_user 'api_token' in your Jupyterhub config")
9086
raise
9187
courses = set()
92-
try:
93-
for group in response['groups']:
94-
if group.startswith('nbgrader-') or group.startswith('formgrade-'):
95-
courses.add(group.split('-', 1)[1])
96-
except KeyError:
97-
print("KeyError: See Jupyterhub API: " + str(response))
98-
self.log.error("KeyError: See Jupyterhub API: " + str(response))
88+
for group in response['groups']:
89+
if group.startswith('nbgrader-') or group.startswith('formgrade-'):
90+
course = group.split('-', 1)[1]
91+
if course:
92+
courses.add(course)
9993
return list(courses)
10094

10195
def add_student_to_course(self, student_id, course_id):

nbgrader/server_extensions/course_list/handlers.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@
1313

1414
from notebook.utils import url_path_join as ujoin
1515
from notebook.base.handlers import IPythonHandler
16-
from traitlets.config import Config
1716
from jupyter_core.paths import jupyter_config_path
1817

1918
from ...apps import NbGrader
2019
from ...auth import Authenticator
2120
from ...auth.jupyterhub import (JupyterhubEnvironmentError, get_jupyterhub_api_url,
22-
get_jupyterhub_authorization, get_jupyterhub_url, get_jupyterhub_user)
21+
get_jupyterhub_authorization, get_jupyterhub_user)
2322
from ...coursedir import CourseDirectory
2423
from ... import __version__ as nbgrader_version
2524

nbgrader/tests/test_auth.py

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,28 +52,54 @@ def test_default_authenticator():
5252

5353

5454
def test_jupyterhub_get_student_courses(env, jupyterhub_auth):
55-
# this will fail, because the api token hasn't been set
55+
# this will fail, because the user hasn't been set
56+
env['JUPYTERHUB_API_TOKEN'] = 'abcd1234'
57+
env['JUPYTERHUB_USER'] = ''
5658
with pytest.raises(JupyterhubEnvironmentError):
5759
jupyterhub_auth.get_student_courses('foo')
5860

59-
# should still fail, because the user hasn't been set
60-
env['JUPYTERHUB_API_TOKEN'] = 'abcd1234'
61+
# this will fail, because the api token hasn't been set
62+
env['JUPYTERHUB_API_TOKEN'] = ''
63+
env['JUPYTERHUB_USER'] = 'foo'
6164
with pytest.raises(JupyterhubEnvironmentError):
6265
jupyterhub_auth.get_student_courses('foo')
6366

6467
# should fail, because the server returns a forbidden response
68+
env['JUPYTERHUB_API_TOKEN'] = 'abcd1234'
6569
env['JUPYTERHUB_USER'] = 'foo'
6670
with requests_mock.Mocker() as m:
6771
_mock_api_call(m.get, '/users/foo', status_code=403)
6872
with pytest.raises(JupyterhubApiError):
6973
jupyterhub_auth.get_student_courses('foo')
7074

71-
# should succeed
75+
# should succeed, but give no courses, because the group name is invalid
7276
with requests_mock.Mocker() as m:
77+
_mock_api_call(m.get, '/users/foo', json={'groups': ['nbgrader-']})
78+
assert jupyterhub_auth.get_student_courses('foo') == []
79+
80+
_mock_api_call(m.get, '/users/foo', json={'groups': ['course101']})
81+
assert jupyterhub_auth.get_student_courses('foo') == []
82+
7383
_mock_api_call(
7484
m.get, '/users/foo', json={'groups': ['nbgrader-course123']})
7585
assert jupyterhub_auth.get_student_courses('foo') == ['course123']
7686

87+
# should succeed
88+
with requests_mock.Mocker() as m:
89+
_mock_api_call(
90+
m.get, '/users/foo', json={'groups': ['nbgrader-course123']})
91+
assert jupyterhub_auth.get_student_courses('*') == ['course123']
92+
93+
94+
def test_jupyterhub_has_access(env, jupyterhub_auth):
95+
env['JUPYTERHUB_API_TOKEN'] = 'abcd1234'
96+
env['JUPYTERHUB_USER'] = 'foo'
97+
with requests_mock.Mocker() as m:
98+
_mock_api_call(
99+
m.get, '/users/foo', json={'groups': ['nbgrader-course123']})
100+
assert jupyterhub_auth.has_access('foo', 'course123')
101+
assert not jupyterhub_auth.has_access('foo', 'courseABC')
102+
77103

78104
def test_jupyterhub_add_student_to_course_no_token(jupyterhub_auth):
79105
# this will fail, because the api token hasn't been set
@@ -98,6 +124,16 @@ def test_jupyterhub_add_student_to_course_forbidden(env, jupyterhub_auth, caplog
98124
assert 'ERROR' in [rec.levelname for rec in caplog.records]
99125

100126

127+
def test_jupyterhub_add_student_to_course_no_courseid(env, jupyterhub_auth, caplog):
128+
# test case where something goes wrong
129+
env['JUPYTERHUB_API_TOKEN'] = 'abcd1234'
130+
env['JUPYTERHUB_USER'] = 'foo'
131+
with requests_mock.Mocker() as m:
132+
_mock_api_call(m.get, '/groups', status_code=403)
133+
jupyterhub_auth.add_student_to_course('foo', None)
134+
assert 'ERROR' in [rec.levelname for rec in caplog.records]
135+
136+
101137
def test_jupyterhub_add_student_to_course_success(env, jupyterhub_auth, caplog):
102138
env['JUPYTERHUB_API_TOKEN'] = 'abcd1234'
103139
env['JUPYTERHUB_USER'] = 'foo'
@@ -108,6 +144,12 @@ def test_jupyterhub_add_student_to_course_success(env, jupyterhub_auth, caplog):
108144
jupyterhub_auth.add_student_to_course('foo', 'course123')
109145
assert 'ERROR' not in [rec.levelname for rec in caplog.records]
110146

147+
# Check that it also works if the group already exists
148+
_mock_api_call(m.get, '/groups', json=[{'name': 'nbgrader-course123'}])
149+
_mock_api_call(m.post, '/groups/nbgrader-course123/users')
150+
jupyterhub_auth.add_student_to_course('foo', 'course123')
151+
assert 'ERROR' not in [rec.levelname for rec in caplog.records]
152+
111153

112154
def test_jupyterhub_remove_student_from_course_no_token(jupyterhub_auth):
113155
# this will fail, because the api token hasn't been set
@@ -132,6 +174,16 @@ def test_jupyterhub_remove_student_from_course_forbidden(env, jupyterhub_auth, c
132174
assert 'ERROR' in [rec.levelname for rec in caplog.records]
133175

134176

177+
def test_jupyterhub_remove_student_from_course_no_courseid(env, jupyterhub_auth, caplog):
178+
# test case where something goes wrong
179+
env['JUPYTERHUB_API_TOKEN'] = 'abcd1234'
180+
env['JUPYTERHUB_USER'] = 'foo'
181+
with requests_mock.Mocker() as m:
182+
_mock_api_call(m.delete, '/groups/nbgrader-course123/users')
183+
jupyterhub_auth.remove_student_from_course('foo', None)
184+
assert 'ERROR' in [rec.levelname for rec in caplog.records]
185+
186+
135187
def test_jupyterhub_remove_student_from_course_success(env, jupyterhub_auth, caplog):
136188
env['JUPYTERHUB_API_TOKEN'] = 'abcd1234'
137189
env['JUPYTERHUB_USER'] = 'foo'

0 commit comments

Comments
 (0)