def test_get_program_api_data(self): """ Verify the method returns data from the Catalog API. """ program_certificate = ProgramCertificateFactory(site=self.site) program_uuid = program_certificate.program_uuid.hex program_endpoint = 'programs/{uuid}/'.format(uuid=program_uuid) body = { 'uuid': program_uuid, 'title': 'A Fake Program', 'type': 'fake', 'authoring_organizations': [{ 'uuid': uuid.uuid4().hex, 'key': 'FakeX', 'name': 'Fake University', 'logo_image_url': 'https://static.fake.edu/logo.png', }], 'courses': [] } self.mock_access_token_response() self.mock_catalog_api_response(program_endpoint, body) self.assertEqual(program_certificate.get_program_api_data(), body) # Verify the data is cached responses.reset() self.assertEqual(program_certificate.get_program_api_data(), body)
def setUp(self): super(CredentialFieldTests, self).setUp() self.program_certificate = ProgramCertificateFactory(site=self.site) self.course_certificate = CourseCertificateFactory( site=self.site, certificate_type='verified') self.field_instance = CredentialField() self.field_instance.context['request'] = namedtuple( 'HttpRequest', ['site'])(self.site)
def test_str(self): instance = ProgramCertificateFactory() self.assertEqual(str(instance), 'ProgramCertificate: ' + str(instance.program_uuid)) instance = ProgramCertificateFactory(program_uuid=None) self.assertEqual(str(instance), 'ProgramCertificate: ' + str(instance.program_id))
def test_get_program_api_data(self): """ Verify the method returns data from the Catalog API. """ program_certificate = ProgramCertificateFactory(site=self.site) expected = {"uuid": program_certificate.program_uuid.hex} with mock.patch.object(SiteConfiguration, "get_program", return_value=expected) as mock_method: self.assertEqual(program_certificate.get_program_api_data(), expected) mock_method.assert_called_with(program_certificate.program_uuid)
def test_program_details_missing_program(self): """Test program details when there is no matching program""" program_certificate = ProgramCertificateFactory(site=self.site) # replace good UUID with new one program_certificate.program_uuid = uuid.uuid4() with self.assertRaises(NoMatchingProgramException): # attempt to access the program_details property program_certificate.program_details # pylint: disable=pointless-statement
def setUp(self): super(CredentialFieldTests, self).setUp() self.program_certificate = ProgramCertificateFactory(site=self.site) self.course_certificate = CourseCertificateFactory(site=self.site, certificate_type='verified') self.field_instance = CredentialField() # see: https://github.com/encode/django-rest-framework/blob/3.9.x/rest_framework/fields.py#L610 # pylint: disable=protected-access self.field_instance._context = { 'request': namedtuple('HttpRequest', ['site'])(self.site), }
def test_create_with_duplicate_attributes(self): """ Verify an error is returned if an attempt is made to create a UserCredential with multiple attributes of the same name. """ program_certificate = ProgramCertificateFactory(site=self.site) data = { 'username': '******', 'credential': { 'program_uuid': str(program_certificate.program_uuid) }, 'attributes': [{ 'name': 'attr-name', 'value': 'attr-value', }, { 'name': 'attr-name', 'value': 'another-attr-value', }], } self.authenticate_user(self.user) self.add_user_permission(self.user, 'add_usercredential') response = self.client.post(self.list_path, data=json.dumps(data), content_type=JSON_CONTENT_TYPE) self.assertEqual(response.status_code, 400) self.assertEqual( response.data, {'attributes': ['Attribute names cannot be duplicated.']})
def setUp(self): super(ProgramCertificateIssuerTests, self).setUp() self.issuer = ProgramCertificateIssuer() self.program_certificate = ProgramCertificateFactory.create() self.username = '******' self.user_program_cred = self.issuer.issue_credential(self.program_certificate, self.username) self.attributes = [{"name": "whitelist_reason", "value": "Reason for whitelisting."}]
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_program_credential(self): request = APIRequestFactory().get("/") program_certificate = ProgramCertificateFactory() user_credential = UserCredentialFactory(credential=program_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": "program", "program_uuid": program_certificate.program_uuid, "credential_id": program_certificate.id, }, "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_program_credential(self): request = APIRequestFactory().get('/') program_certificate = ProgramCertificateFactory() user_credential = UserCredentialFactory(credential=program_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': 'program', 'program_uuid': program_certificate.program_uuid, 'credential_id': program_certificate.id, }, '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_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_create_with_duplicate_attributes(self): """Verify an error is returned if an attempt is made to create a UserCredential with multiple attributes of the same name.""" program_certificate = ProgramCertificateFactory(site=self.site) data = { "username": "******", "credential": { "program_uuid": str(program_certificate.program_uuid) }, "attributes": [ { "name": "attr-name", "value": "attr-value", }, { "name": "attr-name", "value": "another-attr-value", }, ], } self.authenticate_user(self.user) self.add_user_permission(self.user, "add_usercredential") response = self.client.post(self.list_path, data=json.dumps(data), content_type=JSON_CONTENT_TYPE) self.assertEqual(response.status_code, 400) self.assertEqual( response.data, {"attributes": ["Attribute names cannot be duplicated."]})
def _setup_program_and_program_cert(self, program_type): self.program = ProgramFactory(site=self.site) self.program.type = program_type self.program.type_slug = slugify(program_type) self.program.save() self.program_cert = ProgramCertificateFactory( site=self.site, program_uuid=self.program.uuid)
class CredentialFieldTests(TestCase): def setUp(self): super(CredentialFieldTests, self).setUp() self.program_certificate = ProgramCertificateFactory() self.field_instance = CredentialField() def assert_program_uuid_validation_error_raised(self, program_uuid): try: self.field_instance.to_internal_value({'program_uuid': program_uuid}) except ValidationError as ex: expected = {'program_uuid': 'No active ProgramCertificate exists for program [{}]'.format(program_uuid)} self.assertEqual(ex.detail, expected) def test_to_internal_value_with_empty_program_uuid(self): """ Verify an error is raised if no program UUID is provided. """ with self.assertRaisesRegex(ValidationError, 'Credential identifier is missing'): self.field_instance.to_internal_value({'program_uuid': ''}) def test_to_internal_value_with_invalid_program_uuid(self, ): """ Verify the method raises a ValidationError if the passed program UUID does not correspond to a ProgramCertificate. """ self.assert_program_uuid_validation_error_raised(uuid4()) def test_to_internal_value_with_inactive_program_certificate(self, ): """ Verify the method raises a ValidationError if the ProgramCertificate is NOT active. """ self.program_certificate.is_active = False self.program_certificate.save() self.assert_program_uuid_validation_error_raised(self.program_certificate.program_uuid) def test_to_internal_value_with_valid_program_credential(self): """ Verify the method returns the ProgramCertificate corresponding to the specified UUID. """ self.assertEqual( self.field_instance.to_internal_value({'program_uuid': self.program_certificate.program_uuid}), self.program_certificate ) def test_to_representation_data_with_program(self): """ Verify the method serializes the credential details to a dict. """ expected = { 'program_uuid': self.program_certificate.program_uuid, 'credential_id': self.program_certificate.id } self.assertEqual(self.field_instance.to_representation(self.program_certificate), 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_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(AccreditorTests, self).setUp() self.accreditor = Accreditor() self.program_cert = ProgramCertificateFactory() self.program_credential = ProgramCertificate self.attributes = [{ "name": "whitelist_reason", "value": "Reason for whitelisting." }]
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 test_program_details(self, use_org_name, credential_title): """ Verify the method returns the details of program associated with the ProgramCertificate. """ program_certificate = ProgramCertificateFactory(site=self.site, use_org_name=use_org_name, title=credential_title) program_uuid = program_certificate.program_uuid.hex courses = [ {'key': 'ACMEx/101x'}, {'key': 'FakeX/101x'}, ] expected = ProgramDetails( uuid=program_uuid, title='Test Program', subtitle='Test Subtitle', type='MicroFakers', credential_title=credential_title, course_count=len(courses), organizations=[ OrganizationDetails( uuid=uuid.uuid4().hex, key='ACMEx', name='ACME University', display_name='ACME University' if use_org_name else 'ACMEx', certificate_logo_image_url='http://example.com/acme.jpg' ), OrganizationDetails( uuid=uuid.uuid4().hex, key='FakeX', name='Fake University', display_name='Fake University' if use_org_name else 'FakeX', certificate_logo_image_url='http://example.com/fakex.jpg' ) ], hours_of_effort=None ) body = { 'uuid': expected.uuid, 'title': expected.title, 'subtitle': expected.subtitle, 'type': expected.type, 'authoring_organizations': [ { 'uuid': organization.uuid, 'key': organization.key, 'name': organization.name, 'certificate_logo_image_url': organization.certificate_logo_image_url, } for organization in expected.organizations ], 'courses': courses } with mock.patch.object(SiteConfiguration, 'get_program', return_value=body) as mock_method: self.assertEqual(program_certificate.program_details, expected) mock_method.assert_called_with(program_certificate.program_uuid)
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_no_user_credential(self): """ Verify that the view rejects a User attempting to create a ProgramCertRecord for which they don't have the User Credentials """ pc2 = ProgramCertificateFactory() rev = reverse('records:cert_creation') data = { 'username': self.USERNAME, 'program_cert_uuid': pc2.program_uuid } response = self.client.post(rev, data) self.assertEqual(response.status_code, 404)
def test_list_program_uuid_filtering(self): """ Verify the endpoint returns data for all UserCredentials awarded for the given program. """ UserCredentialFactory.create_batch(3) program_certificate = ProgramCertificateFactory(site=self.site) expected = UserCredentialFactory.create_batch(3, credential=program_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_certificate.program_uuid)) self.assertEqual(response.status_code, 200) self.assertEqual(response.data['results'], self.serialize_user_credential(expected, many=True))
def test_program_details(self, use_org_name, credential_title): """Verify the method returns the details of program associated with the ProgramCertificate.""" program_certificate = ProgramCertificateFactory( site=self.site, use_org_name=use_org_name, title=credential_title) program_uuid = program_certificate.program_uuid.hex courses = [ { "key": "ACMEx/101x" }, { "key": "FakeX/101x" }, ] expected = ProgramDetails( uuid=program_uuid, title="Test Program", type="MicroFakers", type_slug=slugify("MicroFakers"), credential_title=credential_title, course_count=len(courses), organizations=[ OrganizationDetails( uuid=uuid.uuid4().hex, key="ACMEx", name="ACME University", display_name="ACME University" if use_org_name else "ACMEx", certificate_logo_image_url="http://example.com/acme.jpg", ), OrganizationDetails( uuid=uuid.uuid4().hex, key="FakeX", name="Fake University", display_name="Fake University" if use_org_name else "FakeX", certificate_logo_image_url="http://example.com/fakex.jpg", ), ], hours_of_effort=None, status="active", ) # Mocked at apps.credentials instead of apps.catalog because that's where it's being referenced with mock.patch( "credentials.apps.credentials.models.get_program_details_by_uuid" ) as mock_program_get: mock_program_get.return_value = expected self.assertEqual(program_certificate.program_details, expected) mock_program_get.assert_called_with( uuid=program_certificate.program_uuid, site=program_certificate.site)
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 setUp(self): super().setUp() dump_random_state() 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.pcr = ProgramCertRecordFactory(program=self.program, user=self.user) self.data = {'username': self.USERNAME, 'pathway_id': self.pathway.id} self.url = reverse('records:share_program', kwargs={'uuid': self.program.uuid.hex}) mail.outbox = []
def test_multiple_programs(self): """ Test that multiple programs can appear, in progress and completed """ # Create a second program, and delete the first one's certificate new_course = CourseFactory.create(site=self.site) new_course_run = CourseRunFactory.create(course=new_course) new_program = ProgramFactory.create(title='ZTestProgram', course_runs=[new_course_run], authoring_organizations=self.orgs, site=self.site) new_course_cert = CourseCertificateFactory.create(course_id=new_course_run.key, site=self.site) new_program_cert = ProgramCertificateFactory.create(program_uuid=new_program.uuid, site=self.site) # Make a new user credential UserCredentialFactory.create( username=self.user.username, credential_content_type=self.program_credential_content_type, credential=new_course_cert ) # Make a new program credential UserCredentialFactory.create( username=self.user.username, credential_content_type=self.program_credential_content_type, credential=new_program_cert ) self.program_user_credential.delete() response = self.client.get(reverse('records:index')) self.assertEqual(response.status_code, 200) program_data = json.loads(response.context_data['programs']) expected_program_data = [ { 'name': self.program.title, 'partner': 'TestOrg1, TestOrg2', 'uuid': self.program.uuid.hex, 'type': slugify(self.program.type), 'completed': False, 'empty': False, }, { 'name': new_program.title, 'partner': 'TestOrg1, TestOrg2', 'uuid': new_program.uuid.hex, 'type': slugify(new_program.type), 'completed': True, 'empty': False, } ] self.assertEqual(program_data, expected_program_data)
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 test_create(self): program = ProgramFactory(site=self.site) program_certificate = ProgramCertificateFactory( site=self.site, program_uuid=program.uuid) expected_username = self.user.username expected_attribute_name = 'fake-name' expected_attribute_value = 'fake-value' data = { 'username': expected_username, 'credential': { 'program_uuid': str(program_certificate.program_uuid) }, 'status': 'awarded', 'attributes': [{ 'name': expected_attribute_name, 'value': expected_attribute_value, }], } # Verify users without the add permission are denied access self.assert_access_denied(self.user, 'post', self.list_path, data=data) self.authenticate_user(self.user) self.add_user_permission(self.user, 'add_usercredential') response = self.client.post(self.list_path, data=json.dumps(data), content_type=JSON_CONTENT_TYPE) user_credential = UserCredential.objects.last() self.assertEqual(response.status_code, 201) self.assertEqual(response.data, self.serialize_user_credential(user_credential)) self.assertEqual(user_credential.username, expected_username) self.assertEqual(user_credential.credential, program_certificate) self.assertEqual(user_credential.attributes.count(), 1) attribute = user_credential.attributes.first() self.assertEqual(attribute.name, expected_attribute_name) self.assertEqual(attribute.value, expected_attribute_value)
def test_create(self): program = ProgramFactory(site=self.site) program_certificate = ProgramCertificateFactory( site=self.site, program_uuid=program.uuid) expected_username = self.user.username expected_attribute_name = "fake-name" expected_attribute_value = "fake-value" data = { "username": expected_username, "credential": { "program_uuid": str(program_certificate.program_uuid) }, "status": "awarded", "attributes": [{ "name": expected_attribute_name, "value": expected_attribute_value, }], } # Verify users without the add permission are denied access self.assert_access_denied(self.user, "post", self.list_path, data=data) self.authenticate_user(self.user) self.add_user_permission(self.user, "add_usercredential") response = self.client.post(self.list_path, data=json.dumps(data), content_type=JSON_CONTENT_TYPE) user_credential = UserCredential.objects.last() self.assertEqual(response.status_code, 201) self.assertEqual(response.data, self.serialize_user_credential(user_credential)) self.assertEqual(user_credential.username, expected_username) self.assertEqual(user_credential.credential, program_certificate) self.assertEqual(user_credential.attributes.count(), 1) attribute = user_credential.attributes.first() self.assertEqual(attribute.name, expected_attribute_name) self.assertEqual(attribute.value, expected_attribute_value)