F: Implement create-block API
This commit is contained in:
parent
1f15a6a53c
commit
0bdfe67fb1
|
@ -19,6 +19,7 @@ from apps.rsform.models import (
|
|||
)
|
||||
|
||||
from .Argument import Argument
|
||||
from .Block import Block
|
||||
from .Inheritance import Inheritance
|
||||
from .Layout import Layout
|
||||
from .Operation import Operation
|
||||
|
@ -60,6 +61,10 @@ class OperationSchema:
|
|||
''' Get QuerySet containing all operations of current OSS. '''
|
||||
return Operation.objects.filter(oss=self.model)
|
||||
|
||||
def blocks(self) -> QuerySet[Block]:
|
||||
''' Get QuerySet containing all blocks of current OSS. '''
|
||||
return Block.objects.filter(oss=self.model)
|
||||
|
||||
def arguments(self) -> QuerySet[Argument]:
|
||||
''' Operation arguments. '''
|
||||
return Argument.objects.filter(operation__oss=self.model)
|
||||
|
@ -99,6 +104,12 @@ class OperationSchema:
|
|||
self.save(update_fields=['time_update'])
|
||||
return result
|
||||
|
||||
def create_block(self, **kwargs) -> Block:
|
||||
''' Insert new block. '''
|
||||
result = Block.objects.create(oss=self.model, **kwargs)
|
||||
self.save(update_fields=['time_update'])
|
||||
return result
|
||||
|
||||
def delete_operation(self, target: int, keep_constituents: bool = False):
|
||||
''' Delete operation. '''
|
||||
self.cache.ensure_loaded()
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
from .basics import LayoutSerializer, SubstitutionExSerializer
|
||||
from .data_access import (
|
||||
ArgumentSerializer,
|
||||
BlockCreateSerializer,
|
||||
BlockSerializer,
|
||||
OperationCreateSerializer,
|
||||
OperationDeleteSerializer,
|
||||
OperationSchemaSerializer,
|
||||
|
@ -12,4 +14,9 @@ from .data_access import (
|
|||
RelocateConstituentsSerializer,
|
||||
SetOperationInputSerializer
|
||||
)
|
||||
from .responses import ConstituentaReferenceResponse, NewOperationResponse, NewSchemaResponse
|
||||
from .responses import (
|
||||
ConstituentaReferenceResponse,
|
||||
NewBlockResponse,
|
||||
NewOperationResponse,
|
||||
NewSchemaResponse
|
||||
)
|
||||
|
|
|
@ -11,7 +11,7 @@ from apps.rsform.models import Constituenta
|
|||
from apps.rsform.serializers import SubstitutionSerializerBase
|
||||
from shared import messages as msg
|
||||
|
||||
from ..models import Argument, Inheritance, Operation, OperationSchema, OperationType
|
||||
from ..models import Argument, Block, Inheritance, Operation, OperationSchema, OperationType
|
||||
from .basics import LayoutSerializer, SubstitutionExSerializer
|
||||
|
||||
|
||||
|
@ -24,6 +24,15 @@ class OperationSerializer(serializers.ModelSerializer):
|
|||
read_only_fields = ('id', 'oss')
|
||||
|
||||
|
||||
class BlockSerializer(serializers.ModelSerializer):
|
||||
''' Serializer: Block data. '''
|
||||
class Meta:
|
||||
''' serializer metadata. '''
|
||||
model = Block
|
||||
fields = '__all__'
|
||||
read_only_fields = ('id', 'oss')
|
||||
|
||||
|
||||
class ArgumentSerializer(serializers.ModelSerializer):
|
||||
''' Serializer: Operation data. '''
|
||||
class Meta:
|
||||
|
@ -32,6 +41,49 @@ class ArgumentSerializer(serializers.ModelSerializer):
|
|||
fields = ('operation', 'argument')
|
||||
|
||||
|
||||
class BlockCreateSerializer(serializers.Serializer):
|
||||
''' Serializer: Block creation. '''
|
||||
class BlockCreateData(serializers.ModelSerializer):
|
||||
''' Serializer: Block creation data. '''
|
||||
|
||||
class Meta:
|
||||
''' serializer metadata. '''
|
||||
model = Block
|
||||
fields = 'title', 'description', 'parent'
|
||||
|
||||
layout = LayoutSerializer()
|
||||
|
||||
item_data = BlockCreateData()
|
||||
width = serializers.FloatField()
|
||||
height = serializers.FloatField()
|
||||
position_x = serializers.FloatField()
|
||||
position_y = serializers.FloatField()
|
||||
children_operations = PKField(many=True, queryset=Operation.objects.all().only('oss_id'))
|
||||
children_blocks = PKField(many=True, queryset=Block.objects.all().only('oss_id'))
|
||||
|
||||
def validate(self, attrs):
|
||||
oss = cast(LibraryItem, self.context['oss'])
|
||||
if 'parent' in attrs['item_data'] and \
|
||||
attrs['item_data']['parent'] is not None and \
|
||||
attrs['item_data']['parent'].oss_id != oss.pk:
|
||||
raise serializers.ValidationError({
|
||||
'parent': msg.parentNotInOSS()
|
||||
})
|
||||
|
||||
for operation in attrs['children_operations']:
|
||||
if operation.oss_id != oss.pk:
|
||||
raise serializers.ValidationError({
|
||||
'children_operations': msg.childNotInOSS()
|
||||
})
|
||||
|
||||
for block in attrs['children_blocks']:
|
||||
if block.oss_id != oss.pk:
|
||||
raise serializers.ValidationError({
|
||||
'children_blocks': msg.childNotInOSS()
|
||||
})
|
||||
return attrs
|
||||
|
||||
|
||||
class OperationCreateSerializer(serializers.Serializer):
|
||||
''' Serializer: Operation creation. '''
|
||||
class OperationCreateData(serializers.ModelSerializer):
|
||||
|
@ -47,13 +99,31 @@ class OperationCreateSerializer(serializers.Serializer):
|
|||
'description', 'result', 'parent'
|
||||
|
||||
layout = LayoutSerializer()
|
||||
position_x = serializers.FloatField()
|
||||
position_y = serializers.FloatField()
|
||||
|
||||
item_data = OperationCreateData()
|
||||
position_x = serializers.FloatField()
|
||||
position_y = serializers.FloatField()
|
||||
create_schema = serializers.BooleanField(default=False, required=False)
|
||||
arguments = PKField(many=True, queryset=Operation.objects.all().only('pk'), required=False)
|
||||
|
||||
def validate(self, attrs):
|
||||
oss = cast(LibraryItem, self.context['oss'])
|
||||
if 'parent' in attrs['item_data'] and \
|
||||
attrs['item_data']['parent'] is not None and \
|
||||
attrs['item_data']['parent'].oss_id != oss.pk:
|
||||
raise serializers.ValidationError({
|
||||
'parent': msg.parentNotInOSS()
|
||||
})
|
||||
|
||||
if 'arguments' not in attrs:
|
||||
return attrs
|
||||
for operation in attrs['arguments']:
|
||||
if operation.oss_id != oss.pk:
|
||||
raise serializers.ValidationError({
|
||||
'arguments': msg.operationNotInOSS(oss.title)
|
||||
})
|
||||
return attrs
|
||||
|
||||
|
||||
class OperationUpdateSerializer(serializers.Serializer):
|
||||
''' Serializer: Operation update. '''
|
||||
|
@ -74,10 +144,19 @@ class OperationUpdateSerializer(serializers.Serializer):
|
|||
)
|
||||
|
||||
def validate(self, attrs):
|
||||
oss = cast(LibraryItem, self.context['oss'])
|
||||
if 'parent' in attrs['item_data'] and attrs['item_data']['parent'].oss_id != oss.pk:
|
||||
raise serializers.ValidationError({
|
||||
'parent': msg.parentNotInOSS()
|
||||
})
|
||||
|
||||
if 'arguments' not in attrs:
|
||||
if 'substitutions' in attrs:
|
||||
raise serializers.ValidationError({
|
||||
'arguments': msg.missingArguments()
|
||||
})
|
||||
return attrs
|
||||
|
||||
oss = cast(LibraryItem, self.context['oss'])
|
||||
for operation in attrs['arguments']:
|
||||
if operation.oss_id != oss.pk:
|
||||
raise serializers.ValidationError({
|
||||
|
@ -175,6 +254,9 @@ class OperationSchemaSerializer(serializers.ModelSerializer):
|
|||
operations = serializers.ListField(
|
||||
child=OperationSerializer()
|
||||
)
|
||||
blocks = serializers.ListField(
|
||||
child=BlockSerializer()
|
||||
)
|
||||
arguments = serializers.ListField(
|
||||
child=ArgumentSerializer()
|
||||
)
|
||||
|
@ -194,12 +276,15 @@ class OperationSchemaSerializer(serializers.ModelSerializer):
|
|||
oss = OperationSchema(instance)
|
||||
result['layout'] = oss.layout().data
|
||||
result['operations'] = []
|
||||
result['blocks'] = []
|
||||
result['arguments'] = []
|
||||
result['substitutions'] = []
|
||||
for operation in oss.operations().order_by('pk'):
|
||||
result['operations'].append(OperationSerializer(operation).data)
|
||||
result['arguments'] = []
|
||||
for block in oss.blocks().order_by('pk'):
|
||||
result['blocks'].append(BlockSerializer(block).data)
|
||||
for argument in oss.arguments().order_by('order'):
|
||||
result['arguments'].append(ArgumentSerializer(argument).data)
|
||||
result['substitutions'] = []
|
||||
for substitution in oss.substitutions().values(
|
||||
'operation',
|
||||
'original',
|
||||
|
|
|
@ -3,7 +3,7 @@ from rest_framework import serializers
|
|||
|
||||
from apps.library.serializers import LibraryItemSerializer
|
||||
|
||||
from .data_access import OperationSchemaSerializer, OperationSerializer
|
||||
from .data_access import BlockSerializer, OperationSchemaSerializer, OperationSerializer
|
||||
|
||||
|
||||
class NewOperationResponse(serializers.Serializer):
|
||||
|
@ -12,6 +12,12 @@ class NewOperationResponse(serializers.Serializer):
|
|||
oss = OperationSchemaSerializer()
|
||||
|
||||
|
||||
class NewBlockResponse(serializers.Serializer):
|
||||
''' Serializer: Create block response. '''
|
||||
new_block = BlockSerializer()
|
||||
oss = OperationSchemaSerializer()
|
||||
|
||||
|
||||
class NewSchemaResponse(serializers.Serializer):
|
||||
''' Serializer: Create RSForm for input operation response. '''
|
||||
new_schema = LibraryItemSerializer()
|
||||
|
|
|
@ -8,6 +8,7 @@ from apps.oss.models import Argument, Operation, OperationSchema, OperationType
|
|||
class TestArgument(TestCase):
|
||||
''' Testing Argument model. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
self.oss = OperationSchema.create(alias='T1')
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ from apps.rsform.models import Constituenta, RSForm
|
|||
class TestInheritance(TestCase):
|
||||
''' Testing Inheritance model. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
self.oss = OperationSchema.create(alias='T1')
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ from apps.rsform.models import RSForm
|
|||
class TestOperation(TestCase):
|
||||
''' Testing Operation model. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
self.oss = OperationSchema.create(alias='T1')
|
||||
self.operation = Operation.objects.create(
|
||||
|
|
|
@ -10,6 +10,7 @@ from apps.rsform.models import RSForm
|
|||
class TestSynthesisSubstitution(TestCase):
|
||||
''' Testing Synthesis Substitution model. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
self.oss = OperationSchema.create(alias='T1')
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ from shared.EndpointTester import EndpointTester, decl_endpoint
|
|||
class TestChangeAttributes(EndpointTester):
|
||||
''' Testing LibraryItem view when OSS is associated with RSForms. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.user3 = User.objects.create(
|
||||
|
@ -70,6 +71,7 @@ class TestChangeAttributes(EndpointTester):
|
|||
layout.data = self.layout_data
|
||||
layout.save()
|
||||
|
||||
|
||||
@decl_endpoint('/api/library/{item}/set-owner', method='patch')
|
||||
def test_set_owner(self):
|
||||
data = {'user': self.user3.pk}
|
||||
|
@ -85,6 +87,7 @@ class TestChangeAttributes(EndpointTester):
|
|||
self.assertEqual(self.ks2.model.owner, self.user2)
|
||||
self.assertEqual(self.ks3.model.owner, self.user3)
|
||||
|
||||
|
||||
@decl_endpoint('/api/library/{item}/set-location', method='patch')
|
||||
def test_set_location(self):
|
||||
data = {'location': '/U/temp'}
|
||||
|
@ -100,6 +103,7 @@ class TestChangeAttributes(EndpointTester):
|
|||
self.assertNotEqual(self.ks2.model.location, data['location'])
|
||||
self.assertEqual(self.ks3.model.location, data['location'])
|
||||
|
||||
|
||||
@decl_endpoint('/api/library/{item}/set-access-policy', method='patch')
|
||||
def test_set_access_policy(self):
|
||||
data = {'access_policy': AccessPolicy.PROTECTED}
|
||||
|
@ -115,6 +119,7 @@ class TestChangeAttributes(EndpointTester):
|
|||
self.assertNotEqual(self.ks2.model.access_policy, data['access_policy'])
|
||||
self.assertEqual(self.ks3.model.access_policy, data['access_policy'])
|
||||
|
||||
|
||||
@decl_endpoint('/api/library/{item}/set-editors', method='patch')
|
||||
def test_set_editors(self):
|
||||
Editor.set(self.owned.model.pk, [self.user2.pk])
|
||||
|
@ -133,6 +138,7 @@ class TestChangeAttributes(EndpointTester):
|
|||
self.assertEqual(list(self.ks2.model.getQ_editors()), [])
|
||||
self.assertEqual(set(self.ks3.model.getQ_editors()), set([self.user, self.user3]))
|
||||
|
||||
|
||||
@decl_endpoint('/api/library/{item}', method='patch')
|
||||
def test_sync_from_result(self):
|
||||
data = {'alias': 'KS111', 'title': 'New Title', 'description': 'New description'}
|
||||
|
@ -145,6 +151,7 @@ class TestChangeAttributes(EndpointTester):
|
|||
self.assertEqual(self.operation1.title, data['title'])
|
||||
self.assertEqual(self.operation1.description, data['description'])
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/update-operation', method='patch')
|
||||
def test_sync_from_operation(self):
|
||||
data = {
|
||||
|
@ -163,6 +170,7 @@ class TestChangeAttributes(EndpointTester):
|
|||
self.assertEqual(self.ks3.model.title, data['item_data']['title'])
|
||||
self.assertEqual(self.ks3.model.description, data['item_data']['description'])
|
||||
|
||||
|
||||
@decl_endpoint('/api/library/{item}', method='delete')
|
||||
def test_destroy_oss_consequence(self):
|
||||
response = self.executeNoContent(item=self.owned_id)
|
||||
|
|
|
@ -69,6 +69,7 @@ class TestChangeConstituents(EndpointTester):
|
|||
layout.data = self.layout_data
|
||||
layout.save()
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/details', method='get')
|
||||
def test_retrieve_inheritance(self):
|
||||
response = self.executeOK(item=self.ks3.model.pk)
|
||||
|
@ -96,6 +97,7 @@ class TestChangeConstituents(EndpointTester):
|
|||
},
|
||||
])
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/create-cst', method='post')
|
||||
def test_create_constituenta(self):
|
||||
data = {
|
||||
|
@ -112,6 +114,7 @@ class TestChangeConstituents(EndpointTester):
|
|||
self.assertEqual(inherited_cst.order, 2)
|
||||
self.assertEqual(inherited_cst.definition_formal, 'X1 = X2')
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/rename-cst', method='patch')
|
||||
def test_rename_constituenta(self):
|
||||
data = {'target': self.ks1X1.pk, 'alias': 'D21', 'cst_type': CstType.TERM}
|
||||
|
@ -123,6 +126,7 @@ class TestChangeConstituents(EndpointTester):
|
|||
self.assertEqual(inherited_cst.alias, 'D2')
|
||||
self.assertEqual(inherited_cst.cst_type, data['cst_type'])
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
||||
def test_update_constituenta(self):
|
||||
d2 = self.ks3.insert_new('D2', cst_type=CstType.TERM, definition_raw='@{X1|sing,nomn}')
|
||||
|
@ -149,6 +153,7 @@ class TestChangeConstituents(EndpointTester):
|
|||
self.assertEqual(inherited_cst.definition_formal, r'X1\X1')
|
||||
self.assertEqual(inherited_cst.definition_raw, r'@{X2|sing,datv}')
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/delete-multiple-cst', method='patch')
|
||||
def test_delete_constituenta(self):
|
||||
data = {'items': [self.ks2X1.pk]}
|
||||
|
@ -160,6 +165,7 @@ class TestChangeConstituents(EndpointTester):
|
|||
self.assertEqual(self.ks2D1.definition_formal, r'DEL\DEL')
|
||||
self.assertEqual(inherited_cst.definition_formal, r'DEL\DEL')
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/substitute', method='patch')
|
||||
def test_substitute(self):
|
||||
d2 = self.ks3.insert_new('D2', cst_type=CstType.TERM, definition_formal=r'X1\X2\X3')
|
||||
|
|
|
@ -8,6 +8,7 @@ from shared.EndpointTester import EndpointTester, decl_endpoint
|
|||
class TestChangeOperations(EndpointTester):
|
||||
''' Testing Operations change propagation in OSS. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.owned = OperationSchema.create(
|
||||
|
@ -120,6 +121,7 @@ class TestChangeOperations(EndpointTester):
|
|||
layout.data = self.layout_data
|
||||
layout.save()
|
||||
|
||||
|
||||
def test_oss_setup(self):
|
||||
self.assertEqual(self.ks1.constituents().count(), 3)
|
||||
self.assertEqual(self.ks2.constituents().count(), 3)
|
||||
|
@ -128,6 +130,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks5.constituents().count(), 8)
|
||||
self.assertEqual(self.ks4D1.definition_formal, 'S1 X1')
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/delete-operation', method='patch')
|
||||
def test_delete_input_operation(self):
|
||||
data = {
|
||||
|
@ -148,6 +151,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'X1 DEL DEL DEL D1')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'DEL DEL X3 DEL D1 D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/set-input', method='patch')
|
||||
def test_set_input_null(self):
|
||||
data = {
|
||||
|
@ -171,6 +175,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'X1 DEL DEL DEL D1')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'DEL DEL X3 DEL D1 D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/set-input', method='patch')
|
||||
def test_set_input_change_schema(self):
|
||||
ks6 = RSForm.create(
|
||||
|
@ -206,6 +211,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'X1 DEL DEL DEL D1')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'DEL DEL X3 DEL D1 D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/library/{item}', method='delete')
|
||||
def test_delete_schema(self):
|
||||
self.executeNoContent(item=self.ks1.model.pk)
|
||||
|
@ -222,6 +228,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'DEL X2 X3 S1 DEL')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'X1 X2 X3 S1 DEL D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/delete-operation', method='patch')
|
||||
def test_delete_operation_and_constituents(self):
|
||||
data = {
|
||||
|
@ -243,6 +250,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'DEL X2 X3 S1 DEL')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'X1 X2 X3 S1 DEL D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/delete-operation', method='patch')
|
||||
def test_delete_operation_keep_constituents(self):
|
||||
data = {
|
||||
|
@ -264,6 +272,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'X1 X2 X3 S1 D1')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'X1 X2 X3 S1 D1 D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/delete-operation', method='patch')
|
||||
def test_delete_operation_keep_schema(self):
|
||||
data = {
|
||||
|
@ -288,6 +297,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks5D4.definition_formal, r'X1 X2 X3 S1 D1 D2 D3')
|
||||
self.assertFalse(Constituenta.objects.filter(as_child__parent_id=self.ks1D1.pk).exists())
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/update-operation', method='patch')
|
||||
def test_change_substitutions(self):
|
||||
data = {
|
||||
|
@ -298,6 +308,7 @@ class TestChangeOperations(EndpointTester):
|
|||
'description': 'Comment mod'
|
||||
},
|
||||
'layout': self.layout_data,
|
||||
'arguments': [self.operation1.pk, self.operation2.pk],
|
||||
'substitutions': [
|
||||
{
|
||||
'original': self.ks1X1.pk,
|
||||
|
@ -322,6 +333,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'X1 D1 X3 S1 D1')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'D1 X2 X3 S1 D1 D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/update-operation', method='patch')
|
||||
def test_change_arguments(self):
|
||||
data = {
|
||||
|
@ -360,6 +372,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'X1 DEL DEL DEL D1')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'DEL DEL X3 DEL D1 D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/execute-operation', method='post')
|
||||
def test_execute_middle_operation(self):
|
||||
self.client.delete(f'/api/library/{self.ks4.model.pk}')
|
||||
|
@ -378,6 +391,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertNotEqual(self.operation4.result, None)
|
||||
self.assertEqual(self.ks5.constituents().count(), 8)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/relocate-constituents', method='post')
|
||||
def test_relocate_constituents_up(self):
|
||||
ks1_old_count = self.ks1.constituents().count()
|
||||
|
@ -407,6 +421,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks1.constituents().count(), ks1_old_count + 1)
|
||||
self.assertEqual(self.ks4.constituents().count(), ks4_old_count + 1)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/relocate-constituents', method='post')
|
||||
def test_relocate_constituents_down(self):
|
||||
ks1_old_count = self.ks1.constituents().count()
|
||||
|
|
|
@ -8,6 +8,7 @@ from shared.EndpointTester import EndpointTester, decl_endpoint
|
|||
class TestChangeSubstitutions(EndpointTester):
|
||||
''' Testing Substitutions change propagation in OSS. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.owned = OperationSchema.create(
|
||||
|
@ -129,6 +130,7 @@ class TestChangeSubstitutions(EndpointTester):
|
|||
self.assertEqual(self.ks5.constituents().count(), 8)
|
||||
self.assertEqual(self.ks4D1.definition_formal, 'S1 X1')
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/substitute', method='patch')
|
||||
def test_substitute_original(self):
|
||||
data = {'substitutions': [{
|
||||
|
@ -151,6 +153,7 @@ class TestChangeSubstitutions(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'S1 X2 X3 S1 D1')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'X1 X2 X3 X3 D1 D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/substitute', method='patch')
|
||||
def test_substitute_substitution(self):
|
||||
data = {
|
||||
|
@ -175,6 +178,7 @@ class TestChangeSubstitutions(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'X1 X2 X3 X2 D1')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'X1 X2 X3 X1 D1 D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/delete-multiple-cst', method='patch')
|
||||
def test_delete_original(self):
|
||||
data = {'items': [self.ks1X1.pk, self.ks1D1.pk]}
|
||||
|
@ -189,6 +193,7 @@ class TestChangeSubstitutions(EndpointTester):
|
|||
self.assertEqual(self.ks4D2.definition_formal, r'X1 X2 X3 S1 DEL')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'X1 X2 X3 S1 DEL D2 D3')
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/delete-multiple-cst', method='patch')
|
||||
def test_delete_substitution(self):
|
||||
data = {'items': [self.ks2S1.pk, self.ks2X2.pk]}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
''' Tests for REST API. '''
|
||||
from .t_blocks import *
|
||||
from .t_operations import *
|
||||
from .t_oss import *
|
||||
|
|
167
rsconcept/backend/apps/oss/tests/s_views/t_blocks.py
Normal file
167
rsconcept/backend/apps/oss/tests/s_views/t_blocks.py
Normal file
|
@ -0,0 +1,167 @@
|
|||
''' Testing API: Operation Schema. '''
|
||||
from apps.library.models import AccessPolicy, Editor, LibraryItem, LibraryItemType
|
||||
from apps.oss.models import Operation, OperationSchema, OperationType
|
||||
from apps.rsform.models import Constituenta, RSForm
|
||||
from shared.EndpointTester import EndpointTester, decl_endpoint
|
||||
|
||||
|
||||
class TestOssBlocks(EndpointTester):
|
||||
''' Testing OSS view - operations. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.owned = OperationSchema.create(title='Test', alias='T1', owner=self.user)
|
||||
self.owned_id = self.owned.model.pk
|
||||
self.unowned = OperationSchema.create(title='Test2', alias='T2')
|
||||
self.unowned_id = self.unowned.model.pk
|
||||
self.invalid_id = self.unowned_id + 1337
|
||||
|
||||
|
||||
def populateData(self):
|
||||
self.unowned.create_block()
|
||||
self.unowned.create_block()
|
||||
self.unowned.create_block()
|
||||
self.unowned.create_block()
|
||||
|
||||
self.block1 = self.owned.create_block(
|
||||
title='1',
|
||||
)
|
||||
self.operation1 = self.owned.create_operation(
|
||||
alias='1',
|
||||
operation_type=OperationType.INPUT,
|
||||
parent=self.block1,
|
||||
)
|
||||
self.operation2 = self.owned.create_operation(
|
||||
alias='2',
|
||||
operation_type=OperationType.INPUT,
|
||||
)
|
||||
self.operation3 = self.unowned.create_operation(
|
||||
alias='3',
|
||||
operation_type=OperationType.INPUT
|
||||
)
|
||||
self.block2 = self.owned.create_block(
|
||||
title='2',
|
||||
parent=self.block1
|
||||
)
|
||||
self.block3 = self.unowned.create_block(
|
||||
title='3',
|
||||
parent=self.block1
|
||||
)
|
||||
self.layout_data = {
|
||||
'operations': [
|
||||
{'id': self.operation1.pk, 'x': 0, 'y': 0},
|
||||
{'id': self.operation2.pk, 'x': 0, 'y': 0},
|
||||
],
|
||||
'blocks': [
|
||||
{'id': self.block1.pk, 'x': 0, 'y': 0, 'width': 0.5, 'height': 0.5},
|
||||
{'id': self.block2.pk, 'x': 0, 'y': 0, 'width': 0.5, 'height': 0.5},
|
||||
]
|
||||
}
|
||||
layout = self.owned.layout()
|
||||
layout.data = self.layout_data
|
||||
layout.save()
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/create-block', method='post')
|
||||
def test_create_block(self):
|
||||
self.populateData()
|
||||
self.executeBadData(item=self.owned_id)
|
||||
|
||||
data = {
|
||||
'item_data': {
|
||||
'title': 'Test title',
|
||||
'description': 'Тест кириллицы',
|
||||
},
|
||||
'layout': self.layout_data,
|
||||
'position_x': 1337,
|
||||
'position_y': 1337,
|
||||
'width': 0.42,
|
||||
'height': 0.42,
|
||||
'children_operations': [],
|
||||
'children_blocks': []
|
||||
}
|
||||
self.executeNotFound(data=data, item=self.invalid_id)
|
||||
|
||||
response = self.executeCreated(data=data, item=self.owned_id)
|
||||
self.assertEqual(len(response.data['oss']['blocks']), 3)
|
||||
new_block = response.data['new_block']
|
||||
layout = response.data['oss']['layout']
|
||||
item = [item for item in layout['blocks'] if item['id'] == new_block['id']][0]
|
||||
self.assertEqual(new_block['title'], data['item_data']['title'])
|
||||
self.assertEqual(new_block['description'], data['item_data']['description'])
|
||||
self.assertEqual(new_block['parent'], None)
|
||||
self.assertEqual(item['x'], data['position_x'])
|
||||
self.assertEqual(item['y'], data['position_y'])
|
||||
self.assertEqual(item['width'], data['width'])
|
||||
self.assertEqual(item['height'], data['height'])
|
||||
self.operation1.refresh_from_db()
|
||||
|
||||
self.executeForbidden(data=data, item=self.unowned_id)
|
||||
self.toggle_admin(True)
|
||||
self.executeCreated(data=data, item=self.unowned_id)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/create-block', method='post')
|
||||
def test_create_block_parent(self):
|
||||
self.populateData()
|
||||
data = {
|
||||
'item_data': {
|
||||
'title': 'Test title',
|
||||
'description': 'Тест кириллицы',
|
||||
'parent': self.invalid_id
|
||||
},
|
||||
'layout': self.layout_data,
|
||||
'position_x': 1337,
|
||||
'position_y': 1337,
|
||||
'width': 0.42,
|
||||
'height': 0.42,
|
||||
'children_operations': [],
|
||||
'children_blocks': []
|
||||
}
|
||||
self.executeBadData(data=data, item=self.owned_id)
|
||||
|
||||
data['item_data']['parent'] = self.block3.pk
|
||||
self.executeBadData(data=data)
|
||||
|
||||
data['item_data']['parent'] = self.block1.pk
|
||||
response = self.executeCreated(data=data)
|
||||
new_block = response.data['new_block']
|
||||
self.assertEqual(new_block['parent'], self.block1.pk)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/create-block', method='post')
|
||||
def test_create_block_children(self):
|
||||
self.populateData()
|
||||
data = {
|
||||
'item_data': {
|
||||
'title': 'Test title',
|
||||
'description': 'Тест кириллицы',
|
||||
},
|
||||
'layout': self.layout_data,
|
||||
'position_x': 1337,
|
||||
'position_y': 1337,
|
||||
'width': 0.42,
|
||||
'height': 0.42,
|
||||
'children_operations': [self.invalid_id],
|
||||
'children_blocks': []
|
||||
}
|
||||
self.executeBadData(data=data, item=self.owned_id)
|
||||
|
||||
data['children_operations'] = [self.operation3.pk]
|
||||
self.executeBadData(data=data)
|
||||
|
||||
data['children_operations'] = [self.block1.pk]
|
||||
self.executeBadData(data=data)
|
||||
|
||||
data['children_operations'] = [self.operation1.pk]
|
||||
data['children_blocks'] = [self.operation1.pk]
|
||||
self.executeBadData(data=data)
|
||||
|
||||
data['children_blocks'] = [self.block1.pk]
|
||||
response = self.executeCreated(data=data)
|
||||
new_block = response.data['new_block']
|
||||
self.operation1.refresh_from_db()
|
||||
self.block1.refresh_from_db()
|
||||
self.assertEqual(self.operation1.parent.pk, new_block['id'])
|
||||
self.assertEqual(self.block1.parent.pk, new_block['id'])
|
|
@ -8,15 +8,15 @@ from shared.EndpointTester import EndpointTester, decl_endpoint
|
|||
class TestOssOperations(EndpointTester):
|
||||
''' Testing OSS view - operations. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.owned = OperationSchema.create(title='Test', alias='T1', owner=self.user)
|
||||
self.owned_id = self.owned.model.pk
|
||||
self.unowned = OperationSchema.create(title='Test2', alias='T2')
|
||||
self.unowned_id = self.unowned.model.pk
|
||||
self.private = OperationSchema.create(title='Test2', alias='T2', access_policy=AccessPolicy.PRIVATE)
|
||||
self.private_id = self.private.model.pk
|
||||
self.invalid_id = self.private.model.pk + 1337
|
||||
self.invalid_id = self.unowned_id + 1337
|
||||
|
||||
|
||||
def populateData(self):
|
||||
self.ks1 = RSForm.create(
|
||||
|
@ -72,6 +72,7 @@ class TestOssOperations(EndpointTester):
|
|||
'substitution': self.ks2X1
|
||||
}])
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/create-operation', method='post')
|
||||
def test_create_operation(self):
|
||||
self.populateData()
|
||||
|
@ -116,6 +117,38 @@ class TestOssOperations(EndpointTester):
|
|||
self.toggle_admin(True)
|
||||
self.executeCreated(data=data, item=self.unowned_id)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/create-operation', method='post')
|
||||
def test_create_operation_parent(self):
|
||||
self.populateData()
|
||||
data = {
|
||||
'item_data': {
|
||||
'parent': self.invalid_id,
|
||||
'alias': 'Test3',
|
||||
'title': 'Test title',
|
||||
'description': '',
|
||||
'operation_type': OperationType.INPUT
|
||||
|
||||
},
|
||||
'layout': self.layout_data,
|
||||
'position_x': 1,
|
||||
'position_y': 1
|
||||
|
||||
}
|
||||
self.executeBadData(data=data, item=self.owned_id)
|
||||
|
||||
block_unowned = self.unowned.create_block(title='TestBlock1')
|
||||
data['item_data']['parent'] = block_unowned.id
|
||||
self.executeBadData(data=data, item=self.owned_id)
|
||||
|
||||
block_owned = self.owned.create_block(title='TestBlock2')
|
||||
data['item_data']['parent'] = block_owned.id
|
||||
response = self.executeCreated(data=data, item=self.owned_id)
|
||||
self.assertEqual(len(response.data['oss']['operations']), 4)
|
||||
new_operation = response.data['new_operation']
|
||||
self.assertEqual(new_operation['parent'], block_owned.id)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/create-operation', method='post')
|
||||
def test_create_operation_arguments(self):
|
||||
self.populateData()
|
||||
|
@ -136,6 +169,7 @@ class TestOssOperations(EndpointTester):
|
|||
self.assertTrue(arguments.filter(operation__id=new_operation['id'], argument=self.operation1))
|
||||
self.assertTrue(arguments.filter(operation__id=new_operation['id'], argument=self.operation3))
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/create-operation', method='post')
|
||||
def test_create_operation_result(self):
|
||||
self.populateData()
|
||||
|
@ -154,10 +188,10 @@ class TestOssOperations(EndpointTester):
|
|||
'position_y': 1
|
||||
}
|
||||
response = self.executeCreated(data=data, item=self.owned_id)
|
||||
self.owned.refresh_from_db()
|
||||
new_operation = response.data['new_operation']
|
||||
self.assertEqual(new_operation['result'], self.ks1.model.pk)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/create-operation', method='post')
|
||||
def test_create_operation_schema(self):
|
||||
self.populateData()
|
||||
|
@ -189,6 +223,7 @@ class TestOssOperations(EndpointTester):
|
|||
self.assertEqual(schema.location, self.owned.model.location)
|
||||
self.assertIn(self.user2, schema.getQ_editors())
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/delete-operation', method='patch')
|
||||
def test_delete_operation(self):
|
||||
self.executeNotFound(item=self.invalid_id)
|
||||
|
@ -214,6 +249,7 @@ class TestOssOperations(EndpointTester):
|
|||
self.assertEqual(len(response.data['operations']), 2)
|
||||
self.assertEqual(len(deleted_items), 0)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/create-input', method='patch')
|
||||
def test_create_input(self):
|
||||
self.populateData()
|
||||
|
@ -249,6 +285,7 @@ class TestOssOperations(EndpointTester):
|
|||
data['target'] = self.operation3.pk
|
||||
self.executeBadData(data=data)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/set-input', method='patch')
|
||||
def test_set_input_null(self):
|
||||
self.populateData()
|
||||
|
@ -283,6 +320,7 @@ class TestOssOperations(EndpointTester):
|
|||
self.assertEqual(self.operation1.title, self.ks1.model.title)
|
||||
self.assertEqual(self.operation1.description, self.ks1.model.description)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/set-input', method='patch')
|
||||
def test_set_input_change_schema(self):
|
||||
self.populateData()
|
||||
|
@ -317,6 +355,7 @@ class TestOssOperations(EndpointTester):
|
|||
self.operation1.refresh_from_db()
|
||||
self.assertEqual(self.operation1.result, self.ks2.model)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/update-operation', method='patch')
|
||||
def test_update_operation(self):
|
||||
self.populateData()
|
||||
|
@ -388,6 +427,7 @@ class TestOssOperations(EndpointTester):
|
|||
self.assertEqual(self.operation1.result.title, data['item_data']['title'])
|
||||
self.assertEqual(self.operation1.result.description, data['item_data']['description'])
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/update-operation', method='patch')
|
||||
def test_update_operation_invalid_substitution(self):
|
||||
self.populateData()
|
||||
|
@ -416,6 +456,7 @@ class TestOssOperations(EndpointTester):
|
|||
}
|
||||
self.executeBadData(data=data, item=self.owned_id)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/execute-operation', method='post')
|
||||
def test_execute_operation(self):
|
||||
self.populateData()
|
||||
|
|
|
@ -16,7 +16,8 @@ class TestOssViewset(EndpointTester):
|
|||
self.unowned_id = self.unowned.model.pk
|
||||
self.private = OperationSchema.create(title='Test2', alias='T2', access_policy=AccessPolicy.PRIVATE)
|
||||
self.private_id = self.private.model.pk
|
||||
self.invalid_id = self.private.model.pk + 1337
|
||||
self.invalid_id = self.private_id + 1337
|
||||
|
||||
|
||||
def populateData(self):
|
||||
self.ks1 = RSForm.create(
|
||||
|
@ -68,6 +69,7 @@ class TestOssViewset(EndpointTester):
|
|||
'substitution': self.ks2X1
|
||||
}])
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/details', method='get')
|
||||
def test_details(self):
|
||||
self.populateData()
|
||||
|
@ -117,6 +119,7 @@ class TestOssViewset(EndpointTester):
|
|||
self.executeOK(item=self.unowned_id)
|
||||
self.executeForbidden(item=self.private_id)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/update-layout', method='patch')
|
||||
def test_update_layout(self):
|
||||
self.populateData()
|
||||
|
@ -143,6 +146,7 @@ class TestOssViewset(EndpointTester):
|
|||
self.executeForbidden(data=data, item=self.unowned_id)
|
||||
self.executeForbidden(data=data, item=self.private_id)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/get-predecessor', method='post')
|
||||
def test_get_predecessor(self):
|
||||
self.populateData()
|
||||
|
|
|
@ -38,6 +38,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
if self.action in [
|
||||
'update_layout',
|
||||
'create_operation',
|
||||
'create_block',
|
||||
'delete_operation',
|
||||
'create_input',
|
||||
'set_input',
|
||||
|
@ -104,7 +105,10 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
@action(detail=True, methods=['post'], url_path='create-operation')
|
||||
def create_operation(self, request: Request, pk) -> HttpResponse:
|
||||
''' Create new operation. '''
|
||||
serializer = s.OperationCreateSerializer(data=request.data)
|
||||
serializer = s.OperationCreateSerializer(
|
||||
data=request.data,
|
||||
context={'oss': self.get_object()}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
oss = m.OperationSchema(self.get_object())
|
||||
|
@ -148,6 +152,57 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
}
|
||||
)
|
||||
|
||||
@extend_schema(
|
||||
summary='create block',
|
||||
tags=['OSS'],
|
||||
request=s.BlockCreateSerializer(),
|
||||
responses={
|
||||
c.HTTP_201_CREATED: s.NewBlockResponse,
|
||||
c.HTTP_400_BAD_REQUEST: None,
|
||||
c.HTTP_403_FORBIDDEN: None,
|
||||
c.HTTP_404_NOT_FOUND: None
|
||||
}
|
||||
)
|
||||
@action(detail=True, methods=['post'], url_path='create-block')
|
||||
def create_block(self, request: Request, pk) -> HttpResponse:
|
||||
''' Create new block. '''
|
||||
serializer = s.BlockCreateSerializer(
|
||||
data=request.data,
|
||||
context={'oss': self.get_object()}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
oss = m.OperationSchema(self.get_object())
|
||||
layout = serializer.validated_data['layout']
|
||||
children_blocks: list[m.Block] = serializer.validated_data['children_blocks']
|
||||
children_operations: list[m.Operation] = serializer.validated_data['children_operations']
|
||||
with transaction.atomic():
|
||||
new_block = oss.create_block(**serializer.validated_data['item_data'])
|
||||
layout['blocks'].append({
|
||||
'id': new_block.pk,
|
||||
'x': serializer.validated_data['position_x'],
|
||||
'y': serializer.validated_data['position_y'],
|
||||
'width': serializer.validated_data['width'],
|
||||
'height': serializer.validated_data['height'],
|
||||
})
|
||||
oss.update_layout(layout)
|
||||
if len(children_blocks) > 0:
|
||||
for block in children_blocks:
|
||||
block.parent = new_block
|
||||
m.Block.objects.bulk_update(children_blocks, ['parent'])
|
||||
if len(children_operations) > 0:
|
||||
for operation in children_operations:
|
||||
operation.parent = new_block
|
||||
m.Operation.objects.bulk_update(children_operations, ['parent'])
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_201_CREATED,
|
||||
data={
|
||||
'new_block': s.BlockSerializer(new_block).data,
|
||||
'oss': s.OperationSchemaSerializer(oss.model).data
|
||||
}
|
||||
)
|
||||
|
||||
@extend_schema(
|
||||
summary='delete operation',
|
||||
tags=['OSS'],
|
||||
|
|
|
@ -9,6 +9,7 @@ from apps.rsform.models import Constituenta, CstType, RSForm
|
|||
class TestConstituenta(TestCase):
|
||||
''' Testing Constituenta model. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
self.schema1 = RSForm.create(title='Test1')
|
||||
self.schema2 = RSForm.create(title='Test2')
|
||||
|
@ -47,6 +48,7 @@ class TestConstituenta(TestCase):
|
|||
self.assertEqual(cst.definition_resolved, '')
|
||||
self.assertEqual(cst.definition_raw, '')
|
||||
|
||||
|
||||
def test_extract_references(self):
|
||||
cst = Constituenta.objects.create(
|
||||
alias='X1',
|
||||
|
@ -57,6 +59,7 @@ class TestConstituenta(TestCase):
|
|||
)
|
||||
self.assertEqual(cst.extract_references(), set(['X1', 'X2', 'X3', 'X4', 'X5']))
|
||||
|
||||
|
||||
def text_apply_mapping(self):
|
||||
cst = Constituenta.objects.create(
|
||||
alias='X1',
|
||||
|
|
|
@ -9,6 +9,7 @@ from shared.DBTester import DBTester
|
|||
class TestRSForm(DBTester):
|
||||
''' Testing RSForm wrapper. '''
|
||||
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.user1 = User.objects.create(username='User1')
|
||||
|
@ -103,6 +104,7 @@ class TestRSForm(DBTester):
|
|||
self.assertEqual(x2.schema, self.schema.model)
|
||||
self.assertEqual(x1.order, 0)
|
||||
|
||||
|
||||
def test_create_cst(self):
|
||||
data = {
|
||||
'alias': 'X3',
|
||||
|
@ -194,6 +196,7 @@ class TestRSForm(DBTester):
|
|||
self.assertEqual(d1.definition_raw, '@{DEL|sing}')
|
||||
self.assertEqual(d1.term_raw, '@{X2|plur}')
|
||||
|
||||
|
||||
def test_apply_mapping(self):
|
||||
x1 = self.schema.insert_new('X1')
|
||||
x2 = self.schema.insert_new('X11')
|
||||
|
|
|
@ -138,6 +138,7 @@ class TestRSFormViewset(EndpointTester):
|
|||
self.assertEqual(response.data['typification'], 'LOGIC')
|
||||
self.assertEqual(response.data['valueClass'], 'value')
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/check-constituenta', method='post')
|
||||
def test_check_constituenta_error(self):
|
||||
self.owned.insert_new('X1')
|
||||
|
@ -145,6 +146,7 @@ class TestRSFormViewset(EndpointTester):
|
|||
response = self.executeOK(data=data, item=self.owned_id)
|
||||
self.assertEqual(response.data['parseResult'], False)
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/resolve', method='post')
|
||||
def test_resolve(self):
|
||||
x1 = self.owned.insert_new(
|
||||
|
|
|
@ -7,6 +7,7 @@ from apps.rsform.graph import Graph
|
|||
class TestGraph(unittest.TestCase):
|
||||
''' Test class for graph. '''
|
||||
|
||||
|
||||
def test_construction(self):
|
||||
graph = Graph()
|
||||
self.assertFalse(graph.contains(1))
|
||||
|
@ -26,6 +27,7 @@ class TestGraph(unittest.TestCase):
|
|||
self.assertTrue(graph.has_edge(1, 3))
|
||||
self.assertTrue(graph.has_edge(2, 1))
|
||||
|
||||
|
||||
def test_remove_node(self):
|
||||
graph = Graph({
|
||||
1: [2],
|
||||
|
@ -39,6 +41,7 @@ class TestGraph(unittest.TestCase):
|
|||
self.assertEqual(graph.outputs[1], [])
|
||||
self.assertEqual(len(graph.outputs), 3)
|
||||
|
||||
|
||||
def test_remove_edge(self):
|
||||
graph = Graph({
|
||||
1: [2],
|
||||
|
@ -53,6 +56,7 @@ class TestGraph(unittest.TestCase):
|
|||
self.assertEqual(graph.outputs[1], [])
|
||||
graph.remove_edge(1, 2)
|
||||
|
||||
|
||||
def test_expand_outputs(self):
|
||||
graph = Graph({
|
||||
1: [2],
|
||||
|
@ -67,6 +71,7 @@ class TestGraph(unittest.TestCase):
|
|||
self.assertEqual(graph.expand_outputs([7]), [])
|
||||
self.assertEqual(graph.expand_outputs([2, 5]), [3, 6, 1])
|
||||
|
||||
|
||||
def test_expand_inputs(self):
|
||||
graph = Graph({
|
||||
1: [2],
|
||||
|
@ -101,6 +106,7 @@ class TestGraph(unittest.TestCase):
|
|||
7: [6]
|
||||
})
|
||||
|
||||
|
||||
def test_topological_order(self):
|
||||
self.assertEqual(Graph().topological_order(), [])
|
||||
graph = Graph({
|
||||
|
@ -122,6 +128,7 @@ class TestGraph(unittest.TestCase):
|
|||
})
|
||||
self.assertEqual(graph.topological_order(), [5, 3, 2, 4, 1])
|
||||
|
||||
|
||||
def test_sort_stable(self):
|
||||
graph = Graph({
|
||||
1: [2],
|
||||
|
|
|
@ -8,6 +8,7 @@ from apps.rsform.utils import apply_pattern, fix_old_references
|
|||
class TestUtils(unittest.TestCase):
|
||||
''' Test various utility functions. '''
|
||||
|
||||
|
||||
def test_apply_mapping_patter(self):
|
||||
mapping = {'X101': 'X20'}
|
||||
pattern = re.compile(r'(X[0-9]+)')
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import os
|
||||
import runpy
|
||||
import sys
|
||||
|
||||
# Build the module path from the test file
|
||||
filepath = sys.argv[1]
|
||||
project_root = os.path.join(os.path.dirname(__file__))
|
||||
project_root = os.path.dirname(__file__)
|
||||
relpath = os.path.relpath(filepath, project_root)
|
||||
module_path = relpath.replace('/', '.').replace('\\', '.').rstrip('.py')
|
||||
module_path = relpath.replace('/', '.').replace('\\', '.').removesuffix('.py')
|
||||
|
||||
os.system(f"python manage.py test {module_path}")
|
||||
# Run manage.py in-process so breakpoints work
|
||||
sys.argv = ["manage.py", "test", module_path]
|
||||
runpy.run_path("manage.py", run_name="__main__")
|
||||
|
|
|
@ -14,6 +14,18 @@ def operationNotInOSS(title: str):
|
|||
return f'Операция не принадлежит ОСС: {title}'
|
||||
|
||||
|
||||
def parentNotInOSS():
|
||||
return f'Родительский блок не принадлежит ОСС'
|
||||
|
||||
|
||||
def childNotInOSS():
|
||||
return f'Дочерний элемент блок не принадлежит ОСС'
|
||||
|
||||
|
||||
def missingArguments():
|
||||
return 'Операция не содержит аргументов, при этом содержит отождествления'
|
||||
|
||||
|
||||
def exteorFileCorrupted():
|
||||
return 'Файл Экстеор не соответствует ожидаемому формату. Попробуйте сохранить файл в новой версии'
|
||||
|
||||
|
|
|
@ -5,9 +5,7 @@ import { schemaCstSubstitute } from '@/features/rsform/backend/types';
|
|||
|
||||
import { errorMsg } from '@/utils/labels';
|
||||
|
||||
/**
|
||||
* Represents {@link IOperation} type.
|
||||
*/
|
||||
/** Represents {@link IOperation} type. */
|
||||
export const OperationType = {
|
||||
INPUT: 'input',
|
||||
SYNTHESIS: 'synthesis'
|
||||
|
@ -20,10 +18,13 @@ export type ICstSubstituteInfo = z.infer<typeof schemaCstSubstituteInfo>;
|
|||
/** Represents {@link IOperation} data from server. */
|
||||
export type IOperationDTO = z.infer<typeof schemaOperation>;
|
||||
|
||||
/** Represents {@link IOperation} data from server. */
|
||||
export type IBlockDTO = z.infer<typeof schemaBlock>;
|
||||
|
||||
/** Represents backend data for {@link IOperationSchema}. */
|
||||
export type IOperationSchemaDTO = z.infer<typeof schemaOperationSchema>;
|
||||
|
||||
/** Represents {@link schemaOperation} layout. */
|
||||
/** Represents {@link IOperationSchema} layout. */
|
||||
export type IOssLayout = z.infer<typeof schemaOssLayout>;
|
||||
|
||||
/** Represents {@link IOperation} data, used in creation process. */
|
||||
|
@ -64,15 +65,21 @@ export const schemaOperation = z.strictObject({
|
|||
id: z.number(),
|
||||
operation_type: schemaOperationType,
|
||||
oss: z.number(),
|
||||
|
||||
alias: z.string(),
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
|
||||
parent: z.number().nullable(),
|
||||
result: z.number().nullable()
|
||||
});
|
||||
|
||||
export const schemaBlock = z.strictObject({
|
||||
id: z.number(),
|
||||
oss: z.number(),
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
parent: z.number().nullable()
|
||||
});
|
||||
|
||||
export const schemaCstSubstituteInfo = schemaCstSubstitute.extend({
|
||||
operation: z.number(),
|
||||
original_alias: z.string(),
|
||||
|
@ -81,20 +88,29 @@ export const schemaCstSubstituteInfo = schemaCstSubstitute.extend({
|
|||
substitution_term: z.string()
|
||||
});
|
||||
|
||||
export const schemaPosition = z.strictObject({
|
||||
export const schemaOperationPosition = z.strictObject({
|
||||
id: z.number(),
|
||||
x: z.number(),
|
||||
y: z.number()
|
||||
});
|
||||
|
||||
export const schemaBlockPosition = z.strictObject({
|
||||
id: z.number(),
|
||||
x: z.number(),
|
||||
y: z.number(),
|
||||
width: z.number(),
|
||||
height: z.number()
|
||||
});
|
||||
|
||||
export const schemaOssLayout = z.strictObject({
|
||||
operations: z.array(schemaPosition),
|
||||
blocks: z.array(schemaPosition)
|
||||
operations: z.array(schemaOperationPosition),
|
||||
blocks: z.array(schemaBlockPosition)
|
||||
});
|
||||
|
||||
export const schemaOperationSchema = schemaLibraryItem.extend({
|
||||
editors: z.number().array(),
|
||||
operations: z.array(schemaOperation),
|
||||
blocks: z.array(schemaBlock),
|
||||
layout: schemaOssLayout,
|
||||
arguments: z
|
||||
.object({
|
||||
|
|
Loading…
Reference in New Issue
Block a user