def test_update_mixin(self): # create object obj = User.objects.create_user(username='******', email='*****@*****.**') # create client client = HttpClient() data = {'username': '******'} with apply_routes([ UpdateConsumers.as_routes(model=User, path='/(?P<pk>\d+)/?', channel_name='test') ]): client.send_and_consume('websocket.connect', {'path': '/{}'.format(obj.pk)}) client.send_and_consume( 'websocket.receive', { 'path': '/{}'.format(obj.pk), 'action': 'update', 'data': json.dumps(data) }) client.consume('test') user = User.objects.filter(pk=obj.pk).first() self.assertTrue(user) self.assertEqual(user.username, 'new_name')
def test_list_consumers(self): # create object for i in range(20): User.objects.create_user(username='******' + str(i), email='*****@*****.**') # create client client = HttpClient() with apply_routes([ ListConsumers.as_routes(model=User, path='/', channel_name='test', paginate_by=10) ]): client.send_and_consume(u'websocket.connect', {'path': '/'}) client.send_and_consume(u'websocket.receive', { 'path': '/', 'action': 'list', 'page': 2 }) client.consume('test') rec = client.receive() res = json.loads(json.loads(rec['text'])['response']) self.assertEqual(len(res), 10) self.assertEqual(res[0]['username'], 'test10') self.assertEqual(res[0]['email'], '*****@*****.**') self.assertEqual(res[0]['is_active'], True)
def test_object_sub_with_subs_first(self): # define consumers routes = ObjectSubscribeConsumers.as_routes(path='/(?P<pk>\d+)/?', model=User) # create client client = HttpClient() with apply_routes([routes]): # subscribe for object changes client.send_and_consume(u'websocket.connect', content={'path': '/{}'.format('1')}) # create object User.objects.create_user(username='******', email='*****@*****.**') res = json.loads(client.receive()['text']) self.assertTrue('data' in res.keys()) self.assertTrue('action' in res.keys()) self.assertTrue(res['action'] == 'created') data = res['data'] self.assertEqual(data['username'], 'test') self.assertEqual(data['is_active'], True) self.assertEqual(data['email'], '*****@*****.**') self.assertEqual(data['is_staff'], False) # check that nothing happened self.assertIsNone(client.receive())
def test_demultiplexer_with_wrong_payload(self): class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] with apply_routes([Demultiplexer.as_route(path='/')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') with self.assertRaises(ValueError) as value_error: client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': 'test', }) self.assertEqual(value_error.exception.args[0], 'Multiplexed frame payload is not a dict') message = client.get_next_message('binding.users') self.assertIsNone(message)
def test_demultiplexer_without_payload_and_steam(self): class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] with apply_routes([Demultiplexer.as_route(path='/')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') with self.assertRaises(ValueError) as value_error: client.send_and_consume('websocket.receive', path='/', text={ 'nostream': 'users', 'payload': 'test', }) self.assertIn('no channel/payload key', value_error.exception.args[0]) message = client.get_next_message('binding.users') self.assertIsNone(message) with self.assertRaises(ValueError) as value_error: client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', }) self.assertIn('no channel/payload key', value_error.exception.args[0]) message = client.get_next_message('binding.users') self.assertIsNone(message)
def test_demultiplexer(self): class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] with apply_routes([Demultiplexer.as_route(path='/')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') # assert in group Group('inbound').send({'text': json.dumps({'test': 'yes'})}, immediately=True) self.assertEqual(client.receive(), {'test': 'yes'}) # assert that demultiplexer stream message client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': { 'test': 'yes' } }) message = client.get_next_message('binding.users') self.assertIsNotNone(message) self.assertEqual(message.content['test'], 'yes')
def test_list(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): for n in range(api_settings.DEFAULT_PAGE_SIZE + 1): TestModel.objects.create(name='Name-{}'.format(str(n))) json_content = self._send_and_consume('testmodel', { 'action': 'list', 'request_id': 'client-request-id', 'data': None, }) self.assertEqual(len(json_content['payload']['data']), api_settings.DEFAULT_PAGE_SIZE) json_content = self._send_and_consume('testmodel', { 'action': 'list', 'request_id': 'client-request-id', 'data': { 'page': 2 } }) self.assertEqual(len(json_content['payload']['data']), 1) self.assertEqual('client-request-id', json_content['payload']['request_id'])
def test_inbound_delete(self): user = User.objects.create(username='******', email='*****@*****.**') class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', ] @classmethod def group_names(cls, instance, action): return ['users_outbound'] def has_permission(self, user, action, pk): return True with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]): 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} }) # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer client.consume('binding.users') self.assertIsNone(User.objects.filter(pk=user.pk).first()) self.assertIsNone(client.receive())
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_demultiplexer_send(self): class MyWebsocketConsumer(websockets.JsonWebsocketConsumer): def receive(self, content, multiplexer=None, **kwargs): import pdb pdb.set_trace() # breakpoint 69f2473b // self.send(content) class Demultiplexer(websockets.WebsocketDemultiplexer): consumers = {"mystream": MyWebsocketConsumer} with apply_routes([ route_class(Demultiplexer, path='/path/(?P<id>\d+)'), route_class(MyWebsocketConsumer), ]): client = Client() with self.assertRaises(SendNotAvailableOnDemultiplexer): client.send_and_consume( 'websocket.receive', { 'path': '/path/1', 'text': json.dumps({ "stream": "mystream", "payload": { "text_field": "mytext" } }) }) client.receive()
def test_trigger_outbound_delete(self): class TestBinding(WebsocketBinding): model = User stream = 'test' fields = ['username'] def group_names(self, instance, action): return ["users3"] def has_permission(self, user, action, pk): return True user = User.objects.create(username='******', email='*****@*****.**') with apply_routes([route('test', TestBinding.consumer)]): client = HttpClient() client.join_group('users3') user.delete() 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('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertEqual(received['payload']['action'], 'delete') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], 1) self.assertEqual(received['payload']['data']['username'], 'test') received = client.receive() self.assertIsNone(received)
def test_simple_as_route_method(self): class WebsocketConsumer(websockets.WebsocketConsumer): def connect(self, message, **kwargs): self.send(text=message.get('order')) routes = [ WebsocketConsumer.as_route(attrs={'slight_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 = Client() client.send('websocket.connect', {'path': '/path', 'order': 1}) client.send('websocket.connect', {'path': '/path', 'order': 0}) client.consume('websocket.connect') client.consume('websocket.connect') client.consume('websocket.connect') self.assertEqual(client.receive(), {'text': 0}) self.assertEqual(client.receive(), {'text': 1}) client.send_and_consume('websocket.connect', { 'path': '/path/2', 'order': 'next' }) self.assertEqual(client.receive(), {'text': 'next'})
def test_user_consumer(self): User.objects.create_user('test', '*****@*****.**', '123') class _Consumers(UserMixin, Consumers): path = '/test/(?P<test>\d+)' channel_name = 'test' @consumer def test(self, *args, **kwargs): self.message.reply_channel.send({'test': 123}) return self.user with apply_routes([_Consumers.as_routes(), ]): self.client.send_and_consume(u'websocket.connect', {'path': '/test/123'}) self.client.send_and_consume(u'websocket.receive', {'message': 'test', 'path': '/test/123'}) user = self.client.consume(u'test') self.assertTrue(isinstance(user, AnonymousUser)) self.client.send_and_consume(u'websocket.disconnect', {'path': '/test/123'}) self.client.login(username='******', password='******') self.client.send_and_consume(u'websocket.connect', {'path': '/test/123'}) self.client.send_and_consume(u'websocket.receive', {'message': 'test', 'path': '/test/123'}) user = self.client.consume(u'test') self.assertTrue(isinstance(user, User)) self.assertDictEqual(self.client.receive(), {'test': 123})
def test_base_consumer(self): class Consumers(BaseConsumer): method_mapping = { 'test.create': 'create', 'test.test': 'test', } def create(self, message, **kwargs): self.called = 'create' def test(self, message, **kwargs): self.called = 'test' with apply_routes([route_class(Consumers)]): client = Client() # check that methods for certain channels routes successfully self.assertEqual(client.send_and_consume('test.create').called, 'create') self.assertEqual(client.send_and_consume('test.test').called, 'test') # send to the channels without routes client.send('test.wrong') message = self.get_next_message('test.wrong') self.assertEqual(client.channel_layer.router.match(message), None) client.send('test') message = self.get_next_message('test') self.assertEqual(client.channel_layer.router.match(message), None)
def test_websockets_consumers_handlers(self): class WebsocketConsumer(websockets.WebsocketConsumer): def connect(self, message, **kwargs): self.called = 'connect' self.id = kwargs['id'] def disconnect(self, message, **kwargs): self.called = 'disconnect' def receive(self, text=None, bytes=None, **kwargs): self.text = text with apply_routes( [route_class(WebsocketConsumer, path='/path/(?P<id>\d+)')]): client = Client() consumer = client.send_and_consume('websocket.connect', {'path': '/path/1'}) self.assertEqual(consumer.called, 'connect') self.assertEqual(consumer.id, '1') consumer = client.send_and_consume('websocket.receive', { 'path': '/path/1', 'text': 'text' }) self.assertEqual(consumer.text, 'text') consumer = client.send_and_consume('websocket.disconnect', {'path': '/path/1'}) self.assertEqual(consumer.called, 'disconnect')
def test_base_consumer(self): class Consumers(BaseConsumer): method_mapping = { 'test.create': 'create', 'test.test': 'test', } def create(self, message, **kwargs): self.called = 'create' def test(self, message, **kwargs): self.called = 'test' with apply_routes([route_class(Consumers)]): client = Client() # check that methods for certain channels routes successfully self.assertEqual( client.send_and_consume('test.create').called, 'create') self.assertEqual( client.send_and_consume('test.test').called, 'test') # send to the channels without routes client.send('test.wrong') message = self.get_next_message('test.wrong') self.assertEqual(client.channel_layer.router.match(message), None) client.send('test') message = self.get_next_message('test') self.assertEqual(client.channel_layer.router.match(message), None)
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_model_sub(self): # define consumers routes = ModelSubscribeConsumers.as_routes(model=User) # create client client = HttpClient() # create object user = User.objects.create_user(username='******', email='*****@*****.**') with apply_routes([routes]): # subscribe for Models changes client.send_and_consume(u'websocket.connect') # change object user.username = '******' user.save() res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'updated') self.assertEqual(res['data']['username'], 'new username') self.assertEqual(res['data']['email'], '*****@*****.**') # create new one to_del = User.objects.create_user(username='******', email='*****@*****.**') res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'created') self.assertEqual(res['data']['username'], 'test2') self.assertEqual(res['data']['email'], '*****@*****.**') # delete to_del.delete() res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'deleted') self.assertEqual(res['data']['username'], 'test2') self.assertEqual(res['data']['email'], '*****@*****.**')
def test_simple_as_route_method(self): class WebsocketConsumer(websockets.WebsocketConsumer): def connect(self, message, **kwargs): 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 = Client() client.send('websocket.connect', {'path': '/path', 'order': 1}) client.send('websocket.connect', {'path': '/path', 'order': 0}) client.consume('websocket.connect') client.consume('websocket.connect') client.consume('websocket.connect') self.assertEqual(client.receive(), {'text': 0}) self.assertEqual(client.receive(), {'text': 1}) client.send_and_consume('websocket.connect', {'path': '/path/2', 'order': 'next'}) self.assertEqual(client.receive(), {'text': 'next'})
def test_consumer(self): client = Client() with apply_routes([MyConsumer.as_route()]): spy.reset_mock() client.send_and_consume(u'websocket.connect', {'path': '/'}) client.send_and_consume( u'websocket.receive', { 'path': '/', 'text': json.dumps({ 'type': 'INCREMENT_COUNTER', 'payload': 2, }), }) self.assertEqual(spy.call_count, 1) self.assertEqual( client.receive(), { 'text': json.dumps({ 'type': 'INCREMENTED_COUNTER', 'payload': 2, }), })
def test_websockets_consumers_handlers(self): class WebsocketConsumer(websockets.WebsocketConsumer): def connect(self, message, **kwargs): self.called = 'connect' self.id = kwargs['id'] def disconnect(self, message, **kwargs): self.called = 'disconnect' def receive(self, text=None, bytes=None, **kwargs): self.text = text with apply_routes([route_class(WebsocketConsumer, path='/path/(?P<id>\d+)')]): client = Client() consumer = client.send_and_consume('websocket.connect', {'path': '/path/1'}) self.assertEqual(consumer.called, 'connect') self.assertEqual(consumer.id, '1') consumer = client.send_and_consume('websocket.receive', {'path': '/path/1', 'text': 'text'}) self.assertEqual(consumer.text, 'text') consumer = client.send_and_consume('websocket.disconnect', {'path': '/path/1'}) self.assertEqual(consumer.called, 'disconnect')
def test_filters_and_routing(self): class Test(Consumers): channel_name = 'test' mark = 'default' @consumer(tag='test') def test(this, message): this.reply_channel.send({'status': 'ok'}) @consumer('test2', tag='test') def test2(this, message): this.reply_channel.send({'status': 'ok', 'mark': this.mark}) with apply_routes([Test.as_routes(), Test.as_routes(channel_name='test3', mark='new')]): client = HttpClient() self.assertIsNone(client.send_and_consume(u'test', content={'tag': 'tag'}, fail_on_none=False)) client.send_and_consume(u'test', content={'tag': 'test'}) self.assertDictEqual(client.receive(), {'status': 'ok'}) client.consume('test', fail_on_none=False) self.assertIsNone(client.receive()) client.send_and_consume(u'test3', content={'tag': 'test'}) self.assertDictEqual(client.receive(), {'status': 'ok'}) client.consume('test3', fail_on_none=False) self.assertIsNone(client.receive()) client.send_and_consume(u'test2', content={'tag': 'test'}) self.assertDictEqual(client.receive(), {'status': 'ok', 'mark': 'default'}) client.consume('test2', fail_on_none=False) self.assertIsNone(client.receive())
def test_subscribe(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): json_content = self._send_and_consume('testmodel', { 'action': 'subscribe', 'data': { 'action': 'create' }, 'request_id': 'client-request-id' }) expected_response = { 'action': 'subscribe', 'request_id': 'client-request-id', 'data': {}, 'errors': [], 'response_status': 200 } self.assertEqual(json_content['payload'], expected_response) # it should be on the create group instance = TestModel.objects.create(name='test-name') expected = { 'action': 'create', 'data': TestModelSerializer(instance).data, 'model': 'tests.testmodel', 'pk': instance.id } actual = self._get_next_message() self.assertEqual(expected, actual['payload'])
def test_crud_consumers(self): # create object for i in range(20): User.objects.create_user(username='******' + str(i), email='*****@*****.**') # create client client = HttpClient() with apply_routes([CRUDConsumers.as_routes(model=User, path='/', channel_name='test', paginate_by=10)]): client.send_and_consume(u'websocket.connect', {'path': '/'}) client.send_and_consume(u'websocket.receive', {'path': '/', 'action': 'list', 'page': 2}) client.consume('test') rec = client.receive() res = json.loads(json.loads(rec['text'])['response']) self.assertEqual(len(res), 10) self.assertEqual(res[0]['username'], 'test10') self.assertEqual(res[0]['email'], '*****@*****.**') self.assertEqual(res[0]['is_active'], True) client.send_and_consume(u'websocket.connect', {'path': '/{}'.format(10)}) client.send_and_consume(u'websocket.receive', {'path': '/{}'.format(10), 'action': 'delete'}) client.consume('test') self.assertFalse(User.objects.filter(pk=10).exists()) data = {'username': '******'} client.send_and_consume('websocket.connect', {'path': '/{}'.format(11)}) client.send_and_consume('websocket.receive', {'path': '/{}'.format(11), 'action': 'update', 'data': json.dumps(data)}) client.consume('test') user = User.objects.filter(pk=11).first() self.assertTrue(user) self.assertEqual(user.username, 'new_name')
def test_object_sub_with_fields(self): # create object for subscribe sub_object = User.objects.create_user(username='******', email='*****@*****.**') # define consumers routes = ObjectSubscribeConsumers.as_routes( path='/(?P<pk>\d+)/?', model=User, serializer_kwargs={'fields': ['username', 'is_active']}) # create client client = HttpClient() with apply_routes([routes]): # subscribe for object changes client.send_and_consume( u'websocket.connect', content={'path': '/{}'.format(sub_object.pk)}) # change sub object sub_object.username = '******' sub_object.email = '*****@*****.**' sub_object.save() res = json.loads(client.receive()['text'])['data'] self.assertEqual(res['username'], 'sub_object') self.assertEqual(res['is_active'], True) self.assertNotIn('email', res) self.assertNotIn('is_staff', res) sub_object.username = '******' sub_object.is_active = False sub_object.save() res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'updated') self.assertNotIn('email', res['data']) self.assertNotIn('is_staff', res['data']) self.assertEqual(res['data']['username'], 'test') self.assertEqual(res['data']['is_active'], False) sub_object.username = '******' sub_object.save(update_fields=['username']) res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'updated') self.assertEqual(res['data']['username'], 'test_new') self.assertNotIn('is_active', res['data']) self.assertNotIn('is_staff', res['data']) sub_object.email = '*****@*****.**' sub_object.save(update_fields=['email']) # check that nothing happened self.assertIsNone(client.receive())
def test_create_mixin(self): # create client client = HttpClient() data = {'username': '******', 'email': '*****@*****.**'} with apply_routes([CreateConsumers.as_routes(model=User, path='/', channel_name='test')]): client.send_and_consume(u'websocket.connect', {'path': '/'}) client.send_and_consume(u'websocket.receive', {'path': '/', 'action': 'create', 'data': json.dumps(data)}) client.consume(u'test') self.assertTrue(User.objects.filter(username='******', email='*****@*****.**').exists())
def test_delete_mixin(self): # create object obj = User.objects.create_user(username='******', email='*****@*****.**') # create client client = HttpClient() with apply_routes([DeleteConsumers.as_routes(model=User, path='/(?P<pk>\d+)/?', channel_name='test')]): client.send_and_consume(u'websocket.connect', {'path': '/{}'.format(obj.pk)}) client.send_and_consume(u'websocket.receive', {'path': '/{}'.format(obj.pk), 'action': 'delete'}) client.consume('test') self.assertFalse(User.objects.filter(pk=obj.pk).exists())
def test_crud_consumers(self): # create object for i in range(20): User.objects.create_user(username='******' + str(i), email='*****@*****.**') # create client client = HttpClient() with apply_routes([ CRUDConsumers.as_routes(model=User, path='/', channel_name='test', paginate_by=10) ]): client.send_and_consume(u'websocket.connect', {'path': '/'}) client.send_and_consume(u'websocket.receive', { 'path': '/', 'action': 'list', 'page': 2 }) client.consume('test') rec = client.receive() res = json.loads(json.loads(rec['text'])['response']) self.assertEqual(len(res), 10) self.assertEqual(res[0]['username'], 'test10') self.assertEqual(res[0]['email'], '*****@*****.**') self.assertEqual(res[0]['is_active'], True) client.send_and_consume(u'websocket.connect', {'path': '/{}'.format(10)}) client.send_and_consume(u'websocket.receive', { 'path': '/{}'.format(10), 'action': 'delete' }) client.consume('test') self.assertFalse(User.objects.filter(pk=10).exists()) data = {'username': '******'} client.send_and_consume('websocket.connect', {'path': '/{}'.format(11)}) client.send_and_consume( 'websocket.receive', { 'path': '/{}'.format(11), 'action': 'update', 'data': json.dumps(data) }) client.consume('test') user = User.objects.filter(pk=11).first() self.assertTrue(user) self.assertEqual(user.username, 'new_name')
def test_object_sub_with_fields(self): # create object for subscribe sub_object = User.objects.create_user(username='******', email='*****@*****.**') # define consumers routes = ObjectSubscribeConsumers.as_routes(path='/(?P<pk>\d+)/?', model=User, serializer_kwargs={'fields': ['username', 'is_active']}) # create client client = HttpClient() with apply_routes([routes]): # subscribe for object changes client.send_and_consume(u'websocket.connect', content={'path': '/{}'.format(sub_object.pk)}) # change sub object sub_object.username = '******' sub_object.email = '*****@*****.**' sub_object.save() res = json.loads(client.receive()['text'])['data'] self.assertEqual(res['username'], 'sub_object') self.assertEqual(res['is_active'], True) self.assertNotIn('email', res) self.assertNotIn('is_staff', res) sub_object.username = '******' sub_object.is_active = False sub_object.save() res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'updated') self.assertNotIn('email', res['data']) self.assertNotIn('is_staff', res['data']) self.assertEqual(res['data']['username'], 'test') self.assertEqual(res['data']['is_active'], False) sub_object.username = '******' sub_object.save(update_fields=['username']) res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'updated') self.assertEqual(res['data']['username'], 'test_new') self.assertNotIn('is_active', res['data']) self.assertNotIn('is_staff', res['data']) sub_object.email = '*****@*****.**' sub_object.save(update_fields=['email']) # check that nothing happened self.assertIsNone(client.receive())
def test_dynamic_channels_names(self): class Test(Consumers): channel_name = 'test1' @consumer def test(self, message): return self.channel_name test = Test.as_routes() test_2 = Test.as_routes(channel_name='test') client = HttpClient() with apply_routes([test]): client.send_and_consume(u'websocket.receive') with apply_routes([test_2]): client.send_and_consume(u'websocket.receive') channel_layer = channel_layers[DEFAULT_CHANNEL_LAYER] self.assertEqual(len(channel_layer._channels), 3, channel_layer._channels.keys()) self.assertIn('test', channel_layer._channels.keys())
def test_group_consumers(self): class _GroupConsumers(GroupConsumers): channel_name = 'test' path = '/test' with apply_routes([_GroupConsumers.as_routes()]): self.client.send_and_consume(u'websocket.connect', {'path': '/test', 'reply_channel': 'test.reply_channel'}) self.client.send_and_consume(u'websocket.receive', {'text': 'test', 'path': '/test', 'reply_channel': 'test.reply_channel'}) channel_layer = asgi.channel_layers[DEFAULT_CHANNEL_LAYER] self.assertTrue('test' in channel_layer._groups.keys()) self.assertTrue('test.reply_channel' in channel_layer._groups['test'].keys())
def test_trigger_outbound_update(self): class TestBinding(WebsocketBinding): model = User stream = 'test' fields = ['__all__'] @classmethod def group_names(cls, instance, action): return ["users2"] def has_permission(self, user, action, pk): return True # Make model and clear out pending sends user = User.objects.create(username='******', email='*****@*****.**') consumer_finished.send(sender=None) with apply_routes([route('test', TestBinding.consumer)]): client = HttpClient() client.join_group('users2') user.username = '******' user.save() consumer_finished.send(sender=None) 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_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_inbound_create(self): self.assertEqual(User.objects.all().count(), 0) class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', 'email', 'password', 'last_name'] @classmethod def group_names(cls, instance, action): return ['users_outbound'] def has_permission(self, user, action, pk): return True with apply_routes([ Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer) ]): 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' } } }) # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer client.consume('binding.users') 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_websockets_decorators(self): class WebsocketConsumer(websockets.WebsocketConsumer): slight_ordering = True def connect(self, message, **kwargs): self.order = message['order'] with apply_routes([route_class(WebsocketConsumer, path='/path')]): client = Client() client.send('websocket.connect', {'path': '/path', 'order': 1}) client.send('websocket.connect', {'path': '/path', 'order': 0}) client.consume('websocket.connect') self.assertEqual(client.consume('websocket.connect').order, 0) self.assertEqual(client.consume('websocket.connect').order, 1)
def test_websockets_decorators(self): class WebsocketConsumer(websockets.WebsocketConsumer): strict_ordering = True def connect(self, message, **kwargs): self.order = message['order'] with apply_routes([route_class(WebsocketConsumer, path='/path')]): client = Client() client.send('websocket.connect', {'path': '/path', 'order': 1}) client.send('websocket.connect', {'path': '/path', 'order': 0}) client.consume('websocket.connect') self.assertEqual(client.consume('websocket.connect').order, 0) self.assertEqual(client.consume('websocket.connect').order, 1)
def test_retrieve_404(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): json_content = self._send_and_consume('testmodel', { 'action': 'retrieve', 'pk': 1, 'request_id': 'client-request-id' }) expected = { 'action': 'retrieve', 'data': None, 'errors': ['Not found.'], 'response_status': 404, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected)
def test_as_route_method(self): class WebsocketConsumer(BaseConsumer): trigger = 'new' def test(self, message, **kwargs): self.message.reply_channel.send({'trigger': self.trigger}) method_mapping = {'mychannel': 'test'} with apply_routes([WebsocketConsumer.as_route( {'method_mapping': method_mapping, 'trigger': 'from_as_route'}, name='filter')]): client = Client() client.send_and_consume('mychannel', {'name': 'filter'}) self.assertEqual(client.receive(), {'trigger': 'from_as_route'})
def test_get_mixin(self): # create object obj = User.objects.create_user(username='******', email='*****@*****.**') # create client client = HttpClient() with apply_routes([ReadOnlyConsumers.as_routes(model=User, path='/(?P<pk>\d+)/?', channel_name='test')]): client.send_and_consume(u'websocket.connect', {'path': '/{}'.format(obj.pk)}) client.send_and_consume(u'websocket.receive', {'path': '/{}'.format(obj.pk), 'action': 'get'}) client.consume('test') res = json.loads(json.loads(client.receive()['text'])['response']) self.assertEqual(res['username'], 'test') self.assertEqual(res['email'], '*****@*****.**') self.assertEqual(res['is_active'], True)
def test_inbound_update(self): user = User.objects.create(username='******', email='*****@*****.**') class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', ] @classmethod def group_names(cls, instance, action): return ['users_outbound'] def has_permission(self, user, action, pk): return True with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]): 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': '******'}} }) # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer client.consume('binding.users') 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': '*****@*****.**'}} }) client.consume('binding.users') user = User.objects.get(pk=user.pk) self.assertEqual(user.username, 'test_inbound') self.assertEqual(user.email, '*****@*****.**')
def test_object_sub(self): # create object for subscribe sub_object = User.objects.create_user(username='******', email='*****@*****.**') # create object without subscribers just_object = User.objects.create_user(username='******', email='*****@*****.**') # define consumers routes = ObjectSubscribeConsumers.as_routes(path='/(?P<pk>\d+)/?', model=User) # create client client = HttpClient() with apply_routes([routes]): # subscribe for object changes client.send_and_consume( u'websocket.connect', content={'path': '/{}'.format(sub_object.pk)}) # change sub object sub_object.username = '******' sub_object.email = '*****@*****.**' sub_object.save() res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'updated') self.assertEqual(res['data']['username'], 'sub_object') self.assertEqual(res['data']['email'], '*****@*****.**') self.assertEqual(res['data']['is_staff'], False) # change second object just_object.email = '*****@*****.**' just_object.save() # check that nothing happened self.assertIsNone(client.receive()) # delete sub_object.delete() just_object.delete() res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'deleted') self.assertEqual(res['data']['username'], 'sub_object') self.assertEqual(res['data']['email'], '*****@*****.**') self.assertEqual(res['data']['is_staff'], False)
def test_update_mixin(self): # create object obj = User.objects.create_user(username='******', email='*****@*****.**') # create client client = HttpClient() data = {'username': '******'} with apply_routes([UpdateConsumers.as_routes(model=User, path='/(?P<pk>\d+)/?', channel_name='test')]): client.send_and_consume('websocket.connect', {'path': '/{}'.format(obj.pk)}) client.send_and_consume('websocket.receive', {'path': '/{}'.format(obj.pk), 'action': 'update', 'data': json.dumps(data)}) client.consume('test') user = User.objects.filter(pk=obj.pk).first() self.assertTrue(user) self.assertEqual(user.username, 'new_name')
def test_retrieve(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): instance = TestModel.objects.create(name="Test") json_content = self._send_and_consume('testmodel', { 'action': 'retrieve', 'pk': instance.id, 'request_id': 'client-request-id' }) expected = { 'action': 'retrieve', 'data': TestModelSerializer(instance).data, 'errors': [], 'response_status': 200, 'request_id': 'client-request-id' } self.assertTrue(json_content['payload'] == expected)
def test_list_consumers(self): # create object for i in range(20): User.objects.create_user(username='******' + str(i), email='*****@*****.**') # create client client = HttpClient() with apply_routes([ListConsumers.as_routes(model=User, path='/', channel_name='test', paginate_by=10)]): client.send_and_consume(u'websocket.connect', {'path': '/'}) client.send_and_consume(u'websocket.receive', {'path': '/', 'action': 'list', 'page': 2}) client.consume('test') rec = client.receive() res = json.loads(json.loads(rec['text'])['response']) self.assertEqual(len(res), 10) self.assertEqual(res[0]['username'], 'test10') self.assertEqual(res[0]['email'], '*****@*****.**') self.assertEqual(res[0]['is_active'], True)
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_model_sub_with_fields(self): # define consumers routes = ModelSubscribeConsumers.as_routes(model=User, serializer_kwargs={'fields': ['username']}) # create client client = HttpClient() with apply_routes([routes]): # subscribe for Models changes client.send_and_consume(u'websocket.connect') # create object User.objects.create_user(username='******', email='*****@*****.**') res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'created') self.assertEqual(res['data']['username'], 'test') self.assertNotIn('is_active', res['data']) self.assertNotIn('email', res['data'])
def test_passing_kwargs_and_reply_channel(self): class Test(Consumers): path = '^/(?P<slug>[^/]+)/(?P<pk>\d+)/?' channel_name = 'test' @consumer(tag='(?P<test>[^/]+)') def test(this, message, test): this.reply_channel.send({'test': test, 'kwargs': message.content['_kwargs']['slug'], 'slug': this.kwargs.get('slug', None)}) with apply_routes([Test.as_routes()]): client = HttpClient() client.send_and_consume(u'websocket.connect', content={'path': '/name/123/'}) client.send_and_consume(u'websocket.receive', content={'path': '/name/123', 'tag': 'tag'}) client.consume(u'test') content = client.receive() self.assertDictEqual(content, {'test': 'tag', 'slug': 'name', 'kwargs': 'name'})
def test_object_sub(self): # create object for subscribe sub_object = User.objects.create_user(username='******', email='*****@*****.**') # create object without subscribers just_object = User.objects.create_user(username='******', email='*****@*****.**') # define consumers routes = ObjectSubscribeConsumers.as_routes(path='/(?P<pk>\d+)/?', model=User) # create client client = HttpClient() with apply_routes([routes]): # subscribe for object changes client.send_and_consume(u'websocket.connect', content={'path': '/{}'.format(sub_object.pk)}) # change sub object sub_object.username = '******' sub_object.email = '*****@*****.**' sub_object.save() res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'updated') self.assertEqual(res['data']['username'], 'sub_object') self.assertEqual(res['data']['email'], '*****@*****.**') self.assertEqual(res['data']['is_staff'], False) # change second object just_object.email = '*****@*****.**' just_object.save() # check that nothing happened self.assertIsNone(client.receive()) # delete sub_object.delete() just_object.delete() res = json.loads(client.receive()['text']) self.assertEqual(res['action'], 'deleted') self.assertEqual(res['data']['username'], 'sub_object') self.assertEqual(res['data']['email'], '*****@*****.**') self.assertEqual(res['data']['is_staff'], False)
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_demultiplexer(self): class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] with apply_routes([Demultiplexer.as_route(path='/')]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') # assert in group Group('inbound').send({'text': json.dumps({'test': 'yes'})}, immediately=True) self.assertEqual(client.receive(), {'test': 'yes'}) # assert that demultiplexer stream message client.send_and_consume('websocket.receive', path='/', text={'stream': 'users', 'payload': {'test': 'yes'}}) message = client.get_next_message('binding.users') self.assertIsNotNone(message) self.assertEqual(message.content['test'], 'yes')
def test_inbound_create(self): self.assertEqual(User.objects.all().count(), 0) class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', 'email', 'password', 'last_name'] @classmethod def group_names(cls, instance, action): return ['users_outbound'] def has_permission(self, user, action, pk): return True with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]): 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'}} }) # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer client.consume('binding.users') 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())