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
19 changes: 12 additions & 7 deletions cms/djangoapps/contentstore/features/static-pages.feature
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,25 @@ Feature: CMS.Static Pages
Then I should see a static page named "Empty"

Scenario: Users can delete static pages
Given I have opened a new course in Studio
And I go to the static pages page
And I add a new page
And I "delete" the static page
Given I have created a static page
When I "delete" the static page
Then I am shown a prompt
When I confirm the prompt
Then I should not see any static pages

# Safari won't update the name properly
@skip_safari
Scenario: Users can edit static pages
Given I have opened a new course in Studio
And I go to the static pages page
And I add a new page
Given I have created a static page
When I "edit" the static page
And I change the name to "New"
Then I should see a static page named "New"

# Safari won't update the name properly
@skip_safari
Scenario: Users can reorder static pages
Given I have created two different static pages
When I reorder the tabs
Then the tabs are in the reverse order
And I reload the page
Then the tabs are in the reverse order
44 changes: 44 additions & 0 deletions cms/djangoapps/contentstore/features/static-pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,47 @@ def change_name(step, new_name):
world.trigger_event(input_css)
save_button = 'a.save-button'
world.css_click(save_button)


@step(u'I reorder the tabs')
def reorder_tabs(_step):
# For some reason, the drag_and_drop method did not work in this case.
draggables = world.css_find('.drag-handle')
source = draggables.first
target = draggables.last
source.action_chains.click_and_hold(source._element).perform()
source.action_chains.move_to_element_with_offset(target._element, 0, 50).perform()
source.action_chains.release().perform()


@step(u'I have created a static page')
def create_static_page(step):
step.given('I have opened a new course in Studio')
step.given('I go to the static pages page')
step.given('I add a new page')


@step(u'I have created two different static pages')
def create_two_pages(step):
step.given('I have created a static page')
step.given('I "edit" the static page')
step.given('I change the name to "First"')
step.given('I add a new page')
# Verify order of tabs
_verify_tab_names('First', 'Empty')


@step(u'the tabs are in the reverse order')
def tabs_in_reverse_order(step):
_verify_tab_names('Empty', 'First')


def _verify_tab_names(first, second):
world.wait_for(
func=lambda _: len(world.css_find('.xmodule_StaticTabModule')) == 2,
timeout=200,
timeout_msg="Timed out waiting for two tabs to be present"
)
tabs = world.css_find('.xmodule_StaticTabModule')
assert tabs[0].text == first
assert tabs[1].text == second
94 changes: 59 additions & 35 deletions cms/djangoapps/contentstore/tests/test_contentstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def check_edit_unit(self, test_course_name):
# TODO: uncomment after edit_unit not using locations.
# _test_no_locations(self, resp)

def lockAnAsset(self, content_store, course_location):
def _lock_an_asset(self, content_store, course_location):
"""
Lock an arbitrary asset in the course
:param course_location:
Expand Down Expand Up @@ -407,45 +407,75 @@ def test_create_static_tab_and_rename(self):
self.assertEqual(course.tabs, expected_tabs)

def test_static_tab_reordering(self):
def get_tab_locator(tab):
tab_location = 'i4x://MITx/999/static_tab/{0}'.format(tab['url_slug'])
return unicode(loc_mapper().translate_location(
course.location.course_id, Location(tab_location), False, True
))

module_store = modulestore('direct')
locator = _course_factory_create_course()
course_location = loc_mapper().translate_locator_to_location(locator)

ItemFactory.create(
parent_location=course_location,
category="static_tab",
display_name="Static_1")
ItemFactory.create(
parent_location=course_location,
category="static_tab",
display_name="Static_2")
module_store, course_location, new_location = self._create_static_tabs()

course = module_store.get_item(course_location)

# reverse the ordering
reverse_tabs = []
for tab in course.tabs:
if tab['type'] == 'static_tab':
reverse_tabs.insert(0, get_tab_locator(tab))
reverse_tabs.insert(0, unicode(self._get_tab_locator(course, tab)))

self.client.ajax_post(reverse('reorder_static_tabs'), {'tabs': reverse_tabs})
self.client.ajax_post(new_location.url_reverse('tabs'), {'tabs': reverse_tabs})

course = module_store.get_item(course_location)

# compare to make sure that the tabs information is in the expected order after the server call
course_tabs = []
for tab in course.tabs:
if tab['type'] == 'static_tab':
course_tabs.append(get_tab_locator(tab))
course_tabs.append(unicode(self._get_tab_locator(course, tab)))

self.assertEqual(reverse_tabs, course_tabs)

def test_static_tab_deletion(self):
module_store, course_location, _ = self._create_static_tabs()

course = module_store.get_item(course_location)
num_tabs = len(course.tabs)
last_tab = course.tabs[num_tabs - 1]
url_slug = last_tab['url_slug']
delete_url = self._get_tab_locator(course, last_tab).url_reverse('xblock')

self.client.delete(delete_url)

course = module_store.get_item(course_location)
self.assertEqual(num_tabs - 1, len(course.tabs))

def tab_matches(tab):
""" Checks if the tab matches the one we deleted """
return tab['type'] == 'static_tab' and tab['url_slug'] == url_slug

tab_found = any(tab_matches(tab) for tab in course.tabs)

self.assertFalse(tab_found, "tab should have been deleted")

def _get_tab_locator(self, course, tab):
""" Returns the locator for a given tab. """
tab_location = 'i4x://MITx/999/static_tab/{0}'.format(tab['url_slug'])
return loc_mapper().translate_location(
course.location.course_id, Location(tab_location), False, True
)

def _create_static_tabs(self):
""" Creates two static tabs in a dummy course. """
module_store = modulestore('direct')
CourseFactory.create(org='edX', course='999', display_name='Robot Super Course')
course_location = Location(['i4x', 'edX', '999', 'course', 'Robot_Super_Course', None])
new_location = loc_mapper().translate_location(course_location.course_id, course_location, False, True)

ItemFactory.create(
parent_location=course_location,
category="static_tab",
display_name="Static_1")
ItemFactory.create(
parent_location=course_location,
category="static_tab",
display_name="Static_2")

return module_store, course_location, new_location

def test_import_polls(self):
module_store = modulestore('direct')
import_from_xml(module_store, 'common/test/data/', ['toy'])
Expand Down Expand Up @@ -633,7 +663,7 @@ def test_asset_delete_and_restore(self):
thumbnail = content_store.find(thumbnail_location, throw_on_not_found=False)
self.assertIsNotNone(thumbnail)

def _delete_asset_in_course (self):
def _delete_asset_in_course(self):
"""
Helper method for:
1) importing course from xml
Expand Down Expand Up @@ -972,7 +1002,7 @@ def test_export_course(self, mock_get):

