Add unit tests to test id creation in custom content blocks
Relates to MS-919
This commit is contained in:
parent
60b28ec022
commit
6ad39bcdb2
|
|
@ -1,15 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Iterativ GmbH
|
|
||||||
# http://www.iterativ.ch/
|
|
||||||
#
|
|
||||||
# Copyright (c) 2018 Iterativ GmbH. All rights reserved.
|
|
||||||
#
|
|
||||||
# Created on 25.09.18
|
|
||||||
# @author: Ramon Wenger <ramon.wenger@iterativ.ch>
|
|
||||||
|
|
||||||
import bleach
|
import bleach
|
||||||
import re
|
import re
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
|
|
||||||
|
|
@ -33,35 +25,45 @@ def get_previous_item(previous_contents: Union[StreamValue, List[dict]], item: d
|
||||||
contents = previous_contents.raw_data
|
contents = previous_contents.raw_data
|
||||||
else:
|
else:
|
||||||
contents = previous_contents
|
contents = previous_contents
|
||||||
return next((c for c in contents if c.get('id', None) == item['id']), None)
|
return next((c for c in contents if c.get("id", None) == item["id"]), None)
|
||||||
|
|
||||||
|
|
||||||
def handle_text(text):
|
def handle_text(text):
|
||||||
is_list = bool(re.search(r'<ul>', text))
|
is_list = bool(re.search(r"<ul>", text))
|
||||||
if is_list:
|
if is_list:
|
||||||
# let's assume this is formatted correctly already, otherwise bleach or the browser should strip / ignore it
|
# let's assume this is formatted correctly already, otherwise bleach or the browser should strip / ignore it
|
||||||
return text
|
return text
|
||||||
else:
|
else:
|
||||||
parts = re.split(r'[\r\n]+', text)
|
parts = re.split(r"[\r\n]+", text)
|
||||||
paragraphs = ['<p>{}</p>'.format(p.strip()) for p in parts]
|
paragraphs = ["<p>{}</p>".format(p.strip()) for p in parts]
|
||||||
return '\n'.join(paragraphs)
|
return "\n".join(paragraphs)
|
||||||
|
|
||||||
|
|
||||||
ALLOWED_BLOCKS = (
|
ALLOWED_BLOCKS = (
|
||||||
'text_block',
|
"text_block",
|
||||||
'student_entry',
|
"student_entry",
|
||||||
'image_url_block',
|
"image_url_block",
|
||||||
'link_block',
|
"link_block",
|
||||||
'video_block',
|
"video_block",
|
||||||
'assignment',
|
"assignment",
|
||||||
'document_block',
|
"document_block",
|
||||||
'content_list_item',
|
"content_list_item",
|
||||||
'subtitle',
|
"subtitle",
|
||||||
'readonly'
|
"readonly",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def handle_content_block(content, context=None, module=None, allowed_blocks=ALLOWED_BLOCKS, previous_contents=None):
|
def get_content_dict(content_type, id, value):
|
||||||
|
return {"type": content_type, "id": id, "value": value}
|
||||||
|
|
||||||
|
|
||||||
|
def handle_content_block(
|
||||||
|
content,
|
||||||
|
context=None,
|
||||||
|
module=None,
|
||||||
|
allowed_blocks=ALLOWED_BLOCKS,
|
||||||
|
previous_contents=None,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Handle different content types of a content block
|
Handle different content types of a content block
|
||||||
|
|
||||||
|
|
@ -75,95 +77,98 @@ def handle_content_block(content, context=None, module=None, allowed_blocks=ALLO
|
||||||
"""
|
"""
|
||||||
# todo: add all the content blocks
|
# todo: add all the content blocks
|
||||||
# todo: sanitize user inputs!
|
# todo: sanitize user inputs!
|
||||||
if content['type'] not in allowed_blocks:
|
if content["type"] not in allowed_blocks:
|
||||||
return
|
return
|
||||||
|
|
||||||
if content['type'] == 'text_block':
|
id = content.get("id")
|
||||||
return {
|
if id is None:
|
||||||
'type': 'text_block',
|
id = str(uuid.uuid4())
|
||||||
'value': {
|
|
||||||
'text': handle_text(bleach.clean(content['value']['text'], strip=True))
|
if content["type"] == "text_block":
|
||||||
}}
|
content_type = "text_block"
|
||||||
elif content['type'] == 'assignment':
|
value = {
|
||||||
|
"text": handle_text(bleach.clean(content["value"]["text"], strip=True))
|
||||||
|
}
|
||||||
|
return get_content_dict(
|
||||||
|
content_type=content_type,
|
||||||
|
id=id,
|
||||||
|
value=value,
|
||||||
|
)
|
||||||
|
elif content["type"] == "assignment":
|
||||||
if module is None:
|
if module is None:
|
||||||
raise AssignmentParameterException('Module is missing for assignment') # todo: define better exception
|
raise AssignmentParameterException(
|
||||||
|
"Module is missing for assignment"
|
||||||
|
) # todo: define better exception
|
||||||
if context is None:
|
if context is None:
|
||||||
raise AssignmentParameterException('Context is missing for assignment')
|
raise AssignmentParameterException("Context is missing for assignment")
|
||||||
value = content['value']
|
value = content["value"]
|
||||||
if value.get('id') is not None:
|
if value.get("id") is not None:
|
||||||
assignment = get_object(Assignment, value.get('id'))
|
assignment = get_object(Assignment, value.get("id"))
|
||||||
if assignment.user_created and assignment.owner == context.user:
|
if assignment.user_created and assignment.owner == context.user:
|
||||||
assignment.title = value.get('title')
|
assignment.title = value.get("title")
|
||||||
assignment.assignment = value.get('assignment')
|
assignment.assignment = value.get("assignment")
|
||||||
assignment.save()
|
assignment.save()
|
||||||
else:
|
else:
|
||||||
assignment = Assignment.objects.create(
|
assignment = Assignment.objects.create(
|
||||||
title=value.get('title'),
|
title=value.get("title"),
|
||||||
assignment=value.get('assignment'),
|
assignment=value.get("assignment"),
|
||||||
owner=context.user,
|
owner=context.user,
|
||||||
module=module,
|
module=module,
|
||||||
user_created=True
|
user_created=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
content_type = "assignment"
|
||||||
'type': 'assignment',
|
value = {"assignment_id": assignment.id}
|
||||||
'value': {
|
return get_content_dict(content_type=content_type, id=id, value=value)
|
||||||
'assignment_id': assignment.id
|
elif content["type"] == "image_url_block":
|
||||||
}}
|
content_type = "image_url_block"
|
||||||
elif content['type'] == 'image_url_block':
|
value = {"url": bleach.clean(content["value"]["url"])}
|
||||||
return {
|
return get_content_dict(content_type=content_type, id=id, value=value)
|
||||||
'type': 'image_url_block',
|
elif content["type"] == "link_block":
|
||||||
'value': {
|
content_type = "link_block"
|
||||||
'url': bleach.clean(content['value']['url'])
|
value = {
|
||||||
}}
|
"text": bleach.clean(content["value"]["text"]),
|
||||||
elif content['type'] == 'link_block':
|
"url": bleach.clean(content["value"]["url"]),
|
||||||
return {
|
|
||||||
'type': 'link_block',
|
|
||||||
'value': {
|
|
||||||
'text': bleach.clean(content['value']['text']),
|
|
||||||
'url': bleach.clean(content['value']['url'])
|
|
||||||
}
|
}
|
||||||
}
|
return get_content_dict(content_type=content_type, id=id, value=value)
|
||||||
elif content['type'] == 'video_block':
|
elif content["type"] == "video_block":
|
||||||
return {
|
content_type = "video_block"
|
||||||
'type': 'video_block',
|
value = {"url": bleach.clean(content["value"]["url"])}
|
||||||
'value': {
|
return get_content_dict(content_type=content_type, id=id, value=value)
|
||||||
'url': bleach.clean(content['value']['url'])
|
elif content["type"] == "document_block":
|
||||||
}}
|
content_type = "document_block"
|
||||||
elif content['type'] == 'document_block':
|
value = {"url": bleach.clean(content["value"]["url"])}
|
||||||
return {
|
return get_content_dict(content_type=content_type, id=id, value=value)
|
||||||
'type': 'document_block',
|
elif content["type"] == "subtitle":
|
||||||
'value': {
|
content_type = "subtitle"
|
||||||
'url': bleach.clean(content['value']['url'])
|
value = {"text": bleach.clean(content["value"]["text"])}
|
||||||
}}
|
return get_content_dict(content_type=content_type, id=id, value=value)
|
||||||
elif content['type'] == 'subtitle':
|
elif content["type"] == "content_list_item":
|
||||||
return {
|
if content.get("id") is not None: # the list block existed already
|
||||||
'type': 'subtitle',
|
previous_item = get_previous_item(
|
||||||
'value': {
|
previous_contents=previous_contents, item=content
|
||||||
'text': bleach.clean(content['value']['text'])
|
)
|
||||||
}
|
previous_content = previous_item.get("value")
|
||||||
}
|
|
||||||
elif content['type'] == 'content_list_item':
|
|
||||||
if content.get('id') is not None: # the list block existed already
|
|
||||||
previous_item = get_previous_item(previous_contents=previous_contents, item=content)
|
|
||||||
previous_content = previous_item.get('value')
|
|
||||||
else:
|
else:
|
||||||
previous_content = None
|
previous_content = None
|
||||||
value = [handle_content_block(c, context, module, previous_contents=previous_content) for c in
|
value = [
|
||||||
content['contents']]
|
handle_content_block(c, context, module, previous_contents=previous_content)
|
||||||
return {'type': 'content_list_item',
|
for c in content["contents"]
|
||||||
'value': value,
|
]
|
||||||
'id': content.get('id')}
|
content_type = "content_list_item"
|
||||||
elif content['type'] == 'readonly' and previous_contents is not None:
|
return get_content_dict(content_type=content_type, id=id, value=value)
|
||||||
|
elif content["type"] == "readonly" and previous_contents is not None:
|
||||||
# get first item that matches the id
|
# get first item that matches the id
|
||||||
# users can re-order readonly items, but we won't let them change them otherwise, so we just take the
|
# users can re-order readonly items, but we won't let them change them otherwise, so we just take the
|
||||||
# item from before and ignore anything else
|
# item from before and ignore anything else
|
||||||
previous_item = get_previous_item(previous_contents=previous_contents, item=content)
|
previous_item = get_previous_item(
|
||||||
|
previous_contents=previous_contents, item=content
|
||||||
|
)
|
||||||
if previous_item is None:
|
if previous_item is None:
|
||||||
raise ContentTypeException('Readonly item found that is not allowed here')
|
raise ContentTypeException("Readonly item found that is not allowed here")
|
||||||
return previous_item
|
return previous_item
|
||||||
|
|
||||||
raise ContentTypeException('Type did not match a case')
|
raise ContentTypeException("Type did not match a case")
|
||||||
|
|
||||||
|
|
||||||
def set_user_defined_block_type(block_type):
|
def set_user_defined_block_type(block_type):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,284 @@
|
||||||
|
import pytest
|
||||||
|
from api.utils import get_object
|
||||||
|
from assignments.models import Assignment
|
||||||
|
from books.factories import ChapterFactory, ContentBlockFactory, ModuleFactory
|
||||||
|
from books.models.contentblock import ContentBlock
|
||||||
|
from core.logger import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
|
add_mutation = """
|
||||||
|
mutation AddContentBlock($input: AddContentBlockInput!) {
|
||||||
|
addContentBlock(input: $input) {
|
||||||
|
newContentBlock {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
errors
|
||||||
|
clientMutationId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
update_mutation = """
|
||||||
|
mutation MutateContentBlock($input: MutateContentBlockInput!) {
|
||||||
|
mutateContentBlock(input: $input) {
|
||||||
|
contentBlock {
|
||||||
|
id
|
||||||
|
contents
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def create_block_input(content_type, value):
|
||||||
|
return {
|
||||||
|
"contents": {
|
||||||
|
"type": content_type,
|
||||||
|
"value": value,
|
||||||
|
},
|
||||||
|
"title": "some title",
|
||||||
|
"type": "NORMAL",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("create_users")
|
||||||
|
class TestCreateCustomContentBlock:
|
||||||
|
def _add_content_block(self, client, input):
|
||||||
|
module = ModuleFactory()
|
||||||
|
chapter = ChapterFactory(parent=module)
|
||||||
|
content_block = ContentBlockFactory(parent=chapter, module=module)
|
||||||
|
after = content_block.graphql_id
|
||||||
|
logger.info(after)
|
||||||
|
result = client.execute(
|
||||||
|
add_mutation,
|
||||||
|
variables={
|
||||||
|
"input": {
|
||||||
|
"contentBlock": input,
|
||||||
|
"after": after,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert result.errors is None
|
||||||
|
assert result.data.get("addContentBlock", None).get("errors", None) is None
|
||||||
|
assert ContentBlock.objects.count() == 2
|
||||||
|
new_content_block_data = result.data.get("addContentBlock").get(
|
||||||
|
"newContentBlock"
|
||||||
|
)
|
||||||
|
new_block_id = new_content_block_data.get("id")
|
||||||
|
new_content_block = get_object(ContentBlock, new_block_id)
|
||||||
|
return new_content_block
|
||||||
|
|
||||||
|
def _update_content_block(self, client, input):
|
||||||
|
update_result = client.execute(update_mutation, variables=input)
|
||||||
|
assert update_result.errors is None
|
||||||
|
assert ContentBlock.objects.count() == 2
|
||||||
|
updated_content_block_id = (
|
||||||
|
update_result.data.get("mutateContentBlock").get("contentBlock").get("id")
|
||||||
|
)
|
||||||
|
updated_content_block = get_object(ContentBlock, updated_content_block_id)
|
||||||
|
return updated_content_block
|
||||||
|
|
||||||
|
def test_add_custom_content_block(self, teacher, get_client):
|
||||||
|
content_block_title = "A new Custom Content Block"
|
||||||
|
content_block_input = {
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"type": "text_block",
|
||||||
|
"value": {"text": "<p>Some nested text</p>"},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "content_list_item",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": content_block_title,
|
||||||
|
"type": "NORMAL",
|
||||||
|
}
|
||||||
|
client = get_client(teacher)
|
||||||
|
new_content_block = self._add_content_block(
|
||||||
|
client=client, input=content_block_input
|
||||||
|
)
|
||||||
|
assert new_content_block.title == content_block_title
|
||||||
|
content_list_content = new_content_block.contents.raw_data[0]
|
||||||
|
logger.debug(content_list_content)
|
||||||
|
content_list_id = content_list_content.get("id")
|
||||||
|
assert content_list_id is not None
|
||||||
|
text_content = content_list_content.get("value")[0]
|
||||||
|
text_id = text_content.get("id")
|
||||||
|
assert text_id is not None
|
||||||
|
|
||||||
|
update_input = {
|
||||||
|
"input": {
|
||||||
|
"contentBlock": {
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"type": "text_block",
|
||||||
|
"id": text_id,
|
||||||
|
"value": {"text": "<p>Some nested text</p>"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_block",
|
||||||
|
"value": {"text": "<p>Second nested text</p>"},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"id": content_list_id,
|
||||||
|
"type": "content_list_item",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": content_block_title,
|
||||||
|
"type": "NORMAL",
|
||||||
|
},
|
||||||
|
"id": new_content_block.graphql_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updated_content_block = self._update_content_block(client, update_input)
|
||||||
|
updated_content_list_content = updated_content_block.contents.raw_data[0]
|
||||||
|
updated_content_list_id = updated_content_list_content.get("id")
|
||||||
|
assert content_list_id == updated_content_list_id
|
||||||
|
updated_text_content = updated_content_list_content.get("value")[0]
|
||||||
|
updated_text_id = updated_text_content.get("id")
|
||||||
|
assert text_id == updated_text_id
|
||||||
|
added_text_content = updated_content_list_content.get("value")[1]
|
||||||
|
assert added_text_content.get("id") is not None
|
||||||
|
assert (
|
||||||
|
added_text_content.get("value").get("text") == "<p>Second nested text</p>"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_add_text_block_should_get_id(self, teacher, get_client):
|
||||||
|
client = get_client(teacher)
|
||||||
|
content_block_title = "A new Custom Content Block"
|
||||||
|
content_block_input = {
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"value": {"text": "Some text"},
|
||||||
|
"type": "text_block",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": content_block_title,
|
||||||
|
"type": "NORMAL",
|
||||||
|
}
|
||||||
|
new_content_block = self._add_content_block(
|
||||||
|
client=client, input=content_block_input
|
||||||
|
)
|
||||||
|
assert new_content_block.title == content_block_title
|
||||||
|
text_block = new_content_block.contents.raw_data[0]
|
||||||
|
text_id = text_block.get("id")
|
||||||
|
assert text_id is not None
|
||||||
|
|
||||||
|
update_input = {
|
||||||
|
"input": {
|
||||||
|
"contentBlock": {
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"id": text_id,
|
||||||
|
"type": "text_block",
|
||||||
|
"value": {"text": "<p>ein text</p>"},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": content_block_title,
|
||||||
|
"type": "NORMAL",
|
||||||
|
},
|
||||||
|
"id": new_content_block.graphql_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updated_content_block = self._update_content_block(client, update_input)
|
||||||
|
updated_text = updated_content_block.contents.raw_data[0]
|
||||||
|
assert updated_text.get("id") == text_id
|
||||||
|
|
||||||
|
def test_add_text_block(self, teacher, get_client):
|
||||||
|
content_type = "text_block"
|
||||||
|
value = {"text": "<p>some text</p>"}
|
||||||
|
client = get_client(teacher)
|
||||||
|
input = create_block_input(content_type=content_type, value=value)
|
||||||
|
new_content_block = self._add_content_block(client=client, input=input)
|
||||||
|
text_block = new_content_block.contents.raw_data[0]
|
||||||
|
assert text_block.get("id") is not None
|
||||||
|
assert text_block.get("value").get("text") == value.get("text")
|
||||||
|
|
||||||
|
def test_add_assignment(self, teacher, get_client):
|
||||||
|
content_type = "assignment"
|
||||||
|
value = {"title": "Assignment title", "assignment": "Assignment text"}
|
||||||
|
client = get_client(teacher)
|
||||||
|
input = create_block_input(content_type=content_type, value=value)
|
||||||
|
new_content_block = self._add_content_block(client=client, input=input)
|
||||||
|
assignment_block = new_content_block.contents.raw_data[0]
|
||||||
|
logger.debug(assignment_block)
|
||||||
|
assert assignment_block.get("id") is not None
|
||||||
|
assert assignment_block.get("value").get("assignment_id") is not None
|
||||||
|
assert Assignment.objects.count() == 1
|
||||||
|
assignment = Assignment.objects.get(
|
||||||
|
pk=assignment_block.get("value").get("assignment_id")
|
||||||
|
)
|
||||||
|
assert assignment.title == value.get("title")
|
||||||
|
assert assignment.assignment == value.get("assignment")
|
||||||
|
|
||||||
|
def test_add_image_block(self, teacher, get_client):
|
||||||
|
content_type = "image_url_block"
|
||||||
|
value = {"url": "https://hep-verlag.ch/some-image"}
|
||||||
|
client = get_client(teacher)
|
||||||
|
input = create_block_input(content_type=content_type, value=value)
|
||||||
|
new_content_block = self._add_content_block(client=client, input=input)
|
||||||
|
image_block = new_content_block.contents.raw_data[0]
|
||||||
|
assert image_block.get("id") is not None
|
||||||
|
assert image_block.get("value").get("url") == value.get("url")
|
||||||
|
|
||||||
|
def test_add_link_block(self, teacher, get_client):
|
||||||
|
content_type = "link_block"
|
||||||
|
value = {"text": "link of the text", "url": "https://hep-verlag.ch/some-image"}
|
||||||
|
client = get_client(teacher)
|
||||||
|
input = create_block_input(content_type=content_type, value=value)
|
||||||
|
new_content_block = self._add_content_block(client=client, input=input)
|
||||||
|
link_block = new_content_block.contents.raw_data[0]
|
||||||
|
assert link_block.get("id") is not None
|
||||||
|
assert link_block.get("value").get("text") == value.get("text")
|
||||||
|
assert link_block.get("value").get("url") == value.get("url")
|
||||||
|
|
||||||
|
def test_add_video_block(self, teacher, get_client):
|
||||||
|
content_type = "video_block"
|
||||||
|
value = {"url": "https://hep-verlag.ch/some-video"}
|
||||||
|
client = get_client(teacher)
|
||||||
|
input = create_block_input(content_type=content_type, value=value)
|
||||||
|
new_content_block = self._add_content_block(client=client, input=input)
|
||||||
|
video_block = new_content_block.contents.raw_data[0]
|
||||||
|
assert video_block.get("id") is not None
|
||||||
|
assert video_block.get("value").get("url") == value.get("url")
|
||||||
|
|
||||||
|
def test_add_document_block(self, teacher, get_client):
|
||||||
|
content_type = "document_block"
|
||||||
|
value = {"url": "https://hep-verlag.ch/some-document"}
|
||||||
|
client = get_client(teacher)
|
||||||
|
input = create_block_input(content_type=content_type, value=value)
|
||||||
|
new_content_block = self._add_content_block(client=client, input=input)
|
||||||
|
document_block = new_content_block.contents.raw_data[0]
|
||||||
|
assert document_block.get("id") is not None
|
||||||
|
assert document_block.get("value").get("url") == value.get("url")
|
||||||
|
|
||||||
|
def test_add_subtitle(self, teacher, get_client):
|
||||||
|
content_type = "subtitle"
|
||||||
|
value = {"text": "some subtitle"}
|
||||||
|
client = get_client(teacher)
|
||||||
|
input = create_block_input(content_type=content_type, value=value)
|
||||||
|
new_content_block = self._add_content_block(client=client, input=input)
|
||||||
|
subtitle_block = new_content_block.contents.raw_data[0]
|
||||||
|
assert subtitle_block.get("id") is not None
|
||||||
|
assert subtitle_block.get("value").get("text") == value.get("text")
|
||||||
|
|
||||||
|
# def test_add_readonly(self):
|
||||||
|
# content_type = "readonly"
|
||||||
|
# value = {"text": "some subtitle"}
|
||||||
|
# client = get_client(teacher)
|
||||||
|
# input = create_block_input(content_type=content_type, value=value)
|
||||||
|
# new_content_block = self._add_content_block(client=client, input=input)
|
||||||
|
# subtitle_block = new_content_block.contents.raw_data[0]
|
||||||
|
# assert subtitle_block.get("id") is not None
|
||||||
|
# assert subtitle_block.get("value").get("text") == value.get("text")
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
from django.test import RequestFactory
|
||||||
|
from graphene.test import Client
|
||||||
|
from graphql_relay import to_global_id
|
||||||
|
|
||||||
|
from api.schema import schema
|
||||||
|
from books.factories import ModuleFactory
|
||||||
|
from books.models import Chapter, ContentBlock
|
||||||
|
from core.tests.base_test import SkillboxTestCase
|
||||||
|
from users.models import User, SchoolClass
|
||||||
|
|
||||||
|
|
||||||
|
class CustomContentTestCase(SkillboxTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.module = ModuleFactory()
|
||||||
|
self.chapter = Chapter(title="Hello")
|
||||||
|
self.module.add_child(instance=self.chapter)
|
||||||
|
self.createDefault()
|
||||||
|
content_block = ContentBlock(title="bla", slug="bla")
|
||||||
|
self.chapter_id = to_global_id("ChapterNode", self.chapter.id)
|
||||||
|
self.chapter.specific.add_child(instance=content_block)
|
||||||
|
self.user = User.objects.get(username="teacher")
|
||||||
|
school_class2 = SchoolClass.objects.get(name="second_class")
|
||||||
|
school_class2.users.add(self.user)
|
||||||
|
school_class2.save()
|
||||||
|
|
||||||
|
request = RequestFactory().get("/")
|
||||||
|
request.user = self.user
|
||||||
|
assert content_block.id is not None
|
||||||
|
self.content_block_id = to_global_id("ContentBlockNode", content_block.id)
|
||||||
|
|
||||||
|
self.client = Client(schema=schema, context_value=request)
|
||||||
|
|
||||||
|
def test_custom_content_blocks(self):
|
||||||
|
self.assertEqual(self.user.school_classes.count(), 2)
|
||||||
|
chapterQuery = """
|
||||||
|
query ChapterQuery($id: ID!) {
|
||||||
|
chapter(id: $id) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
contentBlocks {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
result = self.get_client().execute(
|
||||||
|
chapterQuery, variables={"id": self.chapter_id}
|
||||||
|
)
|
||||||
|
self.assertIsNone(result.errors)
|
||||||
|
self.assertEqual(len(result.data.get("chapter").get("contentBlocks")), 1)
|
||||||
|
|
||||||
|
custom_content_block = ContentBlock(
|
||||||
|
title="own", slug="own", user_created=True, owner=self.user
|
||||||
|
)
|
||||||
|
self.chapter.specific.add_child(instance=custom_content_block)
|
||||||
|
result = self.get_client().execute(
|
||||||
|
chapterQuery, variables={"id": self.chapter_id}
|
||||||
|
)
|
||||||
|
self.assertEqual(len(result.data.get("chapter").get("contentBlocks")), 2)
|
||||||
|
|
||||||
|
for school_class in self.user.school_classes.all():
|
||||||
|
custom_content_block.visible_for.add(school_class)
|
||||||
|
|
||||||
|
result = self.get_client().execute(
|
||||||
|
chapterQuery, variables={"id": self.chapter_id}
|
||||||
|
)
|
||||||
|
self.assertEqual(len(result.data.get("chapter").get("contentBlocks")), 2)
|
||||||
|
|
||||||
|
def test_mutate_own_content_block(self):
|
||||||
|
query = """
|
||||||
|
query ContentBlockQuery($id: ID!) {
|
||||||
|
contentBlock(id: $id) {
|
||||||
|
contents
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = self.get_client().execute(query, variables={"id": self.content_block_id})
|
||||||
|
self.assertIsNone(res.errors)
|
||||||
|
self.assertEqual(res.data["contentBlock"]["title"], "bla")
|
||||||
|
|
||||||
|
mutation = """
|
||||||
|
mutation MutateContentBlock($input: MutateContentBlockInput!) {
|
||||||
|
mutateContentBlock(input: $input) {
|
||||||
|
contentBlock {
|
||||||
|
contents
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
new_content = {
|
||||||
|
"id": "",
|
||||||
|
"type": "text_block",
|
||||||
|
"value": {"text": "new text \n a new line"},
|
||||||
|
}
|
||||||
|
|
||||||
|
variables = {
|
||||||
|
"input": {
|
||||||
|
"id": self.content_block_id,
|
||||||
|
"contentBlock": {
|
||||||
|
"contents": [new_content],
|
||||||
|
"title": "new title",
|
||||||
|
"type": "NORMAL",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutation_result = self.get_client().execute(mutation, variables=variables)
|
||||||
|
self.assertIsNone(mutation_result.errors)
|
||||||
|
content_block = mutation_result.data["mutateContentBlock"]["contentBlock"]
|
||||||
|
self.assertEqual(content_block["title"], "new title")
|
||||||
|
self.assertEqual(
|
||||||
|
content_block["contents"][0]["value"]["text"],
|
||||||
|
"<p>new text</p>\n<p>a new line</p>",
|
||||||
|
)
|
||||||
|
|
||||||
|
content_with_list = {
|
||||||
|
"id": "",
|
||||||
|
"type": "text_block",
|
||||||
|
"value": {"text": "<ul><li>Hallo</li><li>Velo</li></ul>"},
|
||||||
|
}
|
||||||
|
other_variables = {
|
||||||
|
"input": {
|
||||||
|
"id": self.content_block_id,
|
||||||
|
"contentBlock": {
|
||||||
|
"contents": [content_with_list],
|
||||||
|
"title": "title for list content",
|
||||||
|
"type": "NORMAL",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_mutation_result = self.get_client().execute(
|
||||||
|
mutation, variables=other_variables
|
||||||
|
)
|
||||||
|
self.assertIsNone(list_mutation_result.errors)
|
||||||
|
content_block = list_mutation_result.data["mutateContentBlock"]["contentBlock"]
|
||||||
|
self.assertEqual(content_block["title"], "title for list content")
|
||||||
|
self.assertEqual(
|
||||||
|
content_block["contents"][0]["value"]["text"],
|
||||||
|
"<ul><li>Hallo</li><li>Velo</li></ul>",
|
||||||
|
)
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
from django.test import TestCase, RequestFactory
|
|
||||||
from graphene.test import Client
|
|
||||||
from graphql_relay import to_global_id
|
|
||||||
|
|
||||||
from api.schema import schema
|
|
||||||
from books.factories import ModuleFactory
|
|
||||||
from books.models import Chapter, ContentBlock
|
|
||||||
from core.tests.base_test import SkillboxTestCase
|
|
||||||
from users.models import User, SchoolClass
|
|
||||||
from users.services import create_users
|
|
||||||
|
|
||||||
|
|
||||||
class OwnContentTestCase(SkillboxTestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.module = ModuleFactory()
|
|
||||||
self.chapter = Chapter(title='Hello')
|
|
||||||
self.module.add_child(instance=self.chapter)
|
|
||||||
self.createDefault()
|
|
||||||
content_block = ContentBlock(title='bla', slug='bla')
|
|
||||||
self.chapter_id = to_global_id('ChapterNode', self.chapter.id)
|
|
||||||
self.chapter.specific.add_child(instance=content_block)
|
|
||||||
self.user = User.objects.get(username='teacher')
|
|
||||||
school_class2 = SchoolClass.objects.get(name='second_class')
|
|
||||||
school_class2.users.add(self.user)
|
|
||||||
school_class2.save()
|
|
||||||
|
|
||||||
request = RequestFactory().get('/')
|
|
||||||
request.user = self.user
|
|
||||||
assert content_block.id is not None
|
|
||||||
self.content_block_id = to_global_id('ContentBlockNode', content_block.id)
|
|
||||||
|
|
||||||
self.client = Client(schema=schema, context_value=request)
|
|
||||||
|
|
||||||
def test_custom_content_blocks(self):
|
|
||||||
self.assertEqual(self.user.school_classes.count(), 2)
|
|
||||||
chapterQuery = """
|
|
||||||
query ChapterQuery($id: ID!) {
|
|
||||||
chapter(id: $id) {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
contentBlocks {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
result = self.get_client().execute(chapterQuery, variables={
|
|
||||||
"id": self.chapter_id
|
|
||||||
})
|
|
||||||
self.assertIsNone(result.errors)
|
|
||||||
self.assertEqual(len(result.data.get('chapter').get('contentBlocks')), 1)
|
|
||||||
|
|
||||||
custom_content_block = ContentBlock(title='own', slug='own', user_created=True, owner=self.user)
|
|
||||||
self.chapter.specific.add_child(instance=custom_content_block)
|
|
||||||
result = self.get_client().execute(chapterQuery, variables={
|
|
||||||
"id": self.chapter_id
|
|
||||||
})
|
|
||||||
self.assertEqual(len(result.data.get('chapter').get('contentBlocks')), 2)
|
|
||||||
|
|
||||||
for school_class in self.user.school_classes.all():
|
|
||||||
custom_content_block.visible_for.add(school_class)
|
|
||||||
|
|
||||||
result = self.get_client().execute(chapterQuery, variables={
|
|
||||||
"id": self.chapter_id
|
|
||||||
})
|
|
||||||
self.assertEqual(len(result.data.get('chapter').get('contentBlocks')), 2)
|
|
||||||
|
|
||||||
def test_mutate_own_content_block(self):
|
|
||||||
query = """
|
|
||||||
query ContentBlockQuery($id: ID!) {
|
|
||||||
contentBlock(id: $id) {
|
|
||||||
contents
|
|
||||||
title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
res = self.get_client().execute(query, variables={'id': self.content_block_id})
|
|
||||||
self.assertIsNone(res.errors)
|
|
||||||
self.assertEqual(res.data['contentBlock']['title'], 'bla')
|
|
||||||
|
|
||||||
mutation = """
|
|
||||||
mutation MutateContentBlock($input: MutateContentBlockInput!) {
|
|
||||||
mutateContentBlock(input: $input) {
|
|
||||||
contentBlock {
|
|
||||||
contents
|
|
||||||
title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
new_content = {
|
|
||||||
'id': '',
|
|
||||||
'type': 'text_block',
|
|
||||||
'value': {
|
|
||||||
'text': 'new text \n a new line'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
variables = {
|
|
||||||
'input': {
|
|
||||||
'id': self.content_block_id,
|
|
||||||
'contentBlock': {
|
|
||||||
'contents': [
|
|
||||||
new_content
|
|
||||||
],
|
|
||||||
'title': 'new title',
|
|
||||||
'type': 'NORMAL'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutation_result = self.get_client().execute(mutation, variables=variables)
|
|
||||||
self.assertIsNone(mutation_result.errors)
|
|
||||||
content_block = mutation_result.data['mutateContentBlock']['contentBlock']
|
|
||||||
self.assertEqual(content_block['title'], 'new title')
|
|
||||||
self.assertEqual(content_block['contents'][0]['value']['text'], '<p>new text</p>\n<p>a new line</p>')
|
|
||||||
|
|
||||||
content_with_list = {
|
|
||||||
'id': '',
|
|
||||||
'type': 'text_block',
|
|
||||||
'value': {
|
|
||||||
'text': '<ul><li>Hallo</li><li>Velo</li></ul>'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
other_variables = {
|
|
||||||
'input': {
|
|
||||||
'id': self.content_block_id,
|
|
||||||
'contentBlock': {
|
|
||||||
'contents': [
|
|
||||||
content_with_list
|
|
||||||
],
|
|
||||||
'title': 'title for list content',
|
|
||||||
'type': 'NORMAL'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list_mutation_result = self.get_client().execute(mutation, variables=other_variables)
|
|
||||||
self.assertIsNone(list_mutation_result.errors)
|
|
||||||
content_block = list_mutation_result.data['mutateContentBlock']['contentBlock']
|
|
||||||
self.assertEqual(content_block['title'], 'title for list content')
|
|
||||||
self.assertEqual(content_block['contents'][0]['value']['text'], '<ul><li>Hallo</li><li>Velo</li></ul>')
|
|
||||||
Loading…
Reference in New Issue