from interface.tests import AccessTestCase from byostorage.user import UserStorage from . import models from .views.api import WorkSerializer import tempfile import json class LibraryTestCase(AccessTestCase): USERS = ( {'username': 'admin', 'password': 'secret', 'is_superuser': True, 'is_staff': True}, {'username': 'homer', 'password': 'maggie'}, ) ENSEMBLES = ( {'name': 'The Be Sharps', 'slug': 'be-sharps', 'admins': ['homer']}, {'name': 'Lisa & the Bleeding Gums', 'slug': 'bleeding-gums'}, {'name': 'Party Posse'}, ) PROJECTS = ( {'name': 'Baker St', 'ensemble': 'bleeding-gums', 'when': -12}, {'name': 'Navy Recruitment Day', 'ensemble': 'party-posse', 'when': 6}, {'name': 'Barbershop Contest', 'ensemble': 'be-sharps', 'when': 28}, {'name': 'Open Mic Night', 'ensemble': 'bleeding-gums', 'when': 1 }, ) COLLECTIONS = ( {'name': 'Springfield Elementary Library', 'prefix': 'sel'}, {'name': 'Neds Library', 'prefix': 'ned', 'admins': ['homer']}, ) WORKS = ( {'name': 'Baby on Board', 'collection': 'ned', 'docs': [{'upload': 'local:baby_on_board.pdf'}]}, {'name': 'Star Spangled Banner', 'collection': 'sel'}, ) PROTECTED_URLS = ( '/collections/1', '/collections/1/add', '/collections/2/works/1', '/collections/2/works/1/edit', '/collections/2/works/1/partset', '/collections/2/works/1/add_to_project', '/collections/2/works/1/upload', '/collections/2/docs/1/annotate', # Need to add storage before we can test these '/api/collections/2', '/api/collections/2/works/1', '/admin/library/collection/', '/admin/library/document/', '/admin/library/ensembleaccess/', '/admin/library/orchestration/', '/admin/library/projectitem/', '/admin/library/work/', ) @classmethod def setUpTestData(cls): super().setUpTestData() cls.temp_dir = tempfile.TemporaryDirectory() cls.storage = UserStorage.objects.create(name='local', storage='django.core.files.storage.FileSystemStorage', settings_data=json.dumps({'location': cls.temp_dir.name, 'base_url': 'file://' + cls.temp_dir.name})) cls.collections = {} for details in cls.COLLECTIONS: admins = details.pop('admins', []) obj = models.Collection.objects.create(storage=cls.storage, **details) for admin in admins: obj.administrators.add(cls.users[admin]) cls.collections[details['prefix']] = obj cls.works = {} for details in cls.WORKS: collection = cls.collections[details.pop('collection')] #details.setdefault('docs', []) #details.setdefault('meta_info', []) #s = WorkSerializer(data=details) #assert s.is_valid(), s.errors #s.save(collection_id=collection.pk) docs = details.pop('docs', []) obj = models.Work.objects.create(collection=collection, **details) for doc in docs: obj.docs.create(**doc) cls.works[details['name']] = obj def setUp(self): pass @classmethod def tearDownClass(cls): cls.temp_dir.cleanup() def test_integration(self): pass def test_superuser_access(self): self.login('admin', 'secret') self.assertAccess({ '/collections': True, '/collections/1': True, '/collections/2/works/1': True, }) def test_administrator_access(self): self.login('homer', 'maggie') self.assertAccess({ '/collections': True, '/collections/1': False, '/collections/2': True, '/collections/2/works/1': True, }) def test_link_access(self): self.assertAccess({ '/collections': True, '/collections/1': False, '/collections/2': False, '/collections/2/works/1': False, }) self.authorize(models.Collection, pk=2) self.assertAccess({ '/collections': True, '/collections/1': False, '/collections/2': True, '/collections/2/works/1': True, }) def test_anon_access(self): self.assertAccess({ '/collections': True, '/collections/1': False, '/collections/2': False, '/collections/2/works/1': False, }) def test_export_and_import(self): self.login('admin', 'secret') data = self.client.get('/api/collections/1/works/2', HTTP_ACCEPT="application/json").json() response = self.client.post('/api/collections/2/import', data, "application/json") self.assertEqual(response.status_code, 201) def test_movement_from_large_work(self): ''' Will be common to store a work which has several movements, but the project is only going to play one. This also should give us the ability to store an anthology as one Work have Project reference 'no:23' ''' work = self.collections['sel'].works.create(name="Some Quartet", composer="Beethoven") for g in ('vl-1', 'vl-2', 'vla', 'vc'): doc = work.docs.create(upload=f'sel/beethoven/some_quartet/some_quartet_{g}.pdf') doc.sections.create(tag='mvmt-1', start=1, end=3) doc.sections.create(tag='mvmt-2', start=4, end=8) doc.sections.create(tag='mvmt-3', start=9, end=12) doc.sections.create(tag=g) # no tags - get nothing (should it be everything?) self.assertEqual(work.list_sections(), []) # single tag - should get just that range self.assertEqual(work.list_sections('vl-1'), [('sel/beethoven/some_quartet/some_quartet_vl-1.pdf', None, None)]) # single tag - returns all documents with that range result = work.list_sections('mvmt-2') self.assertEqual(len(result), 4) # multiple tags - returns the overlapping portion of all documents that have all tags self.assertEqual(work.list_sections('vl-1', 'mvmt-2'), [('sel/beethoven/some_quartet/some_quartet_vl-1.pdf', 4, 8)]) self.assertEqual(work.list_sections('vl-1', 'vl-2'), [])