214 lines
6.8 KiB
Python
214 lines
6.8 KiB
Python
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"), [])
|