def test_list_visible_filtering(self): """ Verify the endpoint can filter by visible date. """ program_certificate = ProgramCertificateFactory(site=self.site) course_certificate = CourseCertificateFactory(site=self.site) course_cred = UserCredentialFactory(credential=course_certificate) program_cred = UserCredentialFactory(credential=program_certificate) UserCredentialAttributeFactory( user_credential=program_cred, name="visible_date", value="9999-01-01T01:01:01Z", ) self.authenticate_user(self.user) self.add_user_permission(self.user, "view_usercredential") both = [course_cred, program_cred] response = self.client.get(self.list_path) self.assertEqual(response.status_code, 200) self.assertEqual(response.data["results"], self.serialize_user_credential(both, many=True)) response = self.client.get(self.list_path + "?only_visible=True") self.assertEqual(response.status_code, 200) self.assertEqual( response.data["results"], self.serialize_user_credential([course_cred], many=True)) response = self.client.get(self.list_path + "?only_visible=False") self.assertEqual(response.status_code, 200) self.assertEqual(response.data["results"], self.serialize_user_credential(both, many=True))
def test_list_program_uuid_filtering(self): """ Verify the endpoint returns data for all UserCredentials in the given program. """ # Course run 1 is in a program, course run 2 is not course1_run = CourseRunFactory() course2_run = CourseRunFactory() program = ProgramFactory(course_runs=[course1_run]) program_certificate = ProgramCertificateFactory( site=self.site, program_uuid=program.uuid) course1_certificate = CourseCertificateFactory( site=self.site, course_id=course1_run.key) course2_certificate = CourseCertificateFactory( site=self.site, course_id=course2_run.key) # Create some credentials related to the program course1_cred = UserCredentialFactory(credential=course1_certificate) program_creds = UserCredentialFactory.create_batch( 3, credential=program_certificate) expected = [course1_cred] + program_creds # Create some more credentials that we don't expect to see returned UserCredentialFactory.create_batch(3) UserCredentialFactory(credential=course2_certificate) self.authenticate_user(self.user) self.add_user_permission(self.user, 'view_usercredential') response = self.client.get(self.list_path + '?program_uuid={}'.format(program.uuid)) self.assertEqual(response.status_code, 200) self.assertEqual(response.data['results'], self.serialize_user_credential(expected, many=True))
def test_site_filtering(self): """ Verify the endpoint only returns credentials linked to a single site. """ credential = UserCredentialFactory(credential__site=self.site) UserCredentialFactory() self.authenticate_user(self.user) self.add_user_permission(self.user, 'view_usercredential') self.assertEqual(UserCredential.objects.count(), 2) response = self.client.get(self.list_path) self.assertEqual(response.data['count'], 1) self.assertEqual(response.data['results'][0], self.serialize_user_credential(credential))
def test_create_with_existing_user_credential(self): """ Verify that, if a user has already been issued a credential, further attempts to issue the same credential will NOT create a new credential, but update the attributes of the existing credential. """ user_credential = UserCredentialFactory(credential__site=self.site) self.authenticate_user(self.user) self.add_user_permission(self.user, 'add_usercredential') # POSTing the exact data that exists in the database should not change the UserCredential data = self.serialize_user_credential(user_credential) response = self.client.post(self.list_path, data=JSONRenderer().render(data), content_type=JSON_CONTENT_TYPE) self.assertEqual(response.status_code, 201) # POSTing with modified status/attributes should update the existing UserCredential data = self.serialize_user_credential(user_credential) expected_attribute = UserCredentialAttributeFactory.build() data['status'] = 'revoked' data['attributes'] = [ UserCredentialAttributeSerializer(expected_attribute).data ] response = self.client.post(self.list_path, data=JSONRenderer().render(data), content_type=JSON_CONTENT_TYPE) self.assertEqual(response.status_code, 201) user_credential.refresh_from_db() self.assertEqual(response.data, self.serialize_user_credential(user_credential)) self.assertEqual(user_credential.attributes.count(), 1) actual_attribute = user_credential.attributes.first() self.assertEqual(actual_attribute.name, expected_attribute.name) self.assertEqual(actual_attribute.value, expected_attribute.value)
def test_course_credential(self): request = APIRequestFactory().get('/') course_certificate = CourseCertificateFactory() user_credential = UserCredentialFactory(credential=course_certificate) user_credential_attribute = UserCredentialAttributeFactory(user_credential=user_credential) expected_url = 'http://testserver{}'.format( reverse('credentials:render', kwargs={'uuid': user_credential.uuid.hex})) expected = { 'username': user_credential.username, 'uuid': str(user_credential.uuid), 'credential': { 'type': 'course-run', 'course_run_key': course_certificate.course_id, 'mode': course_certificate.certificate_type, }, 'download_url': user_credential.download_url, 'status': user_credential.status, 'attributes': [ { 'name': user_credential_attribute.name, 'value': user_credential_attribute.value } ], 'created': user_credential.created.strftime(api_settings.DATETIME_FORMAT), 'modified': user_credential.modified.strftime(api_settings.DATETIME_FORMAT), 'certificate_url': expected_url } actual = UserCredentialSerializer(user_credential, context={'request': request}).data self.assertEqual(actual, expected)
def test_data(self): """ Verify the serializer serializes a UserCredential exactly as UserCredentialSerializer does. """ request = APIRequestFactory().get('/') user_credential = UserCredentialFactory() actual = UserCredentialCreationSerializer(user_credential, context={'request': request}).data expected = UserCredentialSerializer(user_credential, context={'request': request}).data self.assertEqual(actual, expected)
def test_course_credential(self): request = APIRequestFactory().get("/") course_certificate = CourseCertificateFactory() user_credential = UserCredentialFactory(credential=course_certificate) user_credential_attribute = UserCredentialAttributeFactory(user_credential=user_credential) expected_url = "http://testserver{}".format( reverse("credentials:render", kwargs={"uuid": user_credential.uuid.hex}) ) expected = { "username": user_credential.username, "uuid": str(user_credential.uuid), "credential": { "type": "course-run", "course_run_key": course_certificate.course_id, "mode": course_certificate.certificate_type, }, "download_url": user_credential.download_url, "status": user_credential.status, "attributes": [{"name": user_credential_attribute.name, "value": user_credential_attribute.value}], "created": user_credential.created.strftime(api_settings.DATETIME_FORMAT), "modified": user_credential.modified.strftime(api_settings.DATETIME_FORMAT), "certificate_url": expected_url, } actual = UserCredentialSerializer(user_credential, context={"request": request}).data self.assertEqual(actual, expected)
def test_course_run_order(self): """ Test that the course_runs are returned in the program order """ new_course_run = CourseRunFactory() self.program.course_runs.add(new_course_run) # pylint: disable=no-member UserGradeFactory(username=self.MOCK_USER_DATA['username'], course_run=new_course_run, letter_grade='C', percent_grade=.70) new_course_cert = CourseCertificateFactory( course_id=new_course_run.key, site=self.site) UserCredentialFactory( username=self.MOCK_USER_DATA['username'], credential_content_type=self.credential_content_type, credential=new_course_cert) response = self.client.get( reverse('records:programs', kwargs={'uuid': self.program.uuid.hex})) grades = json.loads(response.context_data['record'])['grades'] expected_course_run_keys = [ course_run.key for course_run in [self.course_runs[1], new_course_run] ] actual_course_run_keys = [grade['course_id'] for grade in grades] self.assertEqual(expected_course_run_keys, actual_course_run_keys)
def test_data(self): program_certificate = ProgramCertificateFactory() user_credential = UserCredentialFactory(credential=program_certificate) program_certificate_attr = UserCredentialAttributeFactory(user_credential=user_credential) expected = {"name": program_certificate_attr.name, "value": program_certificate_attr.value} actual = UserCredentialAttributeSerializer(program_certificate_attr).data self.assertEqual(actual, expected)
def setUp(self): super().setUp() user = UserFactory(username=self.USERNAME) self.client.login(username=user.username, password=USER_PASSWORD) self.user_credential = UserCredentialFactory(username=self.USERNAME) self.pc = ProgramCertificateFactory() self.user_credential.credential = self.pc self.user_credential.save()
def test_list_type_filtering(self): """ Verify the endpoint returns data for all UserCredentials for the given type. """ program_certificate = ProgramCertificateFactory(site=self.site) course_certificate = CourseCertificateFactory(site=self.site) course_cred = UserCredentialFactory(credential=course_certificate) program_cred = UserCredentialFactory(credential=program_certificate) self.authenticate_user(self.user) self.add_user_permission(self.user, 'view_usercredential') response = self.client.get(self.list_path + '?type=course-run') self.assertEqual(response.status_code, 200) self.assertEqual(response.data['results'], self.serialize_user_credential([course_cred], many=True)) response = self.client.get(self.list_path + '?type=program') self.assertEqual(response.status_code, 200) self.assertEqual(response.data['results'], self.serialize_user_credential([program_cred], many=True))
def setUp(self): super().setUp() dump_random_state() self.user = UserFactory(username=self.MOCK_USER_DATA["username"]) self.client.login(username=self.user.username, password=USER_PASSWORD) self.course = CourseFactory(site=self.site) self.course_runs = CourseRunFactory.create_batch(3, course=self.course) self.user_grade_low = UserGradeFactory( username=self.MOCK_USER_DATA["username"], course_run=self.course_runs[0], letter_grade="A", percent_grade=0.70, ) self.user_grade_high = UserGradeFactory( username=self.MOCK_USER_DATA["username"], course_run=self.course_runs[1], letter_grade="C", percent_grade=1.00, ) self.user_grade_revoked_cert = UserGradeFactory( username=self.MOCK_USER_DATA["username"], course_run=self.course_runs[2], letter_grade="B", percent_grade=0.80, ) self.course_certs = [ CourseCertificateFactory(course_id=course_run.key, site=self.site) for course_run in self.course_runs ] self.credential_content_type = ContentType.objects.get(app_label="credentials", model="coursecertificate") self.program_cert = ProgramCertificateFactory(site=self.site) self.program_content_type = ContentType.objects.get(app_label="credentials", model="programcertificate") self.user_credentials = [ UserCredentialFactory( username=self.MOCK_USER_DATA["username"], credential_content_type=self.credential_content_type, credential=course_cert, ) for course_cert in self.course_certs ] self.user_credentials[2].status = UserCredential.REVOKED self.user_credentials[2].save() self.org_names = ["CCC", "AAA", "BBB"] self.orgs = [OrganizationFactory(name=name, site=self.site) for name in self.org_names] self.program = ProgramFactory( course_runs=self.course_runs, authoring_organizations=self.orgs, site=self.site, uuid=self.program_cert.program_uuid, ) self.pcr = ProgramCertRecordFactory(program=self.program, user=self.user) self.pathway = PathwayFactory(site=self.site) self.pathway.programs.set([self.program])
def setUp(self): super(UserCredentialSerializerTests, self).setUp() self.program_cert = ProgramCertificateFactory() self.program_credential = UserCredentialFactory(credential=self.program_cert) self.program_cert_attr = UserCredentialAttributeFactory(user_credential=self.program_credential) self.course_cert = CourseCertificateFactory.create() self.course_credential = UserCredentialFactory.create(credential=self.course_cert) self.course_cert_attr = UserCredentialAttributeFactory(user_credential=self.course_credential) self.request = APIRequestFactory().get('/')
def test_site_filtering(self): """ Verify the endpoint only returns credentials linked to a single site. """ credential = UserCredentialFactory(credential__site=self.site) UserCredentialFactory() self.authenticate_user(self.user) self.add_user_permission(self.user, 'view_usercredential') self.assertEqual(UserCredential.objects.count(), 2) response = self.client.get(self.list_path) self.assertEqual(response.data['count'], 1) self.assertEqual(response.data['results'][0], self.serialize_user_credential(credential)) # Verify switch *disabling* site filtering disables site filtering Switch.objects.update_or_create( name=DISABLE_API_SITE_FILTERING_SWITCH_NAME, defaults={'active': True}) response = self.client.get(self.list_path) self.assertEqual(response.data['count'], 2)
def setUp(self): super().setUp() self.user = UserFactory(username=self.USERNAME) self.client.login(username=self.user.username, password=USER_PASSWORD) self.program = ProgramFactory(site=self.site) self.pathway = PathwayFactory(site=self.site, programs=[self.program]) self.pc = ProgramCertificateFactory(site=self.site, program_uuid=self.program.uuid) self.user_credential = UserCredentialFactory(username=self.USERNAME, credential=self.pc) self.data = {"username": self.USERNAME, "pathway_id": self.pathway.id} self.url = reverse("records:send_program", kwargs={"uuid": self.program.uuid.hex}) mail.outbox = []
def test_program_visible_date(self, date, completed): """ Test that the program's visible_date is considered """ program_credential = UserCredentialFactory( username=self.MOCK_USER_DATA['username'], credential_content_type=self.program_content_type, credential=self.program_cert) if date: UserCredentialAttributeFactory( user_credential=program_credential, name='visible_date', value=date, ) response = self.client.get(reverse('records:private_programs', kwargs={'uuid': self.program.uuid.hex})) self.assertEqual(json.loads(response.context_data['record'])['program']['completed'], completed)
def test_program_visible_date(self, date, completed): """ Test that the program's visible_date is considered """ program_credential = UserCredentialFactory( username=self.MOCK_USER_DATA["username"], credential_content_type=self.program_content_type, credential=self.program_cert, ) if date: UserCredentialAttributeFactory( user_credential=program_credential, name="visible_date", value=date, ) response = self.client.get(reverse("records:private_programs", kwargs={"uuid": self.program.uuid.hex})) self.assertEqual(json.loads(response.context_data["record"])["program"]["completed"], completed)
def setUp(self): super().setUp() self.user = UserFactory(username=self.MOCK_USER_DATA['username']) self.client.login(username=self.user.username, password=USER_PASSWORD) self.course = CourseFactory(site=self.site) self.course_runs = [ CourseRunFactory(course=self.course) for _ in range(3) ] self.user_grade_low = UserGradeFactory( username=self.MOCK_USER_DATA['username'], course_run=self.course_runs[0], letter_grade='A', percent_grade=0.70) self.user_grade_high = UserGradeFactory( username=self.MOCK_USER_DATA['username'], course_run=self.course_runs[1], letter_grade='C', percent_grade=1.00) self.user_grade_revoked_cert = UserGradeFactory( username=self.MOCK_USER_DATA['username'], course_run=self.course_runs[2], letter_grade='B', percent_grade=.80) self.course_certs = [ CourseCertificateFactory(course_id=course_run.key, site=self.site) for course_run in self.course_runs ] self.credential_content_type = ContentType.objects.get( app_label='credentials', model='coursecertificate') self.user_credentials = [ UserCredentialFactory( username=self.MOCK_USER_DATA['username'], credential_content_type=self.credential_content_type, credential=course_cert) for course_cert in self.course_certs ] self.user_credentials[2].status = UserCredential.REVOKED self.org_names = ['CCC', 'AAA', 'BBB'] self.orgs = [ OrganizationFactory(name=name, site=self.site) for name in self.org_names ] self.program = ProgramFactory(course_runs=self.course_runs, authoring_organizations=self.orgs, site=self.site)
def test_retrieve(self): """ Verify the endpoint returns data for a single UserCredential. """ credential = UserCredentialFactory(credential__site=self.site, username=self.user.username) path = reverse('api:v2:credentials-detail', kwargs={'uuid': credential.uuid}) # Verify users without the view permission are denied access self.assert_access_denied(self.user, 'get', path) self.authenticate_user(self.user) self.add_user_permission(self.user, 'view_usercredential') response = self.client.get(path) self.assertEqual(response.status_code, 200) self.assertEqual(response.data, self.serialize_user_credential(credential))
def test_destroy(self): """ Verify the endpoint does NOT support the DELETE operation. """ credential = UserCredentialFactory(credential__site=self.site, status=UserCredential.AWARDED, username=self.user.username) path = reverse('api:v2:credentials-detail', kwargs={'uuid': credential.uuid}) # Verify users without the view permission are denied access self.assert_access_denied(self.user, 'delete', path) self.authenticate_user(self.user) self.add_user_permission(self.user, 'delete_usercredential') response = self.client.delete(path) credential.refresh_from_db() self.assertEqual(credential.status, UserCredential.REVOKED) self.assertEqual(response.status_code, 200) self.assertEqual(response.data, self.serialize_user_credential(credential))
def test_update(self, method): """ Verify the endpoint supports updating the status of a UserCredential, but no other fields. """ credential = UserCredentialFactory(credential__site=self.site, username=self.user.username) path = reverse('api:v2:credentials-detail', kwargs={'uuid': credential.uuid}) expected_status = UserCredential.REVOKED data = {'status': expected_status} # Verify users without the change permission are denied access self.assert_access_denied(self.user, method, path, data=data) self.authenticate_user(self.user) self.add_user_permission(self.user, 'change_usercredential') response = getattr(self.client, method)(path, data=data) credential.refresh_from_db() self.assertEqual(credential.status, expected_status) self.assertEqual(response.status_code, 200) self.assertEqual(response.data, self.serialize_user_credential(credential))
def test_course_run_order(self): """ Test that the course_runs are returned in the program order """ new_course_run = CourseRunFactory() self.program.course_runs.add(new_course_run) UserGradeFactory( username=self.MOCK_USER_DATA["username"], course_run=new_course_run, letter_grade="C", percent_grade=0.70 ) new_course_cert = CourseCertificateFactory(course_id=new_course_run.key, site=self.site) UserCredentialFactory( username=self.MOCK_USER_DATA["username"], credential_content_type=self.credential_content_type, credential=new_course_cert, ) response = self.client.get(reverse("records:private_programs", kwargs={"uuid": self.program.uuid.hex})) grades = json.loads(response.context_data["record"])["grades"] expected_course_run_keys = [course_run.key for course_run in [self.course_runs[1], new_course_run]] actual_course_run_keys = [grade["course_id"] for grade in grades] self.assertEqual(expected_course_run_keys, actual_course_run_keys)
def setUp(self): super(UserCredentialAttributeSerializerTests, self).setUp() self.program_cert = ProgramCertificateFactory() self.program_credential = UserCredentialFactory(credential=self.program_cert) self.program_cert_attr = UserCredentialAttributeFactory(user_credential=self.program_credential)
def test_revoke(self): credential = UserCredentialFactory(status=UserCredential.AWARDED) self.assertEqual(credential.status, UserCredential.AWARDED) credential.revoke() self.assertEqual(credential.status, UserCredential.REVOKED)