391 lines
15 KiB
Python
391 lines
15 KiB
Python
from django.test import RequestFactory
|
|
from graphene.test import Client
|
|
from graphql_relay import to_global_id, from_global_id
|
|
|
|
from api.schema import schema
|
|
from books.factories import ModuleFactory, ChapterFactory, ContentBlockFactory
|
|
from books.models import Snapshot, ChapterSnapshot
|
|
from core.tests.base_test import SkillboxTestCase
|
|
from objectives.factories import ObjectiveGroupFactory, ObjectiveFactory
|
|
from users.factories import SchoolClassFactory
|
|
from users.models import User, SchoolClass
|
|
|
|
MODULE_QUERY = """
|
|
query ModulesQuery($slug: String, $id: ID) {
|
|
module(slug: $slug, id: $id) {
|
|
id
|
|
title
|
|
objectiveGroups {
|
|
objectives {
|
|
id
|
|
text
|
|
hiddenFor {
|
|
name
|
|
}
|
|
visibleFor {
|
|
name
|
|
}
|
|
}
|
|
}
|
|
chapters {
|
|
id
|
|
contentBlocks {
|
|
id
|
|
title
|
|
visibleFor {
|
|
name
|
|
}
|
|
hiddenFor {
|
|
name
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"""
|
|
|
|
CREATE_SNAPSHOT_MUTATION = """
|
|
mutation CreateSnapshot($input: CreateSnapshotInput!) {
|
|
createSnapshot(input: $input) {
|
|
snapshot {
|
|
id
|
|
created
|
|
creator
|
|
objectiveGroups {
|
|
objectives {
|
|
text
|
|
hidden
|
|
}
|
|
}
|
|
chapters {
|
|
id
|
|
descriptionHidden
|
|
titleHidden
|
|
title
|
|
description
|
|
contentBlocks {
|
|
id
|
|
title
|
|
hidden
|
|
}
|
|
}
|
|
}
|
|
success
|
|
}
|
|
}
|
|
"""
|
|
APPLY_SNAPSHOT_MUTATION = """
|
|
mutation ApplySnapshot($input: ApplySnapshotInput!) {
|
|
applySnapshot(input: $input) {
|
|
success
|
|
}
|
|
}
|
|
"""
|
|
|
|
SNAPSHOT_MODULE_QUERY = """
|
|
query SnapshotDetail($id: ID!) {
|
|
snapshot(id: $id) {
|
|
id
|
|
chapters {
|
|
id
|
|
description
|
|
title
|
|
titleHidden
|
|
descriptionHidden
|
|
contentBlocks {
|
|
id
|
|
title
|
|
hidden
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"""
|
|
|
|
SHARE_SNAPSHOT_MUTATION = """
|
|
mutation ShareSnapshot($input: ShareSnapshotInput!) {
|
|
shareSnapshot(input: $input) {
|
|
success
|
|
snapshot {
|
|
shared
|
|
}
|
|
}
|
|
}
|
|
"""
|
|
|
|
MODULE_SNAPSHOTS_QUERY = """
|
|
query SnapshotQuery($slug: String!) {
|
|
module(slug: $slug) {
|
|
snapshots {
|
|
id
|
|
title
|
|
created
|
|
creator
|
|
}
|
|
}
|
|
}
|
|
"""
|
|
|
|
|
|
def edges_to_array(entity):
|
|
return [edge['node'] for edge in entity.get('edges')]
|
|
|
|
|
|
class CreateSnapshotTestCase(SkillboxTestCase):
|
|
def setUp(self):
|
|
self.createDefault()
|
|
self.client = self.get_client()
|
|
# teacher will create snapshot
|
|
self.slug = 'some-module'
|
|
|
|
self.module = ModuleFactory(slug=self.slug)
|
|
self.skillbox_class = SchoolClass.objects.get(name='skillbox')
|
|
|
|
# module M has a chapter
|
|
self.chapter = ChapterFactory(parent=self.module, slug='some-chapter')
|
|
ChapterFactory(parent=self.module, slug='some-other-chapter')
|
|
|
|
# chapter has some content blocks a, b, c
|
|
self.title_visible = 'visible'
|
|
self.title_hidden = 'hidden'
|
|
self.title_custom = 'custom'
|
|
self.visible_content_block = ContentBlockFactory(parent=self.chapter, module=self.module,
|
|
title=self.title_visible, slug='cb-a')
|
|
self.hidden_content_block = ContentBlockFactory(parent=self.chapter, module=self.module,
|
|
title=self.title_hidden, slug='cb-b')
|
|
# content block c is user created
|
|
self.custom_content_block = ContentBlockFactory(parent=self.chapter, owner=self.teacher, user_created=True,
|
|
module=self.module, title=self.title_custom,
|
|
slug='cb-c')
|
|
# content block a and c are visible to school class X
|
|
self.hidden_content_block.hidden_for.add(self.skillbox_class)
|
|
self.custom_content_block.visible_for.add(self.skillbox_class)
|
|
|
|
# chapter description is hidden for school class X
|
|
self.chapter.title_hidden_for.add(self.skillbox_class)
|
|
|
|
# we make a snapshot S of the module M
|
|
# snapshot S looks like module M for school class X
|
|
|
|
objective_group = ObjectiveGroupFactory(module=self.module)
|
|
self.visible_objective = ObjectiveFactory(text='visible-objective', group=objective_group)
|
|
self.hidden_objective = ObjectiveFactory(text='hidden-objective', group=objective_group)
|
|
self.custom_objective = ObjectiveFactory(text='custom-objective', group=objective_group, owner=self.teacher)
|
|
|
|
self.hidden_objective.hidden_for.add(self.skillbox_class)
|
|
self.custom_objective.visible_for.add(self.skillbox_class)
|
|
|
|
def _test_module_visibility(self, client, school_class_name):
|
|
result = client.execute(MODULE_QUERY, variables={
|
|
'slug': self.module.slug
|
|
})
|
|
self.assertIsNone(result.get('errors'))
|
|
module = result.get('data').get('module')
|
|
chapter = module.get('chapters')[0]
|
|
self.assertIsNotNone(chapter)
|
|
content_blocks = chapter.get('contentBlocks')
|
|
content_block_titles = [content_block['title'] for content_block in content_blocks]
|
|
self.assertTrue(self.title_visible in content_block_titles)
|
|
self.assertTrue(self.title_hidden in content_block_titles)
|
|
self.assertTrue(self.title_custom in content_block_titles)
|
|
hidden_content_block = [content_block for content_block in content_blocks if
|
|
content_block['title'] == self.title_hidden][0]
|
|
custom_content_block = [content_block for content_block in content_blocks if
|
|
content_block['title'] == self.title_custom][0]
|
|
# check if hidden content block is hidden for this school class
|
|
self.assertTrue(
|
|
school_class_name in [school_class['name'] for school_class in
|
|
hidden_content_block.get('hiddenFor')])
|
|
# check if the custom content block is visible for this school class
|
|
self.assertTrue(
|
|
school_class_name in [school_class['name'] for school_class in
|
|
custom_content_block.get('visibleFor')])
|
|
|
|
objectives = module['objectiveGroups'][0]['objectives']
|
|
|
|
self.assertEqual(len(objectives), 3)
|
|
|
|
hidden_objective = [objective for objective in objectives if
|
|
objective['text'] == self.hidden_objective.text][0]
|
|
custom_objective = [objective for objective in objectives if
|
|
objective['text'] == self.custom_objective.text][0]
|
|
|
|
# check if hidden objective is hidden for this school class
|
|
self.assertTrue(
|
|
school_class_name in [school_class['name'] for school_class in
|
|
hidden_objective.get('hiddenFor')])
|
|
# check if the custom objective is visible for this school class
|
|
self.assertTrue(
|
|
school_class_name in [school_class['name'] for school_class in
|
|
custom_objective.get('visibleFor')])
|
|
|
|
def test_setup(self):
|
|
# make sure everything is setup correctly
|
|
self._test_module_visibility(self.client, 'skillbox')
|
|
|
|
def test_create_snapshot(self):
|
|
result = self.client.execute(CREATE_SNAPSHOT_MUTATION, variables={
|
|
'input': {
|
|
'module': self.slug,
|
|
'selectedClass': to_global_id('SchoolClassNode', self.skillbox_class.pk),
|
|
}
|
|
})
|
|
self.assertIsNone(result.get('errors'))
|
|
snapshot = result.get('data').get('createSnapshot').get('snapshot')
|
|
chapter = snapshot.get('chapters')[0]
|
|
|
|
self.assertIsNotNone(snapshot.get('created'))
|
|
self.assertEqual(snapshot.get('creator'), f'{self.teacher.first_name} {self.teacher.last_name}')
|
|
|
|
self.assertTrue(chapter['titleHidden'])
|
|
self.assertFalse(chapter['descriptionHidden'])
|
|
_, chapter_id = from_global_id(chapter['id'])
|
|
self.assertEqual(int(chapter_id), self.chapter.id)
|
|
|
|
content_blocks = chapter['contentBlocks']
|
|
self.assertEqual(len(content_blocks), 3)
|
|
visible, hidden, custom = content_blocks
|
|
self.assertEqual(visible['title'], self.title_visible)
|
|
self.assertEqual(visible['hidden'], False)
|
|
self.assertEqual(hidden['title'], self.title_hidden)
|
|
self.assertEqual(hidden['hidden'], True)
|
|
self.assertEqual(custom['title'], self.title_custom)
|
|
self.assertEqual(custom['hidden'], False)
|
|
self.assertEqual(ChapterSnapshot.objects.count(), 2)
|
|
|
|
visible, hidden, custom = snapshot['objectiveGroups'][0]['objectives']
|
|
self.assertEqual(visible['text'], self.visible_objective.text)
|
|
self.assertEqual(visible['hidden'], False)
|
|
self.assertEqual(hidden['text'], self.hidden_objective.text)
|
|
self.assertEqual(hidden['hidden'], True)
|
|
self.assertEqual(custom['text'], self.custom_objective.text)
|
|
self.assertEqual(custom['hidden'], False)
|
|
|
|
|
|
def test_apply_snapshot(self):
|
|
self.snapshot = Snapshot.objects.create_snapshot(module=self.module, school_class=self.skillbox_class,
|
|
user=self.teacher)
|
|
self.assertEqual(Snapshot.objects.count(), 1)
|
|
self.assertEqual(self.snapshot.custom_objectives.count(), 1)
|
|
school_class_name = 'second_class'
|
|
second_class = SchoolClass.objects.get(name=school_class_name)
|
|
request = RequestFactory().get('/')
|
|
teacher2 = User.objects.get(username='teacher2')
|
|
request.user = teacher2
|
|
client = Client(schema=schema, context_value=request)
|
|
result = client.execute(APPLY_SNAPSHOT_MUTATION, variables={
|
|
'input': {
|
|
'snapshot': to_global_id('SnapshotNode', self.snapshot.pk),
|
|
'selectedClass': to_global_id('SchoolClassNode', second_class.pk),
|
|
}
|
|
})
|
|
self.assertIsNone(result.get('errors'))
|
|
self._test_module_visibility(client, school_class_name)
|
|
|
|
def test_display_snapshot_module(self):
|
|
self.snapshot = Snapshot.objects.create_snapshot(module=self.module, school_class=self.skillbox_class,
|
|
user=self.teacher)
|
|
id = to_global_id('SnapshotNode', self.snapshot.id)
|
|
snapshot_result = self.client.execute(SNAPSHOT_MODULE_QUERY, variables={
|
|
'id': id
|
|
})
|
|
self.assertIsNone(snapshot_result.get('errors'))
|
|
snapshot = snapshot_result.get('data').get('snapshot')
|
|
chapters = snapshot.get('chapters')
|
|
self.assertEqual(len(chapters), 2)
|
|
chapter = chapters[0]
|
|
content_blocks = chapter.get('contentBlocks')
|
|
self.assertEqual(len(content_blocks), 3)
|
|
first, second, third = content_blocks
|
|
self.assertEqual(first['title'], 'visible')
|
|
self.assertEqual(second['title'], 'hidden')
|
|
self.assertEqual(second['hidden'], True)
|
|
self.assertEqual(third['title'], 'custom')
|
|
|
|
def test_apply_initial_snapshot(self):
|
|
teacher2 = User.objects.get(username='teacher2')
|
|
teacher2_client = self.get_client(user=teacher2)
|
|
third_class = SchoolClassFactory(
|
|
users=[teacher2],
|
|
name='third_class'
|
|
)
|
|
|
|
# make a neutral snapshot, nothing new, nothing hidden
|
|
result = teacher2_client.execute(CREATE_SNAPSHOT_MUTATION, variables={
|
|
'input': {
|
|
'module': self.slug,
|
|
'selectedClass': to_global_id('SchoolClassNode', third_class.pk),
|
|
}
|
|
})
|
|
self.assertIsNone(result.get('errors'))
|
|
snapshot_id = result['data']['createSnapshot']['snapshot']['id']
|
|
|
|
result = self.client.execute(APPLY_SNAPSHOT_MUTATION, variables={
|
|
'input': {
|
|
'snapshot': snapshot_id,
|
|
'selectedClass': to_global_id('SchoolClassNode', self.skillbox_class.pk),
|
|
}
|
|
})
|
|
self.assertIsNone(result.get('errors'))
|
|
|
|
result = self.client.execute(MODULE_QUERY, variables={
|
|
'slug': self.module.slug
|
|
})
|
|
self.assertIsNone(result.get('errors'))
|
|
module = result['data']['module']
|
|
chapter1, chapter2 = module['chapters']
|
|
cb1, cb2, cb3 = chapter1['contentBlocks']
|
|
self.assertTrue(self.skillbox_class.name not in [sc['name'] for sc in cb1['hiddenFor']])
|
|
self.assertTrue(self.skillbox_class.name not in [sc['name'] for sc in cb2['hiddenFor']])
|
|
self.assertTrue(self.skillbox_class.name not in [sc['name'] for sc in cb3['visibleFor']])
|
|
|
|
|
|
class SnapshotTestCase(SkillboxTestCase):
|
|
def setUp(self) -> None:
|
|
self.createDefault()
|
|
self.client = self.get_client()
|
|
self.slug = 'some-module'
|
|
|
|
self.teacher2 = User.objects.get(username='teacher2')
|
|
self.module = ModuleFactory(slug=self.slug)
|
|
self.skillbox_class = SchoolClass.objects.get(name='skillbox')
|
|
self.snapshot = Snapshot.objects.create_snapshot(module=self.module, school_class=self.skillbox_class,
|
|
user=self.teacher)
|
|
Snapshot.objects.create_snapshot(module=self.module, school_class=self.skillbox_class,
|
|
user=self.teacher2)
|
|
|
|
def test_show_only_own_snapshots(self):
|
|
result = self.client.execute(MODULE_SNAPSHOTS_QUERY, variables={
|
|
"slug": self.slug
|
|
})
|
|
self.assertIsNone(result.get('errors'))
|
|
snapshots = result['data']['module']['snapshots']
|
|
self.assertEqual(len(snapshots), 1)
|
|
self.assertEqual(snapshots[0]['creator'], f'{self.teacher.first_name} {self.teacher.last_name}')
|
|
|
|
def test_share_snapshot(self):
|
|
self.assertFalse(self.snapshot.shared)
|
|
result = self.client.execute(SHARE_SNAPSHOT_MUTATION, variables={
|
|
'input': {
|
|
'snapshot': to_global_id('Snapshot', self.snapshot.id),
|
|
'shared': True
|
|
}
|
|
})
|
|
self.assertIsNone(result.get('errors'))
|
|
data = result['data']['shareSnapshot']
|
|
self.assertTrue(data['success'])
|
|
self.assertTrue(data['snapshot']['shared'])
|
|
snapshot = Snapshot.objects.get(pk=self.snapshot.pk)
|
|
self.assertTrue(snapshot.shared)
|
|
|
|
def test_dont_share_foreign_snapshot(self):
|
|
self.assertFalse(self.snapshot.shared)
|
|
teacher2_client = self.get_client(self.teacher2)
|
|
result = teacher2_client.execute(SHARE_SNAPSHOT_MUTATION, variables={
|
|
'input': {
|
|
'snapshot': to_global_id('Snapshot', self.snapshot.id),
|
|
'shared': True
|
|
}
|
|
})
|
|
self.assertIsNotNone(result.get('errors'))
|