def test_regenerating_method_results(reahl_system_fixture, web_fixture, remote_method_fixture, regenerate_method_result_scenarios): """If a MethodResult is set up to replay_request=True, the view it is part of (and thus itself) is recreated before the (new incarnation of the) MethodResult generates its actual response. Replaying the request means recreating all Widgets on the current View as well as the MethodResult itself. The construction of any of these objects may happen differently because of the changes made during the RemoteMethod's execution. Replaying the request ensures that the MethodResult reflects such changes, yet ensures that the RemoteMethod is not executed twice. """ wsgi_app = remote_method_fixture.new_wsgi_app( remote_method=regenerate_method_result_scenarios.remote_method) browser = Browser(wsgi_app) import sqlalchemy.orm @stubclass(sqlalchemy.orm.Session) class TransactionStub: is_active = True def commit(self): pass def rollback(self): pass def wrapped_nested_transaction(): return web_fixture.nested_transaction web_fixture.nested_transaction = TransactionStub() with replaced(Session().begin_nested, wrapped_nested_transaction): with CallMonitor(web_fixture.nested_transaction.commit) as monitor: browser.post('/_amethod_method', {}) assert browser.raw_html == regenerate_method_result_scenarios.expected_response assert monitor.times_called == 2
def test_web_session_handling(reahl_system_fixture, web_fixture): """The core web framework (this egg) does not implement a notion of session directly. It relies on such a notion, but expects an implementation for this to be supplied. An implementation should implement the UserSessionProtocol. The implementation is thus responsible for associating an instance of itself with the current request. The implementation to be used is set in the web.session_class configuration setting. The framework ensures that an instance of web.session_class is available during any Request. The database is committed before any user code executes, so that any database activity done by web.session_class would be committed even if an exception in the user code occurs. After user code is executed, methods are called on the web.session_class so that it can set its key on the response and save the last_activity_time. Finally, another commit is issued to the database so that any database activity during these last actions would also be saved. """ stubclass(UserSessionProtocol) class UserSessionStub(UserSessionProtocol): session = None last_activity_time_set = False key_is_set = False @classmethod def for_current_session(cls): assert None, 'Not implemented' @classmethod def get_or_create_session(cls): cls.session = cls() return cls.session @classmethod def initialise_web_session_on(cls, context): context.session = cls.get_or_create_session() def set_session_key(self, response): self.key_is_set = True self.saved_response = response def is_active(self): pass def is_secured(self): pass def set_as_logged_in(self, party, stay_logged_in): pass def log_out(self): pass def set_last_activity_time(self): self.last_activity_time_set = True def get_interface_locale(self): return 'en_gb' import sqlalchemy.orm @stubclass(sqlalchemy.orm.Session) class TransactionStub: is_active = True def commit(self): pass def rollback(self): pass web_fixture.nested_transaction = TransactionStub() def wrapped_nested_transaction(): return web_fixture.nested_transaction with replaced(Session().begin_nested, wrapped_nested_transaction): # Setting the implementation in config web_fixture.config.web.session_class = UserSessionStub with CallMonitor(web_fixture.nested_transaction.commit) as monitor: @stubclass(Resource) class ResourceStub: should_commit = True def cleanup_after_transaction(self): assert monitor.times_called == 2 # The database has been committed after user code started executed, before cleanup def handle_request(self, request): context = ExecutionContext.get_context() assert context.session is UserSessionStub.session # By the time user code executes, the session is set assert monitor.times_called == 1 # The database has been committed before user code started executing assert context.session.last_activity_time_set assert not UserSessionStub.session.key_is_set return Response() @stubclass(ReahlWSGIApplication) class ReahlWSGIApplicationStub2(ReahlWSGIApplicationStub): def resource_for(self, request): return ResourceStub() browser = Browser(ReahlWSGIApplicationStub2(web_fixture.config)) # A session is obtained, and the correct params passed to the hook methods assert not UserSessionStub.session # Before the request, the session is not yet set assert monitor.times_called == 0 # ... and the database is not yet committed browser.open('/') assert monitor.times_called == 2 # The database is committed to save session changes before user code and again after user code executed assert UserSessionStub.session # The session was set assert UserSessionStub.session.key_is_set # The set_session_key was called assert UserSessionStub.session.saved_response.status_int is 200 # The correct response was passed to set_session_key assert UserSessionStub.session.last_activity_time_set # set_last_activity_time was called