def remote_methods(self, fixture): """A RemoteMethod is a SubResource representing a method on the server side which can be invoked via POSTing to an URL.""" def callable_object(): return 'value returned from method' encoding = 'koi8_r' # Deliberate remote_method = RemoteMethod( 'amethod', callable_object, MethodResult(mime_type='ttext/hhtml', encoding=encoding)) @stubclass(Widget) class WidgetWithRemoteMethod(Widget): def __init__(self, view): super(WidgetWithRemoteMethod, self).__init__(view) view.add_resource(remote_method) wsgi_app = fixture.new_wsgi_app( view_slots={'main': WidgetWithRemoteMethod.factory()}) browser = Browser(wsgi_app) # By default you cannot GET, since the method is not immutable browser.open('/_amethod_method', status=405) # POSTing to the URL, returns the result of the method browser.post('/_amethod_method', {}) vassert(browser.raw_html == 'value returned from method') vassert(browser.last_response.charset == encoding) vassert(browser.last_response.content_type == 'ttext/hhtml')
def test_immutable_remote_methods(web_fixture, remote_method_fixture, sql_alchemy_fixture): """The database is always rolled back at the end of an immutable RemoteMethod.""" class TestObject(Base): __tablename__ = 'test_remotemethods_test_object' id = Column(Integer, primary_key=True) name = Column(UnicodeText) with sql_alchemy_fixture.persistent_test_classes(TestObject): def callable_object(): Session.add(TestObject(name='new object')) assert Session.query(TestObject).count() == 1 return 'value returned from method' remote_method = RemoteMethod(web_fixture.view, 'amethod', callable_object, MethodResult(), immutable=True, disable_csrf_check=True) assert remote_method.idempotent # Immutable methods are idempotent wsgi_app = remote_method_fixture.new_wsgi_app( remote_method=remote_method) browser = Browser(wsgi_app) browser.open('/_amethod_method') assert browser.raw_html == 'value returned from method' # The database is rolled back to ensure immutability assert Session.query(TestObject).count() == 0
def test_arguments_to_remote_methods(web_fixture, remote_method_fixture, argument_scenarios): """A RemoteMethod can get arguments from a query string or submitted form values, depending on the scenario.""" fixture = argument_scenarios def callable_object(**kwargs): fixture.method_kwargs = kwargs return '' remote_method = RemoteMethod(web_fixture.view, 'amethod', callable_object, MethodResult(), idempotent=fixture.idempotent, disable_csrf_check=True) wsgi_app = remote_method_fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) kwargs_sent = {'a': 'AAA', 'b': 'BBB'} if fixture.idempotent: browser.open('/_amethod_method?a=AAA&b=BBB') else: browser.post('/_amethod_method', kwargs_sent) assert fixture.method_kwargs == kwargs_sent
def test_remote_methods(web_fixture, remote_method_fixture): """A RemoteMethod is a SubResource representing a method on the server side which can be invoked via POSTing to an URL.""" fixture = remote_method_fixture def callable_object(): return 'value returned from method' encoding = 'koi8_r' # Deliberate remote_method = RemoteMethod(web_fixture.view, 'amethod', callable_object, MethodResult(mime_type='ttext/hhtml', encoding=encoding), disable_csrf_check=True) wsgi_app = fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) # By default you cannot GET, since the method is not immutable browser.open('/_amethod_method', status=405) # POSTing to the URL, returns the result of the method browser.post('/_amethod_method', {}) assert browser.raw_html == 'value returned from method' assert browser.last_response.charset == encoding assert browser.last_response.content_type == 'ttext/hhtml'
def test_remote_methods_via_ajax(web_fixture, remote_method_fixture): """A RemoteMethod can be called via AJAX with CSRF protection built-in.""" fixture = remote_method_fixture def callable_object(): return 'value returned from method' remote_method = RemoteMethod(web_fixture.view, 'amethod', callable_object, MethodResult(), disable_csrf_check=False) wsgi_app = fixture.new_wsgi_app(remote_method=remote_method, enable_js=True) web_fixture.reahl_server.set_app(wsgi_app) browser = web_fixture.driver_browser # Case: using jquery to POST to the method includes the necessary xsrf info automatically browser.open('/') browser.execute_script( '$.post("/_amethod_method", success=function(data){ $("body").attr("data-result", data) })' ) results = browser.execute_script('return $("body").attr("data-result")') assert results == 'value returned from method' # Case: POSTing without a csrf token breaks browser = Browser(wsgi_app) browser.post('/_amethod_method', {}, status=403)
def new_remote_method(self): fixture = self def callable_to_call(): fixture.method_called += 1 if fixture.exception: raise DomainException('ex') return RemoteMethod('amethod', callable_to_call, self.method_result, immutable=False)
def test_exception_handling(web_fixture, remote_method_fixture): """The RemoteMethod sends back the str() of an exception raised for the specified exception class.""" def fail(): raise Exception('I failed') remote_method = RemoteMethod(web_fixture.view, 'amethod', fail, MethodResult(catch_exception=Exception)) wsgi_app = remote_method_fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) browser.post('/_amethod_method', {}) assert browser.raw_html == 'I failed'
def exception_handling(self, fixture): """The RemoteMethod sends back the six.text_type() of an exception raised for the specified exception class.""" def fail(): raise Exception('I failed') remote_method = RemoteMethod('amethod', fail, MethodResult(catch_exception=Exception)) wsgi_app = fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) browser.post('/_amethod_method', {}) vassert(browser.raw_html == 'I failed')
def exception_handling_for_widgets(self, fixture): """How exceptions are handled with WidgetResult.""" def fail(): raise Exception('exception text') remote_method = RemoteMethod('amethod', fail, default_result=fixture.method_result) wsgi_app = fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) with expected(Exception): browser.post('/_amethod_method', {})
def new_remote_method(self): fixture = self def callable_to_call(): fixture.method_called += 1 if fixture.exception: raise DomainException('ex') return RemoteMethod(self.web_fixture.view, 'amethod', callable_to_call, self.method_result, immutable=False, disable_csrf_check=True)
def __init__(self, view): super(WidgetWithRemoteMethod, self).__init__(view) method_result = WidgetResult(fixture.WidgetStub(view), as_json_and_result=True) def change_something(): fixture.changes_made = True if fixture.exception: raise DomainException('ex') remote_method = RemoteMethod('amethod', change_something, default_result=method_result, immutable=False) view.add_resource(remote_method)
def exception_handling_for_json(self, fixture): """How exceptions are handled with JsonResult.""" def fail(): raise Exception('exception text') remote_method = RemoteMethod('amethod', fail, default_result=fixture.method_result) wsgi_app = fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) browser.post('/_amethod_method', {}) vassert(browser.raw_html == fixture.exception_response) vassert(browser.last_response.charset == fixture.expected_charset) vassert(browser.last_response.content_type == fixture.expected_content_type)
def different_kinds_of_result(self, fixture): """Different kinds of MethodResult can be specified for a method.""" def callable_object(): return fixture.value_to_return remote_method = RemoteMethod('amethod', callable_object, default_result=fixture.method_result) wsgi_app = fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) browser.post('/_amethod_method', {}) vassert( fixture.results_match(fixture.expected_response, browser.raw_html)) vassert(browser.last_response.charset == fixture.expected_charset) vassert(browser.last_response.content_type == fixture.expected_content_type)
def __init__(self, view): super().__init__(view) method_result = WidgetResult(fixture.WidgetStub(view), as_json_and_result=True) def change_something(): fixture.changes_made = True if fixture.exception: raise DomainException( message='breaking intentionally', handled_inline=fixture.handle_inline) remote_method = RemoteMethod(view, 'amethod', change_something, default_result=method_result, immutable=False, disable_csrf_check=True) view.add_resource(remote_method)
def test_exception_handling_for_widgets(web_fixture, remote_method_fixture, widget_result_scenario): """How exceptions are handled with WidgetResult.""" fixture = widget_result_scenario def fail(): raise Exception('exception text') remote_method = RemoteMethod(web_fixture.view, 'amethod', fail, default_result=fixture.method_result) wsgi_app = remote_method_fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) with expected(Exception): browser.post('/_amethod_method', {})
def immutable_remote_methods(self, fixture): """A RemoteMethod that is immutable is accessible via GET (instead of POST).""" def callable_object(): return 'value returned from method' remote_method = RemoteMethod('amethod', callable_object, MethodResult(), immutable=True) wsgi_app = fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) # GET, since the method is immutable browser.open('/_amethod_method') vassert(browser.raw_html == 'value returned from method') # POSTing to the URL, is not supported browser.post('/_amethod_method', {}, status=405)
def __init__(self, view): super(WidgetWithRemoteMethod, self).__init__(view) coactive_widgets = [ self.add_child( CoactiveWidgetStub(view, 'coactive1', [ self.add_child( CoactiveWidgetStub(view, 'coactive2', [])) ])) ] result_widget = self.add_child(CoactiveWidgetStub( view, 'main', [])) result_widget.add_child( CoactiveWidgetStub(view, 'child', coactive_widgets)) method_result = WidgetResult(result_widget, as_json_and_result=True) remote_method = RemoteMethod(view, 'amethod', lambda: None, default_result=method_result) view.add_resource(remote_method)
def test_idempotent_remote_methods(web_fixture, remote_method_fixture): """A RemoteMethod that is idempotent is accessible via GET (instead of POST).""" def callable_object(): return 'value returned from method' remote_method = RemoteMethod(web_fixture.view, 'amethod', callable_object, MethodResult(), idempotent=True) wsgi_app = remote_method_fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) # GET, since the method is idempotent browser.open('/_amethod_method') assert browser.raw_html == 'value returned from method' # POSTing to the URL, is not supported browser.post('/_amethod_method', {}, status=405)
def arguments_to_remote_methods(self, fixture): """A RemoteMethod can get arguments from a query string or submitted form values, depending on the scenario.""" def callable_object(**kwargs): fixture.method_kwargs = kwargs return '' remote_method = RemoteMethod('amethod', callable_object, MethodResult(), immutable=fixture.immutable) wsgi_app = fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) kwargs_sent = {'a': 'AAA', 'b': 'BBB'} if fixture.immutable: browser.open('/_amethod_method?a=AAA&b=BBB') else: browser.post('/_amethod_method', kwargs_sent) vassert(fixture.method_kwargs == kwargs_sent)
def test_different_kinds_of_result(web_fixture, remote_method_fixture, result_scenarios): """Different kinds of MethodResult can be specified for a method.""" fixture = result_scenarios def callable_object(): return fixture.value_to_return remote_method = RemoteMethod(web_fixture.view, 'amethod', callable_object, default_result=fixture.method_result) wsgi_app = remote_method_fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) browser.post('/_amethod_method', {}) assert fixture.results_match(fixture.expected_response, browser.raw_html) assert browser.last_response.charset == fixture.expected_charset assert browser.last_response.content_type == fixture.expected_content_type
def test_exception_handling_for_json(web_fixture, remote_method_fixture, json_result_scenario): """How exceptions are handled with JsonResult.""" fixture = json_result_scenario def fail(): raise Exception('exception text') remote_method = RemoteMethod(web_fixture.view, 'amethod', fail, default_result=fixture.method_result) wsgi_app = remote_method_fixture.new_wsgi_app(remote_method=remote_method) browser = Browser(wsgi_app) browser.post('/_amethod_method', {}) assert browser.raw_html == fixture.exception_response assert browser.last_response.charset == fixture.expected_charset assert browser.last_response.content_type == fixture.expected_content_type