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.
215 lines
7.7 KiB
Python
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'}
|