diff --git a/common/test/acceptance/pages/studio/settings_group_configurations.py b/common/test/acceptance/pages/studio/settings_group_configurations.py
index eb98c4dac8..83eee7387e 100644
--- a/common/test/acceptance/pages/studio/settings_group_configurations.py
+++ b/common/test/acceptance/pages/studio/settings_group_configurations.py
@@ -12,6 +12,8 @@ class GroupConfigurationsPage(CoursePage):
"""
url_path = "group_configurations"
+ experiment_groups_css = ".experiment-groups"
+ content_groups_css = ".content-groups"
def is_browser_on_page(self):
"""
@@ -30,26 +32,72 @@ class GroupConfigurationsPage(CoursePage):
return True
@property
- def group_configurations(self):
+ def experiment_group_configurations(self):
"""
- Return list of the group configurations for the course.
+ Return list of the experiment group configurations for the course.
"""
- css = '.group-configurations-list-item'
- return [GroupConfiguration(self, index) for index in xrange(len(self.q(css=css)))]
+ return self._get_groups(self.experiment_groups_css)
- def create(self):
+ @property
+ def content_groups(self):
+ """
+ Return list of the content groups for the course.
+ """
+ return self._get_groups(self.content_groups_css)
+
+ def _get_groups(self, prefix):
+ """
+ Return list of the group-configurations-list-item's of specified type for the course.
+ """
+ css = prefix + ' .group-configurations-list-item'
+ return [GroupConfiguration(self, prefix, index) for index in xrange(len(self.q(css=css)))]
+
+ def create_experiment_group_configuration(self):
"""
Creates new group configuration.
"""
- self.q(css=".experiment-groups .new-button").first.click()
+ self.q(css=self.experiment_groups_css + " .new-button").first.click()
+
+ def create_first_content_group(self):
+ """
+ Creates new content group when there are none initially defined.
+ """
+ self.q(css=self.content_groups_css + " .new-button").first.click()
+
+ def add_content_group(self):
+ """
+ Creates new content group when at least one already exists
+ """
+ self.q(css=self.content_groups_css + " .action-add").first.click()
@property
- def no_group_configuration_message_is_present(self):
- return self.q(css='.wrapper-content .experiment-groups .no-group-configurations-content').present
+ def no_experiment_groups_message_is_present(self):
+ return self._no_content_message(self.experiment_groups_css).present
@property
- def no_group_configuration_message_text(self):
- return self.q(css='.wrapper-content .experiment-groups .no-group-configurations-content').text[0]
+ def no_content_groups_message_is_present(self):
+ return self._no_content_message(self.content_groups_css).present
+
+ @property
+ def no_experiment_groups_message_text(self):
+ return self._no_content_message(self.experiment_groups_css).text[0]
+
+ @property
+ def no_content_groups_message_text(self):
+ return self._no_content_message(self.content_groups_css).text[0]
+
+ def _no_content_message(self, prefix):
+ """
+ Returns the message about "no content" for the specified type.
+ """
+ return self.q(css='.wrapper-content ' + prefix + ' .no-group-configurations-content')
+
+ @property
+ def experiment_group_sections_present(self):
+ """
+ Returns whether or not anything related to content experiments is present.
+ """
+ return self.q(css=self.experiment_groups_css).present or self.q(css=".experiment-groups-doc").present
class GroupConfiguration(object):
@@ -57,9 +105,9 @@ class GroupConfiguration(object):
Group Configuration wrapper.
"""
- def __init__(self, page, index):
+ def __init__(self, page, prefix, index):
self.page = page
- self.SELECTOR = '.group-configurations-list-item-{}'.format(index)
+ self.SELECTOR = prefix + ' .group-configurations-list-item-{}'.format(index)
self.index = index
def get_selector(self, css=''):
diff --git a/common/test/acceptance/tests/studio/test_studio_settings.py b/common/test/acceptance/tests/studio/test_studio_settings.py
index 51c98961a3..72f22fe407 100644
--- a/common/test/acceptance/tests/studio/test_studio_settings.py
+++ b/common/test/acceptance/tests/studio/test_studio_settings.py
@@ -7,6 +7,127 @@ from nose.plugins.attrib import attr
from base_studio_test import StudioCourseTest
from ...pages.studio.settings_advanced import AdvancedSettingsPage
+from ...pages.studio.settings_group_configurations import GroupConfigurationsPage
+
+
+@attr('shard_1')
+class ContentGroupConfigurationTest(StudioCourseTest):
+ """
+ Tests for content groups in the Group Configurations Page.
+ There are tests for the experiment groups in test_studio_split_test.
+ """
+ def setUp(self):
+ super(ContentGroupConfigurationTest, self).setUp()
+ self.group_configurations_page = GroupConfigurationsPage(
+ self.browser,
+ self.course_info['org'],
+ self.course_info['number'],
+ self.course_info['run']
+ )
+
+ def create_and_verify_content_group(self, name, existing_groups):
+ """
+ Creates a new content group and verifies that it was properly created.
+ """
+ self.assertEqual(existing_groups, len(self.group_configurations_page.content_groups))
+ if existing_groups == 0:
+ self.group_configurations_page.create_first_content_group()
+ else:
+ self.group_configurations_page.add_content_group()
+ config = self.group_configurations_page.content_groups[existing_groups]
+ config.name = name
+ # Save the content group
+ self.assertEqual(config.get_text('.action-primary'), "Create")
+ self.assertTrue(config.delete_button_is_absent)
+ config.save()
+ self.assertIn(name, config.name)
+ return config
+
+ def test_no_content_groups_by_default(self):
+ """
+ Scenario: Ensure that message telling me to create a new content group is
+ shown when no content groups exist.
+ Given I have a course without content groups
+ When I go to the Group Configuration page in Studio
+ Then I see "You have not created any content groups yet." message
+ """
+ self.group_configurations_page.visit()
+ self.assertTrue(self.group_configurations_page.no_content_groups_message_is_present)
+ self.assertIn(
+ "You have not created any content groups yet.",
+ self.group_configurations_page.no_content_groups_message_text
+ )
+
+ def test_can_create_and_edit_content_groups(self):
+ """
+ Scenario: Ensure that the content groups can be created and edited correctly.
+ Given I have a course without content groups
+ When I click button 'Add your first Content Group'
+ And I set new the name and click the button 'Create'
+ Then I see the new content is added and has correct data
+ And I click 'New Content Group' button
+ And I set the name and click the button 'Create'
+ Then I see the second content group is added and has correct data
+ When I edit the second content group
+ And I change the name and click the button 'Save'
+ Then I see the second content group is saved successfully and has the new name
+ """
+ self.group_configurations_page.visit()
+ self.create_and_verify_content_group("New Content Group", 0)
+ second_config = self.create_and_verify_content_group("Second Content Group", 1)
+
+ # Edit the second content group
+ second_config.edit()
+ second_config.name = "Updated Second Content Group"
+ self.assertEqual(second_config.get_text('.action-primary'), "Save")
+ second_config.save()
+
+ self.assertIn("Updated Second Content Group", second_config.name)
+
+ def test_cannot_delete_content_group(self):
+ """
+ Scenario: Delete is not currently supported for content groups.
+ Given I have a course without content groups
+ When I create a content group
+ Then there is no delete button
+ """
+ self.group_configurations_page.visit()
+ config = self.create_and_verify_content_group("New Content Group", 0)
+ self.assertTrue(config.delete_button_is_absent)
+
+ def test_must_supply_name(self):
+ """
+ Scenario: Ensure that validation of the content group works correctly.
+ Given I have a course without content groups
+ And I create new content group without specifying a name click the button 'Create'
+ Then I see error message "Content Group name is required."
+ When I set a name and click the button 'Create'
+ Then I see the content group is saved successfully
+ """
+ self.group_configurations_page.visit()
+ self.group_configurations_page.create_first_content_group()
+ config = self.group_configurations_page.content_groups[0]
+ config.save()
+ self.assertEqual(config.mode, 'edit')
+ self.assertEqual("Group name is required", config.validation_message)
+ config.name = "Content Group Name"
+ config.save()
+ self.assertIn("Content Group Name", config.name)
+
+ def test_can_cancel_creation_of_content_group(self):
+ """
+ Scenario: Ensure that creation of a content group can be canceled correctly.
+ Given I have a course without content groups
+ When I click button 'Add your first Content Group'
+ And I set new the name and click the button 'Cancel'
+ Then I see that there is no content groups in the course
+ """
+ self.group_configurations_page.visit()
+ self.group_configurations_page.create_first_content_group()
+ config = self.group_configurations_page.content_groups[0]
+ config.name = "Content Group"
+ config.cancel()
+ self.assertEqual(0, len(self.group_configurations_page.content_groups))
@attr('shard_1')
diff --git a/common/test/acceptance/tests/studio/test_studio_split_test.py b/common/test/acceptance/tests/studio/test_studio_split_test.py
index 0225cf7439..395cb1f48b 100644
--- a/common/test/acceptance/tests/studio/test_studio_split_test.py
+++ b/common/test/acceptance/tests/studio/test_studio_split_test.py
@@ -202,28 +202,28 @@ class SplitTest(ContainerBase, SplitTestMixin):
@attr('shard_1')
-class SettingsMenuTest(StudioCourseTest):
+class GroupConfigurationsNoSplitTest(StudioCourseTest):
"""
- Tests that Settings menu is rendered correctly in Studio
+ Tests how the Group Configuration page should look when the split_test module is not enabled.
"""
-
def setUp(self):
- super(SettingsMenuTest, self).setUp()
- self.advanced_settings = AdvancedSettingsPage(
+ super(GroupConfigurationsNoSplitTest, self).setUp()
+ self.group_configurations_page = GroupConfigurationsPage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
- self.advanced_settings.visit()
- def test_link_exist(self):
+ def test_no_content_experiment_sections(self):
"""
- Ensure that the link to the "Group Configurations" page is shown in the
- Settings menu.
+ Scenario: if split_test module is not present in Advanced Settings, content experiment
+ parts of the Group Configurations page are not shown.
+ Given I have a course with split_test module not enabled
+ Then when I go to the Group Configurations page there are no content experiment sections
"""
- link_css = 'li.nav-course-settings-group-configurations a'
- self.assertTrue(self.advanced_settings.q(css=link_css).present)
+ self.group_configurations_page.visit()
+ self.assertFalse(self.group_configurations_page.experiment_group_sections_present)
@attr('shard_1')
@@ -329,7 +329,7 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
# Go to the Group Configuration Page
self.page.visit()
- config = self.page.group_configurations[0]
+ config = self.page.experiment_group_configurations[0]
if associate_experiment:
return config, split_test
@@ -364,14 +364,14 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
shown when group configurations were not added.
Given I have a course without group configurations
When I go to the Group Configuration page in Studio
- Then I see "You haven't created any group configurations yet." message
- And "Create new Group Configuration" button is available
+ Then I see "You have not created any group configurations yet." message
"""
self.page.visit()
- self.assertTrue(self.page.no_group_configuration_message_is_present)
+ self.assertTrue(self.page.experiment_group_sections_present)
+ self.assertTrue(self.page.no_experiment_groups_message_is_present)
self.assertIn(
- "You haven't created any group configurations yet.",
- self.page.no_group_configuration_message_text
+ "You have not created any group configurations yet.",
+ self.page.no_experiment_groups_message_text
)
def test_group_configurations_have_correct_data(self):
@@ -405,7 +405,7 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
})
self.page.visit()
- config = self.page.group_configurations[0]
+ config = self.page.experiment_group_configurations[0]
# no groups when the the configuration is collapsed
self.assertEqual(len(config.groups), 0)
self._assert_fields(
@@ -415,7 +415,7 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
groups=["Group 0", "Group 1"]
)
- config = self.page.group_configurations[1]
+ config = self.page.experiment_group_configurations[1]
self._assert_fields(
config,
@@ -438,10 +438,10 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
Then I see the group configuration is saved successfully and has the new data
"""
self.page.visit()
- self.assertEqual(len(self.page.group_configurations), 0)
+ self.assertEqual(len(self.page.experiment_group_configurations), 0)
# Create new group configuration
- self.page.create()
- config = self.page.group_configurations[0]
+ self.page.create_experiment_group_configuration()
+ config = self.page.experiment_group_configurations[0]
config.name = "New Group Configuration Name"
config.description = "New Description of the group configuration."
config.groups[1].name = "New Group Name"
@@ -496,8 +496,8 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
"""
self.page.visit()
# Create new group configuration
- self.page.create()
- config = self.page.group_configurations[0]
+ self.page.create_experiment_group_configuration()
+ config = self.page.experiment_group_configurations[0]
config.name = "New Group Configuration Name"
# Add new group
config.add_group()
@@ -547,7 +547,7 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
split_test = self._add_split_test_to_vertical(number=0, group_configuration_metadata={'user_partition_id': 0})
self.page.visit()
- config = self.page.group_configurations[0]
+ config = self.page.experiment_group_configurations[0]
config.edit()
config.name = "Second Group Configuration Name"
# `Group C` -> `Second Group`
@@ -591,11 +591,11 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
"""
self.page.visit()
- self.assertEqual(len(self.page.group_configurations), 0)
+ self.assertEqual(len(self.page.experiment_group_configurations), 0)
# Create new group configuration
- self.page.create()
+ self.page.create_experiment_group_configuration()
- config = self.page.group_configurations[0]
+ config = self.page.experiment_group_configurations[0]
config.name = "Name of the Group Configuration"
config.description = "Description of the group configuration."
# Add new group
@@ -603,7 +603,7 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
# Cancel the configuration
config.cancel()
- self.assertEqual(len(self.page.group_configurations), 0)
+ self.assertEqual(len(self.page.experiment_group_configurations), 0)
def test_can_cancel_editing_of_group_configuration(self):
"""
@@ -633,7 +633,7 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
},
})
self.page.visit()
- config = self.page.group_configurations[0]
+ config = self.page.experiment_group_configurations[0]
config.name = "New Group Configuration Name"
config.description = "New Description of the group configuration."
# Add 2 new groups
@@ -674,9 +674,9 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
self.page.visit()
# Create new group configuration
- self.page.create()
+ self.page.create_experiment_group_configuration()
# Leave empty required field
- config = self.page.group_configurations[0]
+ config = self.page.experiment_group_configurations[0]
config.description = "Description of the group configuration."
try_to_save_and_verify_error_message("Group Configuration name is required.")
@@ -725,7 +725,7 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
# Go to the Group Configuration Page and click on outline anchor
self.page.visit()
- config = self.page.group_configurations[0]
+ config = self.page.experiment_group_configurations[0]
config.toggle()
config.click_outline_anchor()
@@ -770,7 +770,7 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
# Go to the Group Configuration Page and click unit anchor
self.page.visit()
- config = self.page.group_configurations[0]
+ config = self.page.experiment_group_configurations[0]
config.toggle()
usage = config.usages[0]
config.click_unit_anchor()
@@ -815,18 +815,18 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
})
self.page.visit()
- self.assertEqual(len(self.page.group_configurations), 2)
- config = self.page.group_configurations[1]
+ self.assertEqual(len(self.page.experiment_group_configurations), 2)
+ config = self.page.experiment_group_configurations[1]
# Delete first group configuration via detail view
config.delete()
- self.assertEqual(len(self.page.group_configurations), 1)
+ self.assertEqual(len(self.page.experiment_group_configurations), 1)
- config = self.page.group_configurations[0]
+ config = self.page.experiment_group_configurations[0]
config.edit()
self.assertFalse(config.delete_button_is_disabled)
# Delete first group configuration via edit view
config.delete()
- self.assertEqual(len(self.page.group_configurations), 0)
+ self.assertEqual(len(self.page.experiment_group_configurations), 0)
def test_cannot_delete_used_group_configuration(self):
"""
@@ -858,7 +858,7 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
# Go to the Group Configuration Page and click unit anchor
self.page.visit()
- config = self.page.group_configurations[0]
+ config = self.page.experiment_group_configurations[0]
self.assertTrue(config.delete_button_is_disabled)
self.assertIn('Cannot delete when in use by an experiment', config.delete_note)
@@ -915,12 +915,12 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
self.page.wait_for_page()
# Appropriate Group Configuration is expanded.
- self.assertFalse(self.page.group_configurations[0].is_expanded)
- self.assertTrue(self.page.group_configurations[1].is_expanded)
+ self.assertFalse(self.page.experiment_group_configurations[0].is_expanded)
+ self.assertTrue(self.page.experiment_group_configurations[1].is_expanded)
self.assertEqual(
group_configuration_link_name,
- self.page.group_configurations[1].name
+ self.page.experiment_group_configurations[1].name
)
def test_details_error_validation_message(self):