Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions course_discovery/apps/api/v1/tests/test_views/test_catalogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ def assert_catalog_created(self, **headers):
self.assertEqual(catalog.query, query)
self.assertListEqual(list(catalog.viewers), [viewer])

def assert_catalog_contains_query_string(self, query_string_kwargs, course_key):
"""
Helper method to validate the provided course key or course run key
in the catalog contains endpoint.
"""
query_string = urllib.parse.urlencode(query_string_kwargs)
url = '{base_url}?{query_string}'.format(
base_url=reverse('api:v1:catalog-contains', kwargs={'id': self.catalog.id}),
query_string=query_string
)
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, {'courses': {course_key: True}})

def grant_catalog_permission_to_user(self, user, action, catalog=None):
""" Grant the user access to view `self.catalog`. """
catalog = catalog or self.catalog
Expand Down Expand Up @@ -152,18 +166,24 @@ def test_courses(self):
assert response.status_code == 200
assert response.data['results'] == self.serialize_catalog_course(courses, many=True)

def test_contains(self):
""" Verify the endpoint returns a filtered list of courses contained in the catalog. """
def test_contains_for_course_key(self):
"""
Verify the endpoint returns a filtered list of courses contained in
the catalog for course keys with the format "org+course".
"""
course_key = self.course.key
query_string = urllib.parse.urlencode({'course_id': course_key})
url = '{base_url}?{query_string}'.format(
base_url=reverse('api:v1:catalog-contains', kwargs={'id': self.catalog.id}),
query_string=query_string
)

response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, {'courses': {course_key: True}})
query_string_kwargs = {'course_id': course_key}
self.assert_catalog_contains_query_string(query_string_kwargs, course_key)

def test_contains_for_course_run_key(self):
"""
Verify the endpoint returns a filtered list of courses contained in
the catalog for course run keys with the format "org/course/run" or
"course-v1:org+course+key".
"""
course_run_key = self.course_run.key
query_string_kwargs = {'course_run_id': course_run_key}
self.assert_catalog_contains_query_string(query_string_kwargs, course_run_key)

def test_csv(self):
SeatFactory(type='audit', course_run=self.course_run)
Expand Down
17 changes: 15 additions & 2 deletions course_discovery/apps/api/v1/views/catalogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,25 @@ def contains(self, request, id=None): # pylint: disable=redefined-builtin,unuse
type: string
paramType: query
multiple: true
- name: course_run_id
description: Course run IDs to check for existence in the Catalog.
required: false
type: string
paramType: query
multiple: true
"""
course_ids = request.query_params.get('course_id')
course_ids = course_ids.split(',')
course_run_ids = request.query_params.get('course_run_id')

catalog = self.get_object()
courses = catalog.contains(course_ids)
courses = {}
if course_ids:
course_ids = course_ids.split(',')
courses.update(catalog.contains(course_ids))

if course_run_ids:
course_run_ids = course_run_ids.split(',')
courses.update(catalog.contains_course_runs(course_run_ids))

instance = {'courses': courses}
serializer = serializers.ContainedCoursesSerializer(instance)
Expand Down
19 changes: 18 additions & 1 deletion course_discovery/apps/catalogs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from haystack.query import SearchQuerySet

from course_discovery.apps.core.mixins import ModelPermissionsMixin
from course_discovery.apps.course_metadata.models import Course
from course_discovery.apps.course_metadata.models import Course, CourseRun


class Catalog(ModelPermissionsMixin, TimeStampedModel):
Expand Down Expand Up @@ -56,6 +56,23 @@ def contains(self, course_ids): # pylint: disable=unused-argument

return contains

def contains_course_runs(self, course_run_ids): # pylint: disable=unused-argument
"""
Determines if the given course runs are contained in this catalog.

Arguments:
course_run_ids (str[]): List of course run IDs

Returns:
dict: Mapping of course IDs to booleans indicating if course run is
contained in this catalog.
"""
contains = {course_run_id: False for course_run_id in course_run_ids}
course_runs = CourseRun.search(self.query).filter(key__in=course_run_ids).values_list('key', flat=True)
contains.update({course_run_id: course_run_id in course_runs for course_run_id in course_run_ids})

return contains

@property
def viewers(self):
""" Returns a QuerySet of users who have been granted explicit access to view this Catalog.
Expand Down
11 changes: 10 additions & 1 deletion course_discovery/apps/catalogs/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from course_discovery.apps.catalogs.tests import factories
from course_discovery.apps.core.tests.factories import UserFactory
from course_discovery.apps.core.tests.mixins import ElasticsearchTestMixin
from course_discovery.apps.course_metadata.tests.factories import CourseFactory
from course_discovery.apps.course_metadata.tests.factories import CourseFactory, CourseRunFactory


@ddt.ddt
Expand Down Expand Up @@ -39,6 +39,15 @@ def test_contains(self):
{self.course.key: True, uncontained_course.key: False}
)

def test_contains_course_runs(self):
""" Verify the method returns a mapping of course run IDs to booleans. """
course_run = CourseRunFactory(course=self.course)
uncontained_course_run = CourseRunFactory(title_override='ABD')
self.assertDictEqual(
self.catalog.contains_course_runs([course_run.key, uncontained_course_run.key]),
{course_run.key: True, uncontained_course_run.key: False}
)

def test_courses_count(self):
""" Verify the method returns the number of courses contained in the Catalog. """
self.assertEqual(self.catalog.courses_count, 1)
Expand Down