class FinishedPickupReceiverTest(ChannelTestCase): def setUp(self): self.client = WSClient() self.member = UserFactory() self.group = GroupFactory(members=[self.member]) self.store = StoreFactory(group=self.group) self.pickup = PickupDateFactory(store=self.store, collectors=[self.member]) def test_receive_feedback_possible_and_history(self): self.pickup.date = timezone.now() - relativedelta(days=1) self.pickup.save() self.client.force_login(self.member) self.client.send_and_consume('websocket.connect', path='/') call_command('process_finished_pickup_dates') response = self.client.receive(json=True) self.assertEqual(response['topic'], 'history:history') self.assertEqual(response['payload']['typus'], 'PICKUP_DONE') response = self.client.receive(json=True) self.assertEqual(response['topic'], 'pickups:feedback_possible') self.assertEqual(response['payload']['id'], self.pickup.id) self.assertIsNone(self.client.receive(json=True))
def test_receives_messages(self): client = WSClient() user = UserFactory() author = UserFactory() # join a conversation conversation = ConversationFactory() conversation.join(user) conversation.join(author) # login and connect client.force_login(user) client.send_and_consume('websocket.connect', path='/') # add a message to the conversation message = ConversationMessage.objects.create(conversation=conversation, content='yay', author=author) # hopefully they receive it! response = client.receive(json=True) response['payload']['created_at'] = parse(response['payload']['created_at']) self.assertEqual(response, { 'topic': 'conversations:message', 'payload': { 'id': message.id, 'content': message.content, 'author': message.author.id, 'conversation': conversation.id, 'created_at': message.created_at } })
def test_receives_messages(self): self.maxDiff = None client = WSClient() user = UserFactory() author_client = WSClient() author = UserFactory() # join a conversation conversation = ConversationFactory() conversation.join(user) conversation.join(author) # login and connect client.force_login(user) client.send_and_consume('websocket.connect', path='/') author_client.force_login(author) author_client.send_and_consume('websocket.connect', path='/') # add a message to the conversation message = ConversationMessage.objects.create(conversation=conversation, content='yay', author=author) # hopefully they receive it! response = client.receive(json=True) parse_dates(response) self.assertEqual( response, make_conversation_message_broadcast(message) ) # and they should get an updated conversation object response = client.receive(json=True) parse_dates(response) del response['payload']['participants'] self.assertEqual( response, make_conversation_broadcast(conversation, unread_message_count=1) ) # author should get message & updated conversations object too response = author_client.receive(json=True) parse_dates(response) self.assertEqual( response, make_conversation_message_broadcast(message, is_editable=True) ) # Author receives more recent `update_at` time, # because their `seen_up_to` status is set after sending the message. author_participant = conversation.conversationparticipant_set.get(user=author) response = author_client.receive(json=True) parse_dates(response) del response['payload']['participants'] self.assertEqual( response, make_conversation_broadcast(conversation, seen_up_to=message.id, updated_at=author_participant.updated_at) )
class PickupDateReceiverTests(ChannelTestCase): def setUp(self): self.client = WSClient() self.member = UserFactory() self.group = GroupFactory(members=[self.member]) self.store = StoreFactory(group=self.group) self.pickup = PickupDateFactory(store=self.store) def test_receive_pickup_changes(self): self.client.force_login(self.member) self.client.send_and_consume('websocket.connect', path='/') # change property date = faker.future_datetime(end_date='+30d', tzinfo=timezone.utc) self.pickup.date = date self.pickup.save() response = self.client.receive(json=True) self.assertEqual(response['topic'], 'pickups:pickupdate') self.assertEqual(parse(response['payload']['date']), date) # join self.pickup.collectors.add(self.member) response = self.client.receive(json=True) self.assertEqual(response['topic'], 'pickups:pickupdate') self.assertEqual(response['payload']['collector_ids'], [self.member.id]) response = self.client.receive(json=True) self.assertEqual(response['topic'], 'conversations:conversation') self.assertEqual(response['payload']['participants'], [self.member.id]) # leave self.pickup.collectors.remove(self.member) response = self.client.receive(json=True) self.assertEqual(response['topic'], 'pickups:pickupdate') self.assertEqual(response['payload']['collector_ids'], []) response = self.client.receive(json=True) self.assertEqual(response['topic'], 'conversations:leave') self.assertIsNone(self.client.receive(json=True)) def test_receive_pickup_delete(self): self.client.force_login(self.member) self.client.send_and_consume('websocket.connect', path='/') self.pickup.deleted = True self.pickup.save() response = self.client.receive(json=True) self.assertEqual(response['topic'], 'pickups:pickupdate_deleted') self.assertEqual(response['payload']['id'], self.pickup.id) self.assertIsNone(self.client.receive(json=True))
def test_adds_subscription(self): client = WSClient() user = UserFactory() client.force_login(user) self.assertEqual( ChannelSubscription.objects.filter(user=user).count(), 0) client.send_and_consume('websocket.connect', path='/') self.assertEqual( ChannelSubscription.objects.filter(user=user).count(), 1, 'Did not add subscription')
def test_saves_reply_channel(self): client = WSClient() user = UserFactory() client.force_login(user) client.send_and_consume('websocket.connect', path='/') subscription = ChannelSubscription.objects.filter(user=user).first() self.assertIsNotNone(subscription.reply_channel) # send a message on it Channel(subscription.reply_channel).send({'message': 'hey! whaatsup?'}) self.assertEqual(client.receive(json=True), {'message': 'hey! whaatsup?'})
def test_updates_away(self): client = WSClient() user = UserFactory() client.force_login(user) client.send_and_consume('websocket.connect', path='/') client.send_and_consume('websocket.receive', text={'type': 'away'}, path='/') subscription = ChannelSubscription.objects.get(user=user) self.assertIsNotNone(subscription.away_at) client.send_and_consume('websocket.receive', text={'type': 'back'}, path='/') subscription.refresh_from_db() self.assertIsNone(subscription.away_at)
def test_updates_lastseen(self): client = WSClient() user = UserFactory() client.force_login(user) client.send_and_consume('websocket.connect', path='/') # update the lastseen timestamp to ages ago the_past = timezone.now() - relativedelta(hours=6) ChannelSubscription.objects.filter(user=user).update( lastseen_at=the_past) # send a message, and it should update client.send_and_consume('websocket.receive', text={'message': 'hey'}, path='/') subscription = ChannelSubscription.objects.filter(user=user).first() difference = subscription.lastseen_at - the_past self.assertGreater(difference.seconds, 1000)
class WSUsuario: def __init__(self, usuario, path='/'): self.user = usuario self.wsclient = WSClient() self.wsclient.force_login(usuario) self.wsclient.send_and_consume('websocket.connect', path=path) self.path = path def receive(self, *args, **kwargs): return self.wsclient.receive(*args, **kwargs) def send_and_consume(self, message, data=None): self.wsclient.send_and_consume('websocket.receive', text={ "message": message, "data": data }, path=self.path)
class FeedbackReceiverTests(ChannelTestCase): def setUp(self): self.client = WSClient() self.member = UserFactory() self.group = GroupFactory(members=[self.member]) self.store = StoreFactory(group=self.group) self.pickup = PickupDateFactory(store=self.store) def test_receive_feedback_changes(self): self.client.force_login(self.member) self.client.send_and_consume('websocket.connect', path='/') feedback = FeedbackFactory(given_by=self.member, about=self.pickup) response = self.client.receive(json=True) self.assertEqual(response['topic'], 'feedback:feedback') self.assertEqual(response['payload']['weight'], feedback.weight) self.assertIsNone(self.client.receive(json=True))
def test_other_participants_receive_update_on_join(self): client = WSClient() user = UserFactory() joining_user = UserFactory() # join a conversation conversation = ConversationFactory() conversation.join(user) # login and connect client.force_login(user) client.send_and_consume('websocket.connect', path='/') conversation.join(joining_user) response = client.receive(json=True) self.assertEqual(response['topic'], 'conversations:conversation') self.assertEqual(set(response['payload']['participants']), {user.id, joining_user.id})
class StoreReceiverTests(ChannelTestCase): def setUp(self): self.client = WSClient() self.member = UserFactory() self.group = GroupFactory(members=[self.member]) self.store = StoreFactory(group=self.group) def test_receive_store_changes(self): self.client.force_login(self.member) self.client.send_and_consume('websocket.connect', path='/') name = faker.name() self.store.name = name self.store.save() response = self.client.receive(json=True) self.assertEqual(response['topic'], 'stores:store') self.assertEqual(response['payload']['name'], name) self.assertIsNone(self.client.receive(json=True))
def tests_receive_message_on_leave(self): client = WSClient() user = UserFactory() # join a conversation conversation = ConversationFactory() conversation.join(user) # login and connect client.force_login(user) client.send_and_consume('websocket.connect', path='/') conversation.leave(user) self.assertEqual(client.receive(json=True), { 'topic': 'conversations:leave', 'payload': { 'id': conversation.id } })
class GroupReceiverTests(ChannelTestCase): def setUp(self): self.client = WSClient() self.member = UserFactory() self.user = UserFactory() self.group = GroupFactory(members=[self.member]) def test_receive_group_changes(self): self.client.force_login(self.member) self.client.send_and_consume('websocket.connect', path='/') name = faker.name() self.group.name = name self.group.save() response = self.client.receive(json=True) self.assertEqual(response['topic'], 'groups:group_detail') self.assertEqual(response['payload']['name'], name) self.assertTrue('description' in response['payload']) response = self.client.receive(json=True) self.assertEqual(response['topic'], 'groups:group_preview') self.assertEqual(response['payload']['name'], name) self.assertTrue('description' not in response['payload']) self.assertIsNone(self.client.receive(json=True)) def test_receive_group_changes_as_nonmember(self): self.client.force_login(self.user) self.client.send_and_consume('websocket.connect', path='/') name = faker.name() self.group.name = name self.group.save() response = self.client.receive(json=True) self.assertEqual(response['topic'], 'groups:group_preview') self.assertEqual(response['payload']['name'], name) self.assertTrue('description' not in response['payload']) self.assertIsNone(self.client.receive(json=True))
class PickupDateSeriesReceiverTests(ChannelTestCase): def setUp(self): self.client = WSClient() self.member = UserFactory() self.group = GroupFactory(members=[self.member]) self.store = StoreFactory(group=self.group) # Create far in the future to generate no pickup dates # They would lead to interfering websocket messages self.series = PickupDateSeriesFactory(store=self.store, start_date=timezone.now() + relativedelta(months=2)) def test_receive_series_changes(self): self.client.force_login(self.member) self.client.send_and_consume('websocket.connect', path='/') date = faker.future_datetime( end_date='+30d', tzinfo=timezone.utc) + relativedelta(months=2) self.series.start_date = date self.series.save() response = self.client.receive(json=True) self.assertEqual(response['topic'], 'pickups:series') self.assertEqual(parse(response['payload']['start_date']), date) self.assertIsNone(self.client.receive(json=True)) def test_receive_series_delete(self): self.client.force_login(self.member) self.client.send_and_consume('websocket.connect', path='/') id = self.series.id self.series.delete() response = self.client.receive(json=True) self.assertEqual(response['topic'], 'pickups:series_deleted') self.assertEqual(response['payload']['id'], id) self.assertIsNone(self.client.receive(json=True))
class UserReceiverTest(ChannelTestCase): def setUp(self): self.client = WSClient() self.member = UserFactory() self.other_member = UserFactory() self.unrelated_user = UserFactory() self.group = GroupFactory(members=[self.member, self.other_member]) pathlib.Path(settings.MEDIA_ROOT).mkdir(exist_ok=True) copyfile(os.path.join(os.path.dirname(__file__), './photo.jpg'), os.path.join(settings.MEDIA_ROOT, 'photo.jpg')) self.member.photo = 'photo.jpg' self.member.save() self.other_member.photo = 'photo.jpg' self.other_member.save() def test_receive_own_user_changes(self): self.client.force_login(self.member) self.client.send_and_consume('websocket.connect', path='/') name = faker.name() self.member.display_name = name self.member.save() response = self.client.receive(json=True) self.assertEqual(response['topic'], 'auth:user') self.assertEqual(response['payload']['display_name'], name) self.assertTrue('current_group' in response['payload']) self.assertTrue( response['payload']['photo_urls']['full_size'].startswith( settings.HOSTNAME)) self.assertIsNone(self.client.receive(json=True)) def test_receive_changes_of_other_user(self): self.client.force_login(self.member) self.client.send_and_consume('websocket.connect', path='/') name = faker.name() self.other_member.display_name = name self.other_member.save() response = self.client.receive(json=True) self.assertEqual(response['topic'], 'users:user') self.assertEqual(response['payload']['display_name'], name) self.assertTrue('current_group' not in response['payload']) self.assertTrue( response['payload']['photo_urls']['full_size'].startswith( settings.HOSTNAME)) self.assertIsNone(self.client.receive(json=True)) def test_unrelated_user_receives_no_changes(self): self.client.force_login(self.unrelated_user) self.client.send_and_consume('websocket.connect', path='/') self.member.display_name = faker.name() self.member.save() self.assertIsNone(self.client.receive(json=True))
def test_websockets_http_session_and_channel_session(self): class WebsocketConsumer(websockets.WebsocketConsumer): http_user_and_session = True user_model = get_user_model() user = user_model.objects.create_user(username='******', email='*****@*****.**', password='******') client = WSClient() client.force_login(user) with apply_routes([route_class(WebsocketConsumer, path='/path')]): connect = client.send_and_consume('websocket.connect', {'path': '/path'}) receive = client.send_and_consume('websocket.receive', {'path': '/path'}, text={'key': 'value'}) disconnect = client.send_and_consume('websocket.disconnect', {'path': '/path'}) self.assertEqual(connect.message.http_session.session_key, receive.message.http_session.session_key) self.assertEqual(connect.message.http_session.session_key, disconnect.message.http_session.session_key)
class ProviderAuctionStreamTestCase(BaseChannelTestCase): fixtures = [ 'users.json', 'currencies.json', 'experiences.json', 'auctions.json' ] def setUp(self): super(ProviderAuctionStreamTestCase, self).setUp() self.client = WSClient() self.auction = Auction.objects.get(pk=1) def test_unauthenticated(self): self.client.send_and_consume('websocket.connect', path='/ws/provider/auctions/1/stream/', check_accept=False) self.assertEqual(self.client.receive(), {'accept': False}) def test_guest(self): self.client.force_login(self.guest) self.client.send_and_consume('websocket.connect', path='/ws/provider/auctions/1/stream/', check_accept=False) self.assertEqual(self.client.receive(), {'accept': False}) def test_provider(self): self.client.force_login(self.provider) self.client.send_and_consume( 'websocket.connect', path='/ws/provider/auctions/1/stream/', ) bid = Bid.objects.create( auction=self.auction, user=self.guest, price=self.auction.current_price() + 1, ) message = self.client.receive() self.assertEqual(message['id'], bid.id)
class ResourceBindingTestCase(ChannelTestCase): def setUp(self): super(ResourceBindingTestCase, self).setUp() self.client = WSClient() def _send_and_consume(self, channel, data): """Helper that sends and consumes message and returns the next message.""" self.client.send_and_consume(force_text(channel), data) return self._get_next_message() def _get_next_message(self): msg = self.client.get_next_message(self.client.reply_channel) return json.loads(msg['text']) def _build_message(self, stream, payload): return {"text": json.dumps({"stream": stream, "payload": payload}), "path": "/"} def test_create(self): """Integration that asserts routing a message to the create channel. Asserts response is correct and an object is created. """ json_content = self._send_and_consume("websocket.receive", self._build_message("testmodel", { 'action': 'create', 'pk': None, 'request_id': 'client-request-id', 'data': {'name': 'some-thing'} })) # it should create an object self.assertEqual(TestModel.objects.count(), 1) expected = { 'action': 'create', 'data': TestModelSerializer(TestModel.objects.first()).data, 'errors': [], 'request_id': 'client-request-id', 'response_status': 201 } # it should respond with the serializer.data self.assertEqual(json_content['payload'], expected) def test_create_failure(self): """Integration that asserts error handling of a message to the create channel.""" json_content = self._send_and_consume('websocket.receive', self._build_message("testmodel", { 'action': 'create', 'pk': None, 'request_id': 'client-request-id', 'data': {}, })) # it should not create an object self.assertEqual(TestModel.objects.count(), 0) expected = { 'action': 'create', 'data': None, 'request_id': 'client-request-id', 'errors': [{'name': ['This field is required.']}], 'response_status': 400 } # it should respond with an error self.assertEqual(json_content['payload'], expected) def test_delete(self): instance = TestModel.objects.create(name='test-name') json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel', { 'action': 'delete', 'pk': instance.id, 'request_id': 'client-request-id', })) expected = { 'action': 'delete', 'errors': [], 'data': {}, 'request_id': 'client-request-id', 'response_status': 200 } self.assertEqual(json_content['payload'], expected) self.assertEqual(TestModel.objects.count(), 0) def test_delete_failure(self): json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel', { 'action': 'delete', 'pk': -1, 'request_id': 'client-request-id' })) expected = { 'action': 'delete', 'errors': ['Not found.'], 'data': None, 'request_id': 'client-request-id', 'response_status': 404 } self.assertEqual(json_content['payload'], expected) def test_list(self): for n in range(api_settings.DEFAULT_PAGE_SIZE + 1): TestModel.objects.create(name='Name-{}'.format(str(n))) json_content = self._send_and_consume('websocket.receive', self._build_message('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('websocket.receive', self._build_message('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_retrieve(self): instance = TestModel.objects.create(name="Test") json_content = self._send_and_consume('websocket.receive', self._build_message('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_retrieve_404(self): json_content = self._send_and_consume('websocket.receive', self._build_message('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_retrieve_invalid_pk_404(self): json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel', { 'action': 'retrieve', 'pk': 'invalid-pk-value', '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_subscribe(self): json_content = self._send_and_consume('websocket.receive', self._build_message("testmodel",{ 'action': 'subscribe', 'data': { 'action': 'create' }, 'request_id': 'client-request-id' })) expected_response = { 'action': 'subscribe', 'request_id': 'client-request-id', 'data': { 'action': 'create' }, '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_subscribe_failure(self): json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel', { 'action': 'subscribe', 'data': { }, 'request_id': 'client-request-id' })) expected = { 'action': 'subscribe', 'data': None, 'errors': ['action required'], 'request_id': 'client-request-id', 'response_status': 400 } self.assertEqual(expected, json_content['payload']) def test_update(self): instance = TestModel.objects.create(name='some-test') json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel',{ 'action': 'update', 'pk': instance.id, 'data': {'name': 'some-value'}, 'request_id': 'client-request-id' })) instance.refresh_from_db() expected = { 'action': 'update', 'errors': [], 'data': TestModelSerializer(instance).data, 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_update_failure(self): instance = TestModel.objects.create(name='some-test') json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel', { 'action': 'update', 'pk': -1, 'data': {'name': 'some-value'}, 'request_id': 'client-request-id' })) expected = { 'data': None, 'action': 'update', 'errors': ['Not found.'], 'response_status': 404, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_list_action(self): json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel',{ 'action': 'test_list', 'pk': None, 'data': {}, 'request_id': 'client-request-id', })) expected = { 'action': 'test_list', 'errors': [], 'data': 'some data', 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_detail_action(self): instance = TestModel.objects.create(name='some-test') json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel',{ 'action': 'test_detail', 'pk': instance.id, 'data': {}, 'request_id': 'client-request-id' })) expected = { 'action': 'test_detail', 'errors': [], 'data': instance.name, 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_named_list_action(self): json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel',{ 'action': 'named_list', 'pk': None, 'data': {}, 'request_id': 'client-request-id', })) expected = { 'action': 'named_list', 'errors': [], 'data': 'some data', 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_named_detail_action(self): instance = TestModel.objects.create(name='some-test') json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel',{ 'action': 'named_detail', 'pk': instance.id, 'data': {}, 'request_id': 'client-request-id' })) expected = { 'action': 'named_detail', 'errors': [], 'data': instance.name, 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_bad_permission_reply(self): mock_has_perm = Mock() mock_has_perm.return_value = False with patch.object(TestModelResourceBinding, 'has_permission', mock_has_perm): json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel',{ 'action': 'named_detail', 'pk': 546, 'data': {}, 'request_id': 'client-request-id' })) expected = { 'action': 'named_detail', 'errors': ['Permission Denied'], 'data': None, 'response_status': 401, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) self.assertEqual(mock_has_perm.called, True) def test_bad_action_reply(self): json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel',{ 'action': 'named_detail_not_set', 'pk': 123, 'data': {}, 'request_id': 'client-request-id' })) expected = { 'action': 'named_detail_not_set', 'errors': ['Invalid Action'], 'data': None, 'response_status': 400, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_is_authenticated_permission(self): with patch.object(TestModelResourceBinding, 'permission_classes', (IsAuthenticated,)): content = { 'action': 'test_list', 'pk': None, 'data': {}, 'request_id': 'client-request-id', } json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel', content)) # It should block the request self.assertEqual(json_content['payload']['response_status'], 401) user = User.objects.create(username="******", password="******") self.client.force_login(user) self.client._session_cookie = True json_content = self._send_and_consume('websocket.receive', self._build_message('testmodel', content)) self.assertEqual(json_content['payload']['response_status'], 200)
def test_receives_messages(self): self.maxDiff = None client = WSClient() user = UserFactory() author_client = WSClient() author = UserFactory() # join a conversation conversation = ConversationFactory() conversation.join(user) conversation.join(author) # login and connect client.force_login(user) client.send_and_consume('websocket.connect', path='/') author_client.force_login(author) author_client.send_and_consume('websocket.connect', path='/') # add a message to the conversation message = ConversationMessage.objects.create(conversation=conversation, content='yay', author=author) # hopefully they receive it! response = client.receive(json=True) response['payload']['created_at'] = parse( response['payload']['created_at']) self.assertEqual( response, { 'topic': 'conversations:message', 'payload': { 'id': message.id, 'content': message.content, 'author': message.author.id, 'conversation': conversation.id, 'created_at': message.created_at, 'received_via': '' } }) # and they should get an updated conversation object response = client.receive(json=True) response['payload']['created_at'] = parse( response['payload']['created_at']) response['payload']['updated_at'] = parse( response['payload']['updated_at']) del response['payload']['participants'] self.assertEqual( response, { 'topic': 'conversations:conversation', 'payload': { 'id': conversation.id, 'created_at': conversation.created_at, 'updated_at': conversation.updated_at, 'seen_up_to': None, 'unread_message_count': 1, 'email_notifications': True, } }) # author should get message & updated conversations object too response = author_client.receive(json=True) response['payload']['created_at'] = parse( response['payload']['created_at']) self.assertEqual( response, { 'topic': 'conversations:message', 'payload': { 'id': message.id, 'content': message.content, 'author': message.author.id, 'conversation': conversation.id, 'created_at': message.created_at, 'received_via': '' } }) # Author receives more recent `update_at` time, # because their `seen_up_to` status is set after sending the message. author_participant = conversation.conversationparticipant_set.get( user=author) response = author_client.receive(json=True) response['payload']['created_at'] = parse( response['payload']['created_at']) response['payload']['updated_at'] = parse( response['payload']['updated_at']) del response['payload']['participants'] self.assertEqual( response, { 'topic': 'conversations:conversation', 'payload': { 'id': conversation.id, 'created_at': conversation.created_at, 'updated_at': author_participant.updated_at, 'seen_up_to': message.id, 'unread_message_count': 0, 'email_notifications': True, } })
class ResourceBindingTestCase(ChannelTestCase): def setUp(self): super(ResourceBindingTestCase, self).setUp() self.client = WSClient() def _send_and_consume(self, channel, data): """Helper that sends and consumes message and returns the next message.""" self.client.send_and_consume(force_text(channel), data) return self._get_next_message() def _get_next_message(self): msg = self.client.get_next_message(self.client.reply_channel) return json.loads(msg['text']) def _build_message(self, stream, payload): return { "text": json.dumps({ "stream": stream, "payload": payload }), "path": "/" } def test_create(self): """Integration that asserts routing a message to the create channel. Asserts response is correct and an object is created. """ json_content = self._send_and_consume( "websocket.receive", self._build_message( "testmodel", { 'action': 'create', 'pk': None, 'request_id': 'client-request-id', 'data': { 'name': 'some-thing' } })) # it should create an object self.assertEqual(TestModel.objects.count(), 1) expected = { 'action': 'create', 'data': TestModelSerializer(TestModel.objects.first()).data, 'errors': [], 'request_id': 'client-request-id', 'response_status': 201 } # it should respond with the serializer.data self.assertEqual(json_content['payload'], expected) def test_create_failure(self): """Integration that asserts error handling of a message to the create channel.""" json_content = self._send_and_consume( 'websocket.receive', self._build_message( "testmodel", { 'action': 'create', 'pk': None, 'request_id': 'client-request-id', 'data': {}, })) # it should not create an object self.assertEqual(TestModel.objects.count(), 0) expected = { 'action': 'create', 'data': None, 'request_id': 'client-request-id', 'errors': [{ 'name': ['This field is required.'] }], 'response_status': 400 } # it should respond with an error self.assertEqual(json_content['payload'], expected) def test_delete(self): instance = TestModel.objects.create(name='test-name') json_content = self._send_and_consume( 'websocket.receive', self._build_message( 'testmodel', { 'action': 'delete', 'pk': instance.id, 'request_id': 'client-request-id', })) expected = { 'action': 'delete', 'errors': [], 'data': {}, 'request_id': 'client-request-id', 'response_status': 200 } self.assertEqual(json_content['payload'], expected) self.assertEqual(TestModel.objects.count(), 0) def test_delete_failure(self): json_content = self._send_and_consume( 'websocket.receive', self._build_message('testmodel', { 'action': 'delete', 'pk': -1, 'request_id': 'client-request-id' })) expected = { 'action': 'delete', 'errors': ['Not found.'], 'data': None, 'request_id': 'client-request-id', 'response_status': 404 } self.assertEqual(json_content['payload'], expected) def test_list(self): for n in range(api_settings.DEFAULT_PAGE_SIZE + 1): TestModel.objects.create(name='Name-{}'.format(str(n))) json_content = self._send_and_consume( 'websocket.receive', self._build_message( '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( 'websocket.receive', self._build_message( '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_retrieve(self): instance = TestModel.objects.create(name="Test") json_content = self._send_and_consume( 'websocket.receive', self._build_message( '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_retrieve_404(self): json_content = self._send_and_consume( 'websocket.receive', self._build_message('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_retrieve_invalid_pk_404(self): json_content = self._send_and_consume( 'websocket.receive', self._build_message( 'testmodel', { 'action': 'retrieve', 'pk': 'invalid-pk-value', '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_subscribe(self): json_content = self._send_and_consume( 'websocket.receive', self._build_message( "testmodel", { 'action': 'subscribe', 'data': { 'action': 'create' }, 'request_id': 'client-request-id' })) expected_response = { 'action': 'subscribe', 'request_id': 'client-request-id', 'data': { 'action': 'create' }, '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_subscribe_failure(self): json_content = self._send_and_consume( 'websocket.receive', self._build_message( 'testmodel', { 'action': 'subscribe', 'data': {}, 'request_id': 'client-request-id' })) expected = { 'action': 'subscribe', 'data': None, 'errors': ['action required'], 'request_id': 'client-request-id', 'response_status': 400 } self.assertEqual(expected, json_content['payload']) def test_update(self): instance = TestModel.objects.create(name='some-test') json_content = self._send_and_consume( 'websocket.receive', self._build_message( 'testmodel', { 'action': 'update', 'pk': instance.id, 'data': { 'name': 'some-value' }, 'request_id': 'client-request-id' })) instance.refresh_from_db() expected = { 'action': 'update', 'errors': [], 'data': TestModelSerializer(instance).data, 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_update_failure(self): instance = TestModel.objects.create(name='some-test') json_content = self._send_and_consume( 'websocket.receive', self._build_message( 'testmodel', { 'action': 'update', 'pk': -1, 'data': { 'name': 'some-value' }, 'request_id': 'client-request-id' })) expected = { 'data': None, 'action': 'update', 'errors': ['Not found.'], 'response_status': 404, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_list_action(self): json_content = self._send_and_consume( 'websocket.receive', self._build_message( 'testmodel', { 'action': 'test_list', 'pk': None, 'data': {}, 'request_id': 'client-request-id', })) expected = { 'action': 'test_list', 'errors': [], 'data': 'some data', 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_detail_action(self): instance = TestModel.objects.create(name='some-test') json_content = self._send_and_consume( 'websocket.receive', self._build_message( 'testmodel', { 'action': 'test_detail', 'pk': instance.id, 'data': {}, 'request_id': 'client-request-id' })) expected = { 'action': 'test_detail', 'errors': [], 'data': instance.name, 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_named_list_action(self): json_content = self._send_and_consume( 'websocket.receive', self._build_message( 'testmodel', { 'action': 'named_list', 'pk': None, 'data': {}, 'request_id': 'client-request-id', })) expected = { 'action': 'named_list', 'errors': [], 'data': 'some data', 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_named_detail_action(self): instance = TestModel.objects.create(name='some-test') json_content = self._send_and_consume( 'websocket.receive', self._build_message( 'testmodel', { 'action': 'named_detail', 'pk': instance.id, 'data': {}, 'request_id': 'client-request-id' })) expected = { 'action': 'named_detail', 'errors': [], 'data': instance.name, 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected) def test_is_authenticated_permission(self): with patch.object(TestModelResourceBinding, 'permission_classes', (IsAuthenticated, )): content = { 'action': 'test_list', 'pk': None, 'data': {}, 'request_id': 'client-request-id', } json_content = self._send_and_consume( 'websocket.receive', self._build_message('testmodel', content)) # It should block the request self.assertEqual(json_content['payload']['response_status'], 401) user = User.objects.create(username="******", password="******") self.client.force_login(user) self.client._session_cookie = True json_content = self._send_and_consume( 'websocket.receive', self._build_message('testmodel', content)) self.assertEqual(json_content['payload']['response_status'], 200)