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
85ca1f3e
Commit
85ca1f3e
authored
May 27, 2016
by
Renzo Lucioni
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #12575 from edx/renzo/program-detail-data
Include raw program data on the detail page
parents
4e77d509
a6b97254
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
55 additions
and
13 deletions
+55
-13
lms/djangoapps/learner_dashboard/tests/test_programs.py
+42
-8
lms/djangoapps/learner_dashboard/views.py
+5
-2
lms/templates/learner_dashboard/program_details.html
+3
-1
openedx/core/djangoapps/programs/utils.py
+5
-2
No files found.
lms/djangoapps/learner_dashboard/tests/test_programs.py
View file @
85ca1f3e
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
Unit tests covering the program listing and detail pages.
Unit tests covering the program listing and detail pages.
"""
"""
import
datetime
import
datetime
import
json
import
unittest
import
unittest
from
urlparse
import
urljoin
from
urlparse
import
urljoin
...
@@ -16,10 +17,11 @@ from provider.constants import CONFIDENTIAL
...
@@ -16,10 +17,11 @@ from provider.constants import CONFIDENTIAL
from
openedx.core.djangoapps.credentials.models
import
CredentialsApiConfig
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
import
factories
as
credentials_factories
from
openedx.core.djangoapps.credentials.tests.mixins
import
CredentialsDataMixin
,
CredentialsApiConfigMixin
from
openedx.core.djangoapps.credentials.tests.mixins
import
CredentialsDataMixin
,
CredentialsApiConfigMixin
from
openedx.core.djangoapps.programs.models
import
ProgramsApiConfig
from
openedx.core.djangoapps.programs.tests
import
factories
from
openedx.core.djangoapps.programs.tests.mixins
import
(
from
openedx.core.djangoapps.programs.tests.mixins
import
(
ProgramsApiConfigMixin
,
ProgramsApiConfigMixin
,
ProgramsDataMixin
)
ProgramsDataMixin
)
from
openedx.core.djangoapps.programs.models
import
ProgramsApiConfig
from
student.models
import
CourseEnrollment
from
student.models
import
CourseEnrollment
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
...
@@ -226,25 +228,56 @@ class TestProgramListing(
...
@@ -226,25 +228,56 @@ class TestProgramListing(
self
.
assertNotContains
(
response
,
certificate
[
'credential_url'
])
self
.
assertNotContains
(
response
,
certificate
[
'credential_url'
])
@
unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
@
httpretty.activate
@override_settings
(
MKTG_URLS
=
{
'ROOT'
:
'http://edx.org'
})
@override_settings
(
MKTG_URLS
=
{
'ROOT'
:
'http://edx.org'
})
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
class
TestProgramDetails
(
ProgramsApiConfigMixin
,
TestCase
):
class
TestProgramDetails
(
ProgramsApiConfigMixin
,
TestCase
):
"""
"""
Unit tests for the program details page
Unit tests for the program details page
"""
"""
program_id
=
123
password
=
'test'
def
setUp
(
self
):
def
setUp
(
self
):
super
(
TestProgramDetails
,
self
)
.
setUp
()
super
(
TestProgramDetails
,
self
)
.
setUp
()
self
.
details_page
=
reverse
(
'program_details_view'
,
args
=
[
self
.
program_id
])
self
.
user
=
UserFactory
()
self
.
user
=
UserFactory
()
self
.
details_page
=
reverse
(
'program_details_view'
,
args
=
[
'123'
])
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
self
.
password
)
ClientFactory
(
name
=
ProgramsApiConfig
.
OAUTH2_CLIENT_NAME
,
client_type
=
CONFIDENTIAL
)
self
.
data
=
factories
.
Program
(
organizations
=
[
factories
.
Organization
()],
course_codes
=
[
factories
.
CourseCode
(
run_modes
=
[
factories
.
RunMode
()]),
]
)
def
_mock_programs_api
(
self
):
"""Helper for mocking out Programs API URLs."""
self
.
assertTrue
(
httpretty
.
is_enabled
(),
msg
=
'httpretty must be enabled to mock Programs API calls.'
)
url
=
'{api_root}/programs/{id}/'
.
format
(
api_root
=
ProgramsApiConfig
.
current
()
.
internal_api_url
.
strip
(
'/'
),
id
=
self
.
program_id
)
body
=
json
.
dumps
(
self
.
data
)
httpretty
.
register_uri
(
httpretty
.
GET
,
url
,
body
=
body
,
content_type
=
'application/json'
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
'test'
)
def
_assert_program_data_present
(
self
,
response
):
"""Verify that program data is present."""
self
.
assertContains
(
response
,
'programData'
)
self
.
assertContains
(
response
,
self
.
data
[
'name'
])
def
test_login_required
(
self
):
def
test_login_required
(
self
):
"""
"""
Verify that login is required to access the page.
Verify that login is required to access the page.
"""
"""
self
.
create_programs_config
()
self
.
create_programs_config
()
self
.
_mock_programs_api
()
self
.
client
.
logout
()
self
.
client
.
logout
()
...
@@ -254,10 +287,10 @@ class TestProgramDetails(ProgramsApiConfigMixin, TestCase):
...
@@ -254,10 +287,10 @@ class TestProgramDetails(ProgramsApiConfigMixin, TestCase):
'{}?next={}'
.
format
(
reverse
(
'signin_user'
),
self
.
details_page
)
'{}?next={}'
.
format
(
reverse
(
'signin_user'
),
self
.
details_page
)
)
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
'test'
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
self
.
password
)
response
=
self
.
client
.
get
(
self
.
details_page
)
response
=
self
.
client
.
get
(
self
.
details_page
)
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
_assert_program_data_present
(
response
)
def
test_404_if_disabled
(
self
):
def
test_404_if_disabled
(
self
):
"""
"""
...
@@ -271,12 +304,13 @@ class TestProgramDetails(ProgramsApiConfigMixin, TestCase):
...
@@ -271,12 +304,13 @@ class TestProgramDetails(ProgramsApiConfigMixin, TestCase):
def
test_page_routing
(
self
):
def
test_page_routing
(
self
):
"""Verify that the page can be hit with or without a program name in the URL."""
"""Verify that the page can be hit with or without a program name in the URL."""
self
.
create_programs_config
()
self
.
create_programs_config
()
self
.
_mock_programs_api
()
response
=
self
.
client
.
get
(
self
.
details_page
)
response
=
self
.
client
.
get
(
self
.
details_page
)
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
_assert_program_data_present
(
response
)
response
=
self
.
client
.
get
(
self
.
details_page
+
'program_name/'
)
response
=
self
.
client
.
get
(
self
.
details_page
+
'program_name/'
)
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
_assert_program_data_present
(
response
)
response
=
self
.
client
.
get
(
self
.
details_page
+
'program_name/invalid/'
)
response
=
self
.
client
.
get
(
self
.
details_page
+
'program_name/invalid/'
)
self
.
assertEquals
(
response
.
status_code
,
404
)
self
.
assertEquals
(
response
.
status_code
,
404
)
lms/djangoapps/learner_dashboard/views.py
View file @
85ca1f3e
...
@@ -9,7 +9,7 @@ from django.http import Http404
...
@@ -9,7 +9,7 @@ from django.http import Http404
from
edxmako.shortcuts
import
render_to_response
from
edxmako.shortcuts
import
render_to_response
from
openedx.core.djangoapps.credentials.utils
import
get_programs_credentials
from
openedx.core.djangoapps.credentials.utils
import
get_programs_credentials
from
openedx.core.djangoapps.programs.models
import
ProgramsApiConfig
from
openedx.core.djangoapps.programs.models
import
ProgramsApiConfig
from
openedx.core.djangoapps.programs.utils
import
ProgramProgressMeter
,
get_display_category
from
openedx.core.djangoapps.programs.utils
import
ProgramProgressMeter
,
get_
programs
,
get_
display_category
from
student.views
import
get_course_enrollments
from
student.views
import
get_course_enrollments
...
@@ -50,13 +50,16 @@ def view_programs(request):
...
@@ -50,13 +50,16 @@ def view_programs(request):
@login_required
@login_required
@require_GET
@require_GET
def
program_details
(
request
,
program_id
):
# pylint: disable=unused-argument
def
program_details
(
request
,
program_id
):
"""View details about a specific program."""
"""View details about a specific program."""
show_program_details
=
ProgramsApiConfig
.
current
()
.
show_program_details
show_program_details
=
ProgramsApiConfig
.
current
()
.
show_program_details
if
not
show_program_details
:
if
not
show_program_details
:
raise
Http404
raise
Http404
program_data
=
get_programs
(
request
.
user
,
program_id
=
program_id
)
context
=
{
context
=
{
'program_data'
:
program_data
,
'nav_hidden'
:
True
,
'nav_hidden'
:
True
,
'disable_courseware_js'
:
True
,
'disable_courseware_js'
:
True
,
'uses_pattern_library'
:
True
'uses_pattern_library'
:
True
...
...
lms/templates/learner_dashboard/program_details.html
View file @
85ca1f3e
...
@@ -13,7 +13,9 @@ from openedx.core.djangolib.js_utils import (
...
@@ -13,7 +13,9 @@ from openedx.core.djangolib.js_utils import (
<
%
block
name=
"js_extra"
>
<
%
block
name=
"js_extra"
>
<
%
static:require_module
module_name=
"js/learner_dashboard/program_details_factory"
class_name=
"ProgramDetailsFactory"
>
<
%
static:require_module
module_name=
"js/learner_dashboard/program_details_factory"
class_name=
"ProgramDetailsFactory"
>
ProgramDetailsFactory({});
ProgramDetailsFactory({
programData: ${program_data | n, dump_js_escaped_json}
});
</
%
static:require
_module
>
</
%
static:require
_module
>
</
%
block>
</
%
block>
...
...
openedx/core/djangoapps/programs/utils.py
View file @
85ca1f3e
...
@@ -10,7 +10,7 @@ from openedx.core.lib.edx_api_utils import get_edx_api_data
...
@@ -10,7 +10,7 @@ from openedx.core.lib.edx_api_utils import get_edx_api_data
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
def
get_programs
(
user
):
def
get_programs
(
user
,
program_id
=
None
):
"""Given a user, get programs from the Programs service.
"""Given a user, get programs from the Programs service.
Returned value is cached depending on user permissions. Staff users making requests
Returned value is cached depending on user permissions. Staff users making requests
against Programs will receive unpublished programs, while regular users will only receive
against Programs will receive unpublished programs, while regular users will only receive
...
@@ -19,6 +19,9 @@ def get_programs(user):
...
@@ -19,6 +19,9 @@ def get_programs(user):
Arguments:
Arguments:
user (User): The user to authenticate as when requesting programs.
user (User): The user to authenticate as when requesting programs.
Keyword Arguments:
program_id (int): Identifies a specific program for which to retrieve data.
Returns:
Returns:
list of dict, representing programs returned by the Programs service.
list of dict, representing programs returned by the Programs service.
"""
"""
...
@@ -27,7 +30,7 @@ def get_programs(user):
...
@@ -27,7 +30,7 @@ def get_programs(user):
# Bypass caching for staff users, who may be creating Programs and want
# Bypass caching for staff users, who may be creating Programs and want
# to see them displayed immediately.
# to see them displayed immediately.
cache_key
=
programs_config
.
CACHE_KEY
if
programs_config
.
is_cache_enabled
and
not
user
.
is_staff
else
None
cache_key
=
programs_config
.
CACHE_KEY
if
programs_config
.
is_cache_enabled
and
not
user
.
is_staff
else
None
return
get_edx_api_data
(
programs_config
,
user
,
'programs'
,
cache_key
=
cache_key
)
return
get_edx_api_data
(
programs_config
,
user
,
'programs'
,
resource_id
=
program_id
,
cache_key
=
cache_key
)
def
flatten_programs
(
programs
,
course_ids
):
def
flatten_programs
(
programs
,
course_ids
):
...
...
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