202 lines
7.7 KiB
Python
202 lines
7.7 KiB
Python
"""
|
|
Basic unit tests related to content libraries.
|
|
|
|
Higher-level tests are in `cms/djangoapps/contentstore`.
|
|
"""
|
|
|
|
import pytest
|
|
import ddt
|
|
from bson.objectid import ObjectId
|
|
from opaque_keys.edx.locator import LibraryLocator
|
|
|
|
from xmodule.modulestore.exceptions import DuplicateCourseError
|
|
from xmodule.modulestore.tests.factories import BlockFactory, LibraryFactory, check_mongo_calls
|
|
from xmodule.modulestore.tests.utils import MixedSplitTestCase
|
|
|
|
|
|
@ddt.ddt
|
|
class TestLibraries(MixedSplitTestCase):
|
|
"""
|
|
Test for libraries.
|
|
Mostly tests code found throughout split mongo, but also tests library_root_xblock.py
|
|
"""
|
|
|
|
def test_create_library(self):
|
|
"""
|
|
Test that we can create a library, and see how many database calls it uses to do so.
|
|
|
|
Expected mongo calls, in order:
|
|
-> insert(definition: {'block_type': 'library', 'fields': {}})
|
|
-> insert_structure(bulk)
|
|
-> insert_course_index(bulk)
|
|
|
|
Expected MySQL calls in order:
|
|
-> SELECT from SplitModulestoreCourseIndex case insensitive search for existing libraries
|
|
-> SELECT from SplitModulestoreCourseIndex lookup library with that exact ID
|
|
-> SELECT from XBlockConfiguration (?)
|
|
-> INSERT into SplitModulestoreCourseIndex to save the new library
|
|
-> INSERT a historical record of the SplitModulestoreCourseIndex
|
|
"""
|
|
with check_mongo_calls(0, 3), self.assertNumQueries(5):
|
|
LibraryFactory.create(modulestore=self.store)
|
|
|
|
def test_duplicate_library(self):
|
|
"""
|
|
Make sure we cannot create duplicate libraries
|
|
"""
|
|
org, lib_code = ('DuplicateX', "DUP")
|
|
LibraryFactory.create(org=org, library=lib_code, modulestore=self.store)
|
|
with pytest.raises(DuplicateCourseError):
|
|
LibraryFactory.create(org=org, library=lib_code, modulestore=self.store)
|
|
|
|
@ddt.data(
|
|
"This is a test library!",
|
|
"Ωμέγα Βιβλιοθήκη",
|
|
)
|
|
def test_str_repr(self, name):
|
|
"""
|
|
Test __unicode__() and __str__() methods of libraries
|
|
"""
|
|
library = LibraryFactory.create(metadata={"display_name": name}, modulestore=self.store)
|
|
assert name in str(library)
|
|
if not isinstance(name, str):
|
|
assert name in str(library)
|
|
|
|
def test_display_with_default_methods(self):
|
|
"""
|
|
Check that the display_x_with_default methods have been implemented, for
|
|
compatibility with courses.
|
|
"""
|
|
org = 'TestOrgX'
|
|
lib_code = 'LC101'
|
|
library = LibraryFactory.create(org=org, library=lib_code, modulestore=self.store)
|
|
assert library.display_org_with_default == org
|
|
assert library.display_number_with_default == lib_code
|
|
|
|
def test_block_with_children(self):
|
|
"""
|
|
Test that blocks used from a library can have children.
|
|
"""
|
|
library = LibraryFactory.create(modulestore=self.store)
|
|
|
|
# In the library, create a vertical block with a child:
|
|
vert_block = BlockFactory.create(
|
|
category="vertical",
|
|
parent_location=library.location,
|
|
user_id=self.user_id,
|
|
publish_item=False,
|
|
modulestore=self.store,
|
|
)
|
|
child_block = BlockFactory.create(
|
|
category="html",
|
|
parent_location=vert_block.location,
|
|
user_id=self.user_id,
|
|
publish_item=False,
|
|
metadata={"data": "Hello world", },
|
|
modulestore=self.store,
|
|
)
|
|
assert child_block.parent.replace(version_guid=None, branch=None) == vert_block.location
|
|
|
|
def test_update_item(self):
|
|
"""
|
|
Test that update_item works for a block in a library
|
|
"""
|
|
library = LibraryFactory.create(modulestore=self.store)
|
|
|
|
block = BlockFactory.create(
|
|
category="html",
|
|
parent_location=library.location,
|
|
user_id=self.user_id,
|
|
publish_item=False,
|
|
metadata={"data": "Hello world", },
|
|
modulestore=self.store,
|
|
)
|
|
block_key = block.location
|
|
block.data = "NEW"
|
|
old_version = self.store.get_item(block_key, remove_version=False, remove_branch=False).location.version_guid
|
|
self.store.update_item(block, self.user_id)
|
|
# Reload block from the modulestore
|
|
block = self.store.get_item(block_key)
|
|
assert block.data == 'NEW'
|
|
assert block.location == block_key
|
|
new_version = self.store.get_item(block_key, remove_version=False, remove_branch=False).location.version_guid
|
|
assert old_version != new_version
|
|
|
|
def test_delete_item(self):
|
|
"""
|
|
Test to make sure delete_item() works on blocks in a library
|
|
"""
|
|
library = LibraryFactory.create(modulestore=self.store)
|
|
lib_key = library.location.library_key
|
|
block = BlockFactory.create(
|
|
category="html",
|
|
parent_location=library.location,
|
|
user_id=self.user_id,
|
|
publish_item=False,
|
|
modulestore=self.store,
|
|
)
|
|
library = self.store.get_library(lib_key)
|
|
assert len(library.children) == 1
|
|
self.store.delete_item(block.location, self.user_id)
|
|
library = self.store.get_library(lib_key)
|
|
assert len(library.children) == 0
|
|
|
|
def test_get_library_non_existent(self):
|
|
""" Test get_library() with non-existent key """
|
|
result = self.store.get_library(LibraryLocator("non", "existent"))
|
|
assert result is None
|
|
|
|
def test_get_library_keys(self):
|
|
""" Test get_library_keys() """
|
|
libraries = [LibraryFactory.create(modulestore=self.store) for _ in range(3)]
|
|
lib_keys_expected = {lib.location.library_key for lib in libraries}
|
|
lib_keys_actual = set(self.store.get_library_keys())
|
|
assert lib_keys_expected == lib_keys_actual
|
|
|
|
def test_get_libraries(self):
|
|
""" Test get_libraries() """
|
|
libraries = [LibraryFactory.create(modulestore=self.store) for _ in range(3)]
|
|
lib_dict = {lib.location.library_key: lib for lib in libraries}
|
|
|
|
lib_list = self.store.get_libraries()
|
|
|
|
assert len(lib_list) == len(libraries)
|
|
for lib in lib_list:
|
|
assert lib.location.library_key in lib_dict
|
|
|
|
def test_strip(self):
|
|
"""
|
|
Test that library keys coming out of MixedModuleStore are stripped of
|
|
branch and version info by default.
|
|
"""
|
|
# Create a library
|
|
lib_key = LibraryFactory.create(modulestore=self.store).location.library_key
|
|
# Re-load the library from the modulestore, explicitly including version information:
|
|
lib = self.store.get_library(lib_key)
|
|
assert lib.location.version_guid is None
|
|
assert lib.location.branch is None
|
|
assert lib.location.library_key.version_guid is None
|
|
assert lib.location.library_key.branch is None
|
|
|
|
def test_get_lib_version(self):
|
|
"""
|
|
Test that we can get version data about a library from get_library()
|
|
"""
|
|
# Create a library
|
|
lib_key = LibraryFactory.create(modulestore=self.store).location.library_key
|
|
# Re-load the library from the modulestore, explicitly including version information:
|
|
lib = self.store.get_library(lib_key, remove_version=False, remove_branch=False)
|
|
version = lib.location.library_key.version_guid
|
|
assert isinstance(version, ObjectId)
|
|
|
|
def test_xblock_in_lib_have_published_version_returns_false(self):
|
|
library = LibraryFactory.create(modulestore=self.store)
|
|
block = BlockFactory.create(
|
|
category="html",
|
|
parent_location=library.location,
|
|
user_id=self.user_id,
|
|
publish_item=False,
|
|
modulestore=self.store,
|
|
)
|
|
assert not self.store.has_published_version(block)
|