Course Dashboard Visual Update
ECOM-4398
This commit is contained in:
41
openedx/core/djangoapps/credentials/tests/factories.py
Normal file
41
openedx/core/djangoapps/credentials/tests/factories.py
Normal file
@@ -0,0 +1,41 @@
|
||||
"""Factories for generating fake credentials-related data."""
|
||||
import factory
|
||||
from factory.fuzzy import FuzzyText
|
||||
|
||||
|
||||
class UserCredential(factory.Factory):
|
||||
"""Factory for stubbing user credentials resources from the User Credentials
|
||||
API (v1).
|
||||
"""
|
||||
class Meta(object):
|
||||
model = dict
|
||||
|
||||
id = factory.Sequence(lambda n: n) # pylint: disable=invalid-name
|
||||
username = FuzzyText(prefix='user_')
|
||||
status = 'awarded'
|
||||
uuid = FuzzyText(prefix='uuid_')
|
||||
certificate_url = 'http=//credentials.edx.org/credentials/dummy-uuid'
|
||||
credential = {}
|
||||
|
||||
|
||||
class ProgramCredential(factory.Factory):
|
||||
"""Factory for stubbing program credentials resources from the Program
|
||||
Credentials API (v1).
|
||||
"""
|
||||
class Meta(object):
|
||||
model = dict
|
||||
|
||||
credential_id = factory.Sequence(lambda n: n)
|
||||
program_id = factory.Sequence(lambda n: n)
|
||||
|
||||
|
||||
class CourseCredential(factory.Factory):
|
||||
"""Factory for stubbing course credentials resources from the Course
|
||||
Credentials API (v1).
|
||||
"""
|
||||
class Meta(object):
|
||||
model = dict
|
||||
|
||||
course_id = 'edx/test01/2015'
|
||||
credential_id = factory.Sequence(lambda n: n)
|
||||
certificate_type = 'verified'
|
||||
@@ -4,6 +4,7 @@ import json
|
||||
import httpretty
|
||||
|
||||
from openedx.core.djangoapps.credentials.models import CredentialsApiConfig
|
||||
from openedx.core.djangoapps.credentials.tests import factories
|
||||
|
||||
|
||||
class CredentialsApiConfigMixin(object):
|
||||
@@ -33,103 +34,63 @@ class CredentialsDataMixin(object):
|
||||
CREDENTIALS_API_RESPONSE = {
|
||||
"next": None,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"username": "test",
|
||||
"credential": {
|
||||
"credential_id": 1,
|
||||
"program_id": 1
|
||||
},
|
||||
"status": "awarded",
|
||||
"uuid": "dummy-uuid-1",
|
||||
"certificate_url": "http://credentials.edx.org/credentials/dummy-uuid-1/"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"username": "test",
|
||||
"credential": {
|
||||
"credential_id": 2,
|
||||
"program_id": 2
|
||||
},
|
||||
"status": "awarded",
|
||||
"uuid": "dummy-uuid-2",
|
||||
"certificate_url": "http://credentials.edx.org/credentials/dummy-uuid-2/"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"username": "test",
|
||||
"credential": {
|
||||
"credential_id": 3,
|
||||
"program_id": 3
|
||||
},
|
||||
"status": "revoked",
|
||||
"uuid": "dummy-uuid-3",
|
||||
"certificate_url": "http://credentials.edx.org/credentials/dummy-uuid-3/"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"username": "test",
|
||||
"credential": {
|
||||
"course_id": "edx/test01/2015",
|
||||
"credential_id": 4,
|
||||
"certificate_type": "honor"
|
||||
},
|
||||
"status": "awarded",
|
||||
"uuid": "dummy-uuid-4",
|
||||
"certificate_url": "http://credentials.edx.org/credentials/dummy-uuid-4/"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"username": "test",
|
||||
"credential": {
|
||||
"course_id": "edx/test02/2015",
|
||||
"credential_id": 5,
|
||||
"certificate_type": "verified"
|
||||
},
|
||||
"status": "awarded",
|
||||
"uuid": "dummy-uuid-5",
|
||||
"certificate_url": "http://credentials.edx.org/credentials/dummy-uuid-5/"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"username": "test",
|
||||
"credential": {
|
||||
"course_id": "edx/test03/2015",
|
||||
"credential_id": 6,
|
||||
"certificate_type": "honor"
|
||||
},
|
||||
"status": "revoked",
|
||||
"uuid": "dummy-uuid-6",
|
||||
"certificate_url": "http://credentials.edx.org/credentials/dummy-uuid-6/"
|
||||
}
|
||||
factories.UserCredential(
|
||||
id=1,
|
||||
username='test',
|
||||
credential=factories.ProgramCredential(
|
||||
program_id=1
|
||||
)
|
||||
),
|
||||
factories.UserCredential(
|
||||
id=2,
|
||||
username='test',
|
||||
credential=factories.ProgramCredential(
|
||||
program_id=2
|
||||
)
|
||||
),
|
||||
factories.UserCredential(
|
||||
id=3,
|
||||
status='revoked',
|
||||
username='test',
|
||||
credential=factories.ProgramCredential()
|
||||
),
|
||||
factories.UserCredential(
|
||||
id=4,
|
||||
username='test',
|
||||
credential=factories.CourseCredential(
|
||||
certificate_type='honor'
|
||||
)
|
||||
),
|
||||
factories.UserCredential(
|
||||
id=5,
|
||||
username='test',
|
||||
credential=factories.CourseCredential(
|
||||
course_id='edx/test02/2015'
|
||||
)
|
||||
),
|
||||
factories.UserCredential(
|
||||
id=6,
|
||||
username='test',
|
||||
credential=factories.CourseCredential(
|
||||
course_id='edx/test02/2015'
|
||||
)
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
CREDENTIALS_NEXT_API_RESPONSE = {
|
||||
"next": None,
|
||||
"results": [
|
||||
{
|
||||
"id": 7,
|
||||
"username": "test",
|
||||
"credential": {
|
||||
"credential_id": 7,
|
||||
"program_id": 7
|
||||
},
|
||||
"status": "awarded",
|
||||
"uuid": "dummy-uuid-7",
|
||||
"certificate_url": "http://credentials.edx.org/credentials/dummy-uuid-7"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"username": "test",
|
||||
"credential": {
|
||||
"credential_id": 8,
|
||||
"program_id": 8
|
||||
},
|
||||
"status": "awarded",
|
||||
"uuid": "dummy-uuid-8",
|
||||
"certificate_url": "http://credentials.edx.org/credentials/dummy-uuid-8/"
|
||||
}
|
||||
factories.UserCredential(
|
||||
id=7,
|
||||
username='test',
|
||||
credential=factories.ProgramCredential()
|
||||
),
|
||||
factories.UserCredential(
|
||||
id=8,
|
||||
username='test',
|
||||
credential=factories.ProgramCredential()
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,19 @@ import unittest
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.test import TestCase
|
||||
from nose.plugins.attrib import attr
|
||||
import httpretty
|
||||
from edx_oauth2_provider.tests.factories import ClientFactory
|
||||
from provider.constants import CONFIDENTIAL
|
||||
|
||||
from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfigMixin, CredentialsDataMixin
|
||||
from openedx.core.djangoapps.credentials.models import CredentialsApiConfig
|
||||
from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfigMixin, CredentialsDataMixin
|
||||
from openedx.core.djangoapps.credentials.utils import (
|
||||
get_user_credentials, get_user_program_credentials
|
||||
get_user_credentials,
|
||||
get_user_program_credentials,
|
||||
get_programs_credentials
|
||||
)
|
||||
from openedx.core.djangoapps.credentials.tests import factories
|
||||
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin, ProgramsDataMixin
|
||||
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
@@ -39,6 +41,39 @@ class TestCredentialsRetrieval(ProgramsApiConfigMixin, CredentialsApiConfigMixin
|
||||
|
||||
cache.clear()
|
||||
|
||||
def _expected_progam_credentials_data(self):
|
||||
"""
|
||||
Dry method for getting expected program credentials response data.
|
||||
"""
|
||||
return [
|
||||
factories.UserCredential(
|
||||
id=1,
|
||||
username='test',
|
||||
credential=factories.ProgramCredential()
|
||||
),
|
||||
factories.UserCredential(
|
||||
id=2,
|
||||
username='test',
|
||||
credential=factories.ProgramCredential()
|
||||
)
|
||||
]
|
||||
|
||||
def expected_credentials_display_data(self):
|
||||
""" Returns expected credentials data to be represented. """
|
||||
program_credentials_data = self._expected_progam_credentials_data()
|
||||
return [
|
||||
{
|
||||
'display_name': self.PROGRAMS_API_RESPONSE['results'][0]['name'],
|
||||
'subtitle': self.PROGRAMS_API_RESPONSE['results'][0]['subtitle'],
|
||||
'credential_url':program_credentials_data[0]['certificate_url']
|
||||
},
|
||||
{
|
||||
'display_name': self.PROGRAMS_API_RESPONSE['results'][1]['name'],
|
||||
'subtitle':self.PROGRAMS_API_RESPONSE['results'][1]['subtitle'],
|
||||
'credential_url':program_credentials_data[1]['certificate_url']
|
||||
}
|
||||
]
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_user_credentials(self):
|
||||
"""Verify user credentials data can be retrieve."""
|
||||
@@ -98,9 +133,10 @@ class TestCredentialsRetrieval(ProgramsApiConfigMixin, CredentialsApiConfigMixin
|
||||
self.mock_credentials_api(self.user, reset_url=False)
|
||||
|
||||
actual = get_user_program_credentials(self.user)
|
||||
program_credentials_data = self._expected_progam_credentials_data()
|
||||
expected = self.PROGRAMS_API_RESPONSE['results'][:2]
|
||||
expected[0]['credential_url'] = self.PROGRAMS_CREDENTIALS_DATA[0]['certificate_url']
|
||||
expected[1]['credential_url'] = self.PROGRAMS_CREDENTIALS_DATA[1]['certificate_url']
|
||||
expected[0]['credential_url'] = program_credentials_data[0]['certificate_url']
|
||||
expected[1]['credential_url'] = program_credentials_data[1]['certificate_url']
|
||||
|
||||
# checking response from API is as expected
|
||||
self.assertEqual(len(actual), 2)
|
||||
@@ -125,3 +161,57 @@ class TestCredentialsRetrieval(ProgramsApiConfigMixin, CredentialsApiConfigMixin
|
||||
self.mock_credentials_api(self.user, data=credential_data)
|
||||
actual = get_user_program_credentials(self.user)
|
||||
self.assertEqual(actual, [])
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_programs_credentials(self):
|
||||
""" Verify that the program credentials data required for display can
|
||||
be retrieved.
|
||||
"""
|
||||
# create credentials and program configuration
|
||||
self.create_credentials_config()
|
||||
self.create_programs_config()
|
||||
|
||||
# Mocking the API responses from programs and credentials
|
||||
self.mock_programs_api()
|
||||
self.mock_credentials_api(self.user, reset_url=False)
|
||||
actual = get_programs_credentials(self.user, category='xseries')
|
||||
expected = self.expected_credentials_display_data()
|
||||
|
||||
# Checking result is as expected
|
||||
self.assertEqual(len(actual), 2)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_programs_credentials_category(self):
|
||||
""" Verify behaviour when program category is provided."""
|
||||
# create credentials and program configuration
|
||||
self.create_credentials_config()
|
||||
self.create_programs_config()
|
||||
|
||||
# Mocking the API responses from programs and credentials
|
||||
self.mock_programs_api()
|
||||
self.mock_credentials_api(self.user, reset_url=False)
|
||||
actual = get_programs_credentials(self.user, category='dummy_category')
|
||||
expected = self.expected_credentials_display_data()
|
||||
|
||||
self.assertEqual(len(actual), 0)
|
||||
|
||||
actual = get_programs_credentials(self.user, category='xseries')
|
||||
|
||||
self.assertEqual(len(actual), 2)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_programs_credentials_no_category(self):
|
||||
""" Verify behaviour when no program category is provided. """
|
||||
self.create_credentials_config()
|
||||
self.create_programs_config()
|
||||
|
||||
# Mocking the API responses from programs and credentials
|
||||
self.mock_programs_api()
|
||||
self.mock_credentials_api(self.user, reset_url=False)
|
||||
actual = get_programs_credentials(self.user)
|
||||
expected = self.expected_credentials_display_data()
|
||||
|
||||
self.assertEqual(len(actual), 2)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
@@ -64,3 +64,35 @@ def get_user_program_credentials(user):
|
||||
programs_credentials_data = get_programs_for_credentials(user, programs_credentials)
|
||||
|
||||
return programs_credentials_data
|
||||
|
||||
|
||||
def get_programs_credentials(user, category=None):
|
||||
"""Return program credentials data required for display.
|
||||
|
||||
Given a user, find all programs for which certificates have been earned
|
||||
and return list of dictionaries of required program data.
|
||||
|
||||
Arguments:
|
||||
user (User): user object for getting programs credentials.
|
||||
category(str) : program category for getting credentials.
|
||||
|
||||
Returns:
|
||||
list of dict, containing data corresponding to the programs for which
|
||||
the user has been awarded a credential.
|
||||
"""
|
||||
programs_credentials = get_user_program_credentials(user)
|
||||
credentials_data = []
|
||||
for program in programs_credentials:
|
||||
is_included = (category is None) or (program.get('category') == category)
|
||||
if is_included:
|
||||
try:
|
||||
program_data = {
|
||||
'display_name': program['name'],
|
||||
'subtitle': program['subtitle'],
|
||||
'credential_url': program['credential_url'],
|
||||
}
|
||||
credentials_data.append(program_data)
|
||||
except KeyError:
|
||||
log.warning('Program structure is invalid: %r', program)
|
||||
|
||||
return credentials_data
|
||||
|
||||
@@ -100,31 +100,6 @@ class ProgramsDataMixin(object):
|
||||
]
|
||||
}
|
||||
|
||||
PROGRAMS_CREDENTIALS_DATA = [
|
||||
{
|
||||
"id": 1,
|
||||
"username": "test",
|
||||
"credential": {
|
||||
"credential_id": 1,
|
||||
"program_id": 1
|
||||
},
|
||||
"status": "awarded",
|
||||
"uuid": "dummy-uuid-1",
|
||||
"certificate_url": "http://credentials.edx.org/credentials/dummy-uuid-1/"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"username": "test",
|
||||
"credential": {
|
||||
"credential_id": 2,
|
||||
"program_id": 2
|
||||
},
|
||||
"status": "awarded",
|
||||
"uuid": "dummy-uuid-2",
|
||||
"certificate_url": "http://credentials.edx.org/credentials/dummy-uuid-2/"
|
||||
}
|
||||
]
|
||||
|
||||
def mock_programs_api(self, data=None, status_code=200):
|
||||
"""Utility for mocking out Programs API URLs."""
|
||||
self.assertTrue(httpretty.is_enabled(), msg='httpretty must be enabled to mock Programs API calls.')
|
||||
|
||||
@@ -12,7 +12,8 @@ from edx_oauth2_provider.tests.factories import ClientFactory
|
||||
from provider.constants import CONFIDENTIAL
|
||||
|
||||
from lms.djangoapps.certificates.api import MODES
|
||||
from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfigMixin
|
||||
from openedx.core.djangoapps.credentials.tests import factories as credentials_factories
|
||||
from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfigMixin, CredentialsDataMixin
|
||||
from openedx.core.djangoapps.programs import utils
|
||||
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
|
||||
from openedx.core.djangoapps.programs.tests import factories
|
||||
@@ -26,7 +27,7 @@ UTILS_MODULE = 'openedx.core.djangoapps.programs.utils'
|
||||
|
||||
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
@attr('shard_2')
|
||||
class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin,
|
||||
class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, CredentialsDataMixin,
|
||||
CredentialsApiConfigMixin, CacheIsolationTestCase):
|
||||
"""Tests covering the retrieval of programs from the Programs service."""
|
||||
|
||||
@@ -40,6 +41,27 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin,
|
||||
|
||||
cache.clear()
|
||||
|
||||
def _expected_progam_credentials_data(self):
|
||||
"""
|
||||
Dry method for getting expected program credentials response data.
|
||||
"""
|
||||
return [
|
||||
credentials_factories.UserCredential(
|
||||
id=1,
|
||||
username='test',
|
||||
credential=credentials_factories.ProgramCredential(
|
||||
program_id=1
|
||||
)
|
||||
),
|
||||
credentials_factories.UserCredential(
|
||||
id=2,
|
||||
username='test',
|
||||
credential=credentials_factories.ProgramCredential(
|
||||
program_id=2
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_programs(self):
|
||||
"""Verify programs data can be retrieved."""
|
||||
@@ -152,11 +174,12 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin,
|
||||
"""Verify programs data can be retrieved and parsed correctly for certificates."""
|
||||
self.create_programs_config()
|
||||
self.mock_programs_api()
|
||||
program_credentials_data = self._expected_progam_credentials_data()
|
||||
|
||||
actual = utils.get_programs_for_credentials(self.user, self.PROGRAMS_CREDENTIALS_DATA)
|
||||
actual = utils.get_programs_for_credentials(self.user, program_credentials_data)
|
||||
expected = self.PROGRAMS_API_RESPONSE['results'][:2]
|
||||
expected[0]['credential_url'] = self.PROGRAMS_CREDENTIALS_DATA[0]['certificate_url']
|
||||
expected[1]['credential_url'] = self.PROGRAMS_CREDENTIALS_DATA[1]['certificate_url']
|
||||
expected[0]['credential_url'] = program_credentials_data[0]['certificate_url']
|
||||
expected[1]['credential_url'] = program_credentials_data[1]['certificate_url']
|
||||
|
||||
self.assertEqual(len(actual), 2)
|
||||
self.assertEqual(actual, expected)
|
||||
@@ -167,8 +190,9 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin,
|
||||
self.create_programs_config()
|
||||
self.create_credentials_config()
|
||||
self.mock_programs_api(data={'results': []})
|
||||
program_credentials_data = self._expected_progam_credentials_data()
|
||||
|
||||
actual = utils.get_programs_for_credentials(self.user, self.PROGRAMS_CREDENTIALS_DATA)
|
||||
actual = utils.get_programs_for_credentials(self.user, program_credentials_data)
|
||||
self.assertEqual(actual, [])
|
||||
|
||||
@httpretty.activate
|
||||
|
||||
Reference in New Issue
Block a user