diora-web/projects/tests.py
mrwnslz e5a170838b
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Has been cancelled
Projekte mit Preset Forschung: Quellen (Paper per DOI, Bücher, Folgen mit Zeitmarke, Artikel), Zitierschlüssel, BibTeX/CSL-Export, Markdown-Notizen mit [@key]; Ende-zu-Ende-verschlüsselt. Navigation: Projekte als Tab am Handy, Suche als Lupe; sw v141
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 20:14:17 +02:00

109 lines
5.5 KiB
Python

"""Projekte: the API (projects/views.py)."""
import json
from unittest.mock import patch
from django.contrib.auth.models import User
from django.core.cache import cache
from django.test import TestCase
from .models import Project, ProjectItem
from .views import doi_of
IV = 'a1' * 12
class Base(TestCase):
def setUp(self):
cache.clear()
self.user = User.objects.create_user(username='forscher', password='pw12345678')
self.client.force_login(self.user)
def post(self, url, body=None):
return self.client.post(url, json.dumps(body or {}), content_type='application/json')
def make(self, ct='name'):
return self.post('/projects/create/', {'preset': 'research', 'data_ct': ct, 'data_iv': IV}).json()['project']
class ProjectTests(Base):
def test_create_list_update(self):
p = self.make()
self.assertEqual(p['preset'], 'research')
r = self.client.get('/projects/').json()
self.assertEqual([x['id'] for x in r['projects']], [p['id']])
self.assertIn('research', r['presets'])
r = self.post(f"/projects/{p['id']}/", {'data_ct': 'neu', 'data_iv': 'b2' * 12, 'base_iv': IV})
self.assertEqual(r.json()['project']['data_ct'], 'neu')
# Written from an old state: refused with the current one.
r = self.post(f"/projects/{p['id']}/", {'data_ct': 'alt', 'data_iv': 'c3' * 12, 'base_iv': IV})
self.assertEqual((r.status_code, r.json()['project']['data_ct']), (409, 'neu'))
def test_bad_input(self):
self.assertEqual(self.post('/projects/create/', {'data_ct': 'x', 'data_iv': 'zz'}).status_code, 400)
self.assertEqual(self.post('/projects/create/', {'preset': 'nope', 'data_ct': 'x', 'data_iv': IV}).status_code, 400)
def test_only_ones_own(self):
p = self.make()
other = User.objects.create_user(username='andere', password='pw12345678')
self.client.force_login(other)
self.assertEqual(self.client.get(f"/projects/{p['id']}/").status_code, 404)
self.assertEqual(self.post(f"/projects/{p['id']}/items/add/", {'kind': 'note', 'data_ct': 'x', 'data_iv': IV}).status_code, 404)
self.assertEqual(self.client.get('/projects/').json()['projects'], [])
self.client.logout()
self.assertEqual(self.client.get('/projects/').status_code, 401)
def test_delete_takes_the_items(self):
p = self.make()
self.post(f"/projects/{p['id']}/items/add/", {'kind': 'note', 'data_ct': 'x', 'data_iv': IV})
self.post(f"/projects/{p['id']}/delete/")
self.assertEqual((Project.objects.count(), ProjectItem.objects.count()), (0, 0))
class ItemTests(Base):
def test_links_once_notes_many(self):
p = self.make()
url = f"/projects/{p['id']}/items/add/"
a = self.post(url, {'kind': 'book', 'ref': 12, 'data_ct': 'b', 'data_iv': IV}).json()
b = self.post(url, {'kind': 'book', 'ref': 12, 'data_ct': 'b2', 'data_iv': IV}).json()
self.assertEqual((a['existing'], b['existing'], a['item']['id']), (False, True, b['item']['id']))
self.post(url, {'kind': 'note', 'data_ct': 'n', 'data_iv': IV})
self.post(url, {'kind': 'note', 'ref': 5, 'data_ct': 'n', 'data_iv': IV}) # a note has no ref
self.post(url, {'kind': 'episode', 'ref': 7, 'data_ct': 'e', 'data_iv': IV})
self.assertEqual(self.post(url, {'kind': 'episode', 'data_ct': 'e', 'data_iv': IV}).status_code, 400)
got = self.client.get(f"/projects/{p['id']}/").json()
self.assertEqual([(i['kind'], i['ref']) for i in got['items']],
[('book', 12), ('note', None), ('note', None), ('episode', 7)])
links = self.client.get('/projects/').json()['links']
self.assertEqual(sorted((l['kind'], l['ref']) for l in links), [('book', 12), ('episode', 7)])
def test_update_with_base_and_delete(self):
p = self.make()
i = self.post(f"/projects/{p['id']}/items/add/", {'kind': 'note', 'data_ct': 'v1', 'data_iv': IV}).json()['item']
r = self.post(f"/projects/items/{i['id']}/", {'data_ct': 'v2', 'data_iv': 'b2' * 12, 'base_iv': IV})
self.assertEqual(r.status_code, 200)
r = self.post(f"/projects/items/{i['id']}/", {'data_ct': 'v3', 'data_iv': 'c3' * 12, 'base_iv': IV})
self.assertEqual((r.status_code, r.json()['item']['data_ct']), (409, 'v2'))
self.post(f"/projects/items/{i['id']}/delete/")
self.assertFalse(ProjectItem.objects.exists())
class DoiTests(Base):
def test_recognised(self):
self.assertEqual(doi_of('https://doi.org/10.1038/s41586-020-2649-2.'), '10.1038/s41586-020-2649-2')
self.assertEqual(doi_of('https://arxiv.org/abs/2401.01234v2'), '10.48550/arXiv.2401.01234')
self.assertEqual(doi_of('2401.01234'), '10.48550/arXiv.2401.01234')
self.assertIsNone(doi_of('kein doi'))
def test_lookup_trimmed_and_cached(self):
class R:
status_code = 200
def json(self):
return {'title': 'Ein Paper', 'DOI': '10.1234/x', 'reference': [1, 2, 3], 'author': [{'family': 'A'}]}
with patch('projects.views.requests.get', return_value=R()) as get:
a = self.client.get('/projects/doi/', {'q': 'doi:10.1234/x'}).json()
self.client.get('/projects/doi/', {'q': '10.1234/X'})
self.assertEqual(get.call_count, 1)
self.assertEqual(a['csl']['title'], 'Ein Paper')
self.assertNotIn('reference', a['csl'])
self.assertEqual(self.client.get('/projects/doi/', {'q': 'nichts'}).status_code, 400)