def test_get_course_enrollments_for_site_exclude_same_user_different_site( self): """ Test that CEs are not returned from course from another Site, in cases where a user has CEs in desired Site, but also in another Site. """ course_overviews = [CourseOverviewFactory() for i in range(2)] OrganizationCourseFactory(organization=self.organization, course_id=str(course_overviews[0].id)) OrganizationCourseFactory(organization=self.default_site_org, course_id=str(course_overviews[1].id)) uom_our_site = UserOrganizationMappingFactory( organization=self.organization) # enroll same user in a course associated w/ an Organization not connected to our Site uom_other_site = UserOrganizationMappingFactory( user=uom_our_site.user, organization=self.default_site_org) CourseEnrollmentFactory(course_id=course_overviews[1].id, user=uom_our_site.user) expected_ce = [ CourseEnrollmentFactory(course_id=course_overviews[0].id, user=uom_our_site.user) ] course_enrollments = figures.sites.get_course_enrollments_for_site( self.site) assert set([ce.id for ce in course_enrollments ]) == set([ce.id for ce in expected_ce])
def setup(self, db, settings): super(TestLearnerDetailsViewSetMultisite, self).setup(db) # TODO:REFACTOR:Make base 'multisite scaffolding' view test class to # set up the sites, orgs, and users. Put into tests/views/base.py settings.FEATURES['FIGURES_IS_MULTISITE'] = True is_multisite = figures.helpers.is_multisite() assert is_multisite self.my_site_org = OrganizationFactory(sites=[self.site]) self.other_site = SiteFactory(domain='other-site.test') self.other_site_org = OrganizationFactory(sites=[self.other_site]) self.my_course_overviews = [ CourseOverviewFactory() for i in range(0, 4) ] for co in self.my_course_overviews: OrganizationCourseFactory(organization=self.my_site_org, course_id=str(co.id)) # Set up users and enrollments for 'my site' self.my_site_users = [UserFactory() for i in range(3)] for user in self.my_site_users: UserOrganizationMappingFactory(user=user, organization=self.my_site_org) # Create a mix of enrollments: # one learner in one course, same for the other, then two learners in # the same course, and keep one course w/out learners self.my_enrollments = [ CourseEnrollmentFactory(course=self.my_course_overviews[0], user=self.my_site_users[0]), CourseEnrollmentFactory(course=self.my_course_overviews[1], user=self.my_site_users[1]), CourseEnrollmentFactory(course=self.my_course_overviews[2], user=self.my_site_users[0]), CourseEnrollmentFactory(course=self.my_course_overviews[2], user=self.my_site_users[1]), ] self.caller = UserFactory() UserOrganizationMappingFactory(user=self.caller, organization=self.my_site_org, is_amc_admin=True) self.my_site_users.append(self.caller) # Set up other site's data self.other_site_enrollment = CourseEnrollmentFactory() OrganizationCourseFactory( organization=self.other_site_org, course_id=self.other_site_enrollment.course.id) UserOrganizationMappingFactory(user=self.other_site_enrollment.user, organization=self.other_site_org) self.expected_result_keys = [ 'id', 'username', 'name', 'email', 'country', 'is_active', 'year_of_birth', 'level_of_education', 'gender', 'date_joined', 'bio', 'courses', 'language_proficiencies', 'profile_image' ]
def map_users_to_org_site(caller, site, users): org = OrganizationFactory(sites=[site]) UserOrganizationMappingFactory(user=caller, organization=org, is_amc_admin=True) [UserOrganizationMappingFactory(user=user, organization=org) for user in users] # return created objects that the test will need return caller
def test_no_update_has_lcgm_no_sm(self, monkeypatch): """We have an LCGM but not an SM record The function under test should return the existing LCGM """ monkeypatch.setattr( 'figures.pipeline.enrollment_metrics.get_site_for_course', lambda val: self.site) monkeypatch.setattr( 'figures.pipeline.enrollment_metrics._collect_progress_data', lambda val: self.progress_data) # Create a course enrollment for which we won't have student module records ce = CourseEnrollmentFactory( course_id=self.course_enrollment.course_id) if organizations_support_sites(): UserOrganizationMappingFactory(organization=self.org, user=ce.user) lcgm = LearnerCourseGradeMetricsFactory(course_id=ce.course_id, user=ce.user) ce_sm = StudentModule.objects.filter(course_id=ce.course_id, student_id=ce.user.id) assert not ce_sm metrics = collect_metrics_for_enrollment(site=self.site, course_enrollment=ce, date_for=self.today, student_modules=ce_sm) assert not metrics
def test_get_student_modules_for_course_in_site(self): course_overviews = [CourseOverviewFactory() for i in range(3)] for co in course_overviews[:-1]: OrganizationCourseFactory(organization=self.organization, course_id=str(co.id)) assert get_user_model().objects.count() == 0 user = UserFactory() UserOrganizationMappingFactory(user=user, organization=self.organization) sm_count = 2 sm_expected = [StudentModuleFactory(course_id=course_overviews[0].id, student=user ) for i in range(sm_count)] # StudentModule for other course StudentModuleFactory(course_id=course_overviews[1].id) # StudentModule for course not in organization StudentModuleFactory(course_id=course_overviews[2].id) sm = figures.sites.get_student_modules_for_course_in_site( site=self.site, course_id=course_overviews[0].id) assert sm.count() == len(sm_expected) sm = figures.sites.get_student_modules_for_site(site=self.site) assert sm.count() == len(sm_expected) + 1
def setup(self, db): self.date_for = datetime.date(2018, 10, 1) self.site = Site.objects.first() self.users = [ UserFactory(date_joined=as_datetime(self.date_for - datetime.timedelta(days=60))) for i in range(0, 3) ] self.course_overviews = [ CourseOverviewFactory( created=as_datetime(self.date_for - datetime.timedelta(days=60))) for i in range(0, 3) ] self.cdm_recs = [ CourseDailyMetricsFactory(site=self.site, date_for=self.date_for, **cdm) for cdm in CDM_INPUT_TEST_DATA ] self.prev_day_sdm = SiteDailyMetricsFactory(site=self.site, date_for=prev_day( self.date_for), **SDM_DATA[1]) if is_multisite(): self.organization = OrganizationFactory(sites=[self.site]) for co in self.course_overviews: OrganizationCourseFactory(organization=self.organization, course_id=str(co.id)) if organizations_support_sites(): for user in self.users: UserOrganizationMappingFactory( user=user, organization=self.organization)
def map_users_to_org(org, users): """Convenience method to simplify test code """ [ UserOrganizationMappingFactory(user=user, organization=org) for user in users ]
def sm_test_data(db): """ WIP StudentModule test data to test MAU """ year_for = 2019 month_for = 10 created_date = datetime(year_for, month_for, 1).replace(tzinfo=utc) modified_date = datetime(year_for, month_for, 10).replace(tzinfo=utc) course_overviews = [CourseOverviewFactory() for i in range(3)] site = SiteFactory() sm = [] for co in course_overviews: sm += [StudentModuleFactory(course_id=co.id, created=created_date, modified=modified_date) for co in course_overviews] if organizations_support_sites(): org = OrganizationFactory(sites=[site]) for co in course_overviews: OrganizationCourseFactory(organization=org, course_id=str(co.id)) for rec in sm: UserOrganizationMappingFactory(user=rec.student, organization=org) else: org = OrganizationFactory() return dict(site=site, organization=org, course_overviews=course_overviews, student_modules=sm, year_for=year_for, month_for=month_for)
def setup(self, db): self.site = SiteFactory() self.organization = OrganizationFactory(sites=[self.site]) self.callers = [ UserFactory(username='******'), UserFactory(username='******'), UserFactory(username='******'), ] self.user_organization_mappings = [ UserOrganizationMappingFactory(user=self.callers[0], organization=self.organization), UserOrganizationMappingFactory(user=self.callers[1], organization=self.organization, is_amc_admin=True) ] self.callers += create_test_users() self.features = {'FIGURES_IS_MULTISITE': True}
def test_get_course_in_other_site(self, monkeypatch): """ This test is broken. Needs review of django.contrib.sites handling for `get_current_site` """ with mock.patch('figures.helpers.settings.FEATURES', {'FIGURES_IS_MULTISITE': True}): assert figures.helpers.is_multisite() # Stand up site specific data. Candidate for a fixture alpha_site = SiteFactory(domain='alpha.site') alpha_org = OrganizationFactory(sites=[alpha_site]) alpha_course = CourseOverviewFactory(org=alpha_org.short_name) OrganizationCourseFactory(organization=alpha_org, course_id=str(alpha_course.id)) alpha_admin_user = UserFactory(username='******') UserOrganizationMappingFactory(user=alpha_admin_user, organization=alpha_org, is_amc_admin=True) bravo_site = SiteFactory(domain='bravo.site') bravo_org = OrganizationFactory(sites=[bravo_site]) bravo_admin_user = UserFactory(username='******') UserOrganizationMappingFactory(user=bravo_admin_user, organization=bravo_org, is_amc_admin=True) # Run rest of test request = APIRequestFactory().get(self.request_path) request.META['HTTP_HOST'] = alpha_site.domain monkeypatch.setattr(django.contrib.sites.shortcuts, 'get_current_site', lambda req: alpha_site) force_authenticate(request, user=alpha_admin_user) view = self.view_class.as_view({'get': 'retrieve'}) response = view(request, pk=str(alpha_course.id)) assert response.status_code == 200, 'user=alpha_admin_user' monkeypatch.setattr(django.contrib.sites.shortcuts, 'get_current_site', lambda req: bravo_site) force_authenticate(request, user=bravo_admin_user) view = self.view_class.as_view({'get': 'retrieve'}) response = view(request, pk=str(alpha_course.id)) assert response.status_code == 403, 'user=bravo_admin_user'
def setup(self, db): super(TestUserIndexViewSet, self).setup(db) self.users = [make_user(**data) for data in USER_DATA] self.usernames = [data['username'] for data in USER_DATA] self.expected_result_keys = ['id', 'username', 'fullname'] if organizations_support_sites(): self.organization = OrganizationFactory(sites=[self.site]) for user in self.users: UserOrganizationMappingFactory(user=user, organization=self.organization) assert len(self.users) == len(USER_DATA)
def setup(self, db): self.today = date.today() self.site = SiteFactory() if organizations_support_sites(): self.org = OrganizationFactory(sites=[self.site]) else: self.org = OrganizationFactory() self.datetime_1 = datetime(2020, 2, 2, tzinfo=utc) self.datetime_2 = self.datetime_1 + relativedelta( months=1) # future of date_1 self.course_overview = CourseOverviewFactory() self.course_enrollment = CourseEnrollmentFactory( course_id=self.course_overview.id) self.course_enrollment_2 = CourseEnrollmentFactory( course_id=self.course_overview.id) if organizations_support_sites(): OrganizationCourseFactory(organization=self.org, course_id=str(self.course_overview.id)) UserOrganizationMappingFactory(organization=self.org, user=self.course_enrollment.user) UserOrganizationMappingFactory(organization=self.org, user=self.course_enrollment_2.user) self.student_modules = [ StudentModuleFactory(student=self.course_enrollment.user, course_id=self.course_enrollment.course_id, modified=self.datetime_1), StudentModuleFactory(student=self.course_enrollment.user, course_id=self.course_enrollment.course_id, modified=self.datetime_2), # This student module does not belong to the user in course_enrollment StudentModuleFactory(course_id=self.course_enrollment.course_id, modified=self.datetime_2) ] self.learner_sm = StudentModule.objects.filter( course_id=self.course_enrollment.course_id, student=self.course_enrollment.user).order_by('-modified') self.progress_data = dict(points_possible=100, points_earned=25, sections_worked=4, count=5)
def make_caller(org): """Convenience method to create the API caller user """ if organizations_support_sites(): # TODO: set is_staff to False after we have test coverage caller = UserFactory(is_staff=True) UserOrganizationMappingFactory(user=caller, organization=org, is_amc_admin=True) else: caller = UserFactory(is_staff=True) return caller
def simple_mau_test_data(settings): """ Pytest fixture to create the base test data we need for the MAU tests here We set up single site vs multisite mode in this fixture based on which edx-organizations package is declared in the pip requirements file used to run the tests: Community: edx-organizations==0.4.10 Tahoe: git+https://github.com/appsembler/[email protected] """ our_site = SiteFactory() our_org = OrganizationFactory() our_course = CourseOverviewFactory() our_other_course = CourseOverviewFactory() other_site = SiteFactory() other_site_course = CourseOverviewFactory() our_course_data = create_student_module_recs(our_course.id) our_other_course_sm = [ StudentModuleFactory(course_id=our_other_course.id) for i in range(10) ] month_for = date(year=our_course_data['year_for'], month=our_course_data['month_for'], day=1) expected_mau_ids = set( [rec.student.id for rec in our_course_data['in_range']]) test_data = dict( month_for=month_for, expected_mau_ids=expected_mau_ids, our_site=our_site, our_course=our_course, our_course_data=our_course_data, our_other_course=our_other_course, our_other_course_sm=our_other_course_sm, other_site=other_site, other_site_course=other_site_course, ) if organizations_support_sites(): settings.FEATURES['FIGURES_IS_MULTISITE'] = True our_org = OrganizationFactory(sites=[our_site]) for user in set([obj.student for obj in our_course_data['in_range']]): UserOrganizationMappingFactory(user=user, organization=our_org) for course_id in set( [obj.course_id for obj in our_course_data['in_range']]): OrganizationCourseFactory(organization=our_org, course_id=str(course_id)) return test_data
def setup(self, db): self.course_enrollments = [CourseEnrollmentFactory() for i in range(1, 5)] if organizations_support_sites(): self.my_site = SiteFactory(domain='my-site.test') self.my_site_org = OrganizationFactory(sites=[self.my_site]) for ce in self.course_enrollments: OrganizationCourseFactory(organization=self.my_site_org, course_id=str(ce.course.id)) UserOrganizationMappingFactory(user=ce.user, organization=self.my_site_org) self.student_module = StudentModuleFactory()
def setup(self, db, settings): settings.FEATURES['FIGURES_IS_MULTISITE'] = True is_multisite = figures.helpers.is_multisite() assert is_multisite self.site = SiteFactory(domain='foo.test') self.organization = OrganizationFactory(sites=[self.site], ) assert get_user_model().objects.count() == 0 self.users = [UserFactory() for i in range(3)] for user in self.users: UserOrganizationMappingFactory(user=user, organization=self.organization) assert Site.objects.count() == 2 self.features = {'FIGURES_IS_MULTISITE': True}
def setup(self, db): self.today = datetime.date(2018, 6, 1) self.course_overview = CourseOverviewFactory() if OPENEDX_RELEASE == GINKGO: self.course_enrollments = [ CourseEnrollmentFactory(course_id=self.course_overview.id) for i in range(4) ] else: self.course_enrollments = [ CourseEnrollmentFactory(course=self.course_overview) for i in range(4) ] if organizations_support_sites(): self.my_site = SiteFactory(domain='my-site.test') self.my_site_org = OrganizationFactory(sites=[self.my_site]) OrganizationCourseFactory(organization=self.my_site_org, course_id=str(self.course_overview.id)) for ce in self.course_enrollments: UserOrganizationMappingFactory(user=ce.user, organization=self.my_site_org) self.course_access_roles = [ CourseAccessRoleFactory( user=self.course_enrollments[i].user, course_id=self.course_enrollments[i].course_id, role=role, ) for i, role in enumerate(self.COURSE_ROLES) ] # create student modules for yesterday and today for day in [prev_day(self.today), self.today]: self.student_modules = [ StudentModuleFactory(course_id=ce.course_id, student=ce.user, created=ce.created, modified=as_datetime(day)) for ce in self.course_enrollments ] self.cert_days_to_complete = [10, 20, 30] self.expected_avg_cert_days_to_complete = 20 self.generated_certificates = [ GeneratedCertificateFactory( user=self.course_enrollments[i].user, course_id=self.course_enrollments[i].course_id, created_date=(self.course_enrollments[i].created + datetime.timedelta(days=days)), ) for i, days in enumerate(self.cert_days_to_complete) ]
def test_multiple_user_orgs(self, monkeypatch, settings): def test_site(request): return self.site username = '******' request = APIRequestFactory().get('/') request.META['HTTP_HOST'] = self.site.domain request.user = get_user_model().objects.get(username=username) monkeypatch.setattr(django.contrib.sites.shortcuts, 'get_current_site', test_site) settings.FEATURES['FIGURES_IS_MULTISITE'] = True assert figures.helpers.is_multisite() org2 = OrganizationFactory(sites=[self.site]) UserOrganizationMappingFactory(user=request.user, organization=org2), with pytest.raises(figures.permissions.MultipleOrgsPerUserNotSupported): figures.permissions.IsSiteAdminUser().has_permission(request, None)
def create_users_joined_over_time(site, is_multisite, start_date, end_date): """ Creates users. Each user joins on a succesive date between the dates pass as arguments """ users = [] for dt in rrule(DAILY, dtstart=start_date, until=end_date): user = UserFactory(date_joined=dt) if is_multisite: orgs = get_organizations_for_site(site) assert orgs.count() == 1 UserOrganizationMappingFactory(user=user, organization=orgs[0]) users.append(user) return users
def test_student_modules_for_course_enrollment(monkeypatch): """Test we get the correct student modules for the given course enrollment """ site = SiteFactory() ce = CourseEnrollmentFactory() ce_sm = [StudentModuleFactory(student=ce.user, course_id=ce.course_id)] # Create another student module record to make sure this is not in our # query results StudentModuleFactory() if organizations_support_sites(): monkeypatch.setattr('figures.sites.is_multisite', lambda: True) our_org = OrganizationFactory(sites=[site]) other_org = OrganizationFactory(sites=[SiteFactory()]) other_org_ce = CourseEnrollmentFactory() other_sm = StudentModuleFactory(student=other_org_ce.user, course_id=other_org_ce.course_id) UserOrganizationMappingFactory(user=ce.user, organization=our_org) UserOrganizationMappingFactory(user=other_org_ce.user, organization=other_org) sm = figures.sites.student_modules_for_course_enrollment(site, ce) assert set(sm) == set(ce_sm)
def test_get_course_enrollments_for_site(self, ce_count): course_overview = CourseOverviewFactory() OrganizationCourseFactory(organization=self.organization, course_id=str(course_overview.id)) uoms = [ UserOrganizationMappingFactory(organization=self.organization) for i in range(ce_count) ] expected_ce = [ CourseEnrollmentFactory(course_id=course_overview.id, user=uoms[i].user) for i in range(ce_count) ] course_enrollments = figures.sites.get_course_enrollments_for_site( self.site) assert set([ce.id for ce in course_enrollments ]) == set([ce.id for ce in expected_ce])
def backfill_test_data(db): """ TODO: make counts different for each course per month """ months_back = 6 sm_per_month = [10 + i for i in range(months_back + 1)] site = SiteFactory() now = datetime.utcnow().replace(tzinfo=utc) first_month = now - relativedelta(months=months_back) last_month = now - relativedelta(months=1) course_overviews = [CourseOverviewFactory() for i in range(1)] count_check = [] sm = [] for i, dt in enumerate( rrule(freq=MONTHLY, dtstart=first_month, until=last_month)): for co in course_overviews: sm_count = sm_per_month[i] month_sm = [ StudentModuleFactory(course_id=co.id, created=dt, modified=dt) for i in range(sm_count) ] sm += month_sm count_check.append(dict(month=dt, month_sm=month_sm, sm_count=sm_count)) if organizations_support_sites(): org = OrganizationFactory(sites=[site]) for co in course_overviews: OrganizationCourseFactory(organization=org, course_id=str(co.id)) for rec in sm: UserOrganizationMappingFactory(user=rec.student, organization=org) else: org = OrganizationFactory() return dict(site=site, organization=org, course_overview=course_overviews, student_modules=sm, first_month=first_month, now=now, months_back=months_back, sm_per_month=sm_per_month, count_check=count_check)
def test_list(self, monkeypatch, sm_test_data): site = sm_test_data['site'] org = sm_test_data['organization'] if organizations_support_sites(): caller = UserFactory() UserOrganizationMappingFactory(user=caller, organization=org, is_amc_admin=True) else: caller = UserFactory(is_staff=True) request = APIRequestFactory().get(self.request_path) request.META['HTTP_HOST'] = site.domain monkeypatch.setattr(django.contrib.sites.shortcuts, 'get_current_site', lambda req: site) force_authenticate(request, user=caller) view = self.view_class.as_view({'get': 'list'}) response = view(request) assert response.status_code == status.HTTP_200_OK
def setup(self, db): super(TestCourseEnrollmentViewSet, self).setup(db) self.special_fields = ( 'create', 'user', ) self.course_overview = CourseOverviewFactory() self.course_enrollments = [ CourseEnrollmentFactory(course_id=self.course_overview.id) for i in range(1, 5) ] self.sample_course_id = self.course_enrollments[0].course_id if is_multisite(): self.organization = OrganizationFactory(sites=[self.site]) OrganizationCourseFactory(organization=self.organization, course_id=str(self.course_overview.id)) for ce in self.course_enrollments: UserOrganizationMappingFactory(user=ce.user, organization=self.organization)
def test_get_active_users_for_time_period(self): ''' ''' assert figures.helpers.is_multisite() student_module_sets = [] for i in range(0, 3): data = create_student_module_test_data( start_date=self.data_start_date, end_date=self.data_end_date) student_module_sets.append(data) OrganizationCourseFactory(organization=self.alpha_org, course_id=str( data['course_overview'].id)) UserOrganizationMappingFactory(user=data['user'], organization=self.alpha_org) count = get_active_users_for_time_period( site=self.alpha_site, start_date=self.data_start_date, end_date=self.data_end_date) assert count == len(student_module_sets)
def test_multiple_user_orgs(self, monkeypatch, settings, username, allow): """ We updated `figures.permissions` so that a user can belong to multiple organizations """ def test_site(request): return self.site request = APIRequestFactory().get('/') request.META['HTTP_HOST'] = self.site.domain request.user = get_user_model().objects.get(username=username) monkeypatch.setattr(django.contrib.sites.shortcuts, 'get_current_site', test_site) settings.FEATURES['FIGURES_IS_MULTISITE'] = True assert figures.helpers.is_multisite() org2 = OrganizationFactory(sites=[self.site]) UserOrganizationMappingFactory(user=request.user, organization=org2) permission = figures.permissions.IsSiteAdminUser().has_permission( request, None) assert permission == allow, 'User "{username}" should have access'.format( username=username)
def test_get_site_mau_current_month(db): mock_today = date(year=2020, month=3, day=1) freezer = freeze_time(mock_today) freezer.start() start_dt = datetime(mock_today.year, mock_today.month, 1, tzinfo=fuzzy.compat.UTC) end_dt = datetime(mock_today.year, mock_today.month, 31, tzinfo=fuzzy.compat.UTC) date_gen = fuzzy.FuzzyDateTime(start_dt=start_dt, end_dt=end_dt) site = SiteFactory() course_overviews = [CourseOverviewFactory() for i in range(2)] users = [UserFactory() for i in range(2)] sm = [] for user in users: for co in course_overviews: sm.append( StudentModuleFactory(course_id=co.id, student=user, modified=date_gen.evaluate( 2, None, False))) if organizations_support_sites(): org = OrganizationFactory(sites=[site]) for co in course_overviews: OrganizationCourseFactory(organization=org, course_id=str(co.id)) for user in users: UserOrganizationMappingFactory(user=user, organization=org) active_user_count = get_site_mau_current_month(site) freezer.stop() assert active_user_count == len(users)
def map_users_to_org(org, users): [UserOrganizationMappingFactory(user=user, organization=org) for user in users]