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
2813b126
Commit
2813b126
authored
Sep 18, 2015
by
Awais Jibran
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Published orphans in split breaks preview button in Studio
parent
69c47e09
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
143 additions
and
3 deletions
+143
-3
cms/djangoapps/contentstore/tests/test_orphan.py
+114
-1
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+28
-1
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
+1
-1
No files found.
cms/djangoapps/contentstore/tests/test_orphan.py
View file @
2813b126
...
...
@@ -3,10 +3,13 @@ Test finding orphans via the view and django config
"""
import
json
import
ddt
from
contentstore.tests.utils
import
CourseTestCase
from
student.models
import
CourseEnrollment
from
contentstore.utils
import
reverse_course_url
from
opaque_keys.edx.locator
import
BlockUsageLocator
from
student.models
import
CourseEnrollment
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.search
import
path_to_location
from
xmodule.modulestore.tests.factories
import
CourseFactory
...
...
@@ -128,3 +131,113 @@ class TestOrphan(TestOrphanBase):
self
.
assertEqual
(
response
.
status_code
,
403
)
response
=
test_user_client
.
delete
(
orphan_url
)
self
.
assertEqual
(
response
.
status_code
,
403
)
@ddt.data
(
ModuleStoreEnum
.
Type
.
split
)
def
test_path_to_location_for_orphan_vertical
(
self
,
module_store
):
r"""
Make sure that path_to_location works with a component having multiple vertical parents,
from which one of them is orphan.
course
|
chapter
|
vertical vertical
\ /
html
"""
# Get a course with orphan modules
course
=
self
.
create_course_with_orphans
(
module_store
)
# Fetch the required course components.
vertical1
=
self
.
store
.
get_item
(
BlockUsageLocator
(
course
.
id
,
'vertical'
,
'Vertical1'
))
chapter1
=
self
.
store
.
get_item
(
BlockUsageLocator
(
course
.
id
,
'chapter'
,
'Chapter1'
))
orphan_vertical
=
self
.
store
.
get_item
(
BlockUsageLocator
(
course
.
id
,
'vertical'
,
'OrphanVert'
))
multi_parent_html
=
self
.
store
.
get_item
(
BlockUsageLocator
(
course
.
id
,
'html'
,
'multi_parent_html'
))
# Verify `OrphanVert` is an orphan
self
.
assertIn
(
orphan_vertical
.
location
,
self
.
store
.
get_orphans
(
course
.
id
))
# Verify `multi_parent_html` is child of both `Vertical1` and `OrphanVert`
self
.
assertIn
(
multi_parent_html
.
location
,
orphan_vertical
.
children
)
self
.
assertIn
(
multi_parent_html
.
location
,
vertical1
.
children
)
# HTML component has `vertical1` as its parent.
html_parent
=
self
.
store
.
get_parent_location
(
multi_parent_html
.
location
)
self
.
assertNotEqual
(
unicode
(
html_parent
),
unicode
(
orphan_vertical
.
location
))
self
.
assertEqual
(
unicode
(
html_parent
),
unicode
(
vertical1
.
location
))
# Get path of the `multi_parent_html` & verify path_to_location returns a expected path
path
=
path_to_location
(
self
.
store
,
multi_parent_html
.
location
)
expected_path
=
(
course
.
id
,
chapter1
.
location
.
block_id
,
vertical1
.
location
.
block_id
,
multi_parent_html
.
location
.
block_id
,
""
,
path
[
-
1
]
)
self
.
assertIsNotNone
(
path
)
self
.
assertEqual
(
len
(
path
),
6
)
self
.
assertEqual
(
path
,
expected_path
)
@ddt.data
(
ModuleStoreEnum
.
Type
.
split
)
def
test_path_to_location_for_orphan_chapter
(
self
,
module_store
):
r"""
Make sure that path_to_location works with a component having multiple chapter parents,
from which one of them is orphan
course
|
chapter chapter
| |
vertical vertical
\ /
html
"""
# Get a course with orphan modules
course
=
self
.
create_course_with_orphans
(
module_store
)
orphan_chapter
=
self
.
store
.
get_item
(
BlockUsageLocator
(
course
.
id
,
'chapter'
,
'OrphanChapter'
))
chapter1
=
self
.
store
.
get_item
(
BlockUsageLocator
(
course
.
id
,
'chapter'
,
'Chapter1'
))
vertical1
=
self
.
store
.
get_item
(
BlockUsageLocator
(
course
.
id
,
'vertical'
,
'Vertical1'
))
# Verify `OrhanChapter` is an orphan
self
.
assertIn
(
orphan_chapter
.
location
,
self
.
store
.
get_orphans
(
course
.
id
))
# Create a vertical (`Vertical0`) in orphan chapter (`OrphanChapter`).
# OrphanChapter -> Vertical0
vertical0
=
self
.
store
.
create_child
(
self
.
user
.
id
,
orphan_chapter
.
location
,
'vertical'
,
"Vertical0"
)
self
.
store
.
publish
(
vertical0
.
location
,
self
.
user
.
id
)
# Create a component in `Vertical0`
# OrphanChapter -> Vertical0 -> Html
html
=
self
.
store
.
create_child
(
self
.
user
.
id
,
vertical0
.
location
,
'html'
,
"HTML0"
)
self
.
store
.
publish
(
html
.
location
,
self
.
user
.
id
)
# Verify chapter1 is parent of vertical1.
vertical1_parent
=
self
.
store
.
get_parent_location
(
vertical1
.
location
)
self
.
assertEqual
(
unicode
(
vertical1_parent
),
unicode
(
chapter1
.
location
))
# Make `Vertical1` the parent of `HTML0`. So `HTML0` will have to parents (`Vertical0` & `Vertical1`)
vertical1
.
children
.
append
(
html
.
location
)
self
.
store
.
update_item
(
vertical1
,
self
.
user
.
id
)
# Get parent location & verify its either of the two verticals. As both parents are non-orphan,
# alphabetically least is returned
html_parent
=
self
.
store
.
get_parent_location
(
html
.
location
)
self
.
assertEquals
(
unicode
(
html_parent
),
unicode
(
vertical1
.
location
))
# verify path_to_location returns a expected path
path
=
path_to_location
(
self
.
store
,
html
.
location
)
expected_path
=
(
course
.
id
,
chapter1
.
location
.
block_id
,
vertical1
.
location
.
block_id
,
html
.
location
.
block_id
,
""
,
path
[
-
1
]
)
self
.
assertIsNotNone
(
path
)
self
.
assertEqual
(
len
(
path
),
6
)
self
.
assertEqual
(
path
,
expected_path
)
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
View file @
2813b126
...
...
@@ -1121,6 +1121,23 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
else
:
return
[]
def
has_path_to_root
(
self
,
block_key
,
course
):
"""
Check recursively if an xblock has a path to the course root
:param block_key: BlockKey of the component whose path is to be checked
:param course: actual db json of course from structures
:return Bool: whether or not component has path to the root
"""
xblock_parents
=
self
.
_get_parents_from_structure
(
block_key
,
course
.
structure
)
if
len
(
xblock_parents
)
==
0
and
block_key
.
type
in
[
"course"
,
"library"
]:
# Found, xblock has the path to the root
return
True
return
any
(
self
.
has_path_to_root
(
xblock_parent
,
course
)
for
xblock_parent
in
xblock_parents
)
def
get_parent_location
(
self
,
locator
,
**
kwargs
):
"""
Return the location (Locators w/ block_ids) for the parent of this location in this
...
...
@@ -1134,9 +1151,19 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
raise
ItemNotFoundError
(
locator
)
course
=
self
.
_lookup_course
(
locator
.
course_key
)
parent_ids
=
self
.
_get_parents_from_structure
(
BlockKey
.
from_usage_key
(
locator
),
course
.
structure
)
all_parent_ids
=
self
.
_get_parents_from_structure
(
BlockKey
.
from_usage_key
(
locator
),
course
.
structure
)
# Check and verify the found parent_ids are not orphans; Remove parent which has no valid path
# to the course root
parent_ids
=
[
valid_parent
for
valid_parent
in
all_parent_ids
if
self
.
has_path_to_root
(
valid_parent
,
course
)
]
if
len
(
parent_ids
)
==
0
:
return
None
# find alphabetically least
parent_ids
.
sort
(
key
=
lambda
parent
:
(
parent
.
type
,
parent
.
id
))
return
BlockUsageLocator
.
make_relative
(
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
View file @
2813b126
...
...
@@ -643,7 +643,7 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
test_course
=
self
.
store
.
create_course
(
'test_org'
,
'test_course'
,
'test_run'
,
self
.
user_id
)
# create sequential and vertical to test against
sequential
=
self
.
store
.
create_
item
(
self
.
user_id
,
test_course
.
id
,
'sequential'
,
'test_sequential'
)
sequential
=
self
.
store
.
create_
child
(
self
.
user_id
,
test_course
.
location
,
'sequential'
,
'test_sequential'
)
vertical
=
self
.
store
.
create_child
(
self
.
user_id
,
sequential
.
location
,
'vertical'
,
'test_vertical'
)
# publish sequential changes
...
...
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