self.assertIn(private_location_no_draft.url(), sequential.children)

locked_asset = self.lockAnAsset(content_store, location)
locked_asset = self._lock_an_asset(content_store, location)
locked_asset_attrs = content_store.get_attrs(locked_asset)
# the later import will reupload
del locked_asset_attrs['uploadDate']
Expand Down Expand Up @@ -1027,7 +1057,7 @@ def test_export_course(self, mock_get):
shutil.rmtree(root_dir)

def check_import(self, module_store, root_dir, draft_store, content_store, stub_location, course_location,

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.

As long as you're fixing whitespace, I don't think this is yet compliant w/ our guidelines (I could be wrong). I think we're supposed to do these like:
def check_import( -----self, module_store, ... ):
which I find a bit disturbing. (---- s/b spaces but formatted wrong in output)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

In this particular case, I find the recommended formatting much more difficult to read. And what I have doesn't produce any pylint/pep8 warnings.

locked_asset, locked_asset_attrs):
locked_asset, locked_asset_attrs):
# reimport
import_from_xml(
module_store, root_dir, ['test_export'], draft_store=draft_store,
Expand Down Expand Up @@ -1226,7 +1256,7 @@ def test_course_handouts_rewrites(self):
handouts_locator = loc_mapper().translate_location('edX/toy/2012_Fall', handout_location)

# get module info (json)
resp = self.client.get(handouts_locator.url_reverse('/xblock', ''))
resp = self.client.get(handouts_locator.url_reverse('/xblock'))

# make sure we got a successful response
self.assertEqual(resp.status_code, 200)
Expand Down Expand Up @@ -1403,7 +1433,7 @@ def test_forum_unseeding_with_multiple_courses(self):
second_course_data = self.assert_created_course(number_suffix=uuid4().hex)

# unseed the forums for the first course
course_id =_get_course_id(test_course_data)
course_id = _get_course_id(test_course_data)
delete_course_and_groups(course_id, commit=True)
self.assertFalse(are_permissions_roles_seeded(course_id))

Expand Down Expand Up @@ -1625,6 +1655,7 @@ def test_get_html(page):
test_get_html('course_info')
test_get_html('checklists')
test_get_html('assets')
test_get_html('tabs')

# settings_details
resp = self.client.get_html(reverse('settings_details',
Expand Down Expand Up @@ -1677,13 +1708,6 @@ def test_get_html(page):
# TODO: uncomment when edit_unit not using old locations.
# _test_no_locations(self, resp)

resp = self.client.get_html(reverse('edit_tabs',
kwargs={'org': loc.org,
'course': loc.course,
'coursename': loc.name}))
self.assertEqual(resp.status_code, 200)
_test_no_locations(self, resp)

def delete_item(category, name):
""" Helper method for testing the deletion of an xblock item. """
del_loc = loc.replace(category=category, name=name)
Expand Down Expand Up @@ -1997,7 +2021,7 @@ def _create_course(test, course_data):
test.assertEqual(response.status_code, 200)
data = parse_json(response)
test.assertNotIn('ErrMsg', data)
test.assertEqual(data['url'], new_location.url_reverse("course/", ""))
test.assertEqual(data['url'], new_location.url_reverse("course"))


def _course_factory_create_course():
Expand Down
Loading