Skip to content
Open
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
17 changes: 17 additions & 0 deletions common/djangoapps/util/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,20 @@ def test_course_about_page_url_requested_without_filter_configuration(self):
)

self.assertEqual(expected_course_about, course_about_url) # noqa: PT009

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a missing blank line here

class TestInstructorDashCustomTab(PipelineStep):
"""
Utility class used when getting steps for pipeline.
"""

def run_filter(self, tabs, user, course_key): # pylint: disable=arguments-differ,unused-argument
"""Pipeline step that appends a custom instructor dashboard tab."""
result = {
"tabs": tabs + [{
"tab_id": "custom",
"title": "Custom Tab",
"url": f"/courses/{course_key}/instructor/custom",
"sort_order": 999,
}],
}
return result
41 changes: 41 additions & 0 deletions lms/djangoapps/instructor/tests/views/test_api_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from unittest.mock import MagicMock, patch
from uuid import uuid4

from django.test import override_settings
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
Expand Down Expand Up @@ -692,3 +693,43 @@ def test_override_rejects_negative_score(self):
format='json',
)
assert response.status_code == status.HTTP_400_BAD_REQUEST


class CourseMetadataViewTestCase(ModuleStoreTestCase):
"""
Tests for GET /api/instructor/v2/courses/{course_id} with InstructorDashboardTabsRequested filter.
"""
def setUp(self):
super().setUp()
self.client = APIClient()
self.course = CourseFactory.create()
self.instructor = InstructorFactory.create(course_key=self.course.id)
self.client.force_authenticate(user=self.instructor)

@override_settings(
OPEN_EDX_FILTERS_CONFIG={
"org.openedx.learning.instructor.dashboard.tabs.requested.v1": {
"pipeline": [
"common.djangoapps.util.tests.test_filters.TestInstructorDashCustomTab",
],
"fail_silently": False,
},
},
)
def test_tabs_filter_adds_custom_tab(self):
"""Test that override settings drive a custom instructor dashboard tab."""
url = reverse("instructor_api_v2:course_metadata", kwargs={"course_id": str(self.course.id)})
response = self.client.get(url)

assert response.status_code == status.HTTP_200_OK
data = response.json()
tabs_by_id = {tab["tab_id"]: tab for tab in data["tabs"]}

assert "course_info" in tabs_by_id
assert "custom" in tabs_by_id
assert tabs_by_id["custom"] == {
"tab_id": "custom",
"title": "Custom Tab",
"url": f"/courses/{self.course.id}/instructor/custom",
"sort_order": 999,
}
17 changes: 15 additions & 2 deletions lms/djangoapps/instructor/views/serializers_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from django.utils.html import escape
from django.utils.translation import gettext as _
from edx_when.api import is_enabled_for_course
from openedx_filters.learning.filters import InstructorDashboardTabsRequested
from rest_framework import serializers

from common.djangoapps.course_modes.models import CourseMode
Expand Down Expand Up @@ -305,6 +306,19 @@ def get_tabs(self, data):
'sort_order': 110,
})

try:
# .. filter_implemented_name: InstructorDashboardTabsRequested
# .. filter_type: org.openedx.learning.instructor.dashboard.tabs.requested.v1
filtered_tabs = InstructorDashboardTabsRequested.run_filter(
tabs=tabs,
user=request.user,
course_key=course_key
)
custom_tabs = filtered_tabs if filtered_tabs is not None else tabs
except InstructorDashboardTabsRequested.PreventTabsGeneration as exc:
# Plugin provided custom tabs or prevented tab generation
custom_tabs = getattr(exc, 'tabs', [])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a proper test for this?


# We provide the tabs in a specific order based on how it was
# historically presented in the frontend. The frontend can use
# this info or choose to ignore the ordering.
Expand All @@ -322,8 +336,7 @@ def get_tabs(self, data):
'special_exams',
]
order_index = {tab: i for i, tab in enumerate(tabs_order)}
tabs = sorted(tabs, key=lambda x: order_index.get(x['tab_id'], float("inf")))
return tabs
return sorted(custom_tabs, key=lambda x: order_index.get(x['tab_id'], float("inf")))

def get_course_id(self, data):
"""Get course ID as string."""
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ openedx-events==11.2.0
# openedx-authz
# openedx-core
# ora2
openedx-filters==3.3.0
openedx-filters==3.4.0
# via
# -r requirements/edx/kernel.in
# edx-enterprise
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/development.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1413,7 +1413,7 @@ openedx-events==11.2.0
# openedx-authz
# openedx-core
# ora2
openedx-filters==3.3.0
openedx-filters==3.4.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,7 @@ openedx-events==11.2.0
# openedx-authz
# openedx-core
# ora2
openedx-filters==3.3.0
openedx-filters==3.4.0
# via
# -r requirements/edx/base.txt
# edx-enterprise
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,7 @@ openedx-events==11.2.0
# openedx-authz
# openedx-core
# ora2
openedx-filters==3.3.0
openedx-filters==3.4.0
# via
# -r requirements/edx/base.txt
# edx-enterprise
Expand Down
Loading