from django.test import TestCase, 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 users.models import User, SchoolClass from users.services import create_users MODULE_QUERY = """ query ModulesQuery($slug: String!) { module(slug: $slug) { id title chapters { edges { node { id contentBlocks { edges { node { id title visibleFor { edges { node { name } } } hiddenFor { edges { node { name } } } } } } } } } } } """ CREATE_SNAPSHOT_MUTATION = """ mutation CreateSnapshot($input: CreateSnapshotInput!) { createSnapshot(input: $input) { snapshot { id created creator { username } snapshotChapters { edges { node { id descriptionHidden titleHidden title description contentBlocks { edges { node { id title } } } } } } } 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 } } } } """ def edges_to_array(entity): return [edge['node'] for edge in entity.get('edges')] class CreateSnapshotTestCase(TestCase): def setUp(self): create_users() # teacher will create snapshot self.slug = 'some-module' self.teacher = User.objects.get(username='teacher') 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) request = RequestFactory().get('/') request.user = self.teacher self.client = Client(schema=schema, context_value=request) # we make a snapshot S of the module M # snapshot S looks like module M for school class X 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 = edges_to_array(module.get('chapters'))[0] self.assertIsNotNone(chapter) content_blocks = edges_to_array(chapter.get('contentBlocks')) content_block_titles = [node['title'] for node 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_node = [node for node in content_blocks if node['title'] == self.title_hidden][0] custom_node = [node for node in content_blocks if node['title'] == self.title_custom][0] # check if hidden node is hidden for this school class self.assertTrue( school_class_name in [school_class['name'] for school_class in edges_to_array(hidden_node.get('hiddenFor'))]) # check if the custom node is visible for this school class self.assertTrue( school_class_name in [school_class['name'] for school_class in edges_to_array(custom_node.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('snapshotChapters').get('edges')[0]['node'] self.assertIsNotNone(snapshot.get('created')) self.assertEqual(snapshot.get('creator').get('username'), self.teacher.username) 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 = [edge['node'] for edge in chapter['contentBlocks']['edges']] self.assertEqual(len(content_blocks), 2) self.assertEqual(content_blocks[0]['title'], self.title_visible) self.assertEqual(content_blocks[1]['title'], self.title_custom) self.assertEqual(ChapterSnapshot.objects.count(), 2) 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) 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')