Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
fa7ed070
Commit
fa7ed070
authored
May 24, 2016
by
Ahsan Ulhaq
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #12468 from edx/ahsan/ECOM-4398-Course-Dashboard-Visual-Update
Course Dashboard Visual Update
parents
f7e98062
a8f2de83
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
283 additions
and
203 deletions
+283
-203
common/djangoapps/student/views.py
+0
-35
lms/djangoapps/learner_dashboard/tests/test_programs.py
+25
-6
lms/djangoapps/learner_dashboard/views.py
+3
-2
lms/static/sass/multicourse/_dashboard.scss
+4
-6
lms/templates/dashboard.html
+0
-13
openedx/core/djangoapps/credentials/tests/factories.py
+41
-0
openedx/core/djangoapps/credentials/tests/mixins.py
+52
-91
openedx/core/djangoapps/credentials/tests/test_utils.py
+95
-5
openedx/core/djangoapps/credentials/utils.py
+32
-0
openedx/core/djangoapps/programs/tests/mixins.py
+0
-25
openedx/core/djangoapps/programs/tests/test_utils.py
+30
-6
themes/edx.org/lms/templates/dashboard.html
+1
-14
No files found.
common/djangoapps/student/views.py
View file @
fa7ed070
...
...
@@ -122,8 +122,6 @@ from eventtracking import tracker
# Note that this lives in LMS, so this dependency should be refactored.
from
notification_prefs.views
import
enable_notifications
# Note that this lives in openedx, so this dependency should be refactored.
from
openedx.core.djangoapps.credentials.utils
import
get_user_program_credentials
from
openedx.core.djangoapps.credit.email_utils
import
get_credit_provider_display_names
,
make_providers_strings
from
openedx.core.djangoapps.user_api.preferences
import
api
as
preferences_api
from
openedx.core.djangoapps.programs.utils
import
get_programs_for_dashboard
,
get_display_category
...
...
@@ -615,7 +613,6 @@ def dashboard(request):
# This is passed along in the template context to allow rendering of
# program-related information on the dashboard.
course_programs
=
_get_course_programs
(
user
,
[
enrollment
.
course_id
for
enrollment
in
course_enrollments
])
xseries_credentials
=
_get_xseries_credentials
(
user
)
# Construct a dictionary of course mode information
# used to render the course list. We re-use the course modes dict
...
...
@@ -741,7 +738,6 @@ def dashboard(request):
'nav_hidden'
:
True
,
'course_programs'
:
course_programs
,
'disable_courseware_js'
:
True
,
'xseries_credentials'
:
xseries_credentials
,
'show_program_listing'
:
ProgramsApiConfig
.
current
()
.
show_program_listing
,
}
...
...
@@ -2483,34 +2479,3 @@ def _get_course_programs(user, user_enrolled_courses): # pylint: disable=invali
log
.
warning
(
'Program structure is invalid, skipping display:
%
r'
,
program
)
return
programs_data
def
_get_xseries_credentials
(
user
):
"""Return program credentials data required for display on
the learner dashboard.
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.
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
:
if
program
.
get
(
'category'
)
==
'xseries'
:
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
lms/djangoapps/learner_dashboard/tests/test_programs.py
View file @
fa7ed070
...
...
@@ -14,6 +14,7 @@ from opaque_keys.edx import locator
from
provider.constants
import
CONFIDENTIAL
from
openedx.core.djangoapps.credentials.models
import
CredentialsApiConfig
from
openedx.core.djangoapps.credentials.tests
import
factories
as
credentials_factories
from
openedx.core.djangoapps.credentials.tests.mixins
import
CredentialsDataMixin
,
CredentialsApiConfigMixin
from
openedx.core.djangoapps.programs.tests.mixins
import
(
ProgramsApiConfigMixin
,
...
...
@@ -155,18 +156,36 @@ class TestProgramListing(
'{}?next={}'
.
format
(
reverse
(
'signin_user'
),
self
.
url
)
)
# TODO: Use a factory to generate this data.
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
()
),
credentials_factories
.
UserCredential
(
id
=
2
,
username
=
'test'
,
credential
=
credentials_factories
.
ProgramCredential
()
)
]
def
_expected_credentials_data
(
self
):
""" Dry method for getting expected credentials."""
program_credentials_data
=
self
.
_expected_progam_credentials_data
()
return
[
{
"display_name"
:
"Test Program A"
,
"credential_url"
:
"http://credentials.edx.org/credentials/dummy-uuid-1/"
'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"
:
"Test Program B"
,
"credential_url"
:
"http://credentials.edx.org/credentials/dummy-uuid-2/"
'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'
]
}
]
...
...
lms/djangoapps/learner_dashboard/views.py
View file @
fa7ed070
...
...
@@ -7,9 +7,10 @@ from django.views.decorators.http import require_GET
from
django.http
import
Http404
from
edxmako.shortcuts
import
render_to_response
from
openedx.core.djangoapps.credentials.utils
import
get_programs_credentials
from
openedx.core.djangoapps.programs.models
import
ProgramsApiConfig
from
openedx.core.djangoapps.programs.utils
import
ProgramProgressMeter
,
get_display_category
from
student.views
import
get_course_enrollments
,
_get_xseries_credentials
from
student.views
import
get_course_enrollments
@login_required
...
...
@@ -39,7 +40,7 @@ def view_programs(request):
'xseries_url'
:
marketing_root
if
ProgramsApiConfig
.
current
()
.
show_xseries_ad
else
None
,
'nav_hidden'
:
True
,
'show_program_listing'
:
show_program_listing
,
'credentials'
:
_get_xseries_credentials
(
request
.
user
),
'credentials'
:
get_programs_credentials
(
request
.
user
,
category
=
'xseries'
),
'disable_courseware_js'
:
True
,
'uses_pattern_library'
:
True
}
...
...
lms/static/sass/multicourse/_dashboard.scss
View file @
fa7ed070
...
...
@@ -19,9 +19,6 @@
@include
float
(
right
);
@include
margin-left
(
flex-gutter
());
width
:
flex-grid
(
3
);
margin-top
:
(
$baseline
*
2
);
border-top
:
3px
solid
$blue
;
padding
:
$baseline
0
;
.course-advertise
{
@include
clearfix
();
...
...
@@ -36,7 +33,7 @@
}
.ad-link
{
@include
text-align
(
center
);
.btn-
find-courses
{
.btn-
neutral
{
padding-bottom
:
12px
;
padding-top
:
12px
;
}
...
...
@@ -57,6 +54,9 @@
span
{
@include
margin-left
(
$baseline
*
0
.25
);
}
.icon
{
@include
margin-right
(
$baseline
*
0
.25
);
}
}
}
}
...
...
@@ -94,8 +94,6 @@
@include
margin-left
(
flex-gutter
());
width
:
flex-grid
(
3
);
margin-top
:
(
$baseline
*
2
);
border-top
:
3px
solid
$blue
;
padding
:
$baseline
0
;
.user-info
{
@include
clearfix
();
...
...
lms/templates/dashboard.html
View file @
fa7ed070
...
...
@@ -175,19 +175,6 @@ from openedx.core.djangolib.markup import Text, HTML
</ul>
</section>
</section>
% if xseries_credentials:
<div
class=
"wrapper-xseries-certificates"
>
<p
class=
"title"
>
${_("XSeries Program Certificates")}
</p>
<p
class=
"copy"
>
${_("You have received a certificate for the following XSeries programs:")}
</p>
<ul>
% for xseries_credential in xseries_credentials:
<li>
<a
class=
"copy"
href=
"${xseries_credential['credential_url']}"
>
${xseries_credential['display_name']}
</a>
</li>
% endfor
</ul>
</div>
% endif
</section>
</main>
...
...
openedx/core/djangoapps/credentials/tests/factories.py
0 → 100644
View file @
fa7ed070
"""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'
openedx/core/djangoapps/credentials/tests/mixins.py
View file @
fa7ed070
...
...
@@ -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
()
)
]
}
...
...
openedx/core/djangoapps/credentials/tests/test_utils.py
View file @
fa7ed070
...
...
@@ -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
)
openedx/core/djangoapps/credentials/utils.py
View file @
fa7ed070
...
...
@@ -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
openedx/core/djangoapps/programs/tests/mixins.py
View file @
fa7ed070
...
...
@@ -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.'
)
...
...
openedx/core/djangoapps/programs/tests/test_utils.py
View file @
fa7ed070
...
...
@@ -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
...
...
themes/edx.org/lms/templates/dashboard.html
View file @
fa7ed070
...
...
@@ -163,7 +163,7 @@ from openedx.core.djangolib.markup import Text, HTML
${_("Browse recently launched courses and see what's new in your favorite subjects.")}
</div>
<div
class=
"ad-link"
>
<a
class=
"btn-
find-courses
"
href=
"${marketing_link('COURSES')}"
>
<a
class=
"btn-
neutral
"
href=
"${marketing_link('COURSES')}"
>
<span
class=
"icon fa fa-search"
aria-hidden=
"true"
></span>
${_("Explore New Courses")}
</a>
...
...
@@ -193,19 +193,6 @@ from openedx.core.djangolib.markup import Text, HTML
</ul>
</section>
</section>
% if xseries_credentials:
<div
class=
"wrapper-xseries-certificates"
>
<p
class=
"title"
>
${_("XSeries Program Certificates")}
</p>
<p
class=
"copy"
>
${_("You have received a certificate for the following XSeries programs:")}
</p>
<ul>
% for xseries_credential in xseries_credentials:
<li>
<a
class=
"copy"
href=
"${xseries_credential['credential_url']}"
>
${xseries_credential['display_name']}
</a>
</li>
% endfor
</ul>
</div>
% endif
</section>
<section
id=
"email-settings-modal"
class=
"modal"
aria-hidden=
"true"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment