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
61f7373a
Commit
61f7373a
authored
Apr 02, 2015
by
Adam
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #7552 from edx/hotfix/2015-04-01
Fixed static pages removed on import for split course.
parents
41d7d52b
464bcf33
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
142 additions
and
9 deletions
+142
-9
common/djangoapps/student/tests/test_certificates.py
+54
-0
common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
+64
-5
common/lib/xmodule/xmodule/modulestore/xml_exporter.py
+7
-1
common/test/data/split_course_with_static_tabs/course.xml
+3
-0
common/test/data/split_course_with_static_tabs/course/course.xml
+2
-0
common/test/data/split_course_with_static_tabs/policies/assets.json
+1
-0
common/test/data/split_course_with_static_tabs/policies/course/grading_policy.json
+1
-0
common/test/data/split_course_with_static_tabs/policies/course/policy.json
+1
-0
common/test/data/split_course_with_static_tabs/tabs/test_page.html
+1
-0
lms/djangoapps/courseware/management/commands/tests/test_dump_course.py
+3
-1
lms/templates/dashboard/_dashboard_certificate_information.html
+5
-2
No files found.
common/djangoapps/student/tests/test_certificates.py
0 → 100644
View file @
61f7373a
"""Tests for display of certificates on the student dashboard. """
import
unittest
import
ddt
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
student.tests.factories
import
UserFactory
,
CourseEnrollmentFactory
from
certificates.tests.factories
import
GeneratedCertificateFactory
# pylint: disable=import-error
@ddt.ddt
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
class
CertificateDisplayTest
(
ModuleStoreTestCase
):
"""Tests display of certificates on the student dashboard. """
USERNAME
=
"test_user"
PASSWORD
=
"password"
DOWNLOAD_URL
=
"http://www.example.com/certificate.pdf"
def
setUp
(
self
):
super
(
CertificateDisplayTest
,
self
)
.
setUp
()
self
.
user
=
UserFactory
.
create
(
username
=
self
.
USERNAME
,
password
=
self
.
PASSWORD
)
result
=
self
.
client
.
login
(
username
=
self
.
USERNAME
,
password
=
self
.
PASSWORD
)
self
.
assertTrue
(
result
,
msg
=
"Could not log in"
)
self
.
course
=
CourseFactory
()
self
.
course
.
certificates_display_behavior
=
"early_with_info"
self
.
update_course
(
self
.
course
,
self
.
user
.
username
)
@ddt.data
(
'verified'
,
'professional'
)
def
test_display_verified_certificate
(
self
,
enrollment_mode
):
self
.
_create_certificate
(
enrollment_mode
)
self
.
_check_can_download_certificate
()
def
_create_certificate
(
self
,
enrollment_mode
):
"""Simulate that the user has a generated certificate. """
CourseEnrollmentFactory
.
create
(
user
=
self
.
user
,
course_id
=
self
.
course
.
id
,
mode
=
enrollment_mode
)
GeneratedCertificateFactory
(
user
=
self
.
user
,
course_id
=
self
.
course
.
id
,
mode
=
enrollment_mode
,
download_url
=
self
.
DOWNLOAD_URL
,
status
=
"downloadable"
,
grade
=
0.98
,
)
def
_check_can_download_certificate
(
self
):
response
=
self
.
client
.
get
(
reverse
(
'dashboard'
))
self
.
assertContains
(
response
,
u'Download Your ID Verified'
)
self
.
assertContains
(
response
,
self
.
DOWNLOAD_URL
)
common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
View file @
61f7373a
...
...
@@ -13,6 +13,7 @@ and then for each combination of modulestores, performing the sequence:
"""
from
contextlib
import
contextmanager
,
nested
import
itertools
import
os
from
path
import
path
import
random
from
shutil
import
rmtree
...
...
@@ -314,14 +315,15 @@ class MixedModulestoreBuilder(StoreBuilderBase):
# Split stores all asset metadata in the structure collection.
return
store
.
db_connection
.
structures
MIXED_MODULESTORE_BOTH_SETUP
=
MixedModulestoreBuilder
([
(
'draft'
,
MongoModulestoreBuilder
()),
(
'split'
,
VersioningModulestoreBuilder
())
])
DRAFT_MODULESTORE_SETUP
=
MixedModulestoreBuilder
([(
'draft'
,
MongoModulestoreBuilder
())])
SPLIT_MODULESTORE_SETUP
=
MixedModulestoreBuilder
([(
'split'
,
VersioningModulestoreBuilder
())])
MIXED_MODULESTORE_SETUPS
=
(
MixedModulestoreBuilder
([(
'draft'
,
MongoModulestoreBuilder
())])
,
MixedModulestoreBuilder
([(
'split'
,
VersioningModulestoreBuilder
())])
,
DRAFT_MODULESTORE_SETUP
,
SPLIT_MODULESTORE_SETUP
,
)
MIXED_MS_SETUPS_SHORT
=
(
'mixed_mongo'
,
...
...
@@ -347,6 +349,8 @@ COURSE_DATA_NAMES = (
'split_test_module_draft'
,
)
EXPORTED_COURSE_DIR_NAME
=
'exported_source_course'
@ddt.ddt
@attr
(
'mongo'
)
...
...
@@ -397,14 +401,14 @@ class CrossStoreXMLRoundtrip(CourseComparisonTest, PartitionTestCase):
source_content
,
source_course_key
,
self
.
export_dir
,
'exported_source_course'
,
EXPORTED_COURSE_DIR_NAME
,
)
import_course_from_xml
(
dest_store
,
'test_user'
,
self
.
export_dir
,
source_dirs
=
[
'exported_source_course'
],
source_dirs
=
[
EXPORTED_COURSE_DIR_NAME
],
static_content_store
=
dest_content
,
target_id
=
dest_course_key
,
raise_on_failure
=
True
,
...
...
@@ -448,3 +452,58 @@ class CrossStoreXMLRoundtrip(CourseComparisonTest, PartitionTestCase):
dest_store
,
dest_course_key
,
)
def
test_split_course_export_import
(
self
):
# Construct the contentstore for storing the first import
with
MongoContentstoreBuilder
()
.
build
()
as
source_content
:
# Construct the modulestore for storing the first import (using the previously created contentstore)
with
SPLIT_MODULESTORE_SETUP
.
build
(
contentstore
=
source_content
)
as
source_store
:
# Construct the contentstore for storing the second import
with
MongoContentstoreBuilder
()
.
build
()
as
dest_content
:
# Construct the modulestore for storing the second import (using the second contentstore)
with
SPLIT_MODULESTORE_SETUP
.
build
(
contentstore
=
dest_content
)
as
dest_store
:
source_course_key
=
source_store
.
make_course_key
(
'a'
,
'source'
,
'2015_Fall'
)
dest_course_key
=
dest_store
.
make_course_key
(
'a'
,
'dest'
,
'2015_Fall'
)
import_course_from_xml
(
source_store
,
'test_user'
,
TEST_DATA_DIR
,
source_dirs
=
[
'split_course_with_static_tabs'
],
static_content_store
=
source_content
,
target_id
=
source_course_key
,
raise_on_failure
=
True
,
create_if_not_present
=
True
,
)
export_course_to_xml
(
source_store
,
source_content
,
source_course_key
,
self
.
export_dir
,
EXPORTED_COURSE_DIR_NAME
,
)
source_course
=
source_store
.
get_course
(
source_course_key
,
depth
=
None
,
lazy
=
False
)
self
.
assertEqual
(
source_course
.
url_name
,
'course'
)
export_dir_path
=
path
(
self
.
export_dir
)
policy_dir
=
export_dir_path
/
'exported_source_course'
/
'policies'
/
source_course
.
url_name
policy_path
=
policy_dir
/
'policy.json'
self
.
assertTrue
(
os
.
path
.
exists
(
policy_path
))
import_course_from_xml
(
dest_store
,
'test_user'
,
self
.
export_dir
,
source_dirs
=
[
EXPORTED_COURSE_DIR_NAME
],
static_content_store
=
dest_content
,
target_id
=
dest_course_key
,
raise_on_failure
=
True
,
create_if_not_present
=
True
,
)
dest_course
=
dest_store
.
get_course
(
dest_course_key
,
depth
=
None
,
lazy
=
False
)
self
.
assertEqual
(
dest_course
.
url_name
,
'course'
)
common/lib/xmodule/xmodule/modulestore/xml_exporter.py
View file @
61f7373a
...
...
@@ -264,8 +264,14 @@ class CourseExportManager(ExportManager):
'about'
,
'about'
,
'.html'
)
course_policy_dir_name
=
courselike
.
location
.
run
if
courselike
.
url_name
!=
courselike
.
location
.
run
and
courselike
.
url_name
==
'course'
:
# Use url_name for split mongo because course_run is not used when loading policies.
course_policy_dir_name
=
courselike
.
url_name
course_run_policy_dir
=
policies_dir
.
makeopendir
(
course_policy_dir_name
)
# export the grading policy
course_run_policy_dir
=
policies_dir
.
makeopendir
(
courselike
.
location
.
run
)
with
course_run_policy_dir
.
open
(
'grading_policy.json'
,
'w'
)
as
grading_policy
:
grading_policy
.
write
(
dumps
(
courselike
.
grading_policy
,
cls
=
EdxJSONEncoder
,
sort_keys
=
True
,
indent
=
4
))
...
...
common/test/data/split_course_with_static_tabs/course.xml
0 → 100644
View file @
61f7373a
<course
url_name=
'course'
org=
'split_test'
course=
'split_test'
>
</course>
common/test/data/split_course_with_static_tabs/course/course.xml
0 → 100644
View file @
61f7373a
<course
advanced_modules=
"["drag-and-drop-v2"]"
display_name=
"Test Static Tab"
due_date_display_format=
""
graceperiod=
""
no_grade=
"false"
pdf_textbooks=
"[]"
start=
""2015-01-01T00:00:00+00:00""
use_latex_compiler=
"true"
>
</course>
common/test/data/split_course_with_static_tabs/policies/assets.json
0 → 100644
View file @
61f7373a
{}
common/test/data/split_course_with_static_tabs/policies/course/grading_policy.json
0 → 100644
View file @
61f7373a
{
"GRADER"
:
[{
"short_label"
:
"HW"
,
"min_count"
:
12
,
"type"
:
"Homework"
,
"drop_count"
:
2
,
"weight"
:
0.15
},
{
"min_count"
:
12
,
"type"
:
"Lab"
,
"drop_count"
:
2
,
"weight"
:
0.15
},
{
"short_label"
:
"Midterm"
,
"min_count"
:
1
,
"type"
:
"Midterm Exam"
,
"drop_count"
:
0
,
"weight"
:
0.3
},
{
"short_label"
:
"Final"
,
"min_count"
:
1
,
"type"
:
"Final Exam"
,
"drop_count"
:
0
,
"weight"
:
0.4
}],
"GRADE_CUTOFFS"
:
{
"Pass"
:
0.5
}}
common/test/data/split_course_with_static_tabs/policies/course/policy.json
0 → 100644
View file @
61f7373a
{
"course/3111"
:
{
"tabs"
:
[{
"type"
:
"courseware"
,
"name"
:
"Courseware"
},
{
"type"
:
"course_info"
,
"name"
:
"Course Info"
},
{
"type"
:
"textbooks"
,
"name"
:
"Textbooks"
},
{
"type"
:
"discussion"
,
"name"
:
"Discussion"
},
{
"type"
:
"wiki"
,
"name"
:
"Wiki"
},
{
"type"
:
"progress"
,
"name"
:
"Progress"
},
{
"name"
:
"Test Page"
,
"type"
:
"static_tab"
,
"url_slug"
:
"test_page.html"
}],
"advanced_modules"
:
[
"split_test"
],
"display_name"
:
"split export test"
,
"user_partitions"
:
[{
"description"
:
"Experiment 1"
,
"version"
:
1
,
"id"
:
0
,
"groups"
:
[{
"version"
:
1
,
"id"
:
0
,
"name"
:
"group 0"
},
{
"version"
:
1
,
"id"
:
1
,
"name"
:
"group 1"
}],
"name"
:
"Experiment 0,1"
},
{
"description"
:
"Experiment 2"
,
"version"
:
1
,
"id"
:
1
,
"groups"
:
[{
"version"
:
1
,
"id"
:
0
,
"name"
:
"group A"
},
{
"version"
:
1
,
"id"
:
1
,
"name"
:
"group B"
},
{
"version"
:
1
,
"id"
:
2
,
"name"
:
"group C"
}],
"name"
:
"Experiment A,B,C"
}],
"discussion_topics"
:
{
"General"
:
{
"id"
:
"i4x-foo-1111-course-3111"
}}}}
common/test/data/split_course_with_static_tabs/tabs/test_page.html
0 → 100644
View file @
61f7373a
<p>
Add the content you want students to see on this page.
</p>
lms/djangoapps/courseware/management/commands/tests/test_dump_course.py
View file @
61f7373a
...
...
@@ -44,6 +44,7 @@ class CommandsTestBase(ModuleStoreTestCase):
"""
__test__
=
False
url_name
=
'2012_Fall'
def
setUp
(
self
):
super
(
CommandsTestBase
,
self
)
.
setUp
()
...
...
@@ -198,7 +199,7 @@ class CommandsTestBase(ModuleStoreTestCase):
assert_in
=
self
.
assertIn
assert_in
(
'edX-simple-2012_Fall'
,
names
)
assert_in
(
'edX-simple-2012_Fall/policies/
2012_Fall/policy.json'
,
names
)
assert_in
(
'edX-simple-2012_Fall/policies/
{}/policy.json'
.
format
(
self
.
url_name
)
,
names
)
assert_in
(
'edX-simple-2012_Fall/html/toylab.html'
,
names
)
assert_in
(
'edX-simple-2012_Fall/videosequence/A_simple_sequence.xml'
,
names
)
assert_in
(
'edX-simple-2012_Fall/sequential/Lecture_2.xml'
,
names
)
...
...
@@ -229,3 +230,4 @@ class CommandSplitMongoTestCase(CommandsTestBase):
"""
MODULESTORE
=
TEST_DATA_SPLIT_MODULESTORE
__test__
=
True
url_name
=
'course'
lms/templates/dashboard/_dashboard_certificate_information.html
View file @
61f7373a
<
%
page
args=
"cert_status, course, enrollment"
/>
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
from
course_modes
.
models
import
CourseMode
%
>
<
%
namespace
name=
'static'
file=
'../static_content.html'
/>
<
%
...
...
@@ -61,7 +64,7 @@ else:
<a
class=
"btn"
href=
"${cert_status['download_url']}"
title=
"${_('This link will open/download a PDF document')}"
>
${_("Download Your {cert_name_short} (PDF)").format(cert_name_short=cert_name_short)}
</a></li>
% elif cert_status['show_download_url'] and enrollment.mode
== 'verified'
:
% elif cert_status['show_download_url'] and enrollment.mode
in CourseMode.VERIFIED_MODES
:
<li
class=
"action"
>
<a
class=
"btn"
href=
"${cert_status['download_url']}"
title=
"${_('This link will open/download a PDF document of your verified {cert_name_long}.').format(cert_name_long=cert_name_long)}"
>
...
...
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