Skip to content

Commit

Permalink
New Quizzes (#612)
Browse files Browse the repository at this point in the history
* Begin adding coverage for New Quizzes (WIP)

* Finish New Quizzes endpoints
  • Loading branch information
Thetwam committed May 4, 2023
1 parent 6cf11eb commit 2c8be50
Show file tree
Hide file tree
Showing 8 changed files with 318 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

### New Endpoint Coverage

- New Quizzes

### General

- Added support for pagination with metadata when headers are missing (Thanks, [@bennettscience](https://github.com/bennettscience))
Expand Down
78 changes: 77 additions & 1 deletion canvasapi/course.py
Expand Up @@ -24,6 +24,7 @@
from canvasapi.grading_standard import GradingStandard
from canvasapi.license import License
from canvasapi.module import Module
from canvasapi.new_quiz import NewQuiz
from canvasapi.outcome_import import OutcomeImport
from canvasapi.page import Page
from canvasapi.paginated_list import PaginatedList
Expand Down Expand Up @@ -452,6 +453,29 @@ def create_module(self, module, **kwargs):

return Module(self._requester, module_json)

def create_new_quiz(self, **kwargs):
"""
Create a new quiz for the course.
:calls: `POST /api/quiz/v1/courses/:course_id/quizzes \
<https://canvas.instructure.com/doc/api/new_quizzes.html#method.new_quizzes/quizzes_api.create>`_
:returns: The newly-created New Quiz object
:rtype: :class:`canvasapi.new_quiz.NewQuiz`
"""
endpoint = "courses/{}/quizzes".format(self.id)

response = self._requester.request(
"POST",
endpoint,
_url=self._requester.original_url + "/api/quiz/v1/" + endpoint,
_kwargs=combine_kwargs(**kwargs),
)
response_json = response.json()
response_json.update({"course_id": self.id})

return NewQuiz(self._requester, response_json)

def create_page(self, wiki_page, **kwargs):
"""
Create a new wiki page.
Expand Down Expand Up @@ -1701,6 +1725,56 @@ def get_multiple_submissions(self, **kwargs):
_kwargs=combine_kwargs(**kwargs),
)

def get_new_quiz(self, assignment, **kwargs):
"""
Get details about a single new quiz.
:calls: `GET /api/quiz/v1/courses/:course_id/quizzes/:assignment_id \
<https://canvas.instructure.com/doc/api/new_quizzes.html#method.new_quizzes/quizzes_api.show>`_
:param assignment: The id of the assignment associated with the quiz.
:type assignment: :class:`canvasapi.assignment.Assignment`
or :class:`canvasapi.new_quiz.NewQuiz` or int
:returns: A New Quiz object.
:rtype: :class:`canvasapi.new_quiz.NewQuiz`
"""

assignment_id = obj_or_id(assignment, "assignment", (Assignment, NewQuiz))
endpoint = "courses/{}/quizzes/{}".format(self.id, assignment_id)

response = self._requester.request(
"GET",
endpoint,
_url=self._requester.original_url + "/api/quiz/v1/" + endpoint,
_kwargs=combine_kwargs(**kwargs),
)
response_json = response.json()
response_json.update({"course_id": self.id})

return NewQuiz(self._requester, response_json)

def get_new_quizzes(self, **kwargs):
"""
Get a list of new quizzes.
:calls: `GET /api/quiz/v1/courses/:course_id/quizzes \
<https://canvas.instructure.com/doc/api/new_quizzes.html#method.new_quizzes/quizzes_api.index>`_
:returns: A paginated list of New Quiz objects.
:rtype: :class:`canvasapi.paginated_list.PaginatedList`
of :class:`canvasapi.new_quiz.NewQuiz`
"""
endpoint = "courses/{}/quizzes".format(self.id)
return PaginatedList(
NewQuiz,
self._requester,
"GET",
endpoint,
_url_override=self._requester.original_url + "/api/quiz/v1/" + endpoint,
_kwargs=combine_kwargs(**kwargs),
)

def get_outcome_group(self, group, **kwargs):
"""
Returns the details of the Outcome Group with the given id.
Expand All @@ -1719,7 +1793,9 @@ def get_outcome_group(self, group, **kwargs):
outcome_group_id = obj_or_id(group, "group", (OutcomeGroup,))

response = self._requester.request(
"GET", "courses/{}/outcome_groups/{}".format(self.id, outcome_group_id)
"GET",
"courses/{}/outcome_groups/{}".format(self.id, outcome_group_id),
_kwargs=combine_kwargs(**kwargs),
)

return OutcomeGroup(self._requester, response.json())
Expand Down
53 changes: 53 additions & 0 deletions canvasapi/new_quiz.py
@@ -0,0 +1,53 @@
from canvasapi.canvas_object import CanvasObject
from canvasapi.util import combine_kwargs


class NewQuiz(CanvasObject):
def __str__(self):
return "{} ({})".format(self.title, self.id)

def delete(self, **kwargs):
"""
Delete a single new quiz.
:calls: `DELETE /api/quiz/v1/courses/:course_id/quizzes/:assignment_id \
<https://canvas.instructure.com/doc/api/new_quizzes.html#method.new_quizzes/quizzes_api.destroy>`_
:returns: The deleted New Quiz object
:rtype: :class:`canvasapi.new_quiz.NewQuiz`
"""
endpoint = "courses/{}/quizzes/{}".format(self.course_id, self.id)

response = self._requester.request(
"DELETE",
endpoint,
_url=self._requester.original_url + "/api/quiz/v1/" + endpoint,
_kwargs=combine_kwargs(**kwargs),
)
response_json = response.json()
response_json.update({"course_id": self.course_id})

return NewQuiz(self._requester, response_json)

def update(self, **kwargs):
"""
Update a single New Quiz for the course.
:calls: `PATCH /api/quiz/v1/courses/:course_id/quizzes/:assignment_id \
<https://canvas.instructure.com/doc/api/new_quizzes.html#method.new_quizzes/quizzes_api.update>`_
:returns: The updated New Quiz object
:rtype: :class:`canvasapi.new_quiz.NewQuiz`
"""
endpoint = "courses/{}/quizzes/{}".format(self.course_id, self.id)

response = self._requester.request(
"PATCH",
endpoint,
_url=self._requester.original_url + "/api/quiz/v1/" + endpoint,
_kwargs=combine_kwargs(**kwargs),
)
response_json = response.json()
response_json.update({"course_id": self.course_id})

return NewQuiz(self._requester, response_json)
7 changes: 6 additions & 1 deletion canvasapi/paginated_list.py
Expand Up @@ -25,6 +25,7 @@ def __init__(
first_url,
extra_attribs=None,
_root=None,
_url_override=None,
**kwargs
):
self._elements = list()
Expand All @@ -39,6 +40,7 @@ def __init__(
self._extra_attribs = extra_attribs or {}
self._request_method = request_method
self._root = _root
self._url_override = _url_override

def __iter__(self):
for element in self._elements:
Expand All @@ -53,7 +55,10 @@ def __repr__(self):

def _get_next_page(self):
response = self._requester.request(
self._request_method, self._next_url, **self._next_params
self._request_method,
self._next_url,
_url=self._url_override,
**self._next_params,
)
data = response.json()
self._next_url = None
Expand Down
59 changes: 59 additions & 0 deletions tests/fixtures/new_quiz.json
@@ -0,0 +1,59 @@
{
"create_new_quiz": {
"method": "POST",
"endpoint": "courses/1/quizzes",
"data": {
"id": 1,
"title": "New Quiz One",
"instructions": "<p>This is the first New Quiz. Good luck!</p>"
},
"status_code": 200
},
"delete_new_quiz": {
"method": "DELETE",
"endpoint": "courses/1/quizzes/1",
"data": {
"id": 1,
"title": "New Quiz One",
"instructions": "<p>This is the first New Quiz. Good luck!</p>"
},
"status_code": 200
},
"get_new_quiz": {
"method": "GET",
"endpoint": "courses/1/quizzes/1",
"data": {
"id": 1,
"title": "New Quiz One",
"instructions": "<p>This is the first New Quiz. Good luck!</p>"
},
"status_code": 200
},
"get_new_quizzes": {
"method": "GET",
"endpoint": "courses/1/quizzes",
"data": [
{
"id": 1,
"title": "New Quiz One",
"instructions": "<p>This is the first New Quiz. Good luck!</p>"
},
{
"id": 2,
"title": "New Quiz Two",
"instructions": "<p>This is the second New Quiz. Good luck!</p>"
}
],
"status_code": 200
},
"update_new_quiz": {
"method": "PATCH",
"endpoint": "courses/1/quizzes/1",
"data": {
"id": 1,
"title": "New Quiz One - Updated!",
"instructions": "<p>This is the updated New Quiz. You got this!</p>"
},
"status_code": 200
}
}
1 change: 1 addition & 0 deletions tests/settings.py
@@ -1,5 +1,6 @@
BASE_URL = "https://example.com"
BASE_URL_GRAPHQL = "https://example.com/api/"
BASE_URL_NEW_QUIZZES = "https://example.com/api/quiz/v1/"
BASE_URL_WITH_VERSION = "https://example.com/api/v1/"
BASE_URL_AS_HTTP = "http://example.com"
BASE_URL_AS_BLANK = ""
Expand Down
50 changes: 50 additions & 0 deletions tests/test_course.py
Expand Up @@ -35,6 +35,7 @@
from canvasapi.group import Group, GroupCategory
from canvasapi.license import License
from canvasapi.module import Module
from canvasapi.new_quiz import NewQuiz
from canvasapi.outcome import OutcomeGroup, OutcomeLink, OutcomeResult
from canvasapi.outcome_import import OutcomeImport
from canvasapi.paginated_list import PaginatedList
Expand Down Expand Up @@ -333,6 +334,23 @@ def test_create_quiz_fail(self, m):
with self.assertRaises(RequiredFieldMissing):
self.course.create_quiz({})

# create_new_quiz()
def test_create_new_quiz(self, m):
register_uris(
{"new_quiz": ["create_new_quiz"]},
m,
base_url=settings.BASE_URL_NEW_QUIZZES,
)

title = "New Quiz One"
new_new_quiz = self.course.create_new_quiz(quiz={"title": title})

self.assertIsInstance(new_new_quiz, NewQuiz)
self.assertTrue(hasattr(new_new_quiz, "title"))
self.assertEqual(new_new_quiz.title, title)
self.assertTrue(hasattr(new_new_quiz, "course_id"))
self.assertEqual(new_new_quiz.course_id, self.course.id)

# get_quiz()
def test_get_quiz(self, m):
register_uris({"course": ["get_quiz"]}, m)
Expand Down Expand Up @@ -390,6 +408,38 @@ def test_get_quizzes(self, m):
self.assertTrue(hasattr(quiz_list[0], "course_id"))
self.assertEqual(quiz_list[0].course_id, self.course.id)

# get_new_quiz()
def test_get_new_quiz(self, m):
register_uris(
{"new_quiz": ["get_new_quiz"]},
m,
base_url=settings.BASE_URL_NEW_QUIZZES,
)

new_quiz = self.course.get_new_quiz(1)

self.assertIsInstance(new_quiz, NewQuiz)
self.assertTrue(hasattr(new_quiz, "title"))
self.assertEqual(new_quiz.title, "New Quiz One")
self.assertTrue(hasattr(new_quiz, "course_id"))
self.assertEqual(new_quiz.course_id, self.course.id)

# get_new_quizzes()
def test_get_new_quizzes(self, m):
register_uris(
{"new_quiz": ["get_new_quizzes"]},
m,
base_url=settings.BASE_URL_NEW_QUIZZES,
)

new_quizzes = self.course.get_new_quizzes()
new_quiz_list = list(new_quizzes)

self.assertEqual(len(new_quiz_list), 2)
self.assertIsInstance(new_quiz_list[0], NewQuiz)
self.assertTrue(hasattr(new_quiz_list[0], "title"))
self.assertEqual(new_quiz_list[0].title, "New Quiz One")

# get_modules()
def test_get_modules(self, m):
register_uris({"course": ["list_modules", "list_modules2"]}, m)
Expand Down

0 comments on commit 2c8be50

Please sign in to comment.