def test_raise_for_type_mismatch(story, typ, val): command_conf = {'type': typ} line = {'ln': '10'} valid = False if typ == 'string' and isinstance(val, str): valid = True elif typ == 'int' and isinstance(val, int): valid = True elif typ == 'float' and isinstance(val, float): valid = True elif typ == 'list' and isinstance(val, list): valid = True elif typ == 'map' and isinstance(val, dict): valid = True elif typ == 'boolean' and isinstance(val, bool): valid = True elif typ == 'any': valid = True if valid: Services.raise_for_type_mismatch(story, line, 'arg_name', val, command_conf) else: with pytest.raises(ArgumentTypeMismatchError): Services.raise_for_type_mismatch(story, line, 'arg_name', val, command_conf)
async def test_services_execute_args(story, async_mock): handler = async_mock(return_value='output') Services.register_internal('my_service', 'my_command', {'arg1': {'type': 'string'}}, 'any', handler) assert Services.is_internal('my_service', 'my_command') is True line = { Line.service: 'my_service', Line.command: 'my_command', Line.method: 'execute', 'args': [ { '$OBJECT': 'argument', 'name': 'arg1', 'argument': { '$OBJECT': 'string', 'string': 'Hello world!' } } ] } assert await Services.execute(story, line) == 'output' handler.mock.assert_called_with(story=story, line=line, resolved_args={'arg1': 'Hello world!'})
def test_parse_output_invalid_type(story): command_conf = { 'output': { 'type': 'foo' } } with pytest.raises(StoryscriptError): Services.parse_output(command_conf, 'blah', story, {}, '')
def test_parse_output_invalid_cast(story): command_conf = { 'output': { 'type': 'int' } } with pytest.raises(StoryscriptError): Services.parse_output(command_conf, 'not_an_int', story, {}, '')
def test_raise_for_type_mismatch_enum(story, val): command_conf = {'type': 'enum', 'enum': ['a', 'b', 'c']} if val in command_conf['enum']: Services.raise_for_type_mismatch(story, {}, 'arg_name', val, command_conf) else: with pytest.raises(ArgumentTypeMismatchError): Services.raise_for_type_mismatch(story, {}, 'arg_name', val, command_conf)
async def test_services_execute_execute_internal(story, async_mock): handler = async_mock(return_value='output') Services.register_internal('my_service', 'my_command', {}, 'any', handler) assert Services.is_internal('my_service', 'my_command') is True line = { Line.service: 'my_service', Line.command: 'my_command', Line.method: 'execute' } assert await Services.execute(story, line) == 'output'
def test_service_get_command_conf_events(story): chain = deque( [Service('service'), Command('cmd'), Event('foo'), Command('bar')]) story.app.services = { 'service': { 'configuration': { 'actions': { 'cmd': { 'events': { 'foo': { 'output': { 'actions': { 'bar': { 'a': 'b' } } } } } } } } } } assert Services.get_command_conf(story, chain) == {'a': 'b'}
def test_multipart_producer(): w = Writer() boundary = str(uuid.uuid4()) body = { 'simple_arg': FormField('simple_arg', 10), 'simple_arg2': FormField('simple_arg2', 'hello'), 'hello_file': FileFormField('f1', 'hello world'.encode(), 'hello.txt', 'text/plain') } list(Services._multipart_producer(body, boundary, w.write)) expected = ( f'--{boundary}\r\n' 'Content-Disposition: form-data; name="simple_arg"\r\n' '\r\n' '10' '\r\n' f'--{boundary}\r\n' 'Content-Disposition: form-data; name="simple_arg2"\r\n' '\r\n' 'hello' '\r\n' f'--{boundary}\r\n' 'Content-Disposition: form-data; name="f1"; filename="hello.txt"\r\n' 'Content-Type: text/plain\r\n' '\r\n' 'hello world' '\r\n' f'--{boundary}--\r\n') assert w.out == expected
def test_parse_output(output_type, story): line = {} command_conf = {'output': {'type': output_type}} expected_output = None actual_input = None if output_type == 'string': actual_input = 'hello' expected_output = 'hello' elif output_type == 'int': actual_input = b'10' expected_output = 10 elif output_type == 'float': actual_input = b'7.0' expected_output = 7.0 elif output_type == 'boolean': actual_input = f'true' expected_output = True elif output_type is None: actual_input = None expected_output = None elif output_type == 'any': actual_input = b'empty' expected_output = b'empty' assert Services.parse_output(command_conf, actual_input, story, line, '') == expected_output
def test_smart_insert(patch, story, value): patch.object(Services, 'raise_for_type_mismatch') command_conf = {'type': 'string'} m = {} key = 'my_key' if isinstance(value, dict) or isinstance(value, list): expected = json.dumps(value) else: expected = value Services.smart_insert(story, {}, command_conf, key, value, m) Services.raise_for_type_mismatch.assert_called_with( story, {}, key, expected, command_conf) assert m[key] == expected
async def test_services_execute_execute_external(patch, story, async_mock): patch.object(Services, 'execute_external', new=async_mock()) assert Services.is_internal('foo_service', 'blah') is False line = { Line.service: 'foo_service', Line.command: 'foo_command', Line.method: 'execute' } assert await Services.execute(story, line) \ == await Services.execute_external()
def test_service_get_command_conf_simple(story): chain = deque([Service('service'), Command('cmd')]) story.app.services = { 'service': { 'configuration': { 'actions': { 'cmd': {'x': 'y'} } } } } assert Services.get_command_conf(story, chain) == {'x': 'y'}
def test_services_log_registry(logger): Services.init(logger) Services.register_internal('my_service', 'my_command', {}, 'any', None) Services.log_internal() logger.log_raw.assert_called_with( 'info', 'Discovered internal service my_service - [\'my_command\']')
def test_resolve_chain(story): """ The story tested here is: alpine echo as client when client foo as echo_helper alpine echo echo_helper sonar # This isn't possible, but OK. echo_helper sonar """ story.app.services = { 'alpine': {} } story.tree = { '1': { Line.method: 'execute', Line.service: 'alpine', Line.command: 'echo', Line.enter: '2', Line.output: ['client'] }, '2': { Line.method: 'when', Line.service: 'client', Line.command: 'foo', Line.parent: '1', Line.output: ['echo_helper'] }, '3': { Line.method: 'execute', Line.service: 'alpine', Line.command: 'echo', Line.parent: '2', Line.enter: '4' }, '4': { Line.method: 'execute', Line.service: 'echo_helper', Line.command: 'sonar', Line.parent: '3' }, '5': { Line.method: 'execute', Line.service: 'echo_helper', Line.command: 'sonar', Line.parent: '2' } } assert Services.resolve_chain(story, story.tree['1']) \ == deque([Service(name='alpine'), Command(name='echo')]) assert Services.resolve_chain(story, story.tree['2']) \ == deque([Service(name='alpine'), Command(name='echo'), Event(name='foo')]) assert Services.resolve_chain(story, story.tree['3']) \ == deque([Service(name='alpine'), Command(name='echo')]) assert Services.resolve_chain(story, story.tree['4']) \ == deque([Service(name='alpine'), Command(name='echo'), Event(name='foo'), Command(name='sonar')]) assert Services.resolve_chain(story, story.tree['5']) \ == deque([Service(name='alpine'), Command(name='echo'), Event(name='foo'), Command(name='sonar')])
def test_set_logger(logger): Services.set_logger(logger) assert Services.logger == logger
def test_convert_bytes_to_string(): assert Services._convert_bytes_to_string(b'hello') == 'hello' assert Services._convert_bytes_to_string('hello') == 'hello'