Files
edx-platform/cms/djangoapps/contentstore/views/tests/test_tabs.py
Kshitij Sobti 8169aa99da fix: if pages and resources view is disabled, show all pages in studio (#30550)
In a previous PR #28686, the ability to see and enable/disable wiki and progress tabs was removed from studio along with the ability to re-order non-static tabs. The ability to toggle the Wiki tab was moved to the pages and resources section of the course authoring MFE. If that MFE is unavailable this means there is no way to show/hide the Wiki. This reverts some of the old changes if the pages and resources view is disabled.
2022-06-28 21:19:32 +05:00

215 lines
7.7 KiB
Python

""" Tests for tab functions (just primitive). """
import json
import random
from cms.djangoapps.contentstore.tests.utils import CourseTestCase
from cms.djangoapps.contentstore.utils import reverse_course_url
from cms.djangoapps.contentstore.views import tabs
from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory # lint-amnesty, pylint: disable=wrong-import-order
from xmodule.tabs import CourseTabList # lint-amnesty, pylint: disable=wrong-import-order
from xmodule.x_module import STUDENT_VIEW # lint-amnesty, pylint: disable=wrong-import-order
class TabsPageTests(CourseTestCase):
"""Test cases for Tabs (a.k.a Pages) page"""
def setUp(self):
"""Common setup for tests"""
# call super class to setup course, etc.
super().setUp()
# Set the URL for tests
self.url = reverse_course_url('tabs_handler', self.course.id)
# add a static tab to the course, for code coverage
self.test_tab = ItemFactory.create(
parent_location=self.course.location,
category="static_tab",
display_name="Static_1"
)
self.reload_course()
def check_invalid_tab_id_response(self, resp):
"""Verify response is an error listing the invalid_tab_id"""
assert resp.status_code == 400
resp_content = json.loads(resp.content.decode('utf-8'))
assert "error" in resp_content
def test_not_implemented(self):
"""Verify not implemented errors"""
# JSON GET request not supported
with self.assertRaises(NotImplementedError):
self.client.get(self.url)
# JSON POST request not supported
with self.assertRaises(NotImplementedError):
self.client.ajax_post(
self.url,
data=json.dumps({
'tab_id_locator': {'tab_id': 'courseware'},
'unsupported_request': None,
}),
)
# invalid JSON POST request
with self.assertRaises(NotImplementedError):
self.client.ajax_post(
self.url,
data={'invalid_request': None},
)
def test_view_index(self):
"""Basic check that the Pages page responds correctly"""
resp = self.client.get_html(self.url)
self.assertContains(resp, 'course-nav-list')
def test_reorder_tabs(self):
"""Test re-ordering of tabs"""
# get the original tabs
course_tabs = list(self.course.tabs)
num_orig_tabs = len(self.course.tabs)
# make sure we have enough tabs to play around with
assert num_orig_tabs >= 5
# Randomise the order of static tabs, leave the rest intact
course_tabs.sort(key=lambda tab: (100 + random.random()) if tab.type == 'static_tab' else tab.priority)
tabs_data = [
{'tab_locator': str(self.course.id.make_usage_key("static_tab", tab.url_slug))}
for tab in course_tabs
if tab.type == 'static_tab'
]
# Remove one tab randomly. This shouldn't delete the tab.
tabs_data.pop()
# post the request
resp = self.client.ajax_post(
self.url,
data={
'tabs': tabs_data
},
)
assert resp.status_code == 204
# reload the course and verify the new tab order
self.reload_course()
reordered_tab_ids = [tab.tab_id for tab in course_tabs]
new_tab_ids = [tab.tab_id for tab in self.course.tabs]
assert new_tab_ids == reordered_tab_ids
def test_reorder_tabs_invalid_tab(self):
"""Test re-ordering of tabs with invalid tab"""
invalid_tab_ids = ['courseware', 'invalid_tab_id']
# post the request
resp = self.client.ajax_post(
self.url,
data={'tabs': [{'tab_id': tab_id} for tab_id in invalid_tab_ids]},
)
self.check_invalid_tab_id_response(resp)
def check_toggle_tab_visiblity(self, tab_type, new_is_hidden_setting):
"""Helper method to check changes in tab visibility"""
# find the tab
old_tab = CourseTabList.get_tab_by_type(self.course.tabs, tab_type)
# visibility should be different from new setting
assert old_tab.is_hidden != new_is_hidden_setting
# post the request
resp = self.client.ajax_post(
self.url,
data=json.dumps({
'tab_id_locator': {'tab_id': old_tab.tab_id},
'is_hidden': new_is_hidden_setting,
}),
)
assert resp.status_code == 204
# reload the course and verify the new visibility setting
self.reload_course()
new_tab = CourseTabList.get_tab_by_type(self.course.tabs, tab_type)
assert new_tab.is_hidden == new_is_hidden_setting
def test_toggle_tab_visibility(self):
"""Test toggling of tab visibility"""
self.check_toggle_tab_visiblity('wiki', False)
self.check_toggle_tab_visiblity('wiki', True)
def test_toggle_invalid_tab_visibility(self):
"""Test toggling visibility of an invalid tab"""
# post the request
resp = self.client.ajax_post(
self.url,
data=json.dumps({
'tab_id_locator': {'tab_id': 'invalid_tab_id'}
}),
)
self.check_invalid_tab_id_response(resp)
def test_tab_preview_html(self):
"""
Verify that the static tab renders itself with the correct HTML
"""
preview_url = f'/xblock/{self.test_tab.location}/{STUDENT_VIEW}'
resp = self.client.get(preview_url, HTTP_ACCEPT='application/json')
assert resp.status_code == 200
resp_content = json.loads(resp.content.decode('utf-8'))
html = resp_content['html']
# Verify that the HTML contains the expected elements
assert '<span class="action-button-text">Edit</span>' in html
assert '<span class="sr">Duplicate this component</span>' in html
assert '<span class="sr">Delete this component</span>' in html
assert '<span data-tooltip="Drag to reorder" class="drag-handle action"></span>' in html
class PrimitiveTabEdit(ModuleStoreTestCase):
"""Tests for the primitive tab edit data manipulations"""
def test_delete(self):
"""Test primitive tab deletion."""
course = CourseFactory.create()
with self.assertRaises(ValueError):
tabs.primitive_delete(course, 0)
with self.assertRaises(IndexError):
tabs.primitive_delete(course, 6)
assert course.tabs[1] != {'type': 'dates', 'name': 'Dates'}
tabs.primitive_delete(course, 1)
assert {'type': 'progress'} not in course.tabs
# Check that dates has shifted up
assert course.tabs[1] == {'type': 'dates', 'name': 'Dates'}
def test_insert(self):
"""Test primitive tab insertion."""
course = CourseFactory.create()
tabs.primitive_insert(course, 2, 'pdf_textbooks', 'aname')
assert course.tabs[2] == {'type': 'pdf_textbooks', 'name': 'aname'}
with self.assertRaises(ValueError):
tabs.primitive_insert(course, 0, 'pdf_textbooks', 'aname')
with self.assertRaises(ValueError):
tabs.primitive_insert(course, 3, 'static_tab', 'aname')
def test_save(self):
"""Test course saving."""
course = CourseFactory.create()
tabs.primitive_insert(course, 3, 'pdf_textbooks', 'aname')
course2 = modulestore().get_course(course.id)
assert course2.tabs[3] == {'type': 'pdf_textbooks', 'name': 'aname'}