def test_config_error(self): """ If channel layer doesn't specify TEST_CONFIG, `make_test_backend` should result into error. """ with self.assertRaises(InvalidChannelLayerError): channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER)
def test_config_error(self): """ If channel layer doesn't specify TEST_CONFIG, `make_test_backend` should result into error. """ with self.assertRaises(InvalidChannelLayerError): channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER)
async def test_model_observer_delete_wrapper(settings): settings.CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestConsumerObserverDelete(AsyncAPIConsumer): async def accept(self, **kwargs): await self.user_change_observer_delete.subscribe() await super().accept() @model_observer(get_user_model()) async def user_change_observer_delete(self, message, observer=None, **kwargs): await self.send_json(message) communicator = WebsocketCommunicator(TestConsumerObserverDelete, "/testws/") connected, _ = await communicator.connect() assert connected await communicator.receive_nothing() user = await database_sync_to_async(get_user_model() )(username="******", email="*****@*****.**") await database_sync_to_async(user.save)() response = await communicator.receive_json_from() await communicator.receive_nothing() assert { "action": "create", "pk": user.pk, "type": "user.change.observer.delete", } == response pk = user.pk await database_sync_to_async(user.delete)() response = await communicator.receive_json_from() await communicator.receive_nothing() assert { "action": "delete", "pk": pk, "type": "user.change.observer.delete", } == response await communicator.disconnect()
async def test_model_observer_custom_groups_wrapper(settings): settings.CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestConsumer(AsyncAPIConsumer): async def accept(self, **kwargs): await self.user_change_custom_groups_wrapper.subscribe( username="******") await super().accept() @model_observer(get_user_model()) async def user_change_custom_groups_wrapper(self, message, **kwargs): await self.send_json(message) @user_change_custom_groups_wrapper.groups def user_change_custom_groups_wrapper(self, instance=None, username=None, **kwargs): if username: yield "-instance-username-{}".format(slugify(username)) else: yield "-instance-username-{}".format(instance.username) communicator = WebsocketCommunicator(TestConsumer, "/testws/") connected, _ = await communicator.connect() assert connected user = await database_sync_to_async(get_user_model().objects.create )(username="******", email="*****@*****.**") response = await communicator.receive_json_from() assert { "action": "create", "pk": user.pk, "type": "user.change.custom.groups.wrapper", } == response await communicator.disconnect() user = await database_sync_to_async(get_user_model().objects.create )(username="******", email="*****@*****.**") # no event since this is only subscribed to 'test' with pytest.raises(asyncio.TimeoutError): await communicator.receive_json_from()
async def test_model_observer_wrapper_in_transaction(settings): settings.CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestConsumer(AsyncAPIConsumer): async def accept(self, **kwargs): await TestConsumer.user_change_wrapper_in_transaction.subscribe( self) await super().accept() @model_observer(get_user_model()) async def user_change_wrapper_in_transaction(self, message, action, message_type, observer=None, **kwargs): await self.send_json( dict(body=message, action=action, type=message_type)) communicator = WebsocketCommunicator(TestConsumer(), "/testws/") connected, _ = await communicator.connect() assert connected @database_sync_to_async def create_user_and_wait(): with transaction.atomic(): user = get_user_model().objects.create(username="******", email="*****@*****.**") assert async_to_sync(communicator.receive_nothing(timeout=0.1)) user.username = "******" user.save() assert async_to_sync(communicator.receive_nothing(timeout=0.1)) return user user = await create_user_and_wait() response = await communicator.receive_json_from() assert { "action": "create", "body": { "pk": user.pk }, "type": "user.change.wrapper.in.transaction", } == response await communicator.disconnect()
def test_config_instance(self): """ If channel layer provides TEST_CONFIG, `make_test_backend` should return channel layer instance appropriate for testing. """ layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) self.assertEqual(layer.expiry, 100500)
def test_config_instance(self): """ If channel layer provides TEST_CONFIG, `make_test_backend` should return channel layer instance appropriate for testing. """ layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) self.assertEqual(layer.expiry, 100500)
async def test_model_observer_many_connections_wrapper(settings): settings.CHANNEL_LAYERS={ "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestConsumer(AsyncAPIConsumer): async def accept(self): await TestConsumer.user_change.subscribe(self) await super().accept() @model_observer(get_user_model()) async def user_change(self, message, **kwargs): await self.send_json(message) communicator1 = WebsocketCommunicator(TestConsumer, "/testws/") connected, _ = await communicator1.connect() assert connected communicator2 = WebsocketCommunicator(TestConsumer, "/testws/") connected, _ = await communicator2.connect() assert connected user = await database_sync_to_async(get_user_model().objects.create)( username='******', email='*****@*****.**' ) response = await communicator1.receive_json_from() assert { 'action': 'create', 'pk': user.pk, 'type': 'user.change' } == response await communicator1.disconnect() response = await communicator2.receive_json_from() assert { 'action': 'create', 'pk': user.pk, 'type': 'user.change' } == response await communicator2.disconnect()
async def test_observer_wrapper(settings): settings.CHANNEL_LAYERS={ "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestConsumer(AsyncAPIConsumer): async def accept(self): await TestConsumer.handle_user_logged_in.subscribe(self) await super().accept() @observer(user_logged_in) async def handle_user_logged_in(self, *args, observer=None, **kwargs): await self.send_json({ 'message': kwargs, 'observer': observer is not None } ) communicator = WebsocketCommunicator(TestConsumer, "/testws/") connected, _ = await communicator.connect() assert connected user = await database_sync_to_async(get_user_model().objects.create)( username='******', email='*****@*****.**' ) await database_sync_to_async(user_logged_in.send)( sender=user.__class__, request=None, user=user ) response = await communicator.receive_json_from() assert {'message': {}, 'observer': True} == response await communicator.disconnect()
async def test_unsubscribe_observer_model_instance_mixin(settings): settings.CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestConsumer(ObserverModelInstanceMixin, GenericAsyncAPIConsumer): queryset = get_user_model().objects.all() serializer_class = UserSerializer async def accept(self, subprotocol=None): await super().accept() @action() async def update_username(self, pk=None, username=None, **kwargs): user = await database_sync_to_async(self.get_object)(pk=pk) user.username = username await database_sync_to_async(user.save)() return {'pk': pk}, 200 assert not await database_sync_to_async( get_user_model().objects.all().exists)() # Test a normal connection communicator = WebsocketCommunicator(TestConsumer, "/testws/") connected, _ = await communicator.connect() assert connected u1 = await database_sync_to_async(get_user_model().objects.create )(username='******', email='*****@*****.**') # lookup up u1 await communicator.send_json_to({ "action": "subscribe_instance", "pk": u1.id, "request_id": 4 }) response = await communicator.receive_json_from() assert response == { "action": "subscribe_instance", "errors": [], "response_status": 201, "request_id": 4, "data": None } await communicator.send_json_to({ "action": "update_username", "pk": u1.id, "username": "******", "request_id": 5 }) response = await communicator.receive_json_from() assert response == { "action": "update_username", "errors": [], "response_status": 200, "request_id": 5, "data": { 'pk': u1.id } } response = await communicator.receive_json_from() assert response == { "action": "update", "errors": [], "response_status": 200, "request_id": 4, "data": { 'email': '*****@*****.**', 'id': u1.pk, 'username': '******' }, } # unsubscribe # lookup up u1 await communicator.send_json_to({ "action": "unsubscribe_instance", "pk": u1.id, "request_id": 4 }) response = await communicator.receive_json_from() assert response == { "action": "unsubscribe_instance", "errors": [], "response_status": 204, "request_id": 4, "data": None } await communicator.send_json_to({ "action": "update_username", "pk": u1.id, "username": "******", "request_id": 5 }) response = await communicator.receive_json_from() assert response == { "action": "update_username", "errors": [], "response_status": 200, "request_id": 5, "data": { 'pk': u1.id } } await communicator.disconnect()
async def test_two_observer_model_instance_mixins(settings): settings.CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestUserConsumer(ObserverModelInstanceMixin, GenericAsyncAPIConsumer): queryset = get_user_model().objects.all() serializer_class = UserSerializer async def accept(self, subprotocol=None): await super().accept() @action() async def update_username(self, pk=None, username=None, **kwargs): user = await database_sync_to_async(self.get_object)(pk=pk) user.username = username await database_sync_to_async(user.save)() return {'pk': pk}, 200 class TestOtherConsumer(ObserverModelInstanceMixin, GenericAsyncAPIConsumer): queryset = TestModel.objects.all() serializer_class = UserSerializer async def accept(self, subprotocol=None): await super().accept() @action() async def update_username(self, pk=None, name=None, **kwargs): tm = await database_sync_to_async(self.get_object)(pk=pk) tm.name = name await database_sync_to_async(tm.save)() return {'pk': pk}, 200 assert not await database_sync_to_async( get_user_model().objects.all().exists)() # Test a normal connection communicator1 = WebsocketCommunicator(TestOtherConsumer, "/testws/") connected, _ = await communicator1.connect() assert connected # Test a normal connection communicator2 = WebsocketCommunicator(TestUserConsumer, "/testws/") connected, _ = await communicator2.connect() assert connected u1 = await database_sync_to_async(get_user_model().objects.create )(username='******', email='*****@*****.**') t1 = await database_sync_to_async(TestModel.objects.create)(name='test2') await communicator1.send_json_to({ "action": "subscribe_instance", "pk": t1.id, "request_id": 4 }) response = await communicator1.receive_json_from() assert response == { "action": "subscribe_instance", "errors": [], "response_status": 201, "request_id": 4, "data": None } await communicator2.send_json_to({ "action": "subscribe_instance", "pk": u1.id, "request_id": 4 }) response = await communicator2.receive_json_from() assert response == { "action": "subscribe_instance", "errors": [], "response_status": 201, "request_id": 4, "data": None } # update the user u1.username = '******' await database_sync_to_async(u1.save)() # user is updated await communicator2.receive_json_from() # test model is not assert await communicator1.receive_nothing()
async def test_observer_model_instance_mixin_with_many_subs(settings): """ This tests when there are 2 instances subscribed to on the same consumer. """ settings.CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500 }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestConsumerMultipleSubs(ObserverModelInstanceMixin, GenericAsyncAPIConsumer): queryset = get_user_model().objects.all() serializer_class = UserSerializer async def accept(self, subprotocol=None): await super().accept() @action() async def update_username(self, pk=None, username=None, **kwargs): user = await database_sync_to_async(self.get_object)(pk=pk) user.username = username await database_sync_to_async(user.save)() return {"pk": pk}, 200 assert not await database_sync_to_async( get_user_model().objects.all().exists)() # Test a normal connection communicator = WebsocketCommunicator(TestConsumerMultipleSubs(), "/testws/") connected, _ = await communicator.connect() assert connected u1 = await database_sync_to_async(get_user_model().objects.create )(username="******", email="*****@*****.**") u2 = await database_sync_to_async(get_user_model().objects.create )(username="******", email="*****@*****.**") # Subscribe to instance user 1 await communicator.send_json_to({ "action": "subscribe_instance", "pk": u1.id, "request_id": 4 }) response = await communicator.receive_json_from() assert response == { "action": "subscribe_instance", "errors": [], "response_status": 201, "request_id": 4, "data": None, } # Subscribe to instance user 2 await communicator.send_json_to({ "action": "subscribe_instance", "pk": u2.id, "request_id": 5 }) response = await communicator.receive_json_from() assert response == { "action": "subscribe_instance", "errors": [], "response_status": 201, "request_id": 5, "data": None, } # lookup up u1 await communicator.send_json_to({ "action": "update_username", "pk": u1.id, "username": "******", "request_id": 10, }) response = await communicator.receive_json_from() assert response == { "action": "update_username", "errors": [], "response_status": 200, "request_id": 10, "data": { "pk": u1.id }, } response = await communicator.receive_json_from() assert response == { "action": "update", "errors": [], "response_status": 200, "request_id": 4, "data": { "email": "*****@*****.**", "id": u1.id, "username": "******" }, } assert await communicator.receive_nothing() # Update U2 await communicator.send_json_to({ "action": "update_username", "pk": u2.id, "username": "******", "request_id": 11, }) response = await communicator.receive_json_from() assert response == { "action": "update_username", "errors": [], "response_status": 200, "request_id": 11, "data": { "pk": u2.id }, } response = await communicator.receive_json_from() assert response == { "action": "update", "errors": [], "response_status": 200, "request_id": 5, "data": { "email": "*****@*****.**", "id": u2.id, "username": "******" }, } await communicator.disconnect()
async def test_observer_model_instance_mixin(settings): settings.CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestConsumer(ObserverModelInstanceMixin, GenericAsyncAPIConsumer): queryset = get_user_model().objects.all() serializer_class = UserSerializer async def accept(self, subprotocol=None): await super().accept() @action() async def update_username(self, pk=None, username=None, **kwargs): user = await database_sync_to_async(self.get_object)(pk=pk) user.username = username await database_sync_to_async(user.save)() return {"pk": pk}, 200 assert not await database_sync_to_async( get_user_model().objects.all().exists)() # Test a normal connection communicator = WebsocketCommunicator(TestConsumer(), "/testws/") connected, _ = await communicator.connect() assert connected await communicator.send_json_to({ "action": "retrieve", "pk": 100, "request_id": 1 }) response = await communicator.receive_json_from() assert response == { "action": "retrieve", "errors": ["Not found"], "response_status": 404, "request_id": 1, "data": None, } u1 = await database_sync_to_async(get_user_model().objects.create )(username="******", email="*****@*****.**") u2 = await database_sync_to_async(get_user_model().objects.create )(username="******", email="*****@*****.**") # lookup a pk that is not there await communicator.send_json_to({ "action": "retrieve", "pk": u1.id - 1, "request_id": 1 }) response = await communicator.receive_json_from() assert response == { "action": "retrieve", "errors": ["Not found"], "response_status": 404, "request_id": 1, "data": None, } # lookup up u1 await communicator.send_json_to({ "action": "retrieve", "pk": u1.id, "request_id": 1 }) response = await communicator.receive_json_from() assert response == { "action": "retrieve", "errors": [], "response_status": 200, "request_id": 1, "data": { "email": "*****@*****.**", "id": u1.id, "username": "******" }, } # lookup up u1 await communicator.send_json_to({ "action": "subscribe_instance", "pk": u1.id, "request_id": 4 }) response = await communicator.receive_json_from() assert response == { "action": "subscribe_instance", "errors": [], "response_status": 201, "request_id": 4, "data": None, } u3 = await database_sync_to_async(get_user_model().objects.create )(username="******", email="*****@*****.**") # lookup up u1 await communicator.send_json_to({ "action": "update_username", "pk": u1.id, "username": "******", "request_id": 5, }) response = await communicator.receive_json_from() assert response == { "action": "update_username", "errors": [], "response_status": 200, "request_id": 5, "data": { "pk": u1.id }, } response = await communicator.receive_json_from() assert response == { "action": "update", "errors": [], "response_status": 200, "request_id": 4, "data": { "email": "*****@*****.**", "id": u1.id, "username": "******" }, } u1_pk = u1.pk await database_sync_to_async(u1.delete)() response = await communicator.receive_json_from() assert response == { "action": "delete", "errors": [], "response_status": 204, "request_id": 4, "data": { "pk": u1_pk }, } await communicator.disconnect()
async def test_model_observer_many_consumers_wrapper(settings): settings.CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestConsumer(AsyncAPIConsumer): async def accept(self, **kwargs): await self.user_change_many_consumers_wrapper_1.subscribe() await super().accept() @model_observer(get_user_model()) async def user_change_many_consumers_wrapper_1(self, message, action, message_type, observer=None, **kwargs): await self.send_json( dict(body=message, action=action, type=message_type)) class TestConsumer2(AsyncAPIConsumer): async def accept(self, **kwargs): await self.user_change_many_consumers_wrapper_2.subscribe() await super().accept() @model_observer(get_user_model()) async def user_change_many_consumers_wrapper_2(self, message, action, message_type, observer=None, **kwargs): await self.send_json( dict(body=message, action=action, type=message_type)) communicator1 = WebsocketCommunicator(TestConsumer(), "/testws/") connected, _ = await communicator1.connect() assert connected communicator2 = WebsocketCommunicator(TestConsumer2(), "/testws/") connected, _ = await communicator2.connect() assert connected user = await database_sync_to_async(get_user_model().objects.create )(username="******", email="*****@*****.**") response = await communicator1.receive_json_from() assert { "action": "create", "body": { "pk": user.pk }, "type": "user.change.many.consumers.wrapper.1", } == response await communicator1.disconnect() response = await communicator2.receive_json_from() assert { "action": "create", "body": { "pk": user.pk }, "type": "user.change.many.consumers.wrapper.2", } == response await communicator2.disconnect()
async def test_model_observer_with_class_serializer(settings): settings.CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class UserSerializer(serializers.ModelSerializer): class Meta: model = get_user_model() fields = ['id', 'username'] class TestConsumerObserverUsers(AsyncAPIConsumer): async def accept(self, **kwargs): await self.users_changes.subscribe() await super().accept() @model_observer(get_user_model(), serializer_class=UserSerializer) async def users_changes(self, message, action, **kwargs): await self.reply(data=message, action=action) communicator = WebsocketCommunicator(TestConsumerObserverUsers(), "/testws/") connected, _ = await communicator.connect() assert connected user = await database_sync_to_async(get_user_model().objects.create )(username="******", email="*****@*****.**") response = await communicator.receive_json_from() assert { "action": "create", "response_status": 200, "request_id": None, "errors": [], "data": { "id": user.pk, "username": user.username, }, } == response user.username = "******" await database_sync_to_async(user.save)() response = await communicator.receive_json_from() assert { "action": "update", "response_status": 200, "request_id": None, "errors": [], "data": { "id": user.pk, "username": user.username, }, } == response pk = user.pk await database_sync_to_async(user.delete)() response = await communicator.receive_json_from() assert { "action": "delete", "response_status": 200, "request_id": None, "errors": [], "data": { "id": pk, "username": user.username, }, } == response await communicator.disconnect()
async def test_model_observer_with_request_id(settings): settings.CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", "TEST_CONFIG": { "expiry": 100500, }, }, } layer = channel_layers.make_test_backend(DEFAULT_CHANNEL_LAYER) class TestConsumerObserverCustomGroups(AsyncAPIConsumer): @action() async def subscribe(self, username, request_id, **kwargs): await self.user_change_custom_groups.subscribe( username=username, request_id=request_id) @model_observer(get_user_model()) async def user_change_custom_groups(self, message, action, message_type, observer=None, subscribing_request_ids=None, **kwargs): await self.send_json( dict( body=message, action=action, type=message_type, subscribing_request_ids=subscribing_request_ids, )) @user_change_custom_groups.groups_for_signal def user_change_custom_groups(self, instance=None, **kwargs): yield "-instance-username-{}".format(instance.username) @user_change_custom_groups.groups_for_consumer def user_change_custom_groups(self, username=None, **kwargs): yield "-instance-username-{}".format(slugify(username)) communicator = WebsocketCommunicator(TestConsumerObserverCustomGroups(), "/testws/") connected, _ = await communicator.connect() assert connected await communicator.send_json_to({ "action": "subscribe", "username": "******", "request_id": 5, }) user = await database_sync_to_async(get_user_model().objects.create )(username="******", email="*****@*****.**") response = await communicator.receive_json_from() assert { "action": "create", "body": { "pk": user.pk }, "type": "user.change.custom.groups", "subscribing_request_ids": [5], } == response await communicator.disconnect()