def test_trigger_outbound_create_non_auto_pk(self): class TestBinding(WebsocketBinding): model = models.TestUUIDModel stream = 'test' fields = ['name'] @classmethod def group_names(cls, instance): return ["testuuidmodels"] def has_permission(self, user, action, pk): return True client = HttpClient() client.join_group('testuuidmodels') instance = models.TestUUIDModel.objects.create(name='testname') received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('name' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertEqual(received['payload']['action'], 'create') self.assertEqual(received['payload']['model'], 'tests.testuuidmodel') self.assertEqual(received['payload']['pk'], str(instance.pk)) self.assertEqual(received['payload']['data']['name'], 'testname') received = client.receive() self.assertIsNone(received)
def test_trigger_outbound_create_non_auto_pk(self): class TestBinding(WebsocketBinding): model = models.TestUUIDModel stream = 'test' fields = ['name'] @classmethod def group_names(cls, instance): return ["testuuidmodels"] def has_permission(self, user, action, pk): return True client = HttpClient() client.join_group('testuuidmodels') instance = models.TestUUIDModel.objects.create(name='testname') received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('name' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertEqual(received['payload']['action'], 'create') self.assertEqual(received['payload']['model'], 'tests.testuuidmodel') self.assertEqual(received['payload']['pk'], str(instance.pk)) self.assertEqual(received['payload']['data']['name'], 'testname') received = client.receive() self.assertIsNone(received)
def test_websocket_custom_json_serialization(self): class WebsocketConsumer(websockets.JsonWebsocketConsumer): @classmethod def decode_json(cls, text): obj = json.loads(text) return dict((key.upper(), obj[key]) for key in obj) @classmethod def encode_json(cls, content): lowered = dict((key.lower(), content[key]) for key in content) return json.dumps(lowered) def receive(self, content, multiplexer=None, **kwargs): self.content_received = content self.send({"RESPONSE": "HI"}) class MyMultiplexer(websockets.WebsocketMultiplexer): @classmethod def encode_json(cls, content): lowered = dict((key.lower(), content[key]) for key in content) return json.dumps(lowered) with apply_routes([route_class(WebsocketConsumer, path='/path')]): client = HttpClient() consumer = client.send_and_consume('websocket.receive', path='/path', text={"key": "value"}) self.assertEqual(consumer.content_received, {"KEY": "value"}) self.assertEqual(client.receive(), {"response": "HI"}) client.join_group('test_group') WebsocketConsumer.group_send('test_group', {"KEY": "VALUE"}) self.assertEqual(client.receive(), {"key": "VALUE"})
def test_simple_as_route_method(self): class WebsocketConsumer(websockets.WebsocketConsumer): def connect(self, message, **kwargs): self.message.reply_channel.send({'accept': True}) self.send(text=message.get('order')) routes = [ WebsocketConsumer.as_route(attrs={"strict_ordering": True}, path='^/path$'), WebsocketConsumer.as_route(path='^/path/2$'), ] self.assertIsNot(routes[0].consumer, WebsocketConsumer) self.assertIs(routes[1].consumer, WebsocketConsumer) with apply_routes(routes): client = HttpClient() client.send('websocket.connect', {'path': '/path', 'order': 1}) client.send('websocket.connect', {'path': '/path', 'order': 0}) client.consume('websocket.connect', check_accept=False) client.consume('websocket.connect') self.assertEqual(client.receive(json=False), 0) client.consume('websocket.connect') self.assertEqual(client.receive(json=False), 1) client.send_and_consume('websocket.connect', {'path': '/path/2', 'order': 'next'}) self.assertEqual(client.receive(json=False), 'next')
def test_websocket_custom_json_serialization(self): class WebsocketConsumer(websockets.JsonWebsocketConsumer): @classmethod def decode_json(cls, text): obj = json.loads(text) return dict((key.upper(), obj[key]) for key in obj) @classmethod def encode_json(cls, content): lowered = dict((key.lower(), content[key]) for key in content) return json.dumps(lowered) def receive(self, content, multiplexer=None, **kwargs): self.content_received = content self.send({"RESPONSE": "HI"}) class MyMultiplexer(websockets.WebsocketMultiplexer): @classmethod def encode_json(cls, content): lowered = dict((key.lower(), content[key]) for key in content) return json.dumps(lowered) with apply_routes([route_class(WebsocketConsumer, path='/path')]): client = HttpClient() consumer = client.send_and_consume('websocket.receive', path='/path', text={"key": "value"}) self.assertEqual(consumer.content_received, {"KEY": "value"}) self.assertEqual(client.receive(), {"response": "HI"}) client.join_group('test_group') WebsocketConsumer.group_send('test_group', {"KEY": "VALUE"}) self.assertEqual(client.receive(), {"key": "VALUE"})
def test_simple_as_route_method(self): class WebsocketConsumer(websockets.WebsocketConsumer): def connect(self, message, **kwargs): self.message.reply_channel.send({'accept': True}) self.send(text=message.get('order')) routes = [ WebsocketConsumer.as_route(attrs={"strict_ordering": True}, path='^/path$'), WebsocketConsumer.as_route(path='^/path/2$'), ] self.assertIsNot(routes[0].consumer, WebsocketConsumer) self.assertIs(routes[1].consumer, WebsocketConsumer) with apply_routes(routes): client = HttpClient() client.send('websocket.connect', {'path': '/path', 'order': 1}) client.send('websocket.connect', {'path': '/path', 'order': 0}) client.consume('websocket.connect', check_accept=False) client.consume('websocket.connect') self.assertEqual(client.receive(json=False), 0) client.consume('websocket.connect') self.assertEqual(client.receive(json=False), 1) client.send_and_consume('websocket.connect', {'path': '/path/2', 'order': 'next'}) self.assertEqual(client.receive(json=False), 'next')
def test_websockets_demultiplexer_custom_multiplexer(self): class MyWebsocketConsumer(websockets.JsonWebsocketConsumer): def connect(self, message, multiplexer=None, **kwargs): multiplexer.send({"THIS_SHOULD_BE_LOWERCASED": "1"}) class MyMultiplexer(websockets.WebsocketMultiplexer): @classmethod def encode_json(cls, content): lowered = { "stream": content["stream"], "payload": dict((key.lower(), content["payload"][key]) for key in content["payload"]) } return json.dumps(lowered) class Demultiplexer(websockets.WebsocketDemultiplexer): multiplexer_class = MyMultiplexer consumers = { "mystream": MyWebsocketConsumer } with apply_routes([route_class(Demultiplexer, path='/path/(?P<ID>\d+)')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/path/1') self.assertEqual(client.receive(), { "stream": "mystream", "payload": {"this_should_be_lowercased": "1"}, })
def test_websockets_demultiplexer_custom_multiplexer(self): class MyWebsocketConsumer(websockets.JsonWebsocketConsumer): def connect(self, message, multiplexer=None, **kwargs): multiplexer.send({"THIS_SHOULD_BE_LOWERCASED": "1"}) class MyMultiplexer(websockets.WebsocketMultiplexer): @classmethod def encode_json(cls, content): lowered = { "stream": content["stream"], "payload": dict((key.lower(), content["payload"][key]) for key in content["payload"]) } return json.dumps(lowered) class Demultiplexer(websockets.WebsocketDemultiplexer): multiplexer_class = MyMultiplexer consumers = { "mystream": MyWebsocketConsumer } with apply_routes([route_class(Demultiplexer, path='/path/(?P<ID>\d+)')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/path/1') self.assertEqual(client.receive(), { "stream": "mystream", "payload": {"this_should_be_lowercased": "1"}, })
def test_inbound_delete(self): user = User.objects.create(username='******', email='*****@*****.**') class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', ] @classmethod def group_names(cls, instance): return ['users_outbound'] def has_permission(self, user, action, pk): return True class Demultiplexer(WebsocketDemultiplexer): consumers = { 'users': UserBinding.consumer, } groups = ['inbound'] with apply_routes([Demultiplexer.as_route(path='/')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': {'action': DELETE, 'pk': user.pk} }) self.assertIsNone(User.objects.filter(pk=user.pk).first()) self.assertIsNone(client.receive())
def test_trigger_outbound_update(self): class TestBinding(WebsocketBinding): model = User stream = 'test' fields = ['__all__'] @classmethod def group_names(cls, instance): return ["users2"] def has_permission(self, user, action, pk): return True # Make model and clear out pending sends user = User.objects.create(username='******', email='*****@*****.**') client = HttpClient() client.join_group('users2') user.username = '******' user.save() received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('username' in received['payload']['data']) self.assertTrue('email' in received['payload']['data']) self.assertTrue('password' in received['payload']['data']) self.assertTrue('last_name' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertEqual(received['payload']['action'], 'update') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], user.pk) self.assertEqual(received['payload']['data']['email'], '*****@*****.**') self.assertEqual(received['payload']['data']['username'], 'test_new') self.assertEqual(received['payload']['data']['password'], '') self.assertEqual(received['payload']['data']['last_name'], '') received = client.receive() self.assertIsNone(received)
def test_trigger_outbound_update(self): class TestBinding(WebsocketBinding): model = User stream = 'test' fields = ['__all__'] @classmethod def group_names(cls, instance): return ["users2"] def has_permission(self, user, action, pk): return True # Make model and clear out pending sends user = User.objects.create(username='******', email='*****@*****.**') client = HttpClient() client.join_group('users2') user.username = '******' user.save() received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('username' in received['payload']['data']) self.assertTrue('email' in received['payload']['data']) self.assertTrue('password' in received['payload']['data']) self.assertTrue('last_name' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertEqual(received['payload']['action'], 'update') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], user.pk) self.assertEqual(received['payload']['data']['email'], '*****@*****.**') self.assertEqual(received['payload']['data']['username'], 'test_new') self.assertEqual(received['payload']['data']['password'], '') self.assertEqual(received['payload']['data']['last_name'], '') received = client.receive() self.assertIsNone(received)
def test_trigger_outbound_create_exclude(self): class TestBinding(WebsocketBinding): model = User stream = 'test' exclude = ['first_name', 'last_name'] @classmethod def group_names(cls, instance): return ["users_exclude"] def has_permission(self, user, action, pk): return True with apply_routes([route('test', TestBinding.consumer)]): client = HttpClient() client.join_group('users_exclude') user = User.objects.create(username='******', email='*****@*****.**') received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('username' in received['payload']['data']) self.assertTrue('email' in received['payload']['data']) self.assertTrue('password' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertFalse('last_name' in received['payload']['data']) self.assertFalse('first_name' in received['payload']['data']) self.assertEqual(received['payload']['action'], 'create') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], user.pk) self.assertEqual(received['payload']['data']['email'], '*****@*****.**') self.assertEqual(received['payload']['data']['username'], 'test') self.assertEqual(received['payload']['data']['password'], '') received = client.receive() self.assertIsNone(received)
def test_trigger_outbound_create_exclude(self): class TestBinding(WebsocketBinding): model = User stream = 'test' exclude = ['first_name', 'last_name'] @classmethod def group_names(cls, instance): return ["users_exclude"] def has_permission(self, user, action, pk): return True with apply_routes([route('test', TestBinding.consumer)]): client = HttpClient() client.join_group('users_exclude') user = User.objects.create(username='******', email='*****@*****.**') received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('username' in received['payload']['data']) self.assertTrue('email' in received['payload']['data']) self.assertTrue('password' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertFalse('last_name' in received['payload']['data']) self.assertFalse('first_name' in received['payload']['data']) self.assertEqual(received['payload']['action'], 'create') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], user.pk) self.assertEqual(received['payload']['data']['email'], '*****@*****.**') self.assertEqual(received['payload']['data']['username'], 'test') self.assertEqual(received['payload']['data']['password'], '') received = client.receive() self.assertIsNone(received)
def test_websockets_demultiplexer(self): class MyWebsocketConsumer(websockets.JsonWebsocketConsumer): def connect(self, message, multiplexer=None, **kwargs): multiplexer.send(kwargs) def disconnect(self, message, multiplexer=None, **kwargs): multiplexer.send(kwargs) def receive(self, content, multiplexer=None, **kwargs): multiplexer.send(content) class Demultiplexer(websockets.WebsocketDemultiplexer): consumers = { "mystream": MyWebsocketConsumer } with apply_routes([route_class(Demultiplexer, path='/path/(?P<id>\d+)')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/path/1') self.assertEqual(client.receive(), { "stream": "mystream", "payload": {"id": "1"}, }) client.send_and_consume('websocket.receive', text={ "stream": "mystream", "payload": {"text_field": "mytext"}, }, path='/path/1') self.assertEqual(client.receive(), { "stream": "mystream", "payload": {"text_field": "mytext"}, }) client.send_and_consume('websocket.disconnect', path='/path/1') self.assertEqual(client.receive(), { "stream": "mystream", "payload": {"id": "1"}, })
def test_websockets_demultiplexer(self): class MyWebsocketConsumer(websockets.JsonWebsocketConsumer): def connect(self, message, multiplexer=None, **kwargs): multiplexer.send(kwargs) def disconnect(self, message, multiplexer=None, **kwargs): multiplexer.send(kwargs) def receive(self, content, multiplexer=None, **kwargs): multiplexer.send(content) class Demultiplexer(websockets.WebsocketDemultiplexer): consumers = { "mystream": MyWebsocketConsumer } with apply_routes([route_class(Demultiplexer, path='/path/(?P<id>\d+)')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/path/1') self.assertEqual(client.receive(), { "stream": "mystream", "payload": {"id": "1"}, }) client.send_and_consume('websocket.receive', text={ "stream": "mystream", "payload": {"text_field": "mytext"}, }, path='/path/1') self.assertEqual(client.receive(), { "stream": "mystream", "payload": {"text_field": "mytext"}, }) client.send_and_consume('websocket.disconnect', path='/path/1') self.assertEqual(client.receive(), { "stream": "mystream", "payload": {"id": "1"}, })
def test_websocket_demultiplexer_send(self): class MyWebsocketConsumer(websockets.JsonWebsocketConsumer): def receive(self, content, multiplexer=None, **kwargs): self.send(content) class Demultiplexer(websockets.WebsocketDemultiplexer): consumers = { "mystream": MyWebsocketConsumer } with apply_routes([route_class(Demultiplexer, path='/path/(?P<id>\d+)')]): client = HttpClient() with self.assertRaises(SendNotAvailableOnDemultiplexer): client.send_and_consume('websocket.receive', path='/path/1', text={ "stream": "mystream", "payload": {"text_field": "mytext"}, }) client.receive()
def test_websocket_demultiplexer_send(self): class MyWebsocketConsumer(websockets.JsonWebsocketConsumer): def receive(self, content, multiplexer=None, **kwargs): self.send(content) class Demultiplexer(websockets.WebsocketDemultiplexer): consumers = { "mystream": MyWebsocketConsumer } with apply_routes([route_class(Demultiplexer, path='/path/(?P<id>\d+)')]): client = HttpClient() with self.assertRaises(SendNotAvailableOnDemultiplexer): client.send_and_consume('websocket.receive', path='/path/1', text={ "stream": "mystream", "payload": {"text_field": "mytext"}, }) client.receive()
def test_inbound_update(self): user = User.objects.create(username='******', email='*****@*****.**') class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', ] @classmethod def group_names(cls, instance): return ['users_outbound'] def has_permission(self, user, action, pk): return True class Demultiplexer(WebsocketDemultiplexer): consumers = { 'users': UserBinding.consumer, } groups = ['inbound'] with apply_routes([Demultiplexer.as_route(path='/')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': {'action': UPDATE, 'pk': user.pk, 'data': {'username': '******'}} }) user = User.objects.get(pk=user.pk) self.assertEqual(user.username, 'test_inbound') self.assertEqual(user.email, '*****@*****.**') # trying change field that not in binding fields client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': {'action': UPDATE, 'pk': user.pk, 'data': {'email': '*****@*****.**'}} }) user = User.objects.get(pk=user.pk) self.assertEqual(user.username, 'test_inbound') self.assertEqual(user.email, '*****@*****.**') self.assertIsNone(client.receive())
def test_inbound_create(self): self.assertEqual(User.objects.all().count(), 0) class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', 'email', 'password', 'last_name'] @classmethod def group_names(cls, instance): return ['users_outbound'] def has_permission(self, user, action, pk): return True class Demultiplexer(WebsocketDemultiplexer): consumers = { 'users': UserBinding.consumer, } groups = ['inbound'] with apply_routes([Demultiplexer.as_route(path='/')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': { 'action': CREATE, 'data': { 'username': '******', 'email': 'test@user_steam.com' }, }, }) self.assertEqual(User.objects.all().count(), 1) user = User.objects.all().first() self.assertEqual(user.username, 'test_inbound') self.assertEqual(user.email, 'test@user_steam.com') self.assertIsNone(client.receive())
def test_inbound_create(self): self.assertEqual(User.objects.all().count(), 0) class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', 'email', 'password', 'last_name'] @classmethod def group_names(cls, instance): return ['users_outbound'] def has_permission(self, user, action, pk): return True class Demultiplexer(WebsocketDemultiplexer): consumers = { 'users': UserBinding.consumer, } groups = ['inbound'] with apply_routes([Demultiplexer.as_route(path='/')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': { 'action': CREATE, 'data': {'username': '******', 'email': 'test@user_steam.com'}, }, }) self.assertEqual(User.objects.all().count(), 1) user = User.objects.all().first() self.assertEqual(user.username, 'test_inbound') self.assertEqual(user.email, 'test@user_steam.com') self.assertIsNone(client.receive())
class WebSocketTests(ChannelTestCase): def setUp(self): self.client = HttpClient() def test_creating_new_todo_items_in_public_todo_list_send_notification( self): todo_list = TodoList.objects.create(title="Products") self.client.send_and_consume( 'websocket.connect', path='/api/ws/', content={'query_string': 'todo_list={}'.format(str(todo_list.id))}, ) TodoItem.objects.create(title="test_item", todo_list=todo_list) received = self.client.receive() self.assertNotEquals(received, None) def test_can_subscribe_to_read_only_todo_list(self): todo_list = TodoList.objects.create(title="Products", mode=TodoList.ALLOW_READ) self.client.send_and_consume( 'websocket.connect', path='/api/ws/', content={'query_string': 'todo_list={}'.format(str(todo_list.id))}, ) TodoItem.objects.create(title="test_item", todo_list=todo_list) received = self.client.receive() self.assertNotEquals(received, None) def test_cant_subscribe_to_private_todo_list(self): todo_list = TodoList.objects.create(title="Products", mode=TodoList.PRIVATE) self.client.send_and_consume( 'websocket.connect', path='/api/ws/', content={'query_string': 'todo_list={}'.format(str(todo_list.id))}, ) TodoItem.objects.create(title="test_item", todo_list=todo_list) received = self.client.receive() self.assertEquals(received, None) def test_cant_add_new_todo_item_by_ws(self): todo_list = TodoList.objects.create(title="Products") self.client.join_group(str(todo_list.id)) payload = { 'stream': 'todo_item', 'payload': { 'data': { 'title': 'test_item', 'todo_list': str(todo_list.id) }, 'action': 'create', } } self.client.send_and_consume('websocket.receive', path='/api/ws/', text=payload) self.assertEqual(TodoItem.objects.count(), 0) def test_todo_lists_have_separated_notifications(self): todo_list1 = TodoList.objects.create(title="Homework") todo_list2 = TodoList.objects.create(title="Products") # connect to todo_list1 self.client.join_group(str(todo_list1.id)) TodoItem.objects.create(title="brush teeth", todo_list=todo_list1) # get messages from todo_list1 received = self.client.receive() self.assertNotEquals(received, None) # not get messages from todo_list2 TodoItem.objects.create(title="milk", todo_list=todo_list2) received = self.client.receive() self.assertEquals(received, None) def test_if_not_connected_to_todo_list_not_get_notifications(self): todo_list = TodoList.objects.create(title="Products") self.client.send_and_consume('websocket.connect', path='/api/ws/') TodoItem.objects.create(title="test_item", todo_list=todo_list) received = self.client.receive() self.assertEquals(received, None) def test_get_notification_from_watched_not_private_todo_lists_and_own_private( self): user = UserModel.objects.create(username='******') todo_list_private_own = TodoList.objects.create(title="Private own", mode=TodoList.PRIVATE, owner=user) todo_list_private = TodoList.objects.create(title="Private", mode=TodoList.PRIVATE) todo_list_read_only = TodoList.objects.create(title="Read only", mode=TodoList.ALLOW_READ) todo_list_public = TodoList.objects.create( title="Public", mode=TodoList.ALLOW_FULL_ACCESS) [ Watch.objects.create(user=user, todo_list=todo_list) for todo_list in TodoList.objects.all() ] self.client.force_login(user) self.client.send_and_consume('websocket.connect', path='/api/ws/') TodoItem.objects.create(title="test_item1", todo_list=todo_list_private_own) received = self.client.receive() self.assertNotEquals(received, None) TodoItem.objects.create(title="test_item2", todo_list=todo_list_private) received = self.client.receive() self.assertEquals(received, None) TodoItem.objects.create(title="test_item3", todo_list=todo_list_read_only) received = self.client.receive() self.assertNotEquals(received, None) TodoItem.objects.create(title="test_item4", todo_list=todo_list_public) received = self.client.receive() self.assertNotEquals(received, None)
def test_passenger_can_connect_via_websockets(self): client = HttpClient() client.login(username=self.passenger.username, password='******') client.send_and_consume('websocket.connect', path='/passenger/') message = client.receive() self.assertIsNone(message)