def test_bad_callback_objects_raise_exception(self): inst = Sijax() try: inst.execute_callback(callback='non-callable object', args=[]) self.fail('SijaxError not raised when bad callback was given!') except SijaxError: pass
def test_bad_callback_objects_raise_exception(self): inst = Sijax() try: inst.execute_callback(callback='non-callable object', args=[]) self.fail('SijaxError not raised when bad callback was given!') except SijaxError: pass
def test_regular_functions_that_yield_are_not_allowed(self): # Yielding is only supported by streaming functions. # It makes no sense for regular functions to use it. # If a regular function tries to yield, we expect # a SijaxError to be raised inst = Sijax() def callback(obj_response): yield obj_response try: inst.execute_callback([], callback) self.fail("Yielding regular function didn't raise expected exception!") except SijaxError: pass
def test_regular_functions_that_yield_are_not_allowed(self): # Yielding is only supported by streaming functions. # It makes no sense for regular functions to use it. # If a regular function tries to yield, we expect # a SijaxError to be raised inst = Sijax() def callback(obj_response): yield obj_response try: inst.execute_callback([], callback) self.fail( "Yielding regular function didn't raise expected exception!") except SijaxError: pass
def test_executing_regular_callbacks_works(self): from types import StringType calls_history = [] call_args_history = [] def event_before(obj_response): self.assertTrue(isinstance(obj_response, BaseResponse)) calls_history.append("before") obj_response.script("javascript here..") def event_after(obj_response): self.assertTrue(isinstance(obj_response, BaseResponse)) calls_history.append("after") obj_response.css("#element", "backgroundColor", "red") def callback_main(obj_response, arg1, arg2): self.assertTrue(isinstance(obj_response, BaseResponse)) calls_history.append("main") call_args_history.append(arg1) call_args_history.append(arg2) obj_response.alert("alert from main") inst = Sijax() cls = inst.__class__ inst.register_event(cls.EVENT_BEFORE_PROCESSING, event_before) inst.register_event(cls.EVENT_AFTER_PROCESSING, event_after) call_args = ["arg1", 15] response = inst.execute_callback(call_args, callback=callback_main) self.assertEqual(["before", "main", "after"], calls_history) self.assertEqual(call_args, call_args_history) # the response should be a string for regular functions # streaming functions return generators instead.. self.assertTrue(isinstance(response, StringType)) from sijax.helper import json try: commands = json.loads(response) except: self.fail("Invalid JSON response!") else: self.assertTrue(isinstance(commands, list)) commands_history = [] for cmd_params in commands: self.assertTrue(isinstance(cmd_params, dict)) self.assertTrue("type" in cmd_params, "Unknown command type!") commands_history.append(cmd_params["type"]) self.assertEqual(["script", "alert", "css"], commands_history)
def test_executing_regular_callbacks_works(self): calls_history = [] call_args_history = [] def event_before(obj_response): self.assertTrue(isinstance(obj_response, BaseResponse)) calls_history.append("before") obj_response.script("javascript here..") def event_after(obj_response): self.assertTrue(isinstance(obj_response, BaseResponse)) calls_history.append("after") obj_response.css("#element", "backgroundColor", "red") def callback_main(obj_response, arg1, arg2): self.assertTrue(isinstance(obj_response, BaseResponse)) calls_history.append("main") call_args_history.append(arg1) call_args_history.append(arg2) obj_response.alert("alert from main") inst = Sijax() cls = inst.__class__ inst.register_event(cls.EVENT_BEFORE_PROCESSING, event_before) inst.register_event(cls.EVENT_AFTER_PROCESSING, event_after) call_args = ["arg1", 15] response = inst.execute_callback(call_args, callback=callback_main) self.assertEqual(["before", "main", "after"], calls_history) self.assertEqual(call_args, call_args_history) # the response should be a string for regular functions # streaming functions return generators instead.. self.assertTrue(isinstance(response, string_types)) from sijax.helper import json try: commands = json.loads(response) except: self.fail("Invalid JSON response!") else: self.assertTrue(isinstance(commands, list)) commands_history = [] for cmd_params in commands: self.assertTrue(isinstance(cmd_params, dict)) self.assertTrue("type" in cmd_params, "Unknown command type!") commands_history.append(cmd_params["type"]) self.assertEqual(["script", "alert", "css"], commands_history)
def test_streaming_functions_return_generators(self): # Every function registered as streaming should return a generator # when it's executed, even if the actual function decides to act # as a normal function, and not generate anything # This is very important, because it allows mixing streaming with # regular functions when the StreamingIframeResponse is used from types import GeneratorType call_history = [] def callback_before(obj_response): self.assertTrue(isinstance(obj_response, StreamingIframeResponse)) call_history.append("before") obj_response.html("#div", "before html") def callback_after(obj_response): self.assertTrue(isinstance(obj_response, StreamingIframeResponse)) call_history.append("after") # intentionally not pushing new commands # which means it should not be yielding at implicitly def callback_yielding(obj_response): self.assertTrue(isinstance(obj_response, StreamingIframeResponse)) call_history.append("yielding") obj_response.alert("test") yield obj_response obj_response.css("#div", "color", "red") def callback_normal(obj_response): self.assertTrue(isinstance(obj_response, StreamingIframeResponse)) call_history.append("normal") obj_response.script(".. javascript here..") def assert_generator_entries_length(generator, length): items = [] try: while True: items.append(next(generator)) except StopIteration: pass self.assertEqual(length, len(items)) inst = Sijax() cls = inst.__class__ inst.register_event(cls.EVENT_BEFORE_PROCESSING, callback_before) inst.register_event(cls.EVENT_AFTER_PROCESSING, callback_after) options = {cls.PARAM_RESPONSE_CLASS: StreamingIframeResponse} response = inst.execute_callback([], callback=callback_yielding, **options) self.assertTrue(isinstance(response, GeneratorType)) # We should have the following yields: # 1. Implicit yield after callback_before # 2. Explicit yield from callback_yielding # 3. Implicit yield when calback_yielding ends # Note that callback_after should not yield implicitly, # because it has not pushed new commands, so it makes no sense! assert_generator_entries_length(response, 3) def callback_before_new(obj_response): self.assertTrue(isinstance(obj_response, StreamingIframeResponse)) call_history.append("before_new") # this doesn't really push data, as we haven't added commands yet # flushing would be wasteful for i in range(10): yield obj_response for i in range(2): obj_response.alert("hey") yield obj_response inst.register_event(cls.EVENT_BEFORE_PROCESSING, callback_before_new) inst.register_event(cls.EVENT_AFTER_PROCESSING, lambda r: r.alert("this yields")) response = inst.execute_callback([], callback=callback_normal, **options) self.assertTrue(isinstance(response, GeneratorType)) # We're expecting the following yields: # 1. Explicit yield from callback_before_new # 2. Explicit yield from callback_before_new # 3. Implicit yield after callback_normal # 4. Implicit yield after EVENT_AFTER_PROCESSING callback assert_generator_entries_length(response, 4) call_history_expected = [ "before", "yielding", "after", "before_new", "normal" ] self.assertEqual(call_history_expected, call_history)
def test_streaming_functions_return_generators(self): # Every function registered as streaming should return a generator # when it's executed, even if the actual function decides to act # as a normal function, and not generate anything # This is very important, because it allows mixing streaming with # regular functions when the StreamingIframeResponse is used from types import GeneratorType call_history = [] def callback_before(obj_response): self.assertTrue(isinstance(obj_response, StreamingIframeResponse)) call_history.append("before") obj_response.html("#div", "before html") def callback_after(obj_response): self.assertTrue(isinstance(obj_response, StreamingIframeResponse)) call_history.append("after") # intentionally not pushing new commands # which means it should not be yielding at implicitly def callback_yielding(obj_response): self.assertTrue(isinstance(obj_response, StreamingIframeResponse)) call_history.append("yielding") obj_response.alert("test") yield obj_response obj_response.css("#div", "color", "red") def callback_normal(obj_response): self.assertTrue(isinstance(obj_response, StreamingIframeResponse)) call_history.append("normal") obj_response.script(".. javascript here..") def assert_generator_entries_length(generator, length): items = [] try: while True: items.append(next(generator)) except StopIteration: pass self.assertEqual(length, len(items)) inst = Sijax() cls = inst.__class__ inst.register_event(cls.EVENT_BEFORE_PROCESSING, callback_before) inst.register_event(cls.EVENT_AFTER_PROCESSING, callback_after) options = {cls.PARAM_RESPONSE_CLASS: StreamingIframeResponse} response = inst.execute_callback([], callback=callback_yielding, **options) self.assertTrue(isinstance(response, GeneratorType)) # We should have the following yields: # 1. Implicit yield after callback_before # 2. Explicit yield from callback_yielding # 3. Implicit yield when calback_yielding ends # Note that callback_after should not yield implicitly, # because it has not pushed new commands, so it makes no sense! assert_generator_entries_length(response, 3) def callback_before_new(obj_response): self.assertTrue(isinstance(obj_response, StreamingIframeResponse)) call_history.append("before_new") # this doesn't really push data, as we haven't added commands yet # flushing would be wasteful for i in range(10): yield obj_response for i in range(2): obj_response.alert("hey") yield obj_response inst.register_event(cls.EVENT_BEFORE_PROCESSING, callback_before_new) inst.register_event(cls.EVENT_AFTER_PROCESSING, lambda r: r.alert("this yields")) response = inst.execute_callback([], callback=callback_normal, **options) self.assertTrue(isinstance(response, GeneratorType)) # We're expecting the following yields: # 1. Explicit yield from callback_before_new # 2. Explicit yield from callback_before_new # 3. Implicit yield after callback_normal # 4. Implicit yield after EVENT_AFTER_PROCESSING callback assert_generator_entries_length(response, 4) call_history_expected = [ "before", "yielding", "after", "before_new", "normal" ] self.assertEqual(call_history_expected, call_history)