109 lines
5.5 KiB
Python
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)
|