def _add_user_partitions(self, count=1, scheme_id="random"): """ Create user partitions for the course. """ partitions = [ UserPartition( i, 'Name ' + str(i), 'Description ' + str(i), [Group(0, 'Group A'), Group(1, 'Group B'), Group(2, 'Group C')], scheme=None, scheme_id=scheme_id ) for i in range(count) ] self.course.user_partitions = partitions self.save_course()
def create_content_groups(self, content_groups): """ Create a cohorted user partition with the specified content groups. """ # pylint: disable=attribute-defined-outside-init self.content_partition = UserPartition( MINIMUM_STATIC_PARTITION_ID, self.CONTENT_GROUPS_TITLE, 'Contains Groups for Cohorted Courseware', content_groups, scheme_id='cohort') self.course.user_partitions = [self.content_partition] self.store.update_item(self.course, self.user.id)
def setUpClass(cls): super().setUpClass() cls.partition = UserPartition( 0, 'first_partition', 'First Partition', [Group(0, 'alpha'), Group(1, 'beta')]) cls.course = CourseFactory.create(user_partitions=[cls.partition]) cls.chapter = ItemFactory.create( parent_location=cls.course.location, category="chapter", display_name="test chapter", )
def test_split_user_partitions(self): """ Tests the get_split_user_partitions helper method. """ first_random_partition = UserPartition( 0, 'first_partition', 'First Partition', [Group("0", 'alpha'), Group("1", 'beta')], self.random_scheme ) second_random_partition = UserPartition( 0, 'second_partition', 'Second Partition', [Group("4", 'zeta'), Group("5", 'omega')], self.random_scheme ) all_partitions = [ first_random_partition, # Only UserPartitions with scheme "random" will be returned as available options. UserPartition( 1, 'non_random_partition', 'Will Not Be Returned', [Group("1", 'apple'), Group("2", 'banana')], self.non_random_scheme ), second_random_partition ] assert [first_random_partition, second_random_partition] == get_split_user_partitions(all_partitions)
def test_group_configurations_have_correct_data(self): """ Scenario: Ensure that the group configuration is rendered correctly in expanded/collapsed mode. Given I have a course with 2 group configurations And I go to the Group Configuration page in Studio And I work with the first group configuration And I see `name`, `id` are visible and have correct values When I expand the first group configuration Then I see `description` and `groups` appear and also have correct values And I do the same checks for the second group configuration """ self.course_fixture._update_xblock(self.course_fixture._course_location, { "metadata": { u"user_partitions": [ 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.page.visit() config = self.page.group_configurations[0] # no groups when the the configuration is collapsed self.assertEqual(len(config.groups), 0) self._assert_fields( config, cid="0", name="Name of the Group Configuration", description="Description of the group configuration.", groups=["Group 0", "Group 1"] ) config = self.page.group_configurations[1] self._assert_fields( config, name="Name of second Group Configuration", description="Second group configuration.", groups=["Alpha", "Beta", "Gamma"] )
def setUp(self): groups = [Group(0, 'Group 1'), Group(1, 'Group 2')] self.partition_id = 0 self.user_tags_service = MemoryUserTagsService() user_partition = UserPartition(self.partition_id, 'Test Partition', 'for testing purposes', groups) self.partitions_service = StaticPartitionService( [user_partition], user_tags_service=self.user_tags_service, course_id=Mock(), track_function=Mock())
def create_content_groups(self, content_groups): """ Create a cohorted user partition with the specified content groups. """ # pylint: disable=attribute-defined-outside-init self.content_partition = UserPartition( 1, 'Content Groups', 'Contains Groups for Cohorted Courseware', content_groups, scheme_id='cohort') self.course.user_partitions = [self.content_partition] self.store.update_item(self.course, self.user.id)
def test_can_get_correct_usage_info_for_unit(self): """ When group access is set on the unit level, the usage info should return a url to the unit, not the sequential parent of the unit. """ self.course.user_partitions = [ UserPartition( id=0, name='User Partition', scheme=UserPartition.get_scheme('cohort'), description='User Partition', groups=[ Group(id=0, name="Group") ], ), ] vertical, __ = self._create_problem_with_content_group( cid=0, group_id=0, name_suffix='0' ) self.client.ajax_post( reverse_usage_url("xblock_handler", vertical.location), data={'metadata': {'group_access': {0: [0]}}} ) actual = self._get_user_partition('cohort') expected = { 'id': 0, 'name': 'User Partition', 'scheme': 'cohort', 'description': 'User Partition', 'version': UserPartition.VERSION, 'groups': [ {'id': 0, 'name': 'Group', 'version': 1, 'usage': [ { 'url': u"/container/{}".format(vertical.location), 'label': u"Test Subsection 0 / Test Unit 0" }, { 'url': u"/container/{}".format(vertical.location), 'label': u"Test Unit 0 / Test Problem 0" } ]}, ], u'parameters': {}, u'active': True, } self.maxDiff = None self.assertEqual(actual, expected)
def _add_user_partitions(self, count=1): """ Create user partitions for the course. """ partitions = [ UserPartition(i, 'Name ' + str(i), 'Description ' + str(i), [ Group(0, 'Group A'), Group(1, 'Group B'), Group(2, 'Group C') ]) for i in xrange(0, count) ] self.course.user_partitions = partitions self.save_course()
def _setup_course_partitions(self, scheme_id='random', is_cohorted=False): """Helper method to configure the user partitions in the course.""" self.partition_id = 0 # pylint: disable=attribute-defined-outside-init self.course.user_partitions = [ UserPartition( self.partition_id, 'first_partition', 'First Partition', [Group(0, 'alpha'), Group(1, 'beta')], scheme=None, scheme_id=scheme_id), ] self.course.cohort_config = {'cohorted': is_cohorted} self.store.update_item(self.course, self.user.id)
def test_has_access_in_preview_mode_with_group(self): """ Test that a user masquerading as a member of a group sees appropriate content in preview mode. """ # Note about UserPartition and UserPartition Group IDs: these must not conflict with IDs used # by dynamic user partitions. partition_id = MINIMUM_STATIC_PARTITION_ID group_0_id = MINIMUM_STATIC_PARTITION_ID + 1 group_1_id = MINIMUM_STATIC_PARTITION_ID + 2 user_partition = UserPartition( partition_id, 'Test User Partition', '', [Group(group_0_id, 'Group 1'), Group(group_1_id, 'Group 2')], scheme_id='cohort' ) self.course.user_partitions.append(user_partition) self.course.cohort_config = {'cohorted': True} chapter = ItemFactory.create(category="chapter", parent_location=self.course.location) chapter.group_access = {partition_id: [group_0_id]} modulestore().update_item(self.course, ModuleStoreEnum.UserID.test) # User should not be able to preview when masquerading as student (and not in the group above). with patch('courseware.access.get_user_role') as mock_user_role: mock_user_role.return_value = 'student' self.assertFalse( bool(access.has_access(self.global_staff, 'load', chapter, course_key=self.course.id)) ) # Should be able to preview when in staff or instructor role. for mocked_role in ['staff', 'instructor']: with patch('courseware.access.get_user_role') as mock_user_role: mock_user_role.return_value = mocked_role self.assertTrue( bool(access.has_access(self.global_staff, 'load', chapter, course_key=self.course.id)) ) # Now install masquerade group and set staff as a member of that. self.assertEqual(200, masquerade_as_group_member(self.global_staff, self.course, partition_id, group_0_id)) # Can load the chapter since user is in the group. self.assertTrue( bool(access.has_access(self.global_staff, 'load', chapter, course_key=self.course.id)) ) # Move the user to be a part of the second group. self.assertEqual(200, masquerade_as_group_member(self.global_staff, self.course, partition_id, group_1_id)) # Cannot load the chapter since user is in a different group. self.assertFalse( bool(access.has_access(self.global_staff, 'load', chapter, course_key=self.course.id)) )
def setUp(self): super(SplitTestModuleTest, self).setUp() self.course_id = 'test_org/test_course_number/test_run' # construct module course = xml.CourseFactory.build() sequence = xml.SequenceFactory.build(parent=course) split_test = SplitTestModuleFactory( parent=sequence, attribs={ 'user_partition_id': '0', 'group_id_to_child': '{"0": "i4x://edX/xml_test_course/html/split_test_cond0", "1": "i4x://edX/xml_test_course/html/split_test_cond1"}' }) xml.HtmlFactory(parent=split_test, url_name='split_test_cond0', text='HTML FOR GROUP 0') xml.HtmlFactory(parent=split_test, url_name='split_test_cond1', text='HTML FOR GROUP 1') self.course = self.process_xml(course) self.course_sequence = self.course.get_children()[0] self.module_system = get_test_system() self.module_system.descriptor_runtime = self.course.runtime._descriptor_system # pylint: disable=protected-access self.course.runtime.export_fs = MemoryFS() self.partitions_service = StaticPartitionService( [ self.user_partition, UserPartition(1, 'second_partition', 'Second Partition', [ Group("0", 'abel'), Group("1", 'baker'), Group("2", 'charlie') ], MockUserPartitionScheme()) ], user=Mock(username='******', email='*****@*****.**', is_staff=False, is_active=True), course_id=self.course.id, track_function=Mock(name='track_function'), ) self.module_system._services['partitions'] = self.partitions_service # pylint: disable=protected-access self.split_test_module = self.course_sequence.get_children()[0] self.split_test_module.bind_for_student( self.module_system, self.split_test_module._field_data) # pylint: disable=protected-access
def test_group_configuration_url(self): """ Test creation of correct Group Configuration URL. """ mocked_course = Mock(advanced_modules=['split_test']) mocked_modulestore = Mock() mocked_modulestore.get_course.return_value = mocked_course self.split_test_module.system.modulestore = mocked_modulestore self.split_test_module.user_partitions = [ UserPartition(0, 'first_partition', 'First Partition', [Group("0", 'alpha'), Group("1", 'beta')]) ] expected_url = '/group_configurations/edX/xml_test_course/101#0' self.assertEqual(expected_url, self.split_test_module.group_configuration_url)
def test_construct(self): user_partition = UserPartition( self.TEST_ID, self.TEST_NAME, self.TEST_DESCRIPTION, self.TEST_GROUPS, MockUserPartitionScheme(), self.TEST_PARAMETERS, ) self.assertEqual(user_partition.id, self.TEST_ID) self.assertEqual(user_partition.name, self.TEST_NAME) self.assertEqual(user_partition.description, self.TEST_DESCRIPTION) self.assertEqual(user_partition.groups, self.TEST_GROUPS) self.assertEquals(user_partition.scheme.name, self.TEST_SCHEME_NAME) self.assertEquals(user_partition.parameters, self.TEST_PARAMETERS)
def test_construct(self): user_partition = UserPartition( self.TEST_ID, self.TEST_NAME, self.TEST_DESCRIPTION, self.TEST_GROUPS, MockUserPartitionScheme(), self.TEST_PARAMETERS, ) assert user_partition.id == self.TEST_ID assert user_partition.name == self.TEST_NAME assert user_partition.description == self.TEST_DESCRIPTION assert user_partition.groups == self.TEST_GROUPS assert user_partition.scheme.name == self.TEST_SCHEME_NAME assert user_partition.parameters == self.TEST_PARAMETERS
def create_user_partition_json(partition_id, name, description, groups, scheme="random"): """ Helper method to create user partition JSON. If scheme is not supplied, "random" is used. """ # All that is persisted about a scheme is its name. class MockScheme(object): name = scheme return UserPartition(partition_id, name, description, groups, MockScheme()).to_json()
def test_group_configuration_non_empty_usage(self): """ Scenario: When group configuration is used, ensure that the links to units using a group configuration work correctly. Given I have a course without group configurations And I create new group configuration with 2 default groups And I create a unit and assign the newly created group configuration And open the Group Configuration page Then I see a link to the newly created unit When I click on the unit link Then I see correct unit page """ # Create a new group configurations self.course_fixture._update_xblock( self.course_fixture._course_location, { "metadata": { u"user_partitions": [ UserPartition( 0, "Name", "Description.", [Group("0", "Group A"), Group("1", "Group B")]).to_json(), ], }, }) # Assign newly created group configuration to unit vertical = self.course_fixture.get_nested_xblocks( category="vertical")[0] self.course_fixture.create_xblock( vertical.locator, XBlockFixtureDesc('split_test', 'Test Content Experiment', metadata={'user_partition_id': 0})) unit = CourseOutlineUnit(self.browser, vertical.locator) # Go to the Group Configuration Page and click unit anchor self.page.visit() config = self.page.group_configurations[0] config.toggle() usage = config.usages[0] config.click_unit_anchor() unit = ContainerPage(self.browser, vertical.locator) # Waiting for the page load and verify that we've landed on the unit page EmptyPromise(lambda: unit.is_browser_on_page(), "loaded page {!r}".format(unit), timeout=30).fulfill() self.assertIn(unit.name, usage)
def test_to_json(self): groups = [Group(0, 'Group 1'), Group(1, 'Group 2')] upid = 0 upname = "Test Partition" updesc = "for testing purposes" user_partition = UserPartition(upid, upname, updesc, groups) jsonified = user_partition.to_json() act_jsonified = { "id": upid, "name": upname, "description": updesc, "groups": [group.to_json() for group in groups], "version": user_partition.VERSION } self.assertEqual(jsonified, act_jsonified)
def setUp(self): # Set up two user partition schemes: mock and random extensions = [ Extension(self.TEST_SCHEME_NAME, USER_PARTITION_SCHEME_NAMESPACE, MockUserPartitionScheme(self.TEST_SCHEME_NAME), None), Extension("random", USER_PARTITION_SCHEME_NAMESPACE, MockUserPartitionScheme("random"), None), ] UserPartition.scheme_extensions = ExtensionManager.make_test_instance( extensions, namespace=USER_PARTITION_SCHEME_NAMESPACE) # Create a test partition self.user_partition = UserPartition(self.TEST_ID, self.TEST_NAME, self.TEST_DESCRIPTION, self.TEST_GROUPS, extensions[0].plugin)
def setUp(self): """ Regenerate a course with cohort configuration, partition and groups, and a student for each test. """ self.course_key = SlashSeparatedCourseKey("edX", "toy", "2012_Fall") self.course = modulestore().get_course(self.course_key) config_course_cohorts(self.course, [], cohorted=True) self.groups = [Group(10, 'Group 10'), Group(20, 'Group 20')] self.user_partition = UserPartition(0, 'Test Partition', 'for testing purposes', self.groups, scheme=CohortPartitionScheme) self.student = UserFactory.create()
def test_enrollment_track_partition_not_added_if_conflict(self): """ Test that the dynamic enrollment track scheme is NOT added if a UserPartition exists with that ID. """ self.user_partition = UserPartition( ENROLLMENT_TRACK_PARTITION_ID, self.TEST_NAME, self.TEST_DESCRIPTION, self.TEST_GROUPS, self.non_random_scheme, self.TEST_PARAMETERS, ) self.course.user_partitions = [self.user_partition] all_partitions = get_all_partitions_for_course(self.course) self.assertEqual(1, len(all_partitions)) self.assertEqual(self.TEST_SCHEME_NAME, all_partitions[0].scheme.name)
def test_user_in_deleted_group(self): # get a group assigned to the user - should be group 0 or 1 old_group = RandomUserPartitionScheme.get_group_for_user(self.MOCK_COURSE_ID, self.user, self.user_partition) self.assertIn(old_group.id, [0, 1]) # Change the group definitions! No more group 0 or 1 groups = [Group(3, 'Group 3'), Group(4, 'Group 4')] user_partition = UserPartition(self.TEST_ID, 'Test Partition', 'for testing purposes', groups) # Now, get a new group using the same call - should be 3 or 4 new_group = RandomUserPartitionScheme.get_group_for_user(self.MOCK_COURSE_ID, self.user, user_partition) self.assertIn(new_group.id, [3, 4]) # We should get the same group over multiple calls new_group_2 = RandomUserPartitionScheme.get_group_for_user(self.MOCK_COURSE_ID, self.user, user_partition) self.assertEqual(new_group, new_group_2)
def setUp(self): self.partition = UserPartition( 0, 'first_partition', 'First Partition', [Group(0, 'alpha'), Group(1, 'beta')]) self.course = CourseFactory.create(user_partitions=[self.partition]) self.chapter = ItemFactory.create( parent_location=self.course.location, category="chapter", display_name="test chapter", ) self.student = UserFactory.create() CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id) self.client.login(username=self.student.username, password='******')
def test_available_partitions(self): """ Tests that the available partitions are populated correctly when editable_metadata_fields are called """ self.assertEqual([], SplitTestDescriptor.user_partition_id.values) # user_partitions is empty, only the "Not Selected" item will appear. self.split_test_module.user_partition_id = SplitTestFields.no_partition_selected[ 'value'] self.split_test_module.editable_metadata_fields # pylint: disable=pointless-statement partitions = SplitTestDescriptor.user_partition_id.values self.assertEqual(1, len(partitions)) self.assertEqual(SplitTestFields.no_partition_selected['value'], partitions[0]['value']) # Populate user_partitions and call editable_metadata_fields again self.split_test_module.user_partitions = [ UserPartition( 0, 'first_partition', 'First Partition', [Group("0", 'alpha'), Group("1", 'beta')]) ] self.split_test_module.editable_metadata_fields # pylint: disable=pointless-statement partitions = SplitTestDescriptor.user_partition_id.values self.assertEqual(2, len(partitions)) self.assertEqual(SplitTestFields.no_partition_selected['value'], partitions[0]['value']) self.assertEqual(0, partitions[1]['value']) self.assertEqual("first_partition", partitions[1]['display_name']) # Try again with a selected partition and verify that there is no option for "No Selection" self.split_test_module.user_partition_id = 0 self.split_test_module.editable_metadata_fields # pylint: disable=pointless-statement partitions = SplitTestDescriptor.user_partition_id.values self.assertEqual(1, len(partitions)) self.assertEqual(0, partitions[0]['value']) self.assertEqual("first_partition", partitions[0]['display_name']) # Finally try again with an invalid selected partition and verify that "No Selection" is an option self.split_test_module.user_partition_id = 999 self.split_test_module.editable_metadata_fields # pylint: disable=pointless-statement partitions = SplitTestDescriptor.user_partition_id.values self.assertEqual(2, len(partitions)) self.assertEqual(SplitTestFields.no_partition_selected['value'], partitions[0]['value']) self.assertEqual(0, partitions[1]['value']) self.assertEqual("first_partition", partitions[1]['display_name'])
def test_complete_student_attempt_split_test(self, mock_submit): """ Asserts complete_student_attempt correctly publishes completion when a split test is involved This test case exists because we ran into a bug about the user_service not existing when a split_test existed inside of a subsection. Associated with this change was adding in the user state into the module before attempting completion and this ensures that is working properly. """ partition = UserPartition( 0, 'first_partition', 'First Partition', [ Group(0, 'alpha'), Group(1, 'beta') ] ) course = CourseFactory.create(user_partitions=[partition]) section = ItemFactory.create(parent=course, category='chapter') subsection = ItemFactory.create(parent=section, category='sequential') c0_url = course.id.make_usage_key('vertical', 'split_test_cond0') c1_url = course.id.make_usage_key('vertical', 'split_test_cond1') split_test = ItemFactory.create( parent=subsection, category='split_test', user_partition_id=0, group_id_to_child={'0': c0_url, '1': c1_url}, ) cond0vert = ItemFactory.create(parent=split_test, category='vertical', location=c0_url) ItemFactory.create(parent=cond0vert, category='video') ItemFactory.create(parent=cond0vert, category='problem') cond1vert = ItemFactory.create(parent=split_test, category='vertical', location=c1_url) ItemFactory.create(parent=cond1vert, category='video') ItemFactory.create(parent=cond1vert, category='html') with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True): self.service.complete_student_attempt(self.student.username, str(subsection.location)) # Only the group the user was assigned to should have completion published. # Either cond0vert's children or cond1vert's children assert mock_submit.call_count == 2
def setUp(self): """ Regenerate a course with cohort configuration, partition and groups, and a student for each test. """ super(TestCohortPartitionScheme, self).setUp() self.course_key = ToyCourseFactory.create().id self.course = modulestore().get_course(self.course_key) config_course_cohorts(self.course, is_cohorted=True) self.groups = [Group(10, 'Group 10'), Group(20, 'Group 20')] self.user_partition = UserPartition(0, 'Test Partition', 'for testing purposes', self.groups, scheme=CohortPartitionScheme) self.student = UserFactory.create()
def setUp(self): super(GetCourseTopicsTest, self).setUp() self.maxDiff = None # pylint: disable=invalid-name self.partition = UserPartition( 0, "partition", "Test Partition", [Group(0, "Cohort A"), Group(1, "Cohort B")], scheme_id="cohort") self.course = CourseFactory.create(org="x", course="y", run="z", start=datetime.now(UTC), discussion_topics={}, user_partitions=[self.partition], cohort_config={"cohorted": True}, days_early_for_beta=3) self.user = UserFactory.create()
def setUp(self): super(LmsXBlockMixinTestCase, self).setUp() self.user_partition = UserPartition( 0, 'first_partition', 'First Partition', [ Group(0, 'alpha'), Group(1, 'beta') ] ) self.group1 = self.user_partition.groups[0] # pylint: disable=no-member self.group2 = self.user_partition.groups[1] # pylint: disable=no-member self.course = CourseFactory.create(user_partitions=[self.user_partition]) self.section = ItemFactory.create(parent=self.course, category='chapter', display_name='Test Section') self.subsection = ItemFactory.create(parent=self.section, category='sequential', display_name='Test Subsection') self.vertical = ItemFactory.create(parent=self.subsection, category='vertical', display_name='Test Unit') self.video = ItemFactory.create(parent=self.subsection, category='video', display_name='Test Video')
def test_unicode_user_partitions(self): """ Test that user partition groups can contain unicode characters. """ user_groups = [u'ÞrÖfessÖr X', u'MàgnëtÖ'] user_partition = UserPartition( 0, 'x_man', 'X Man', [Group(0, user_groups[0]), Group(1, user_groups[1])]) # Create course with group configurations self.initialize_course( course_factory_kwargs={'user_partitions': [user_partition]}) _groups = [ group.name for group in self.course.user_partitions[0].groups ] self.assertEqual(_groups, user_groups)
def test_view_index_ok(self): """ Basic check that the groups configuration page responds correctly. """ self.course.user_partitions = [ UserPartition(0, 'First name', 'First description', [Group(0, 'Group A'), Group(1, 'Group B'), Group(2, 'Group C')]), ] self.save_course() if SPLIT_TEST_COMPONENT_TYPE not in self.course.advanced_modules: self.course.advanced_modules.append(SPLIT_TEST_COMPONENT_TYPE) self.store.update_item(self.course, self.user.id) response = self.client.get(self._url()) self.assertEqual(response.status_code, 200) self.assertContains(response, 'First name') self.assertContains(response, 'Group C')