def test_required_fields(self): # -- missing id with pytest.raises(TypeError): Domain(name='hi') # -- missing name with pytest.raises(TypeError): Domain(id='hi')
def test_arguments_are_saved(self): m = Meta(title='hi there', description='this is it', domain=Domain(id='d', name='d')) assert m.title == 'hi there' assert m.description == 'this is it' assert m.domain == Domain(id='d', name='d')
def test_conf__is_saved_on_function(self): source = TestCommands.post.command_conf.pop('source') assert TestCommands.post.command_conf == { 'name': 'MAKE_IT', 'method': 'post', 'meta': Meta(title='hi there', description='it is made for all', domain=Domain(id='test', name='test management')), 'access': Access(access_list=['PREMIUM', 'SUPER_PREMIUM']), 'input': Input(body_parser=TestCommands.BodyParser), 'output': Output(serializer=TestCommands.ClientSerializer), 'is_atomic': False, 'fn': TestCommands.post.command_conf['fn'], } assert source.filepath == '/tests/test_base/test_command.py' assert source.start_line == 117 assert source.end_line == 131
class HttpView(View): @command(name='HTTP_IT', meta=Meta(title='http it', description='http it', domain=Domain(id='d', name='d')), access=Access(access_list=[])) def get(self, request): return HttpResponse('http it!')
def test_required_fields(self): # -- missing title with pytest.raises(TypeError): Meta(domain=Domain(id='d', name='d')) # -- missing domain with pytest.raises(TypeError): Meta(title='hi there')
class TestReturnCommands(HTTPCommands): @command(name='ATOMIC', meta=Meta(title='atomic', description='atomic it...', domain=Domain(id='atomic', name='atomic')), is_atomic='default') def get(self, request): return self.event.Executed(event='ATOMIC', context=request, data={})
class DoAndGoCommands(HTTPCommands): @command(name='DO_AND_GO', meta=Meta(title='do and go', domain=Domain(id='test', name='test management')), access=Access(access_list=['PREMIUM'])) def post(self, request): raise self.event.Redirect('DONE_SO_GO', redirect_uri='http://go.there.org')
def test_serialization(self): d = Domain(id='super', name='Super Management') assert DomainSerializer(d).data == { '@type': 'domain', 'id': 'super', 'name': 'Super Management', }
class HttpCommands(HTTPCommands): @command( name='HTTP_IT', meta=Meta(title='http', description='http it...', domain=Domain(id='http', name='http')), ) def get(self, request): return HttpResponse('hello world')
def test_invalid_id(self): with pytest.raises(EventFactory.BrokenRequest) as e: Domain(id='cards manager', name='...') assert e.value.event == 'BROKEN_ARGS_DETECTED' assert e.value.data == { '@event': 'BROKEN_ARGS_DETECTED', '@type': 'error', 'errors': { 'id': [ 'should not contain white characters.', ] } }
def test_serialization(self): m = Meta(title='hi there', description='this is it', domain=Domain(id='a', name='aaa')) assert MetaSerializer(m).data == { '@type': 'meta', 'title': 'hi there', 'description': 'this is it', 'domain': { '@type': 'domain', 'id': 'a', 'name': 'aaa', }, }
class GenericCommands(HTTPCommands): @command( name='GET_IT', meta=Meta(title='get', description='get it...', domain=Domain(id='get', name='get')), ) def get(self, request): status_code = int(request.GET['status_code']) raise self.event.Generic(status_code=status_code, content=json.dumps({ '@event': 'FOUND_IT', '@type': 'what', 'hi': status_code, }))
class BrokenSerializerCommands(HTTPCommands): class ClientSerializer(serializers.Serializer): _type = 'client' card_id = serializers.SerializerMethodField() def get_card_id(self, instance): raise EventFactory.AccessDenied('GO_AWAY') @command(name='BREAK_SERIALIZER', meta=Meta(title='break it', domain=Domain(id='test', name='test management')), output=Output(serializer=ClientSerializer), access=Access(access_list=['PREMIUM', 'SUPER_PREMIUM'])) def post(self, request): raise self.event.Executed(event='NEVER_REACH_IT', instance=FakeClient(name="Jake"))
class SampleView(View): @command(name='POST_IT', meta=Meta(title='post it', description='post it', domain=Domain(id='d', name='d')), access=Access(access_list=[]), output=Output(serializer=SampleSerializer)) def post(self, request): raise self.event.Created(event='CREATED', context=request, data={'hello': 'post'}) @command(name='GET_IT', meta=Meta(title='get it', description='get it', domain=Domain(id='d', name='d')), access=Access(access_list=[]), output=Output(serializer=SampleSerializer)) def get(self, request): _type = request.GET.get('type') if _type in ['a', None]: raise self.event.Executed(event='LISTED', context=request, data={'hello': 'get.a'}) if _type == 'b': raise self.event.Executed(event='LISTED', context=request, data={'hello': 'get.b'}) if _type == 'c': raise self.event.Executed(event='LISTED_AGAIN', context=request, data={'hello': 'get.c'}) if _type == 'd': raise self.event.DoesNotExist(event='ERROR_LISTED', context=request, data={'hello': 'get.d'}) @command(name='PUT_IT', meta=Meta(title='put it', description='put it', domain=Domain(id='d', name='d')), access=Access(access_list=[]), output=Output(serializer=SampleSerializer)) def put(self, request): raise self.event.Executed(event='UPDATED', context=request, data={'hello': 'put'}) @command(name='DELETE_IT', meta=Meta(title='delete it', description='delete it', domain=Domain(id='d', name='d')), access=Access(access_list=[]), output=Output(serializer=SampleSerializer)) def delete(self, request): raise self.event.Executed(event='DELETED', context=request, data={'hello': 'delete'})
def test_arguments_are_saved(self): d = Domain(id='cards', name='Cards Management') assert d.id == 'cards' assert d.name == 'Cards Management'
def test_transform_description(description, expected): m = Meta(title='...', domain=Domain(id='d', name='d')) assert m.transform_description(description) == expected
class TestCommands(HTTPCommands): class BodyParser(parsers.Parser): name = parsers.CharField() age = parsers.IntegerField() class ClientSerializer(serializers.ModelSerializer): _type = 'client' card_id = serializers.SerializerMethodField() def get_access(self, instance): return [(TestCommands.put, True)] class Meta: model = FakeClient fields = ('name', 'card_id') def get_card_id(self, instance): return 190 class SimpleSerializer(serializers.Serializer): _type = 'simple' amount = serializers.IntegerField() @command(name='MAKE_IT', meta=Meta(title='hi there', description='it is made for all', domain=Domain(id='test', name='test management')), input=Input(body_parser=BodyParser), output=Output(serializer=ClientSerializer), access=Access(access_list=['PREMIUM', 'SUPER_PREMIUM'])) def post(self, request, user_id): raise self.event.Executed(event='MADE_IT', instance=FakeClient(name="Jake")) @command(name='GET_IT', meta=Meta(title='get', description='get it...', domain=Domain(id='get', name='get')), output=Output(serializer=ClientSerializer)) def get(self, request): raise self.event.Executed(event='GET_IT', instance=FakeClient(name="Jake")) @command(name='BREAK', meta=Meta(title='break', description='break it...', domain=Domain(id='break', name='break')), output=Output(serializer=SimpleSerializer)) def put(self, request): raise self.event.Executed(event='BROKEN', context=request, data=json.loads(request.body.decode('utf8'))) @command(name='ATOMIC', meta=Meta(title='atomic', description='atomic it...', domain=Domain(id='atomic', name='atomic')), is_atomic='default') def delete(self, request): self.some_stuff() raise self.event.Executed(event='ATOMIC', context=request, data={}) def some_stuff(self): pass
def test_render(self): self.mocker.patch.object(BaseRenderer, 'render').return_value = { 'LIST_ITEMS': { 'path_conf': { 'path': '/items/', 'parameters': {} }, 'method': 'get', 'meta': Meta( title='hi there', description='what?', domain=Domain(id='d', name='items management')), }, 'CREATED': { 'path_conf': { 'path': '/items/', 'parameters': {} }, 'method': 'post', 'meta': Meta( title='hi there', description='what?', domain=Domain(id='d', name='items management')), }, } self.mocker.patch.object( MarkdownRenderer, 'get_examples' ).return_value = { 'CREATED': { '201 (CREATED)': { 'response': { 'content_type': 'application/json', 'status': 201, 'content': { 'user_id': 434, '@event': 'CREATED', } }, 'request': { 'path': 'hello/hi', 'headers': { 'HI-THERE': 'JSON', }, 'content': { 'hi': 'there' } }, 'description': 'CREATE', 'method': 'post' }, }, 'LIST_ITEMS': { '200 (LISTED)': { 'response': { 'content_type': 'application/json', 'status': 200, 'content': { 'user_id': 434, '@event': 'LISTED', } }, 'request': { 'path': 'wat/178', 'headers': { 'HI-THERE': 'JSON', } }, 'description': 'SERVER_ERROR', 'method': 'get' }, '502 (SERVER_ERROR)': { 'response': { 'content_type': 'application/json', 'status': 502, 'content': { 'user_id': 434, '@type': 'error', '@event': 'SERVER_ERROR', } }, 'request': { 'path': 'hello/world', 'headers': { 'HI-THERE': 'JSON', } }, 'description': 'SERVER_ERROR', 'method': 'get' }, } } assert remove_white_chars( MarkdownRenderer(Mock()).render() ) == remove_white_chars(''' # CoSphere API CoSphere's API with hypermedia links ## items management ### CREATED: POST /items/ hi there what? #### 201 (CREATED) Request: ```http POST hello/hi HTTP/1.1 HI-THERE: JSON { "hi": "there" } ``` Respone: ```json { "@event": "CREATED", "user_id": 434 } ``` ### LIST_ITEMS: GET /items/ hi there what? #### 200 (LISTED) Request: ```http GET wat/178 HTTP/1.1 HI-THERE: JSON ``` Respone: ```json { "@event": "LISTED", "user_id": 434 } ``` #### 502 (SERVER_ERROR) Request: ```http GET hello/world HTTP/1.1 HI-THERE: JSON ``` Respone: ```json { "@event": "SERVER_ERROR", "@type": "error", "user_id": 434 } ``` ''')
class EntryPointCommands(HTTPCommands): class EntryPointSerializer(serializers.Serializer): class VersionInfoSerializer(serializers.Serializer): _type = 'version_info' deployed = serializers.CharField() displayed = serializers.CharField() available = serializers.ListField(child=serializers.CharField()) _type = 'entrypoint' version_info = VersionInfoSerializer() name = serializers.CharField() commands = serializers.DictField(child=CommandSerializer()) enums = serializers.ListField(child=serializers.DictField()) class QueryParser(parsers.Parser): commands = parsers.ListField(child=parsers.CharField(), default=None) with_schemas = parsers.BooleanField(default=True) is_private = parsers.BooleanField(default=None) domain_id = parsers.CharField(default=None) version = parsers.CharField(default=None) @command( name=name.Read('ENTRY_POINT'), meta=Meta(title='Read Entry Point', description=''' Serve Service Entry Point data: - current or chosen version of the service - list of all available commands together with their configurations - examples collected for a given service. ''', domain=Domain(id='docs', name='Docs Management')), access=Access( is_private=True, access_list=settings.LILY_ENTRYPOINT_COMMANDS_ACCESS_LIST), input=Input(query_parser=QueryParser), output=Output(serializer=EntryPointSerializer), ) def get(self, request): command_names = request.input.query['commands'] is_private = request.input.query['is_private'] domain_id = request.input.query['domain_id'] version = request.input.query['version'] config = Config() commands = self.get_commands(version) enums = commands.pop('enums') if command_names: commands = { command_name: commands[command_name] for command_name in command_names } if is_private is not None: commands = { name: command for name, command in commands.items() if command['access']['is_private'] == is_private } if domain_id: commands = { name: command for name, command in commands.items() if command['meta'] ['domain']['id'].lower() == domain_id.lower() } raise self.event.Read({ 'name': config.name, 'version_info': { 'deployed': config.version, 'displayed': version or config.version, 'available': self.get_available_versions(), }, 'commands': commands, 'enums': enums, }) def get_available_versions(self): commands_dir_path = os.path.join(Config.get_lily_path(), 'commands') return sorted([ commands_file.replace('.json', '') for commands_file in os.listdir(commands_dir_path) ], key=lambda x: [int(e) for e in x.split('.')], reverse=True) def get_commands(self, version=None): config = Config() version = version or config.version commands_dir_path = os.path.join(Config.get_lily_path(), 'commands') commands_path = os.path.join(commands_dir_path, f'{version}.json') with open(commands_path, 'r') as f: return json.loads(f.read())