mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
Refactoring: add tools to endpoint testing
This commit is contained in:
parent
a47d93a59b
commit
b549580452
|
@ -1,12 +1,12 @@
|
|||
''' Models: RSForm API. '''
|
||||
from typing import Dict, Iterable, Optional, cast
|
||||
from typing import Dict, Iterable, Optional, Union, cast
|
||||
|
||||
from django.db import transaction
|
||||
from django.db.models import QuerySet
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from cctext import Resolver, Entity, extract_entities, split_grams, TermForm
|
||||
from .api_RSLanguage import get_type_prefix, generate_structure
|
||||
from .api_RSLanguage import get_type_prefix, generate_structure, guess_type
|
||||
from .LibraryItem import LibraryItem, LibraryItemType
|
||||
from .Constituenta import CstType, Constituenta
|
||||
from .Version import Version
|
||||
|
@ -90,18 +90,27 @@ class RSForm:
|
|||
return result
|
||||
|
||||
@transaction.atomic
|
||||
def insert_new(self, alias: str, insert_type: CstType, position: int = _INSERT_LAST) -> Constituenta:
|
||||
def insert_new(
|
||||
self,
|
||||
alias: str,
|
||||
cst_type: Union[CstType, None] = None,
|
||||
position: int = _INSERT_LAST,
|
||||
**kwargs
|
||||
) -> Constituenta:
|
||||
''' Insert new constituenta at given position.
|
||||
All following constituents order is shifted by 1 position. '''
|
||||
if self.constituents().filter(alias=alias).exists():
|
||||
raise ValidationError(msg.aliasTaken(alias))
|
||||
position = self._get_insert_position(position)
|
||||
if cst_type is None:
|
||||
cst_type = guess_type(alias)
|
||||
self._shift_positions(position, 1)
|
||||
result = Constituenta.objects.create(
|
||||
schema=self.item,
|
||||
order=position,
|
||||
alias=alias,
|
||||
cst_type=insert_type
|
||||
cst_type=cst_type,
|
||||
**kwargs
|
||||
)
|
||||
self.item.save()
|
||||
result.refresh_from_db()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
''' Models: Definitions and utility function for RSLanguage. '''
|
||||
import json
|
||||
from typing import Tuple
|
||||
from typing import Tuple, cast
|
||||
from enum import IntEnum , unique
|
||||
|
||||
from django.db.models import TextChoices
|
||||
|
@ -54,6 +54,14 @@ def get_type_prefix(cst_type: CstType) -> str:
|
|||
return 'T'
|
||||
return 'X'
|
||||
|
||||
def guess_type(alias: str) -> CstType:
|
||||
''' Get CstType for alias. '''
|
||||
prefix = alias[0]
|
||||
for (value, _) in CstType.choices:
|
||||
if prefix == get_type_prefix(cast(CstType, value)):
|
||||
return cast(CstType, value)
|
||||
return CstType.BASE
|
||||
|
||||
def _get_structure_prefix(alias: str, expression: str, parse: dict) -> Tuple[str, str]:
|
||||
''' Generate prefix and alias for structure generation. '''
|
||||
args = parse['args']
|
||||
|
|
140
rsconcept/backend/apps/rsform/tests/s_views/EndpointTester.py
Normal file
140
rsconcept/backend/apps/rsform/tests/s_views/EndpointTester.py
Normal file
|
@ -0,0 +1,140 @@
|
|||
''' Utils: base tester class for endpoints. '''
|
||||
from rest_framework.test import APITestCase, APIRequestFactory, APIClient
|
||||
from rest_framework import status
|
||||
|
||||
from apps.users.models import User
|
||||
|
||||
|
||||
def decl_endpoint(endpoint: str, method: str):
|
||||
''' Decorator for EndpointTester methods to provide API attributes. '''
|
||||
def set_endpoint_inner(function):
|
||||
def wrapper(*args, **kwargs):
|
||||
if '{' in endpoint:
|
||||
args[0].endpoint = 'UNRESOLVED'
|
||||
args[0].endpoint_mask = endpoint
|
||||
else:
|
||||
args[0].endpoint_mask = None
|
||||
args[0].endpoint = endpoint
|
||||
args[0].method = method
|
||||
return function(*args, **kwargs)
|
||||
return wrapper
|
||||
return set_endpoint_inner
|
||||
|
||||
|
||||
class EndpointTester(APITestCase):
|
||||
''' Abstract base class for Testing endpoints. '''
|
||||
def setUp(self):
|
||||
self.factory = APIRequestFactory()
|
||||
self.user = User.objects.create(username='UserTest')
|
||||
self.client = APIClient()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
|
||||
def toggle_staff(self, value: bool = True):
|
||||
self.user.is_staff = value
|
||||
self.user.save()
|
||||
|
||||
def login(self):
|
||||
self.client.force_authenticate(user=self.user)
|
||||
|
||||
def logout(self):
|
||||
self.client.logout()
|
||||
|
||||
def set_params(self, **kwargs):
|
||||
''' Given named argument values resolve current endpoint_mask. '''
|
||||
if self.endpoint_mask and len(kwargs) > 0:
|
||||
self.endpoint = _resolve_url(self.endpoint_mask, **kwargs)
|
||||
|
||||
def get(self, endpoint: str = '', **kwargs):
|
||||
if endpoint != '':
|
||||
return self.client.get(endpoint)
|
||||
else:
|
||||
self.set_params(**kwargs)
|
||||
return self.client.get(self.endpoint)
|
||||
|
||||
def post(self, data=None, **kwargs):
|
||||
self.set_params(**kwargs)
|
||||
if not data is None:
|
||||
return self.client.post(self.endpoint, data=data, format='json')
|
||||
else:
|
||||
return self.client.post(self.endpoint)
|
||||
|
||||
def patch(self, data=None, **kwargs):
|
||||
self.set_params(**kwargs)
|
||||
if not data is None:
|
||||
return self.client.patch(self.endpoint, data=data, format='json')
|
||||
else:
|
||||
return self.client.patch(self.endpoint)
|
||||
|
||||
def put(self, data, **kwargs):
|
||||
self.set_params(**kwargs)
|
||||
return self.client.get(self.endpoint, data=data, format='json')
|
||||
|
||||
def delete(self, data=None, **kwargs):
|
||||
self.set_params(**kwargs)
|
||||
if not data is None:
|
||||
return self.client.delete(self.endpoint, data=data, format='json')
|
||||
else:
|
||||
return self.client.delete(self.endpoint)
|
||||
|
||||
def assertOK(self, data=None, **kwargs):
|
||||
response = self.execute(data, **kwargs)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
def assertBadData(self, data=None, **kwargs):
|
||||
response = self.execute(data, **kwargs)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def assertForbidden(self, data=None, **kwargs):
|
||||
response = self.execute(data, **kwargs)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def assertNotModified(self, data=None, **kwargs):
|
||||
response = self.execute(data, **kwargs)
|
||||
self.assertEqual(response.status_code, status.HTTP_304_NOT_MODIFIED)
|
||||
|
||||
def assertNotFound(self, data=None, **kwargs):
|
||||
response = self.execute(data, **kwargs)
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
def execute(self, data=None, **kwargs):
|
||||
if self.method == 'get':
|
||||
return self.get(**kwargs)
|
||||
if self.method == 'post':
|
||||
return self.post(data, **kwargs)
|
||||
if self.method == 'put':
|
||||
return self.put(data, **kwargs)
|
||||
if self.method == 'patch':
|
||||
return self.patch(data, **kwargs)
|
||||
if self.method == 'delete':
|
||||
return self.delete(data, **kwargs)
|
||||
return None
|
||||
|
||||
|
||||
def _resolve_url(url: str, **kwargs) -> str:
|
||||
if url == '' or len(kwargs) == 0:
|
||||
return url
|
||||
pos_input: int = 0
|
||||
pos_start: int = 0
|
||||
pos_end: int = 0
|
||||
arg_names = set()
|
||||
output: str = ''
|
||||
while True:
|
||||
pos_start = url.find('{', pos_input)
|
||||
if pos_start == -1:
|
||||
break
|
||||
pos_end = url.find('}', pos_start)
|
||||
if pos_end == -1:
|
||||
break
|
||||
name = url[(pos_start + 1) : pos_end]
|
||||
arg_names.add(name)
|
||||
if not name in kwargs:
|
||||
raise KeyError(f'Missing argument: {name} | Mask: {url}')
|
||||
output += url[pos_input : pos_start]
|
||||
output += str(kwargs[name])
|
||||
pos_input = pos_end + 1
|
||||
if pos_input < len(url):
|
||||
output += url[pos_input : len(url)]
|
||||
for (key, _) in kwargs.items():
|
||||
if key not in arg_names:
|
||||
raise KeyError(f'Unused argument: {name} | Mask: {url}')
|
||||
return output
|
|
@ -1,63 +1,34 @@
|
|||
''' Testing views '''
|
||||
import os
|
||||
import io
|
||||
from zipfile import ZipFile
|
||||
from rest_framework.test import APITestCase, APIRequestFactory, APIClient
|
||||
from rest_framework.exceptions import ErrorDetail
|
||||
from rest_framework import status
|
||||
|
||||
from cctext import ReferenceType, split_grams
|
||||
from cctext import split_grams
|
||||
|
||||
from apps.users.models import User
|
||||
from apps.rsform.models import (
|
||||
RSForm, Constituenta, CstType,
|
||||
LibraryItem, LibraryItemType, Subscription, LibraryTemplate
|
||||
)
|
||||
from apps.rsform.views import (
|
||||
convert_to_ascii,
|
||||
convert_to_math,
|
||||
parse_expression,
|
||||
inflect,
|
||||
parse_text,
|
||||
generate_lexeme
|
||||
)
|
||||
from .EndpointTester import decl_endpoint, EndpointTester
|
||||
|
||||
|
||||
class TestNaturalLanguageViews(APITestCase):
|
||||
def setUp(self):
|
||||
self.factory = APIRequestFactory()
|
||||
self.client = APIClient()
|
||||
|
||||
class TestNaturalLanguageViews(EndpointTester):
|
||||
''' Test natural language endpoints. '''
|
||||
def _assert_tags(self, actual: str, expected: str):
|
||||
self.assertEqual(set(split_grams(actual)), set(split_grams(expected)))
|
||||
|
||||
@decl_endpoint(endpoint='/api/cctext/parse', method='post')
|
||||
def test_parse_text(self):
|
||||
data = {'text': 'синим слонам'}
|
||||
request = self.factory.post(
|
||||
'/api/cctext/parse',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = parse_text(request)
|
||||
response = self.execute(data)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self._assert_tags(response.data['result'], 'datv,NOUN,plur,anim,masc')
|
||||
|
||||
@decl_endpoint(endpoint='/api/cctext/inflect', method='post')
|
||||
def test_inflect(self):
|
||||
data = {'text': 'синий слон', 'grams': 'plur,datv'}
|
||||
request = self.factory.post(
|
||||
'/api/cctext/inflect',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = inflect(request)
|
||||
response = self.execute(data)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['result'], 'синим слонам')
|
||||
|
||||
@decl_endpoint(endpoint='/api/cctext/generate-lexeme', method='post')
|
||||
def test_generate_lexeme(self):
|
||||
data = {'text': 'синий слон'}
|
||||
request = self.factory.post(
|
||||
'/api/cctext/generate-lexeme',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = generate_lexeme(request)
|
||||
response = self.execute(data)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data['items']), 12)
|
||||
self.assertEqual(response.data['items'][0]['text'], 'синий слон')
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
''' Testing API: Constituents. '''
|
||||
from rest_framework.test import APITestCase, APIRequestFactory, APIClient
|
||||
from rest_framework import status
|
||||
|
||||
from apps.users.models import User
|
||||
from apps.rsform.models import RSForm, Constituenta, CstType
|
||||
|
||||
from .EndpointTester import decl_endpoint, EndpointTester
|
||||
|
||||
class TestConstituentaAPI(APITestCase):
|
||||
|
||||
class TestConstituentaAPI(EndpointTester):
|
||||
''' Testing Constituenta view. '''
|
||||
def setUp(self):
|
||||
self.factory = APIRequestFactory()
|
||||
self.user = User.objects.create(username='UserTest')
|
||||
self.client = APIClient()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
super().setUp()
|
||||
self.rsform_owned = RSForm.create(title='Test', alias='T1', owner=self.user)
|
||||
self.rsform_unowned = RSForm.create(title='Test2', alias='T2')
|
||||
self.cst1 = Constituenta.objects.create(
|
||||
alias='X1',
|
||||
cst_type=CstType.BASE,
|
||||
schema=self.rsform_owned.item,
|
||||
order=1,
|
||||
convention='Test',
|
||||
|
@ -25,6 +23,7 @@ class TestConstituentaAPI(APITestCase):
|
|||
term_forms=[{'text':'form1', 'tags':'sing,datv'}])
|
||||
self.cst2 = Constituenta.objects.create(
|
||||
alias='X2',
|
||||
cst_type=CstType.BASE,
|
||||
schema=self.rsform_unowned.item,
|
||||
order=1,
|
||||
convention='Test1',
|
||||
|
@ -40,51 +39,40 @@ class TestConstituentaAPI(APITestCase):
|
|||
definition_raw='Test1',
|
||||
definition_resolved='Test2'
|
||||
)
|
||||
self.invalid_cst = self.cst3.pk + 1337
|
||||
|
||||
@decl_endpoint('/api/constituents/{item}', method='get')
|
||||
def test_retrieve(self):
|
||||
response = self.client.get(f'/api/constituents/{self.cst1.id}')
|
||||
self.assertNotFound(item=self.invalid_cst)
|
||||
response = self.execute(item=self.cst1.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['alias'], self.cst1.alias)
|
||||
self.assertEqual(response.data['convention'], self.cst1.convention)
|
||||
|
||||
@decl_endpoint('/api/constituents/{item}', method='patch')
|
||||
def test_partial_update(self):
|
||||
data = {'convention': 'tt'}
|
||||
response = self.client.patch(
|
||||
f'/api/constituents/{self.cst2.id}',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertForbidden(data, item=self.cst2.id)
|
||||
|
||||
self.client.logout()
|
||||
response = self.client.patch(
|
||||
f'/api/constituents/{self.cst1.id}',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.logout()
|
||||
self.assertForbidden(data, item=self.cst1.id)
|
||||
|
||||
self.client.force_authenticate(user=self.user)
|
||||
response = self.client.patch(
|
||||
f'/api/constituents/{self.cst1.id}',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.login()
|
||||
response = self.execute(data, item=self.cst1.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.cst1.refresh_from_db()
|
||||
self.assertEqual(response.data['convention'], 'tt')
|
||||
self.assertEqual(self.cst1.convention, 'tt')
|
||||
|
||||
response = self.client.patch(
|
||||
f'/api/constituents/{self.cst1.id}',
|
||||
data=data,
|
||||
format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertOK(data, item=self.cst1.id)
|
||||
|
||||
@decl_endpoint('/api/constituents/{item}', method='patch')
|
||||
def test_update_resolved_no_refs(self):
|
||||
data = {
|
||||
'term_raw': 'New term',
|
||||
'definition_raw': 'New def'
|
||||
}
|
||||
response = self.client.patch(f'/api/constituents/{self.cst3.id}', data, format='json')
|
||||
response = self.execute(data, item=self.cst3.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.cst3.refresh_from_db()
|
||||
self.assertEqual(response.data['term_resolved'], 'New term')
|
||||
|
@ -92,15 +80,13 @@ class TestConstituentaAPI(APITestCase):
|
|||
self.assertEqual(response.data['definition_resolved'], 'New def')
|
||||
self.assertEqual(self.cst3.definition_resolved, 'New def')
|
||||
|
||||
@decl_endpoint('/api/constituents/{item}', method='patch')
|
||||
def test_update_resolved_refs(self):
|
||||
data = {
|
||||
'term_raw': '@{X1|nomn,sing}',
|
||||
'definition_raw': '@{X1|nomn,sing} @{X1|sing,datv}'
|
||||
}
|
||||
response = self.client.patch(
|
||||
f'/api/constituents/{self.cst3.id}',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data, item=self.cst3.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.cst3.refresh_from_db()
|
||||
self.assertEqual(self.cst3.term_resolved, self.cst1.term_resolved)
|
||||
|
@ -108,12 +94,10 @@ class TestConstituentaAPI(APITestCase):
|
|||
self.assertEqual(self.cst3.definition_resolved, f'{self.cst1.term_resolved} form1')
|
||||
self.assertEqual(response.data['definition_resolved'], f'{self.cst1.term_resolved} form1')
|
||||
|
||||
@decl_endpoint('/api/constituents/{item}', method='patch')
|
||||
def test_readonly_cst_fields(self):
|
||||
data = {'alias': 'X33', 'order': 10}
|
||||
response = self.client.patch(
|
||||
f'/api/constituents/{self.cst1.id}',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data, item=self.cst1.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['alias'], 'X1')
|
||||
self.assertEqual(response.data['alias'], self.cst1.alias)
|
||||
|
|
|
@ -1,26 +1,25 @@
|
|||
''' Testing API: Library. '''
|
||||
from rest_framework.test import APITestCase, APIRequestFactory, APIClient
|
||||
from rest_framework import status
|
||||
|
||||
from apps.users.models import User
|
||||
from apps.rsform.models import LibraryItem, LibraryItemType, Subscription, LibraryTemplate
|
||||
from apps.rsform.models import LibraryItem, LibraryItemType, Subscription, LibraryTemplate, RSForm
|
||||
|
||||
from ..utils import response_contains
|
||||
|
||||
from .EndpointTester import decl_endpoint, EndpointTester
|
||||
|
||||
class TestLibraryViewset(APITestCase):
|
||||
|
||||
class TestLibraryViewset(EndpointTester):
|
||||
''' Testing Library view. '''
|
||||
def setUp(self):
|
||||
self.factory = APIRequestFactory()
|
||||
self.user = User.objects.create(username='UserTest')
|
||||
self.client = APIClient()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
super().setUp()
|
||||
self.owned = LibraryItem.objects.create(
|
||||
item_type=LibraryItemType.RSFORM,
|
||||
title='Test',
|
||||
alias='T1',
|
||||
owner=self.user
|
||||
)
|
||||
self.schema = RSForm(self.owned)
|
||||
self.unowned = LibraryItem.objects.create(
|
||||
item_type=LibraryItemType.RSFORM,
|
||||
title='Test2',
|
||||
|
@ -33,93 +32,79 @@ class TestLibraryViewset(APITestCase):
|
|||
is_common=True
|
||||
)
|
||||
|
||||
def test_create_anonymous(self):
|
||||
self.client.logout()
|
||||
@decl_endpoint('/api/library', method='post')
|
||||
def test_create(self):
|
||||
data = {'title': 'Title'}
|
||||
response = self.client.post('/api/library', data=data, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_create_populate_user(self):
|
||||
data = {'title': 'Title'}
|
||||
response = self.client.post('/api/library', data=data, format='json')
|
||||
response = self.post(data=data)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['title'], 'Title')
|
||||
self.assertEqual(response.data['owner'], self.user.id)
|
||||
|
||||
self.logout()
|
||||
data = {'title': 'Title2'}
|
||||
self.assertForbidden(data)
|
||||
|
||||
@decl_endpoint('/api/library/{item}', method='patch')
|
||||
def test_update(self):
|
||||
data = {'id': self.unowned.id, 'title': 'New title'}
|
||||
self.assertForbidden(data, item=self.unowned.id)
|
||||
|
||||
data = {'id': self.owned.id, 'title': 'New title'}
|
||||
response = self.client.patch(
|
||||
f'/api/library/{self.owned.id}',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data, item=self.owned.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['title'], 'New title')
|
||||
self.assertEqual(response.data['alias'], self.owned.alias)
|
||||
|
||||
def test_update_unowned(self):
|
||||
data = {'id': self.unowned.id, 'title': 'New title'}
|
||||
response = self.client.patch(
|
||||
f'/api/library/{self.unowned.id}',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
@decl_endpoint('/api/library/{item}', method='delete')
|
||||
def test_destroy(self):
|
||||
response = self.client.delete(f'/api/library/{self.owned.id}')
|
||||
response = self.execute(item=self.owned.id)
|
||||
self.assertTrue(response.status_code in [status.HTTP_202_ACCEPTED, status.HTTP_204_NO_CONTENT])
|
||||
|
||||
def test_destroy_admin_override(self):
|
||||
response = self.client.delete(f'/api/library/{self.unowned.id}')
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.user.is_staff = True
|
||||
self.user.save()
|
||||
response = self.client.delete(f'/api/library/{self.unowned.id}')
|
||||
self.assertForbidden(item=self.unowned.id)
|
||||
self.toggle_staff(True)
|
||||
response = self.execute(item=self.unowned.id)
|
||||
self.assertTrue(response.status_code in [status.HTTP_202_ACCEPTED, status.HTTP_204_NO_CONTENT])
|
||||
|
||||
@decl_endpoint('/api/library/{item}/claim', method='post')
|
||||
def test_claim(self):
|
||||
response = self.client.post(f'/api/library/{self.owned.id}/claim')
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertForbidden(item=self.owned.id)
|
||||
|
||||
self.owned.is_common = True
|
||||
self.owned.save()
|
||||
response = self.client.post(f'/api/library/{self.owned.id}/claim')
|
||||
self.assertEqual(response.status_code, status.HTTP_304_NOT_MODIFIED)
|
||||
|
||||
response = self.client.post(f'/api/library/{self.unowned.id}/claim')
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertNotModified(item=self.owned.id)
|
||||
self.assertForbidden(item=self.unowned.id)
|
||||
|
||||
self.assertFalse(self.user in self.unowned.subscribers())
|
||||
self.unowned.is_common = True
|
||||
self.unowned.save()
|
||||
response = self.client.post(f'/api/library/{self.unowned.id}/claim')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
self.assertOK(item=self.unowned.id)
|
||||
self.unowned.refresh_from_db()
|
||||
self.assertEqual(self.unowned.owner, self.user)
|
||||
self.assertEqual(self.unowned.owner, self.user)
|
||||
self.assertTrue(self.user in self.unowned.subscribers())
|
||||
|
||||
def test_claim_anonymous(self):
|
||||
self.client.logout()
|
||||
response = self.client.post(f'/api/library/{self.owned.id}/claim')
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.logout()
|
||||
self.assertForbidden(item=self.owned.id)
|
||||
|
||||
@decl_endpoint('/api/library/active', method='get')
|
||||
def test_retrieve_common(self):
|
||||
self.client.logout()
|
||||
response = self.client.get('/api/library/active')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response_contains(response, self.common))
|
||||
self.assertFalse(response_contains(response, self.unowned))
|
||||
self.assertFalse(response_contains(response, self.owned))
|
||||
|
||||
def test_retrieve_owned(self):
|
||||
response = self.client.get('/api/library/active')
|
||||
response = self.execute()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response_contains(response, self.common))
|
||||
self.assertFalse(response_contains(response, self.unowned))
|
||||
self.assertTrue(response_contains(response, self.owned))
|
||||
|
||||
self.logout()
|
||||
response = self.execute()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response_contains(response, self.common))
|
||||
self.assertFalse(response_contains(response, self.unowned))
|
||||
self.assertFalse(response_contains(response, self.owned))
|
||||
|
||||
@decl_endpoint('/api/library/active', method='get')
|
||||
def test_retrieve_subscribed(self):
|
||||
response = self.client.get('/api/library/active')
|
||||
response = self.execute()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertFalse(response_contains(response, self.unowned))
|
||||
|
||||
|
@ -127,21 +112,23 @@ class TestLibraryViewset(APITestCase):
|
|||
Subscription.subscribe(user=self.user, item=self.unowned)
|
||||
Subscription.subscribe(user=user2, item=self.unowned)
|
||||
Subscription.subscribe(user=user2, item=self.owned)
|
||||
response = self.client.get('/api/library/active')
|
||||
|
||||
response = self.execute()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response_contains(response, self.unowned))
|
||||
self.assertEqual(len(response.data), 3)
|
||||
|
||||
@decl_endpoint('/api/library/{item}/subscribe', method='post')
|
||||
def test_subscriptions(self):
|
||||
response = self.client.delete(f'/api/library/{self.unowned.id}/unsubscribe')
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
self.assertFalse(self.user in self.unowned.subscribers())
|
||||
|
||||
response = self.client.post(f'/api/library/{self.unowned.id}/subscribe')
|
||||
response = self.execute(item=self.unowned.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
self.assertTrue(self.user in self.unowned.subscribers())
|
||||
|
||||
response = self.client.post(f'/api/library/{self.unowned.id}/subscribe')
|
||||
response = self.execute(item=self.unowned.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
self.assertTrue(self.user in self.unowned.subscribers())
|
||||
|
||||
|
@ -149,16 +136,40 @@ class TestLibraryViewset(APITestCase):
|
|||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
self.assertFalse(self.user in self.unowned.subscribers())
|
||||
|
||||
@decl_endpoint('/api/library/templates', method='get')
|
||||
def test_retrieve_templates(self):
|
||||
response = self.client.get('/api/library/templates')
|
||||
response = self.execute()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertFalse(response_contains(response, self.common))
|
||||
self.assertFalse(response_contains(response, self.unowned))
|
||||
self.assertFalse(response_contains(response, self.owned))
|
||||
|
||||
LibraryTemplate.objects.create(lib_source=self.unowned)
|
||||
response = self.client.get('/api/library/templates')
|
||||
response = self.execute()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertFalse(response_contains(response, self.common))
|
||||
self.assertTrue(response_contains(response, self.unowned))
|
||||
self.assertFalse(response_contains(response, self.owned))
|
||||
|
||||
@decl_endpoint('/api/library/{item}/clone', method='post')
|
||||
def test_clone_rsform(self):
|
||||
x12 = self.schema.insert_new(
|
||||
alias='X12',
|
||||
term_raw = 'человек',
|
||||
term_resolved = 'человек'
|
||||
)
|
||||
d2 = self.schema.insert_new(
|
||||
alias='D2',
|
||||
term_raw = '@{X12|plur}',
|
||||
term_resolved = 'люди'
|
||||
)
|
||||
|
||||
data = {'title': 'Title1337'}
|
||||
response = self.execute(data, item=self.owned.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['title'], data['title'])
|
||||
self.assertEqual(response.data['items'][0]['alias'], x12.alias)
|
||||
self.assertEqual(response.data['items'][0]['term_raw'], x12.term_raw)
|
||||
self.assertEqual(response.data['items'][0]['term_resolved'], x12.term_resolved)
|
||||
self.assertEqual(response.data['items'][1]['term_raw'], d2.term_raw)
|
||||
self.assertEqual(response.data['items'][1]['term_resolved'], d2.term_resolved)
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
import os
|
||||
import io
|
||||
from zipfile import ZipFile
|
||||
from rest_framework.test import APITestCase, APIRequestFactory, APIClient
|
||||
from rest_framework import status
|
||||
|
||||
from apps.users.models import User
|
||||
from apps.rsform.models import (
|
||||
RSForm,
|
||||
Constituenta,
|
||||
|
@ -17,44 +15,69 @@ from apps.rsform.models import (
|
|||
from cctext import ReferenceType
|
||||
from ..utils import response_contains
|
||||
|
||||
from .EndpointTester import decl_endpoint, EndpointTester
|
||||
|
||||
class TestRSFormViewset(APITestCase):
|
||||
|
||||
class TestRSFormViewset(EndpointTester):
|
||||
''' Testing RSForm view. '''
|
||||
def setUp(self):
|
||||
self.factory = APIRequestFactory()
|
||||
self.user = User.objects.create(username='UserTest')
|
||||
self.client = APIClient()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
self.owned = RSForm.create(title='Test', alias='T1', owner=self.user)
|
||||
super().setUp()
|
||||
self.schema = RSForm.create(title='Test', alias='T1', owner=self.user)
|
||||
self.schema_id = self.schema.item.id
|
||||
self.unowned = RSForm.create(title='Test2', alias='T2')
|
||||
self.unowned_id = self.unowned.item.id
|
||||
|
||||
@decl_endpoint('/api/rsforms/create-detailed', method='post')
|
||||
def test_create_rsform_file(self):
|
||||
work_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
with open(f'{work_dir}/data/sample-rsform.trs', 'rb') as file:
|
||||
data = {'file': file, 'title': 'Test123', 'comment': '123', 'alias': 'ks1'}
|
||||
response = self.client.post(self.endpoint, data=data, format='multipart')
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['owner'], self.user.pk)
|
||||
self.assertEqual(response.data['title'], 'Test123')
|
||||
self.assertEqual(response.data['alias'], 'ks1')
|
||||
self.assertEqual(response.data['comment'], '123')
|
||||
|
||||
@decl_endpoint('/api/rsforms/create-detailed', method='post')
|
||||
def test_create_rsform_json(self):
|
||||
data = {'title': 'Test123', 'comment': '123', 'alias': 'ks1'}
|
||||
response = self.execute(data)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['owner'], self.user.pk)
|
||||
self.assertEqual(response.data['title'], 'Test123')
|
||||
self.assertEqual(response.data['alias'], 'ks1')
|
||||
self.assertEqual(response.data['comment'], '123')
|
||||
|
||||
@decl_endpoint('/api/rsforms', method='get')
|
||||
def test_list(self):
|
||||
non_schema = LibraryItem.objects.create(
|
||||
item_type=LibraryItemType.OPERATIONS_SCHEMA,
|
||||
title='Test3'
|
||||
)
|
||||
response = self.client.get('/api/rsforms')
|
||||
response = self.execute()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertFalse(response_contains(response, non_schema))
|
||||
self.assertTrue(response_contains(response, self.unowned.item))
|
||||
self.assertTrue(response_contains(response, self.owned.item))
|
||||
self.assertTrue(response_contains(response, self.schema.item))
|
||||
|
||||
response = self.client.get('/api/library')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response_contains(response, non_schema))
|
||||
self.assertTrue(response_contains(response, self.unowned.item))
|
||||
self.assertTrue(response_contains(response, self.owned.item))
|
||||
self.assertTrue(response_contains(response, self.schema.item))
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/contents', method='get')
|
||||
def test_contents(self):
|
||||
schema = RSForm.create(title='Title1')
|
||||
schema.insert_new(alias='X1', insert_type=CstType.BASE)
|
||||
response = self.client.get(f'/api/rsforms/{schema.item.id}/contents')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
schema.insert_new('X1')
|
||||
self.assertOK(item=schema.item.id)
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/details', method='get')
|
||||
def test_details(self):
|
||||
schema = RSForm.create(title='Test', owner=self.user)
|
||||
x1 = schema.insert_new('X1', CstType.BASE, 1)
|
||||
x2 = schema.insert_new('X2', CstType.BASE, 2)
|
||||
x1 = schema.insert_new('X1')
|
||||
x2 = schema.insert_new('X2')
|
||||
x1.term_raw = 'человек'
|
||||
x1.term_resolved = 'человек'
|
||||
x2.term_raw = '@{X1|plur}'
|
||||
|
@ -62,8 +85,7 @@ class TestRSFormViewset(APITestCase):
|
|||
x1.save()
|
||||
x2.save()
|
||||
|
||||
response = self.client.get(f'/api/rsforms/{schema.item.id}/details')
|
||||
|
||||
response = self.execute(item=schema.item.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['title'], 'Test')
|
||||
self.assertEqual(len(response.data['items']), 2)
|
||||
|
@ -76,14 +98,12 @@ class TestRSFormViewset(APITestCase):
|
|||
self.assertEqual(response.data['items'][1]['term_resolved'], x2.term_resolved)
|
||||
self.assertEqual(response.data['subscribers'], [self.user.pk])
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/check', method='post')
|
||||
def test_check(self):
|
||||
schema = RSForm.create(title='Test')
|
||||
schema.insert_new('X1', CstType.BASE, 1)
|
||||
schema.insert_new('X1')
|
||||
data = {'expression': 'X1=X1'}
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{schema.item.id}/check',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data, item=schema.item.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['parseResult'], True)
|
||||
self.assertEqual(response.data['syntax'], 'math')
|
||||
|
@ -91,22 +111,17 @@ class TestRSFormViewset(APITestCase):
|
|||
self.assertEqual(response.data['typification'], 'LOGIC')
|
||||
self.assertEqual(response.data['valueClass'], 'value')
|
||||
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{self.unowned.item.id}/check',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertOK(data, item=self.unowned_id)
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/resolve', method='post')
|
||||
def test_resolve(self):
|
||||
schema = RSForm.create(title='Test')
|
||||
x1 = schema.insert_new('X1', CstType.BASE, 1)
|
||||
x1 = schema.insert_new('X1')
|
||||
x1.term_resolved = 'синий слон'
|
||||
x1.save()
|
||||
|
||||
data = {'text': '@{1|редкий} @{X1|plur,datv}'}
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{schema.item.id}/resolve',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data, item=schema.item.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['input'], '@{1|редкий} @{X1|plur,datv}')
|
||||
self.assertEqual(response.data['output'], 'редким синим слонам')
|
||||
|
@ -128,19 +143,21 @@ class TestRSFormViewset(APITestCase):
|
|||
self.assertEqual(response.data['refs'][1]['pos_output']['start'], 7)
|
||||
self.assertEqual(response.data['refs'][1]['pos_output']['finish'], 19)
|
||||
|
||||
@decl_endpoint('/api/rsforms/import-trs', method='post')
|
||||
def test_import_trs(self):
|
||||
work_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
with open(f'{work_dir}/data/sample-rsform.trs', 'rb') as file:
|
||||
data = {'file': file}
|
||||
response = self.client.post('/api/rsforms/import-trs', data=data, format='multipart')
|
||||
response = self.client.post(self.endpoint, data=data, format='multipart')
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['owner'], self.user.pk)
|
||||
self.assertTrue(response.data['title'] != '')
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/export-trs', method='get')
|
||||
def test_export_trs(self):
|
||||
schema = RSForm.create(title='Test')
|
||||
schema.insert_new('X1', CstType.BASE, 1)
|
||||
response = self.client.get(f'/api/rsforms/{schema.item.id}/export-trs')
|
||||
schema.insert_new('X1')
|
||||
response = self.execute(item=schema.item.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.headers['Content-Disposition'], 'attachment; filename=Schema.trs')
|
||||
with io.BytesIO(response.content) as stream:
|
||||
|
@ -148,31 +165,15 @@ class TestRSFormViewset(APITestCase):
|
|||
self.assertIsNone(zipped_file.testzip())
|
||||
self.assertIn('document.json', zipped_file.namelist())
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-create', method='post')
|
||||
def test_create_constituenta(self):
|
||||
data = {'alias': 'X3', 'cst_type': 'basic'}
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{self.unowned.item.id}/cst-create',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
data = {'alias': 'X3', 'cst_type': CstType.BASE}
|
||||
self.assertForbidden(data, item=self.unowned_id)
|
||||
|
||||
item = self.owned.item
|
||||
Constituenta.objects.create(
|
||||
schema=item,
|
||||
alias='X1',
|
||||
cst_type='basic',
|
||||
order=1
|
||||
)
|
||||
x2 = Constituenta.objects.create(
|
||||
schema=item,
|
||||
alias='X2',
|
||||
cst_type='basic',
|
||||
order=2
|
||||
)
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{item.id}/cst-create',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.schema.insert_new('X1')
|
||||
x2 = self.schema.insert_new('X2')
|
||||
|
||||
response = self.execute(data, item=self.schema_id)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['new_cst']['alias'], 'X3')
|
||||
x3 = Constituenta.objects.get(alias=response.data['new_cst']['alias'])
|
||||
|
@ -180,15 +181,12 @@ class TestRSFormViewset(APITestCase):
|
|||
|
||||
data = {
|
||||
'alias': 'X4',
|
||||
'cst_type': 'basic',
|
||||
'cst_type': CstType.BASE,
|
||||
'insert_after': x2.id,
|
||||
'term_raw': 'test',
|
||||
'term_forms': [{'text':'form1', 'tags':'sing,datv'}]
|
||||
}
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{item.id}/cst-create',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data, item=self.schema_id)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['new_cst']['alias'], data['alias'])
|
||||
x4 = Constituenta.objects.get(alias=response.data['new_cst']['alias'])
|
||||
|
@ -196,144 +194,87 @@ class TestRSFormViewset(APITestCase):
|
|||
self.assertEqual(x4.term_raw, data['term_raw'])
|
||||
self.assertEqual(x4.term_forms, data['term_forms'])
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-rename', method='patch')
|
||||
def test_rename_constituenta(self):
|
||||
cst1 = Constituenta.objects.create(
|
||||
x1 = self.schema.insert_new(
|
||||
alias='X1',
|
||||
schema=self.owned.item,
|
||||
order=1,
|
||||
convention='Test',
|
||||
term_raw='Test1',
|
||||
term_resolved='Test1',
|
||||
term_forms=[{'text':'form1', 'tags':'sing,datv'}]
|
||||
)
|
||||
cst2 = Constituenta.objects.create(
|
||||
alias='X2',
|
||||
schema=self.unowned.item,
|
||||
order=1
|
||||
)
|
||||
cst3 = Constituenta.objects.create(
|
||||
x2_2 = self.unowned.insert_new('X2')
|
||||
x3 = self.schema.insert_new(
|
||||
alias='X3',
|
||||
schema=self.owned.item, order=2,
|
||||
term_raw='Test3',
|
||||
term_resolved='Test3',
|
||||
definition_raw='Test1',
|
||||
definition_resolved='Test2'
|
||||
)
|
||||
|
||||
data = {'target': cst2.pk, 'alias': 'D2', 'cst_type': 'term'}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{self.unowned.item.id}/cst-rename',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
data = {'target': x2_2.pk, 'alias': 'D2', 'cst_type': CstType.TERM}
|
||||
self.assertForbidden(data, item=self.unowned_id)
|
||||
self.assertBadData(data, item=self.schema_id)
|
||||
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{self.owned.item.id}/cst-rename',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
data = {'target': x1.pk, 'alias': x1.alias, 'cst_type': CstType.TERM}
|
||||
self.assertBadData(data, item=self.schema_id)
|
||||
|
||||
data = {'target': cst1.pk, 'alias': cst1.alias, 'cst_type': 'term'}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{self.owned.item.id}/cst-rename',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
data = {'target': x1.pk, 'alias': x3.alias}
|
||||
self.assertBadData(data, item=self.schema_id)
|
||||
|
||||
data = {'target': cst1.pk, 'alias': cst3.alias}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{self.owned.item.id}/cst-rename',
|
||||
data=data, format='json'
|
||||
d1 = self.schema.insert_new(
|
||||
alias='D1',
|
||||
term_raw = '@{X1|plur}',
|
||||
definition_formal = 'X1'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(x1.order, 1)
|
||||
self.assertEqual(x1.alias, 'X1')
|
||||
self.assertEqual(x1.cst_type, CstType.BASE)
|
||||
|
||||
data = {'target': cst1.pk, 'alias': 'D2', 'cst_type': 'term'}
|
||||
item = self.owned.item
|
||||
d1 = Constituenta.objects.create(schema=item, alias='D1', cst_type='term', order=4)
|
||||
d1.term_raw = '@{X1|plur}'
|
||||
d1.definition_formal = 'X1'
|
||||
d1.save()
|
||||
|
||||
self.assertEqual(d1.order, 4)
|
||||
self.assertEqual(cst1.order, 1)
|
||||
self.assertEqual(cst1.alias, 'X1')
|
||||
self.assertEqual(cst1.cst_type, CstType.BASE)
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{item.id}/cst-rename',
|
||||
data=data, format='json'
|
||||
)
|
||||
data = {'target': x1.pk, 'alias': 'D2', 'cst_type': CstType.TERM}
|
||||
response = self.execute(data, item=self.schema_id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['new_cst']['alias'], 'D2')
|
||||
self.assertEqual(response.data['new_cst']['cst_type'], 'term')
|
||||
self.assertEqual(response.data['new_cst']['cst_type'], CstType.TERM)
|
||||
d1.refresh_from_db()
|
||||
cst1.refresh_from_db()
|
||||
self.assertEqual(d1.order, 4)
|
||||
x1.refresh_from_db()
|
||||
self.assertEqual(d1.term_resolved, '')
|
||||
self.assertEqual(d1.term_raw, '@{D2|plur}')
|
||||
self.assertEqual(cst1.order, 1)
|
||||
self.assertEqual(cst1.alias, 'D2')
|
||||
self.assertEqual(cst1.cst_type, CstType.TERM)
|
||||
self.assertEqual(x1.order, 1)
|
||||
self.assertEqual(x1.alias, 'D2')
|
||||
self.assertEqual(x1.cst_type, CstType.TERM)
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-substitute', method='patch')
|
||||
def test_substitute_constituenta(self):
|
||||
x1 = Constituenta.objects.create(
|
||||
x1 = self.schema.insert_new(
|
||||
alias='X1',
|
||||
schema=self.owned.item,
|
||||
order=1,
|
||||
term_raw='Test1',
|
||||
term_resolved='Test1',
|
||||
term_forms=[{'text':'form1', 'tags':'sing,datv'}]
|
||||
)
|
||||
x2 = Constituenta.objects.create(
|
||||
x2 = self.schema.insert_new(
|
||||
alias='X2',
|
||||
schema=self.owned.item,
|
||||
order=2,
|
||||
term_raw='Test2'
|
||||
)
|
||||
unowned = Constituenta.objects.create(
|
||||
alias='X2',
|
||||
schema=self.unowned.item,
|
||||
order=1
|
||||
)
|
||||
unowned = self.unowned.insert_new('X2')
|
||||
|
||||
data = {'original': x1.pk, 'substitution': unowned.pk, 'transfer_term': True}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{self.unowned.item.id}/cst-substitute',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{self.owned.item.id}/cst-substitute',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertForbidden(data, item=self.unowned_id)
|
||||
self.assertBadData(data, item=self.schema_id)
|
||||
|
||||
data = {'original': unowned.pk, 'substitution': x1.pk, 'transfer_term': True}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{self.owned.item.id}/cst-substitute',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertBadData(data, item=self.schema_id)
|
||||
|
||||
data = {'original': x1.pk, 'substitution': x1.pk, 'transfer_term': True}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{self.owned.item.id}/cst-substitute',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertBadData(data, item=self.schema_id)
|
||||
|
||||
d1 = Constituenta.objects.create(
|
||||
d1 = self.schema.insert_new(
|
||||
alias='D1',
|
||||
schema=self.owned.item,
|
||||
order=3,
|
||||
term_raw='@{X2|sing,datv}',
|
||||
definition_formal='X1'
|
||||
)
|
||||
data = {'original': x1.pk, 'substitution': x2.pk, 'transfer_term': True}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{self.owned.item.id}/cst-substitute',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data, item=self.schema_id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
d1.refresh_from_db()
|
||||
|
@ -342,23 +283,20 @@ class TestRSFormViewset(APITestCase):
|
|||
self.assertEqual(d1.term_resolved, 'form1')
|
||||
self.assertEqual(d1.definition_formal, 'X2')
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-create', method='post')
|
||||
def test_create_constituenta_data(self):
|
||||
data = {
|
||||
'alias': 'X3',
|
||||
'cst_type': 'basic',
|
||||
'cst_type': CstType.BASE,
|
||||
'convention': '1',
|
||||
'term_raw': '2',
|
||||
'definition_formal': '3',
|
||||
'definition_raw': '4'
|
||||
}
|
||||
item = self.owned.item
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{item.id}/cst-create',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data, item=self.schema_id)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['new_cst']['alias'], 'X3')
|
||||
self.assertEqual(response.data['new_cst']['cst_type'], 'basic')
|
||||
self.assertEqual(response.data['new_cst']['cst_type'], CstType.BASE)
|
||||
self.assertEqual(response.data['new_cst']['convention'], '1')
|
||||
self.assertEqual(response.data['new_cst']['term_raw'], '2')
|
||||
self.assertEqual(response.data['new_cst']['term_resolved'], '2')
|
||||
|
@ -366,79 +304,66 @@ class TestRSFormViewset(APITestCase):
|
|||
self.assertEqual(response.data['new_cst']['definition_raw'], '4')
|
||||
self.assertEqual(response.data['new_cst']['definition_resolved'], '4')
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-delete-multiple', method='patch')
|
||||
def test_delete_constituenta(self):
|
||||
schema = self.owned
|
||||
data = {'items': [1337]}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{schema.item.id}/cst-delete-multiple',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.set_params(item=self.schema_id)
|
||||
|
||||
data = {'items': [1337]}
|
||||
self.assertBadData(data)
|
||||
|
||||
x1 = self.schema.insert_new('X1')
|
||||
x2 = self.schema.insert_new('X2')
|
||||
|
||||
x1 = Constituenta.objects.create(schema=schema.item, alias='X1', cst_type='basic', order=1)
|
||||
x2 = Constituenta.objects.create(schema=schema.item, alias='X2', cst_type='basic', order=2)
|
||||
data = {'items': [x1.id]}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{schema.item.id}/cst-delete-multiple',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data)
|
||||
x2.refresh_from_db()
|
||||
schema.item.refresh_from_db()
|
||||
self.schema.item.refresh_from_db()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data['items']), 1)
|
||||
self.assertEqual(schema.constituents().count(), 1)
|
||||
self.assertEqual(self.schema.constituents().count(), 1)
|
||||
self.assertEqual(x2.alias, 'X2')
|
||||
self.assertEqual(x2.order, 1)
|
||||
|
||||
x3 = Constituenta.objects.create(schema=self.unowned.item, alias='X1', cst_type='basic', order=1)
|
||||
x3 = self.unowned.insert_new('X1')
|
||||
data = {'items': [x3.id]}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{schema.item.id}/cst-delete-multiple',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertBadData(data, item=self.schema_id)
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-moveto', method='patch')
|
||||
def test_move_constituenta(self):
|
||||
item = self.owned.item
|
||||
data = {'items': [1337], 'move_to': 1}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{item.id}/cst-moveto',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.set_params(item=self.schema_id)
|
||||
|
||||
data = {'items': [1337], 'move_to': 1}
|
||||
self.assertBadData(data)
|
||||
|
||||
x1 = self.schema.insert_new('X1')
|
||||
x2 = self.schema.insert_new('X2')
|
||||
|
||||
x1 = Constituenta.objects.create(schema=item, alias='X1', cst_type='basic', order=1)
|
||||
x2 = Constituenta.objects.create(schema=item, alias='X2', cst_type='basic', order=2)
|
||||
data = {'items': [x2.id], 'move_to': 1}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{item.id}/cst-moveto',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data)
|
||||
x1.refresh_from_db()
|
||||
x2.refresh_from_db()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['id'], item.id)
|
||||
self.assertEqual(response.data['id'], self.schema_id)
|
||||
self.assertEqual(x1.order, 2)
|
||||
self.assertEqual(x2.order, 1)
|
||||
|
||||
x3 = Constituenta.objects.create(schema=self.unowned.item, alias='X1', cst_type='basic', order=1)
|
||||
x3 = self.unowned.insert_new('X1')
|
||||
data = {'items': [x3.id], 'move_to': 1}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{item.id}/cst-moveto',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertBadData(data)
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/reset-aliases', method='patch')
|
||||
def test_reset_aliases(self):
|
||||
item = self.owned.item
|
||||
response = self.client.patch(f'/api/rsforms/{item.id}/reset-aliases')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['id'], item.id)
|
||||
self.set_params(item=self.schema_id)
|
||||
|
||||
x2 = Constituenta.objects.create(schema=item, alias='X2', cst_type='basic', order=1)
|
||||
x1 = Constituenta.objects.create(schema=item, alias='X1', cst_type='basic', order=2)
|
||||
d11 = Constituenta.objects.create(schema=item, alias='D11', cst_type='term', order=3)
|
||||
response = self.client.patch(f'/api/rsforms/{item.id}/reset-aliases')
|
||||
response = self.execute()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['id'], self.schema_id)
|
||||
|
||||
x2 = self.schema.insert_new('X2')
|
||||
x1 = self.schema.insert_new('X1')
|
||||
d11 = self.schema.insert_new('D11')
|
||||
|
||||
response = self.execute()
|
||||
x1.refresh_from_db()
|
||||
x2.refresh_from_db()
|
||||
d11.refresh_from_db()
|
||||
|
@ -450,103 +375,57 @@ class TestRSFormViewset(APITestCase):
|
|||
self.assertEqual(d11.order, 3)
|
||||
self.assertEqual(d11.alias, 'D1')
|
||||
|
||||
response = self.client.patch(f'/api/rsforms/{item.id}/reset-aliases')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertOK()
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/load-trs', method='patch')
|
||||
def test_load_trs(self):
|
||||
schema = self.owned
|
||||
schema.item.title = 'Test11'
|
||||
schema.item.save()
|
||||
x1 = Constituenta.objects.create(schema=schema.item, alias='X1', cst_type='basic', order=1)
|
||||
self.set_params(item=self.schema_id)
|
||||
self.schema.item.title = 'Test11'
|
||||
self.schema.item.save()
|
||||
x1 = self.schema.insert_new('X1')
|
||||
work_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
with open(f'{work_dir}/data/sample-rsform.trs', 'rb') as file:
|
||||
data = {'file': file, 'load_metadata': False}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{schema.item.id}/load-trs',
|
||||
data=data, format='multipart'
|
||||
)
|
||||
schema.item.refresh_from_db()
|
||||
response = self.client.patch(self.endpoint, data=data, format='multipart')
|
||||
self.schema.item.refresh_from_db()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(schema.item.title, 'Test11')
|
||||
self.assertEqual(self.schema.item.title, 'Test11')
|
||||
self.assertEqual(len(response.data['items']), 25)
|
||||
self.assertEqual(schema.constituents().count(), 25)
|
||||
self.assertEqual(self.schema.constituents().count(), 25)
|
||||
self.assertFalse(Constituenta.objects.filter(pk=x1.id).exists())
|
||||
|
||||
def test_clone(self):
|
||||
item = self.owned.item
|
||||
item.title = 'Test11'
|
||||
item.save()
|
||||
x1 = Constituenta.objects.create(schema=item, alias='X12', cst_type='basic', order=1)
|
||||
d1 = Constituenta.objects.create(schema=item, alias='D2', cst_type='term', order=1)
|
||||
x1.term_raw = 'человек'
|
||||
x1.term_resolved = 'человек'
|
||||
d1.term_raw = '@{X12|plur}'
|
||||
d1.term_resolved = 'люди'
|
||||
x1.save()
|
||||
d1.save()
|
||||
|
||||
data = {'title': 'Title'}
|
||||
response = self.client.post(
|
||||
f'/api/library/{item.id}/clone',
|
||||
data=data, format='json'
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['title'], 'Title')
|
||||
self.assertEqual(response.data['items'][0]['alias'], x1.alias)
|
||||
self.assertEqual(response.data['items'][0]['term_raw'], x1.term_raw)
|
||||
self.assertEqual(response.data['items'][0]['term_resolved'], x1.term_resolved)
|
||||
self.assertEqual(response.data['items'][1]['term_raw'], d1.term_raw)
|
||||
self.assertEqual(response.data['items'][1]['term_resolved'], d1.term_resolved)
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-produce-structure', method='patch')
|
||||
def test_produce_structure(self):
|
||||
item = self.owned.item
|
||||
x1 = Constituenta.objects.create(schema=item, alias='X1', cst_type='basic', order=1)
|
||||
s1 = Constituenta.objects.create(schema=item, alias='S1', cst_type='structure', order=2)
|
||||
s2 = Constituenta.objects.create(schema=item, alias='S2', cst_type='structure', order=3)
|
||||
s3 = Constituenta.objects.create(schema=item, alias='S3', cst_type='structure', order=4)
|
||||
a1 = Constituenta.objects.create(schema=item, alias='A1', cst_type='axiom', order=5)
|
||||
f1 = Constituenta.objects.create(schema=item, alias='F10', cst_type='function', order=6)
|
||||
invalid_id = f1.id + 1
|
||||
s1.definition_formal = 'ℬ(X1×X1)' # ℬ(X1×X1)
|
||||
s2.definition_formal = 'invalid'
|
||||
s3.definition_formal = 'X1×(X1×ℬℬ(X1))×ℬ(X1×X1)'
|
||||
a1.definition_formal = '1=1'
|
||||
f1.definition_formal = '[α∈X1, β∈X1] Fi1[{α,β}](S1)'
|
||||
s1.save()
|
||||
s2.save()
|
||||
s3.save()
|
||||
a1.save()
|
||||
f1.save()
|
||||
|
||||
data = {'target': invalid_id}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{item.id}/cst-produce-structure',
|
||||
data=data, format='json'
|
||||
self.set_params(item=self.schema_id)
|
||||
x1 = self.schema.insert_new('X1')
|
||||
s1 = self.schema.insert_new(
|
||||
alias='S1',
|
||||
definition_formal='ℬ(X1×X1)'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
data = {'target': x1.id}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{item.id}/cst-produce-structure',
|
||||
data=data, format='json'
|
||||
s2 = self.schema.insert_new(
|
||||
alias='S2',
|
||||
definition_formal='invalid'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
data = {'target': s2.id}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{item.id}/cst-produce-structure',
|
||||
data=data, format='json'
|
||||
s3 = self.schema.insert_new(
|
||||
alias='S3',
|
||||
definition_formal='X1×(X1×ℬℬ(X1))×ℬ(X1×X1)'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# Testing simple structure
|
||||
s1.refresh_from_db()
|
||||
data = {'target': s1.id}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{item.id}/cst-produce-structure',
|
||||
data=data, format='json'
|
||||
a1 = self.schema.insert_new(
|
||||
alias='A1',
|
||||
definition_formal='1=1'
|
||||
)
|
||||
f1 = self.schema.insert_new(
|
||||
alias='F10',
|
||||
definition_formal='[α∈X1, β∈X1] Fi1[{α,β}](S1)'
|
||||
)
|
||||
invalid_id = f1.pk + 1337
|
||||
|
||||
self.assertBadData({'target': invalid_id})
|
||||
self.assertBadData({'target': x1.id})
|
||||
self.assertBadData({'target': s2.id})
|
||||
|
||||
# Testing simple structure
|
||||
response = self.execute({'target': s1.id})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
result = response.data['schema']
|
||||
items = [item for item in result['items'] if item['id'] in response.data['cst_list']]
|
||||
|
@ -558,11 +437,7 @@ class TestRSFormViewset(APITestCase):
|
|||
|
||||
# Testing complex structure
|
||||
s3.refresh_from_db()
|
||||
data = {'target': s3.id}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{item.id}/cst-produce-structure',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute({'target': s3.id})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
result = response.data['schema']
|
||||
items = [item for item in result['items'] if item['id'] in response.data['cst_list']]
|
||||
|
@ -572,11 +447,7 @@ class TestRSFormViewset(APITestCase):
|
|||
|
||||
# Testing function
|
||||
f1.refresh_from_db()
|
||||
data = {'target': f1.id}
|
||||
response = self.client.patch(
|
||||
f'/api/rsforms/{item.id}/cst-produce-structure',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute({'target': f1.id})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
result = response.data['schema']
|
||||
items = [item for item in result['items'] if item['id'] in response.data['cst_list']]
|
||||
|
|
|
@ -1,109 +1,41 @@
|
|||
''' Testing views '''
|
||||
import os
|
||||
from rest_framework.test import APITestCase, APIRequestFactory, APIClient
|
||||
from rest_framework.exceptions import ErrorDetail
|
||||
from rest_framework import status
|
||||
|
||||
from apps.users.models import User
|
||||
from apps.rsform.models import RSForm
|
||||
from apps.rsform.views import (
|
||||
convert_to_ascii,
|
||||
convert_to_math,
|
||||
parse_expression
|
||||
)
|
||||
from .EndpointTester import decl_endpoint, EndpointTester
|
||||
|
||||
|
||||
class TestRSLanguageViews(APITestCase):
|
||||
def setUp(self):
|
||||
self.factory = APIRequestFactory()
|
||||
self.user = User.objects.create(username='UserTest')
|
||||
self.client = APIClient()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
|
||||
def test_create_rsform(self):
|
||||
work_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
with open(f'{work_dir}/data/sample-rsform.trs', 'rb') as file:
|
||||
data = {'file': file, 'title': 'Test123', 'comment': '123', 'alias': 'ks1'}
|
||||
response = self.client.post(
|
||||
'/api/rsforms/create-detailed',
|
||||
data=data, format='multipart'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['owner'], self.user.pk)
|
||||
self.assertEqual(response.data['title'], 'Test123')
|
||||
self.assertEqual(response.data['alias'], 'ks1')
|
||||
self.assertEqual(response.data['comment'], '123')
|
||||
|
||||
def test_create_rsform_fallback(self):
|
||||
data = {'title': 'Test123', 'comment': '123', 'alias': 'ks1'}
|
||||
response = self.client.post(
|
||||
'/api/rsforms/create-detailed',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['owner'], self.user.pk)
|
||||
self.assertEqual(response.data['title'], 'Test123')
|
||||
self.assertEqual(response.data['alias'], 'ks1')
|
||||
self.assertEqual(response.data['comment'], '123')
|
||||
|
||||
class TestRSLanguageViews(EndpointTester):
|
||||
''' Test RS language endpoints. '''
|
||||
@decl_endpoint('/api/rslang/to-ascii', method='post')
|
||||
def test_convert_to_ascii(self):
|
||||
data = {'data': '1=1'}
|
||||
self.assertBadData(data)
|
||||
|
||||
data = {'expression': '1=1'}
|
||||
request = self.factory.post(
|
||||
'/api/rslang/to-ascii',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = convert_to_ascii(request)
|
||||
response = self.execute(data)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['result'], r'1 \eq 1')
|
||||
|
||||
def test_convert_to_ascii_missing_data(self):
|
||||
data = {'data': '1=1'}
|
||||
request = self.factory.post(
|
||||
'/api/rslang/to-ascii',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = convert_to_ascii(request)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIsInstance(response.data['expression'][0], ErrorDetail)
|
||||
|
||||
@decl_endpoint('/api/rslang/to-math', method='post')
|
||||
def test_convert_to_math(self):
|
||||
data = {'data': r'1 \eq 1'}
|
||||
self.assertBadData(data)
|
||||
|
||||
data = {'expression': r'1 \eq 1'}
|
||||
request = self.factory.post(
|
||||
'/api/rslang/to-math',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = convert_to_math(request)
|
||||
response = self.execute(data)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['result'], r'1=1')
|
||||
|
||||
def test_convert_to_math_missing_data(self):
|
||||
data = {'data': r'1 \eq 1'}
|
||||
request = self.factory.post(
|
||||
'/api/rslang/to-math',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = convert_to_math(request)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIsInstance(response.data['expression'][0], ErrorDetail)
|
||||
|
||||
@decl_endpoint('/api/rslang/parse-expression', method='post')
|
||||
def test_parse_expression(self):
|
||||
data = {'data': r'1=1'}
|
||||
self.assertBadData(data)
|
||||
|
||||
data = {'expression': r'1=1'}
|
||||
request = self.factory.post(
|
||||
'/api/rslang/parse-expression',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = parse_expression(request)
|
||||
response = self.execute(data)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['parseResult'], True)
|
||||
self.assertEqual(response.data['syntax'], 'math')
|
||||
self.assertEqual(response.data['astText'], '[=[1][1]]')
|
||||
|
||||
def test_parse_expression_missing_data(self):
|
||||
data = {'data': r'1=1'}
|
||||
request = self.factory.post(
|
||||
'/api/rslang/parse-expression',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = parse_expression(request)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIsInstance(response.data['expression'][0], ErrorDetail)
|
||||
|
|
|
@ -1,185 +1,141 @@
|
|||
''' Testing API: Versions. '''
|
||||
import io
|
||||
from typing import cast
|
||||
from sys import version
|
||||
from zipfile import ZipFile
|
||||
from rest_framework.test import APITestCase, APIRequestFactory, APIClient
|
||||
from rest_framework import status
|
||||
|
||||
from apps.users.models import User
|
||||
from apps.rsform.models import RSForm, Constituenta
|
||||
|
||||
from .EndpointTester import decl_endpoint, EndpointTester
|
||||
|
||||
class TestVersionViews(APITestCase):
|
||||
|
||||
class TestVersionViews(EndpointTester):
|
||||
''' Testing versioning endpoints. '''
|
||||
def setUp(self):
|
||||
self.factory = APIRequestFactory()
|
||||
self.user = User.objects.create(username='UserTest')
|
||||
self.client = APIClient()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
self.owned = RSForm.create(title='Test', alias='T1', owner=self.user)
|
||||
self.unowned = RSForm.create(title='Test2', alias='T2')
|
||||
super().setUp()
|
||||
self.owned = RSForm.create(title='Test', alias='T1', owner=self.user).item
|
||||
self.unowned = RSForm.create(title='Test2', alias='T2').item
|
||||
self.x1 = Constituenta.objects.create(
|
||||
schema=self.owned.item,
|
||||
schema=self.owned,
|
||||
alias='X1',
|
||||
cst_type='basic',
|
||||
convention='testStart',
|
||||
order=1
|
||||
)
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/versions/create', method='post')
|
||||
def test_create_version(self):
|
||||
invalid_data = {'description': 'test'}
|
||||
data = {'version': '1.0.0', 'description': 'test'}
|
||||
invalid_id = 1338
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{invalid_id}/versions/create',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
data = {'version': '1.0.0', 'description': 'test'}
|
||||
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{self.unowned.item.id}/versions/create',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertNotFound(data, schema=invalid_id)
|
||||
self.assertForbidden(data, schema=self.unowned.id)
|
||||
self.assertBadData(invalid_data, schema=self.owned.id)
|
||||
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{self.owned.item.id}/versions/create',
|
||||
data=invalid_data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{self.owned.item.id}/versions/create',
|
||||
data=data, format='json'
|
||||
)
|
||||
response = self.execute(data, schema=self.owned.id)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertTrue('version' in response.data)
|
||||
self.assertTrue('schema' in response.data)
|
||||
self.assertTrue(response.data['version'] in [v['id'] for v in response.data['schema']['versions']])
|
||||
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/versions/{version}', method='get')
|
||||
def test_retrieve_version(self):
|
||||
data = {'version': '1.0.0', 'description': 'test'}
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{self.owned.item.id}/versions/create',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
version_id = response.data['version']
|
||||
version_id = self._create_version({'version': '1.0.0', 'description': 'test'})
|
||||
invalid_id = version_id + 1337
|
||||
|
||||
invalid_id = 1338
|
||||
response = self.client.get(f'/api/rsforms/{invalid_id}/versions/{invalid_id}')
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
response = self.client.get(f'/api/rsforms/{self.owned.item.id}/versions/{invalid_id}')
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
response = self.client.get(f'/api/rsforms/{invalid_id}/versions/{version_id}')
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
response = self.client.get(f'/api/rsforms/{self.unowned.item.id}/versions/{version_id}')
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
self.assertNotFound(schema=invalid_id, version=invalid_id)
|
||||
self.assertNotFound(schema=self.owned.id, version=invalid_id)
|
||||
self.assertNotFound(schema=invalid_id, version=version_id)
|
||||
self.assertNotFound(schema=self.unowned.id, version=version_id)
|
||||
|
||||
self.owned.item.alias = 'NewName'
|
||||
self.owned.item.save()
|
||||
self.owned.alias = 'NewName'
|
||||
self.owned.save()
|
||||
self.x1.alias = 'X33'
|
||||
self.x1.save()
|
||||
|
||||
response = self.client.get(f'/api/rsforms/{self.owned.item.id}/versions/{version_id}')
|
||||
response = self.execute(schema=self.owned.id, version=version_id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertNotEqual(response.data['alias'], self.owned.item.alias)
|
||||
self.assertNotEqual(response.data['alias'], self.owned.alias)
|
||||
self.assertNotEqual(response.data['items'][0]['alias'], self.x1.alias)
|
||||
self.assertEqual(response.data['version'], version_id)
|
||||
|
||||
@decl_endpoint('/api/versions/{version}', method='get')
|
||||
def test_access_version(self):
|
||||
data = {'version': '1.0.0', 'description': 'test'}
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{self.owned.item.id}/versions/create',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
version_id = response.data['version']
|
||||
version_id = self._create_version(data)
|
||||
invalid_id = version_id + 1337
|
||||
|
||||
response = self.client.get(f'/api/versions/{invalid_id}')
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
self.assertNotFound(version=invalid_id)
|
||||
|
||||
self.client.logout()
|
||||
response = self.client.get(f'/api/versions/{version_id}')
|
||||
self.set_params(version=version_id)
|
||||
self.logout()
|
||||
response = self.execute()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['version'], data['version'])
|
||||
self.assertEqual(response.data['description'], data['description'])
|
||||
self.assertEqual(response.data['item'], self.owned.item.id)
|
||||
self.assertEqual(response.data['item'], self.owned.id)
|
||||
|
||||
response = self.client.patch(
|
||||
f'/api/versions/{version_id}',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
data = {'version': '1.2.0', 'description': 'test1'}
|
||||
self.method = 'patch'
|
||||
self.assertForbidden(data)
|
||||
|
||||
response = self.client.delete(f'/api/versions/{version_id}')
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.method = 'delete'
|
||||
self.assertForbidden()
|
||||
|
||||
self.client.force_authenticate(user=self.user)
|
||||
|
||||
data = {'version': '1.1.0', 'description': 'test1'}
|
||||
response = self.client.patch(
|
||||
f'/api/versions/{version_id}',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
response = self.client.get(f'/api/versions/{version_id}')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.method = 'patch'
|
||||
self.assertOK(data)
|
||||
response = self.get()
|
||||
self.assertEqual(response.data['version'], data['version'])
|
||||
self.assertEqual(response.data['description'], data['description'])
|
||||
|
||||
response = self.client.delete(f'/api/versions/{version_id}')
|
||||
response = self.delete()
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
|
||||
response = self.client.get(f'/api/versions/{version_id}')
|
||||
response = self.get()
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/versions/{version}', method='get')
|
||||
def test_retrieve_version_details(self):
|
||||
a1 = Constituenta.objects.create(
|
||||
schema=self.owned.item,
|
||||
schema=self.owned,
|
||||
alias='A1',
|
||||
cst_type='axiom',
|
||||
definition_formal='X1=X1',
|
||||
order=2
|
||||
)
|
||||
|
||||
data = {'version': '1.0.0', 'description': 'test'}
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{self.owned.item.id}/versions/create',
|
||||
data=data, format='json'
|
||||
)
|
||||
version_id = response.data['version']
|
||||
|
||||
version_id = self._create_version({'version': '1.0.0', 'description': 'test'})
|
||||
a1.definition_formal = 'X1=X2'
|
||||
a1.save()
|
||||
|
||||
response = self.client.get(f'/api/rsforms/{self.owned.item.id}/versions/{version_id}')
|
||||
response = self.get(schema=self.owned.id, version=version_id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
loaded_a1 = response.data['items'][1]
|
||||
self.assertEqual(loaded_a1['definition_formal'], 'X1=X1')
|
||||
self.assertEqual(loaded_a1['parse']['status'], 'verified')
|
||||
|
||||
@decl_endpoint('/api/versions/{version}/export-file', method='get')
|
||||
def test_export_version(self):
|
||||
invalid_id = 1338
|
||||
response = self.client.get(f'/api/versions/{invalid_id}/export-file')
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
self.assertNotFound(version=invalid_id)
|
||||
|
||||
data = {'version': '1.0.0', 'description': 'test'}
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{self.owned.item.id}/versions/create',
|
||||
data=data, format='json'
|
||||
)
|
||||
version_id = response.data['version']
|
||||
|
||||
response = self.client.get(f'/api/versions/{version_id}/export-file')
|
||||
version_id = self._create_version({'version': '1.0.0', 'description': 'test'})
|
||||
response = self.get(version=version_id)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(
|
||||
response.headers['Content-Disposition'],
|
||||
f'attachment; filename={self.owned.item.alias}.trs'
|
||||
f'attachment; filename={self.owned.alias}.trs'
|
||||
)
|
||||
with io.BytesIO(response.content) as stream:
|
||||
with ZipFile(stream, 'r') as zipped_file:
|
||||
self.assertIsNone(zipped_file.testzip())
|
||||
self.assertIn('document.json', zipped_file.namelist())
|
||||
|
||||
def _create_version(self, data) -> int:
|
||||
response = self.client.post(
|
||||
f'/api/rsforms/{self.owned.id}/versions/create',
|
||||
data=data, format='json'
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
return response.data['version'] # type: ignore
|
||||
|
|
|
@ -64,7 +64,7 @@ def write_zipped_json(json_data: dict, json_filename: str) -> bytes:
|
|||
return content.getvalue()
|
||||
|
||||
def apply_pattern(text: str, mapping: dict[str, str], pattern: re.Pattern[str]) -> str:
|
||||
''' Apply mapping to matching in regular expression patter subgroup 1 '''
|
||||
''' Apply mapping to matching in regular expression pattern subgroup 1 '''
|
||||
if text == '' or pattern == '':
|
||||
return text
|
||||
pos_input: int = 0
|
||||
|
|
Loading…
Reference in New Issue
Block a user