def test_callable(self): """ Providing a callable child will result in that child being called, with no arguments, to produce the actual child value. """ E = ElementMaker() self.assertEqual('<tag><child /></tag>', tostring(E('tag', L.child))) self.assertEqual('<tag>hello</tag>', tostring(E('tag', lambda: 'hello')))
def test_elemfind(self): """ `elemfind` finds the first `QualifiedName` or path specified. """ self.assertEqual( '<child1 />', tostring(elemfind(self.root, 'child1'))) self.assertEqual( '<child2 />', tostring(elemfind(self.root, L.child2)))
def test_list(self): """ Providing a list child will result in all the elements of the list added individually. """ E = ElementMaker() self.assertEqual('<tag><child1 /><child2 /></tag>', tostring(E('tag', [L.child1, L.child2]))) self.assertEqual('<tag>text1text2</tag>', tostring(E('tag', ['text1', 'text2'])))
def test_typemap(self): """ Providing a type map to `ElementMaker` allows the caller to specify how to serialize types other than strings and dictionaries. """ E = ElementMaker(typemap={ float: lambda e, v: '%0.2f' % (v, ), int: lambda e, v: L.int(str(v)) }) self.assertEqual('<tag>2.50</tag>', tostring(E('tag', 2.5))) self.assertEqual('<tag><int>42</int></tag>', tostring(E('tag', 42)))
def test_list(self): """ Providing a list child will result in all the elements of the list added individually. """ E = ElementMaker() self.assertEqual( '<tag><child1 /><child2 /></tag>', tostring(E('tag', [L.child1, L.child2]))) self.assertEqual( '<tag>text1text2</tag>', tostring(E('tag', ['text1', 'text2'])))
def test_callable(self): """ Providing a callable child will result in that child being called, with no arguments, to produce the actual child value. """ E = ElementMaker() self.assertEqual( '<tag><child /></tag>', tostring(E('tag', L.child))) self.assertEqual( '<tag>hello</tag>', tostring(E('tag', lambda: 'hello')))
def test_simple(self): """ Calling `ElementMaker` instances produces ElementTree elements, children and attributes can be provided too. """ E = ElementMaker() self.assertEqual('<tag />', tostring(E('tag'))) self.assertEqual('<tag>hello</tag>', tostring(E('tag', 'hello'))) self.assertEqual('<tag key="value">hello</tag>', tostring(E('tag', 'hello', key='value'))) self.assertEqual('<tag key="value">hello</tag>', tostring(E('tag', 'hello', dict(key='value'))))
def test_element(self): """ `QualifiedName` instances are callable and produce ElementTree elements. """ qname = QualifiedName('tag') self.assertEqual('<tag />', tostring(qname())) self.assertEqual('<tag>hello</tag>', tostring(qname(u'hello'))) self.assertEqual('<tag key="value">hello</tag>', tostring(qname('hello', key='value'))) self.assertEqual('<tag key="value">hello</tag>', tostring(qname('hello', dict(key='value'))))
def test_typemap(self): """ Providing a type map to `ElementMaker` allows the caller to specify how to serialize types other than strings and dictionaries. """ E = ElementMaker(typemap={ float: lambda e, v: '%0.2f' % (v,), int: lambda e, v: L.int(str(v))}) self.assertEqual( '<tag>2.50</tag>', tostring(E('tag', 2.5))) self.assertEqual( '<tag><int>42</int></tag>', tostring(E('tag', 42)))
def test_namespaced(self): """ Tags that are `QualifiedName` instances or use Clark notation produce namespaced XML elements. """ E = ElementMaker() self.assertEqual('<ns0:tag xmlns:ns0="http://example.com" />', tostring(E('{http://example.com}tag'))) self.assertEqual( '<ns0:tag xmlns:ns0="http://example.com" />', tostring(QualifiedName('http://example.com', 'tag')())) ns = Namespace('http://example.com', 'ex') self.assertEqual('<ex:tag xmlns:ex="http://example.com" />', tostring(ns.tag()))
def test_nested(self): """ Children can themselves be ElementTree elements, resulting in nested elements. """ E = ElementMaker() self.assertEqual('<tag><child /></tag>', tostring(E('tag', E('child')))) self.assertEqual('<tag><child>hello</child></tag>', tostring(E('tag', E('child', 'hello')))) self.assertEqual('<tag><child key="value">hello</child></tag>', tostring(E('tag', E('child', 'hello', key='value')))) self.assertEqual( '<tag><child key="value">hello</child></tag>', tostring(E('tag', E('child', 'hello', dict(key='value')))))
def build(cls, code, body, header=None): """ Build a `MockResponse` containing a SOAP envelope. """ return cls( code=code, delivered_body=tostring(soap_envelope(body, header)))
def test_namespaced(self): """ Tags that are `QualifiedName` instances or use Clark notation produce namespaced XML elements. """ E = ElementMaker() self.assertEqual( '<ns0:tag xmlns:ns0="http://example.com" />', tostring(E('{http://example.com}tag'))) self.assertEqual( '<ns0:tag xmlns:ns0="http://example.com" />', tostring(QualifiedName('http://example.com', 'tag')())) ns = Namespace('http://example.com', 'ex') self.assertEqual( '<ex:tag xmlns:ex="http://example.com" />', tostring(ns.tag()))
def test_render_exceptions(self): """ `SmsNotificationService.render_POST` logs any exceptions that occur during processing and writes a SOAP fault back to the request. """ def process(*a, **kw): raise ValueError('What is this') service = SmsNotificationService(None, None) service.process = process request = DummyRequest([]) request.content = StringIO(tostring(soap_envelope('hello'))) d = request.notifyFinish() service.render_POST(request) self.successResultOf(d) self.assertEqual(http.INTERNAL_SERVER_ERROR, request.responseCode) failures = self.flushLoggedErrors(ValueError) self.assertEqual(1, len(failures)) self.assertEqual( { str(SOAP_ENV.Envelope): { str(SOAP_ENV.Body): { str(SOAP_ENV.Fault): { 'faultcode': 'soapenv:Server', 'faultstring': 'What is this' } } } }, element_to_dict(fromstring(''.join(request.written))))
def test_render_soap_fault(self): """ `SmsNotificationService.render_POST` logs any exceptions that occur during processing and writes a SOAP fault back to the request. If the logged exception is a `SoapFault` its ``to_element`` method is invoked to serialize the fault. """ service = SmsNotificationService(None, None) service.process = lambda *a, **kw: L.done() request = DummyRequest([]) request.content = StringIO(tostring(L.hello())) d = request.notifyFinish() service.render_POST(request) self.successResultOf(d) self.assertEqual(http.INTERNAL_SERVER_ERROR, request.responseCode) failures = self.flushLoggedErrors(SoapFault) self.assertEqual(1, len(failures)) self.assertEqual( { str(SOAP_ENV.Envelope): { str(SOAP_ENV.Body): { str(SOAP_ENV.Fault): { 'faultcode': 'soapenv:Client', 'faultstring': 'Malformed SOAP request' } } } }, element_to_dict(fromstring(''.join(request.written))))
def test_render_exceptions(self): """ `SmsNotificationService.render_POST` logs any exceptions that occur during processing and writes a SOAP fault back to the request. """ def process(*a, **kw): raise ValueError('What is this') service = SmsNotificationService(None, None) service.process = process request = DummyRequest([]) request.content = StringIO(tostring(soap_envelope('hello'))) d = request.notifyFinish() service.render_POST(request) self.successResultOf(d) self.assertEqual(http.INTERNAL_SERVER_ERROR, request.responseCode) failures = self.flushLoggedErrors(ValueError) self.assertEqual(1, len(failures)) self.assertEqual( {str(SOAP_ENV.Envelope): { str(SOAP_ENV.Body): { str(SOAP_ENV.Fault): { 'faultcode': 'soapenv:Server', 'faultstring': 'What is this'}}}}, element_to_dict(fromstring(''.join(request.written))))
def test_render_soap_fault(self): """ `SmsNotificationService.render_POST` logs any exceptions that occur during processing and writes a SOAP fault back to the request. If the logged exception is a `SoapFault` its ``to_element`` method is invoked to serialize the fault. """ service = SmsNotificationService(None, None) service.process = lambda *a, **kw: L.done() request = DummyRequest([]) request.content = StringIO(tostring(L.hello())) d = request.notifyFinish() service.render_POST(request) self.successResultOf(d) self.assertEqual(http.INTERNAL_SERVER_ERROR, request.responseCode) failures = self.flushLoggedErrors(SoapFault) self.assertEqual(1, len(failures)) self.assertEqual( {str(SOAP_ENV.Envelope): { str(SOAP_ENV.Body): { str(SOAP_ENV.Fault): { 'faultcode': 'soapenv:Client', 'faultstring': 'Malformed SOAP request'}}}}, element_to_dict(fromstring(''.join(request.written))))
def test_nested(self): """ Children can themselves be ElementTree elements, resulting in nested elements. """ E = ElementMaker() self.assertEqual( '<tag><child /></tag>', tostring(E('tag', E('child')))) self.assertEqual( '<tag><child>hello</child></tag>', tostring(E('tag', E('child', 'hello')))) self.assertEqual( '<tag><child key="value">hello</child></tag>', tostring(E('tag', E('child', 'hello', key='value')))) self.assertEqual( '<tag><child key="value">hello</child></tag>', tostring(E('tag', E('child', 'hello', dict(key='value')))))
def test_simple(self): """ Calling `ElementMaker` instances produces ElementTree elements, children and attributes can be provided too. """ E = ElementMaker() self.assertEqual( '<tag />', tostring(E('tag'))) self.assertEqual( '<tag>hello</tag>', tostring(E('tag', 'hello'))) self.assertEqual( '<tag key="value">hello</tag>', tostring(E('tag', 'hello', key='value'))) self.assertEqual( '<tag key="value">hello</tag>', tostring(E('tag', 'hello', dict(key='value'))))
def test_element(self): """ `QualifiedName` instances are callable and produce ElementTree elements. """ qname = QualifiedName('tag') self.assertEqual( '<tag />', tostring(qname())) self.assertEqual( '<tag>hello</tag>', tostring(qname(u'hello'))) self.assertEqual( '<tag key="value">hello</tag>', tostring(qname('hello', key='value'))) self.assertEqual( '<tag key="value">hello</tag>', tostring(qname('hello', dict(key='value'))))
def perform_soap_request(uri, action, body, header=None, expected_faults=None, http_request_full=http_request_full): """ Perform a SOAP request. If the remote server responds with an HTTP 500 status, then it is assumed that the body contains a SOAP fault, which is then parsed and a `SoapFault` exception raised. :param uri: SOAP endpoint URI. :param action: SOAP action. :param body: SOAP body that will appear in an envelope ``Body`` element. :param header: SOAP header that will appear in an envelope ``Header`` element, or ``None`` so omit the header. :param expected_faults: A `list` of `SoapFault` subclasses to be used to extract fault details from SOAP faults. :param http_request_full: Callable to perform an HTTP request, see `vumi.utils.http_request_full`. :return: `Deferred` that fires with the response, in the case of success, or a `SoapFault` in the case of failure. """ def _parse_soap_response(response): root = fromstring(response.delivered_body) body, header = unwrap_soap_envelope(root) if response.code == http.INTERNAL_SERVER_ERROR: raise SoapFault.from_element(body, expected_faults) return body, header envelope = soap_envelope(body, header) headers = { 'SOAPAction': action, 'Content-Type': 'text/xml; charset="utf-8"' } d = http_request_full(uri, tostring(envelope), headers) d.addCallback(_parse_soap_response) return d
def test_render(self): """ `SmsNotificationService.render_POST` parses a SOAP request and dispatches it to `SmsNotificationService.process` for processing. """ service = SmsNotificationService(None, None) service.process = lambda *a, **kw: L.done() request = DummyRequest([]) request.content = StringIO(tostring(soap_envelope('hello'))) d = request.notifyFinish() service.render_POST(request) self.successResultOf(d) self.assertEqual(http.OK, request.responseCode) self.assertEqual( {str(SOAP_ENV.Envelope): { str(SOAP_ENV.Body): { 'done': None}}}, element_to_dict(fromstring(''.join(request.written))))
def test_render(self): """ `SmsNotificationService.render_POST` parses a SOAP request and dispatches it to `SmsNotificationService.process` for processing. """ service = SmsNotificationService(None, None) service.process = lambda *a, **kw: L.done() request = DummyRequest([]) request.content = StringIO(tostring(soap_envelope('hello'))) d = request.notifyFinish() service.render_POST(request) self.successResultOf(d) self.assertEqual(http.OK, request.responseCode) self.assertEqual( {str(SOAP_ENV.Envelope): { str(SOAP_ENV.Body): { 'done': None } }}, element_to_dict(fromstring(''.join(request.written))))
def perform_soap_request(uri, action, body, header=None, expected_faults=None, http_request_full=http_request_full): """ Perform a SOAP request. If the remote server responds with an HTTP 500 status, then it is assumed that the body contains a SOAP fault, which is then parsed and a `SoapFault` exception raised. :param uri: SOAP endpoint URI. :param action: SOAP action. :param body: SOAP body that will appear in an envelope ``Body`` element. :param header: SOAP header that will appear in an envelope ``Header`` element, or ``None`` so omit the header. :param expected_faults: A `list` of `SoapFault` subclasses to be used to extract fault details from SOAP faults. :param http_request_full: Callable to perform an HTTP request, see `vumi.utils.http_request_full`. :return: `Deferred` that fires with the response, in the case of success, or a `SoapFault` in the case of failure. """ def _parse_soap_response(response): root = fromstring(response.delivered_body) body, header = unwrap_soap_envelope(root) if response.code == http.INTERNAL_SERVER_ERROR: raise SoapFault.from_element(body, expected_faults) return body, header envelope = soap_envelope(body, header) headers = { 'SOAPAction': action, 'Content-Type': 'text/xml; charset="utf-8"'} d = http_request_full(uri, tostring(envelope), headers) d.addCallback(_parse_soap_response) return d
def test_elemfind(self): """ `elemfind` finds the first `QualifiedName` or path specified. """ self.assertEqual('<child1 />', tostring(elemfind(self.root, 'child1'))) self.assertEqual('<child2 />', tostring(elemfind(self.root, L.child2)))
def _writeResponse(response): request.setHeader('Content-Type', 'text/xml; charset="utf-8"') request.write(tostring(soap_envelope(response))) request.finish()
def build(cls, code, body, header=None): """ Build a `MockResponse` containing a SOAP envelope. """ return cls(code=code, delivered_body=tostring(soap_envelope(body, header)))