2026-05-12 11:03:11 +10:00

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"), [])