Files
edx-platform/common/test/acceptance/tests/test_studio_split_test.py
2014-07-08 15:01:22 -04:00

316 lines
12 KiB
Python

"""
Acceptance tests for Studio related to the split_test module.
"""
import json
import os
from unittest import skip, skipUnless
from xmodule.partitions.partitions import Group, UserPartition
from bok_choy.promise import Promise
from ..fixtures.course import CourseFixture, XBlockFixtureDesc
from ..pages.studio.component_editor import ComponentEditorView
from ..pages.studio.settings_advanced import AdvancedSettingsPage
from ..pages.studio.settings_group_configurations import GroupConfigurationsPage
from ..pages.studio.auto_auth import AutoAuthPage
from ..pages.studio.utils import add_advanced_component
from ..pages.xblock.utils import wait_for_xblock_initialization
from .helpers import UniqueCourseTest
from test_studio_container import ContainerBase
class SplitTest(ContainerBase):
"""
Tests for creating and editing split test instances in Studio.
"""
__test__ = True
def setup_fixtures(self):
course_fix = CourseFixture(
self.course_info['org'],
self.course_info['number'],
self.course_info['run'],
self.course_info['display_name']
)
course_fix.add_advanced_settings(
{
u"advanced_modules": {"value": ["split_test"]},
u"user_partitions": {"value": [
UserPartition(0, 'Configuration alpha,beta', 'first', [Group("0", 'alpha'), Group("1", 'beta')]).to_json(),
UserPartition(1, 'Configuration 0,1,2', 'second', [Group("0", 'Group 0'), Group("1", 'Group 1'), Group("2", 'Group 2')]).to_json()
]}
}
)
course_fix.add_children(
XBlockFixtureDesc('chapter', 'Test Section').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
XBlockFixtureDesc('vertical', 'Test Unit')
)
)
).install()
self.course_fix = course_fix
self.user = course_fix.user
def verify_groups(self, container, active_groups, inactive_groups, verify_missing_groups_not_present=True):
"""
Check that the groups appear and are correctly categorized as to active and inactive.
Also checks that the "add missing groups" button/link is not present unless a value of False is passed
for verify_missing_groups_not_present.
"""
def wait_for_xblocks_to_render():
# First xblock is the container for the page, subtract 1.
return (len(active_groups) + len(inactive_groups) == len(container.xblocks) - 1, len(active_groups))
Promise(wait_for_xblocks_to_render, "Number of xblocks on the page are incorrect").fulfill()
def check_xblock_names(expected_groups, actual_blocks):
self.assertEqual(len(expected_groups), len(actual_blocks))
for idx, expected in enumerate(expected_groups):
self.assertEqual('Expand or Collapse\n{}'.format(expected), actual_blocks[idx].name)
check_xblock_names(active_groups, container.active_xblocks)
check_xblock_names(inactive_groups, container.inactive_xblocks)
# Verify inactive xblocks appear after active xblocks
check_xblock_names(active_groups + inactive_groups, container.xblocks[1:])
if verify_missing_groups_not_present:
self.verify_add_missing_groups_button_not_present(container)
def verify_add_missing_groups_button_not_present(self, container):
"""
Checks that the "add missing gorups" button/link is not present.
"""
def missing_groups_button_not_present():
button_present = container.missing_groups_button_present()
return (not button_present, not button_present)
Promise(missing_groups_button_not_present, "Add missing groups button should not be showing.").fulfill()
def create_poorly_configured_split_instance(self):
"""
Creates a split test instance with a missing group and an inactive group.
Returns the container page.
"""
unit = self.go_to_unit_page(make_draft=True)
add_advanced_component(unit, 0, 'split_test')
container = self.go_to_container_page()
container.edit()
component_editor = ComponentEditorView(self.browser, container.locator)
component_editor.set_select_value_and_save('Group Configuration', 'Configuration alpha,beta')
self.course_fix.add_advanced_settings(
{
u"user_partitions": {"value": [
UserPartition(0, 'Configuration alpha,beta', 'first',
[Group("0", 'alpha'), Group("2", 'gamma')]).to_json()
]}
}
)
self.course_fix._add_advanced_settings()
return self.go_to_container_page()
def test_create_and_select_group_configuration(self):
"""
Tests creating a split test instance on the unit page, and then
assigning the group configuration.
"""
unit = self.go_to_unit_page(make_draft=True)
add_advanced_component(unit, 0, 'split_test')
container = self.go_to_container_page()
container.edit()
component_editor = ComponentEditorView(self.browser, container.locator)
component_editor.set_select_value_and_save('Group Configuration', 'Configuration alpha,beta')
self.verify_groups(container, ['alpha', 'beta'], [])
# Switch to the other group configuration. Must navigate again to the container page so
# that there is only a single "editor" on the page.
container = self.go_to_container_page()
container.edit()
component_editor = ComponentEditorView(self.browser, container.locator)
component_editor.set_select_value_and_save('Group Configuration', 'Configuration 0,1,2')
self.verify_groups(container, ['Group 0', 'Group 1', 'Group 2'], ['alpha', 'beta'])
# Reload the page to make sure the groups were persisted.
container = self.go_to_container_page()
self.verify_groups(container, ['Group 0', 'Group 1', 'Group 2'], ['alpha', 'beta'])
@skip("This fails periodically where it fails to trigger the add missing groups action.Dis")
def test_missing_group(self):
"""
The case of a split test with invalid configuration (missing group).
"""
container = self.create_poorly_configured_split_instance()
# Wait for the xblock to be fully initialized so that the add button is rendered
wait_for_xblock_initialization(self, '.xblock[data-block-type="split_test"]')
# Click the add button and verify that the groups were added on the page
container.add_missing_groups()
self.verify_groups(container, ['alpha', 'gamma'], ['beta'])
# Reload the page to make sure the groups were persisted.
container = self.go_to_container_page()
self.verify_groups(container, ['alpha', 'gamma'], ['beta'])
def test_delete_inactive_group(self):
"""
Test deleting an inactive group.
"""
container = self.create_poorly_configured_split_instance()
container.delete(0)
self.verify_groups(container, ['alpha'], [], verify_missing_groups_not_present=False)
@skipUnless(os.environ.get('FEATURE_GROUP_CONFIGURATIONS'), 'Tests Group Configurations feature')
class SettingsMenuTest(UniqueCourseTest):
"""
Tests that Setting menu is rendered correctly in Studio
"""
def setUp(self):
super(SettingsMenuTest, self).setUp()
course_fix = CourseFixture(**self.course_info)
course_fix.install()
self.auth_page = AutoAuthPage(
self.browser,
staff=False,
username=course_fix.user.get('username'),
email=course_fix.user.get('email'),
password=course_fix.user.get('password')
)
self.auth_page.visit()
self.advanced_settings = AdvancedSettingsPage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
self.advanced_settings.visit()
def test_link_exist_if_split_test_enabled(self):
"""
Ensure that the link to the "Group Configurations" page is shown in the
Settings menu.
"""
link_css = 'li.nav-course-settings-group-configurations a'
self.assertFalse(self.advanced_settings.q(css=link_css).present)
self.advanced_settings.set('Advanced Module List', '["split_test"]')
self.browser.refresh()
self.advanced_settings.wait_for_page()
self.assertIn(
"split_test",
json.loads(self.advanced_settings.get('Advanced Module List')),
)
self.assertTrue(self.advanced_settings.q(css=link_css).present)
def test_link_does_not_exist_if_split_test_disabled(self):
"""
Ensure that the link to the "Group Configurations" page does not exist
in the Settings menu.
"""
link_css = 'li.nav-course-settings-group-configurations a'
self.advanced_settings.set('Advanced Module List', '[]')
self.browser.refresh()
self.advanced_settings.wait_for_page()
self.assertFalse(self.advanced_settings.q(css=link_css).present)
@skipUnless(os.environ.get('FEATURE_GROUP_CONFIGURATIONS'), 'Tests Group Configurations feature')
class GroupConfigurationsTest(UniqueCourseTest):
"""
Tests that Group Configurations page works correctly with previously
added configurations in Studio
"""
def setUp(self):
super(GroupConfigurationsTest, self).setUp()
course_fix = CourseFixture(**self.course_info)
course_fix.add_advanced_settings({
u"advanced_modules": {"value": ["split_test"]},
})
course_fix.install()
self.course_fix = course_fix
self.user = course_fix.user
self.auth_page = AutoAuthPage(
self.browser,
staff=False,
username=course_fix.user.get('username'),
email=course_fix.user.get('email'),
password=course_fix.user.get('password')
)
self.auth_page.visit()
self.page = GroupConfigurationsPage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
def test_no_group_configurations_added(self):
"""
Ensure that message telling me to create a new group configuration is
shown when group configurations were not added.
"""
self.page.visit()
css = ".wrapper-content .no-group-configurations-content"
self.assertTrue(self.page.q(css=css).present)
self.assertIn(
"You haven't created any group configurations yet.",
self.page.q(css=css).text[0]
)
def test_group_configurations_have_correct_data(self):
"""
Ensure that the group configuration is rendered correctly in
expanded/collapsed mode.
"""
self.course_fix.add_advanced_settings({
u"user_partitions": {
"value": [
UserPartition(0, 'Name of the Group Configuration', 'Description of the group configuration.', [Group("0", 'Group 0'), Group("1", 'Group 1')]).to_json(),
UserPartition(1, 'Name of second Group Configuration', 'Second group configuration.', [Group("0", 'Alpha'), Group("1", 'Beta'), Group("2", 'Gamma')]).to_json()
],
},
})
self.course_fix._add_advanced_settings()
self.page.visit()
config = self.page.group_configurations()[0]
self.assertIn("Name of the Group Configuration", config.name)
self.assertEqual(config.id, '0')
config.toggle()
self.assertIn("Description of the group configuration.", config.description)
self.assertEqual(len(config.groups), 2)
self.assertEqual("Group 0", config.groups[0].name)
self.assertEqual("50%", config.groups[0].allocation)
config = self.page.group_configurations()[1]
self.assertIn("Name of second Group Configuration", config.name)
self.assertEqual(len(config.groups), 0) # no groups when the partition is collapsed
config.toggle()
self.assertEqual(len(config.groups), 3)
self.assertEqual("Beta", config.groups[1].name)
self.assertEqual("33%", config.groups[1].allocation)