Beispiel #1
0
 def test_leave(self):
     user = UserFactory()
     conversation = ConversationFactory(participants=[
         user,
     ])
     self.assertIn(user, conversation.participants.all())
     conversation.leave(user)
     self.assertNotIn(user, conversation.participants.all())
Beispiel #2
0
 def setUp(self):
     self.conversation = ConversationFactory()
     self.user = UserFactory()
     self.user2 = UserFactory()
     self.conversation.join(self.user)
     self.conversation.join(self.user2)
     self.participant = ConversationParticipant.objects.get(
         conversation=self.conversation, user=self.user)
Beispiel #3
0
 def test_reaction_create(self):
     user = UserFactory()
     conversation = ConversationFactory()
     conversation.sync_users([user])
     message = conversation.messages.create(author=user, content='hello')
     message.reactions.create(message=message, user=user, name='tada')
     self.assertEqual(
         ConversationMessageReaction.objects.filter(message=message,
                                                    user=user).count(), 1)
Beispiel #4
0
 def test_create_message(self):
     conversation = ConversationFactory()
     conversation.join(self.participant1)
     self.client.force_login(user=self.participant1)
     data = {'conversation': conversation.id, 'content': 'a nice message'}
     response = self.client.post('/api/messages/', data, format='json')
     self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data)
     self.assertEqual(response.data['content'], data['content'])
     self.assertEqual(conversation.messages.first().content, data['content'])
Beispiel #5
0
    def test_mark_seen_up_to_fails_for_message_in_other_conversation(self):
        conversation = ConversationFactory()
        conversation.join(self.user)
        message = conversation.messages.create(author=self.user, content='yay')
        self.client.force_login(user=self.user)

        data = {'seen_up_to': message.id}
        response = self.client.post('/api/conversations/{}/mark/'.format(self.conversation.id), data, format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(response.data['seen_up_to'][0], 'Must refer to a message in the conversation')
class ReceiverPushTests(ChannelTestCase):
    def setUp(self):
        self.user = UserFactory()
        self.author = UserFactory()

        self.token = faker.uuid4()
        self.content = faker.text()

        # join a conversation
        self.conversation = ConversationFactory()
        self.conversation.join(self.user)
        self.conversation.join(self.author)

        # add a push subscriber
        PushSubscription.objects.create(user=self.user, token=self.token, platform=PushSubscriptionPlatform.ANDROID)

    def test_sends_to_push_subscribers(self, m):
        def check_json_data(request):
            data = json.loads(request.body.decode('utf-8'))
            self.assertEqual(data['notification']['title'], self.author.display_name)
            self.assertEqual(data['notification']['body'], self.content)
            self.assertEqual(data['to'], self.token)
            return True

        m.post(FCMApi.FCM_END_POINT, json={}, additional_matcher=check_json_data)

        # add a message to the conversation
        ConversationMessage.objects.create(conversation=self.conversation, content=self.content, author=self.author)

    # TODO: add back in once https://github.com/yunity/karrot-frontend/issues/770 is implemented
    # def test_does_not_send_push_notification_if_active_channel_subscription(self, m):
    #     # add a channel subscription to prevent the push being sent
    #     ChannelSubscription.objects.create(user=self.user, reply_channel='foo')
    #
    #     # add a message to the conversation
    #     ConversationMessage.objects.create(conversation=self.conversation, content=self.content, author=self.author)
    #
    #     # if it sent a push message, the requests mock would complain there is no matching request...

    def test_send_push_notification_if_channel_subscription_is_away(self, m):
        def check_json_data(request):
            data = json.loads(request.body.decode('utf-8'))
            self.assertEqual(data['notification']['title'], self.author.display_name)
            self.assertEqual(data['notification']['body'], self.content)
            self.assertEqual(data['to'], self.token)
            return True

        m.post(FCMApi.FCM_END_POINT, json={}, additional_matcher=check_json_data)

        # add a channel subscription to prevent the push being sent
        ChannelSubscription.objects.create(user=self.user, reply_channel='foo', away_at=timezone.now())

        # add a message to the conversation
        ConversationMessage.objects.create(conversation=self.conversation, content=self.content, author=self.author)
Beispiel #7
0
 def test_reaction_remove(self):
     # setup
     user = UserFactory()
     conversation = ConversationFactory()
     conversation.sync_users([user])
     message = conversation.messages.create(author=user, content='hello')
     # creating reaction
     message.reactions.create(message=message, user=user, name='tada')
     instance = ConversationMessageReaction.objects.get(message=message, user=user, name='tada')
     # remove reaction
     instance.delete()
     self.assertEqual(ConversationMessageReaction.objects.filter(message=message, user=user).count(), 0)
    def setUp(self):
        self.user = UserFactory()
        self.author = UserFactory()

        self.token = faker.uuid4()
        self.content = faker.text()

        # join a conversation
        self.conversation = ConversationFactory()
        self.conversation.join(self.user)
        self.conversation.join(self.author)

        # add a push subscriber
        PushSubscription.objects.create(user=self.user, token=self.token, platform=PushSubscriptionPlatform.ANDROID)
    def tests_receive_message_on_leave(self):
        user = UserFactory()

        # join a conversation
        conversation = ConversationFactory(participants=[
            user,
        ])

        # login and connect
        client = self.connect_as(user)

        conversation.leave(user)

        self.assertEqual(client.messages[0], {'topic': 'conversations:leave', 'payload': {'id': conversation.id}})
Beispiel #10
0
    def test_other_participants_receive_update_on_leave(self):
        user = UserFactory()
        leaving_user = UserFactory()

        # join a conversation
        conversation = ConversationFactory(participants=[user, leaving_user])

        # login and connect
        client = self.connect_as(user)

        conversation.leave(leaving_user)

        response = client.messages[0]

        self.assertEqual(response['topic'], 'conversations:conversation')
        self.assertEqual(response['payload']['participants'], [user.id])
Beispiel #11
0
 def test_edit_message(self):
     conversation = ConversationFactory()
     conversation.join(self.participant1)
     self.client.force_login(user=self.participant1)
     data = {'conversation': conversation.id, 'content': 'a nice message'}
     response = self.client.post('/api/messages/', data, format='json')
     self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data)
     self.assertEqual(response.data['content'], data['content'])
     data['content'] = 'a nicer message'
     response = self.client.post('/api/messages/edit', data, format='json')
     self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
     self.assertEqual(response.data['content'], data['content'])
     self.assertEqual(conversation.messages.first().content, data['content'])
     self.assertEqual(conversation.messages.first().modified_at, parse(response.data['modified_at']), response.data)
     self.assertEqual(conversation.messages.first().id, response.data['id'])
     self.assertEqual(conversation.messages.first().author.id, response.data['author'])
Beispiel #12
0
    def test_receive_reaction_update(self):
        self.maxDiff = None
        author, user, reaction_user = [UserFactory() for _ in range(3)]
        conversation = ConversationFactory(participants=[author, user, reaction_user])
        message = ConversationMessage.objects.create(conversation=conversation, content='yay', author=author)

        # login and connect
        client = self.connect_as(user)

        # create reaction
        ConversationMessageReaction.objects.create(
            message=message,
            user=reaction_user,
            name='carrot',
        )

        # check if conversation update was received
        response = client.messages[0]
        parse_dates(response)
        self.assertEqual(
            response,
            make_conversation_message_broadcast(message, reactions=[{
                'name': 'carrot',
                'user': reaction_user.id
            }])
        )
Beispiel #13
0
 def test_message_create(self):
     user = UserFactory()
     conversation = ConversationFactory(participants=[
         user,
     ])
     conversation.messages.create(author=user, content='yay')
     self.assertEqual(ConversationMessage.objects.filter(author=user).count(), 1)
 def test_filter_by_conversation(self):
     more_users = [UserFactory() for _ in range(3)] + [self.user]
     another_conversation = ConversationFactory(participants=more_users)
     self.client.force_login(user=self.user)
     response = self.get_results('/api/users-info/?conversation={}'.format(
         another_conversation.id))
     self.assertEqual(response.status_code, status.HTTP_200_OK)
     self.assertEqual(len(response.data), len(more_users))
Beispiel #15
0
 def setUp(self):
     self.participant1 = UserFactory()
     self.participant2 = UserFactory()
     self.participant3 = UserFactory()
     self.not_participant1 = UserFactory()
     self.not_participant2 = UserFactory()
     self.not_participant3 = UserFactory()
     self.conversation1 = ConversationFactory()
     self.conversation1.sync_users(
         [self.participant1, self.participant2, self.participant3])
     self.conversation1.messages.create(author=self.participant1,
                                        content='hello')
     self.conversation2 = ConversationFactory()
     self.conversation2.sync_users([self.participant1])
     self.conversation2.messages.create(author=self.participant1,
                                        content='hello2')
     self.conversation3 = ConversationFactory()  # conversation noone is in
Beispiel #16
0
    def test_keeps_latest_message_updated(self):
        user = UserFactory()
        conversation = ConversationFactory(participants=[user])
        message = conversation.messages.create(author=user, content='yay')
        self.assertEqual(conversation.latest_message, message)

        message = conversation.messages.create(author=user, content='yay2')
        self.assertEqual(conversation.latest_message, message)
    def test_receives_messages(self):
        self.maxDiff = None
        user = UserFactory()
        author = UserFactory()

        # join a conversation
        conversation = ConversationFactory(participants=[user, author])

        # login and connect
        client = self.connect_as(user)
        author_client = self.connect_as(author)

        # add a message to the conversation
        message = ConversationMessage.objects.create(conversation=conversation,
                                                     content='yay',
                                                     author=author)

        # hopefully they receive it!
        self.assertEqual(len(client.messages), 2, client.messages)
        response = client.messages[0]
        parse_dates(response)
        self.assertEqual(response,
                         make_conversation_message_broadcast(message))

        # and they should get an updated conversation object
        response = client.messages[1]
        parse_dates(response)
        del response['payload']['participants']
        self.assertEqual(
            response,
            make_conversation_broadcast(
                conversation,
                unread_message_count=1,
                updated_at=response['payload']['updated_at'],  # TODO fix test
            ))

        # author should get message & updated conversations object too
        response = author_client.messages[0]
        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.messages[1]
        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))
Beispiel #18
0
 def setUpClass(cls):
     super().setUpClass()
     cls.participant1 = UserFactory()
     cls.participant2 = UserFactory()
     cls.participant3 = UserFactory()
     cls.not_participant1 = UserFactory()
     cls.not_participant2 = UserFactory()
     cls.not_participant3 = UserFactory()
     cls.conversation1 = ConversationFactory()
     cls.conversation1.sync_users([
         cls.participant1, cls.participant2, cls.participant3
     ])
     cls.conversation1.messages.create(author=cls.participant1, content='hello')
     cls.conversation2 = ConversationFactory()
     cls.conversation2.sync_users([
         cls.participant1
     ])
     cls.conversation2.messages.create(author=cls.participant1, content='hello2')
     cls.conversation3 = ConversationFactory()  # conversation noone is in
    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)
        )
Beispiel #21
0
    def setUp(self):
        self.user = UserFactory()
        self.author = UserFactory()

        self.token = faker.uuid4()
        self.content = faker.text()

        # join a conversation
        self.conversation = ConversationFactory(participants=[self.user, self.author])

        # add a push subscriber
        self.subscription = PushSubscription.objects.create(
            user=self.user,
            token=self.token,
            platform=PushSubscriptionPlatform.ANDROID.value,
        )
Beispiel #22
0
    def test_conversations_list(self):
        self.conversation1.messages.create(author=self.participant1,
                                           content='yay')
        self.conversation1.messages.create(author=self.participant1,
                                           content='second!')
        conversation2 = ConversationFactory(
            participants=[self.participant1, self.participant2])
        conversation2.messages.create(author=self.participant1, content='yay')
        self.client.force_login(user=self.participant1)

        response = self.client.get('/api/conversations/', format='json')
        response_conversations = response.data['results']['conversations']
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        # is ordered by latest message first
        self.assertEqual(
            [conversation['id'] for conversation in response_conversations],
            [conversation2.id, self.conversation1.id, self.conversation2.id],
        )
    def test_other_participants_receive_update_on_leave(self):
        client = WSClient()
        user = UserFactory()
        leaving_user = UserFactory()

        # join a conversation
        conversation = ConversationFactory()
        conversation.join(user)
        conversation.join(leaving_user)

        # login and connect
        client.force_login(user)
        client.send_and_consume('websocket.connect', path='/')

        conversation.leave(leaving_user)

        response = client.receive(json=True)

        self.assertEqual(response['topic'], 'conversations:conversation')
        self.assertEqual(response['payload']['participants'], [user.id])
 def test_sync_users(self):
     user1 = UserFactory()
     user2 = UserFactory()
     user3 = UserFactory()
     user4 = UserFactory()
     users = [user1, user2, user3]
     conversation = ConversationFactory()
     conversation.join(user1)  # should not be added again
     conversation.join(user4)  # should be removed
     conversation.sync_users(users)
     self.assertEqual(conversation.participants.count(), 3)
     self.assertIn(user1, conversation.participants.all())
     self.assertIn(user2, conversation.participants.all())
     self.assertIn(user3, conversation.participants.all())
     self.assertNotIn(user4, conversation.participants.all())
Beispiel #25
0
    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
            }
        })
Beispiel #26
0
class TestConversationsSeenUpToAPI(APITestCase):
    def setUp(self):
        self.conversation = ConversationFactory()
        self.user = UserFactory()
        self.conversation.join(self.user)
        self.participant = ConversationParticipant.objects.get(
            conversation=self.conversation, user=self.user)

    def test_conversation_get(self):
        message = self.conversation.messages.create(author=self.user,
                                                    content='yay')
        self.client.force_login(user=self.user)

        response = self.client.get('/api/conversations/{}/'.format(
            self.conversation.id),
                                   format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['seen_up_to'], None)
        self.assertEqual(response.data['unread_message_count'], 1)

        self.participant.seen_up_to = message
        self.participant.save()

        response = self.client.get('/api/conversations/{}/'.format(
            self.conversation.id),
                                   format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['seen_up_to'], message.id)
        self.assertEqual(response.data['unread_message_count'], 0)

    def test_conversation_list(self):
        message = self.conversation.messages.create(author=self.user,
                                                    content='yay')
        self.client.force_login(user=self.user)

        self.participant.seen_up_to = message
        self.participant.save()

        response = self.client.get('/api/conversations/'.format(
            self.conversation.id),
                                   format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data[0]['seen_up_to'], message.id)

    def test_mark_seen_up_to(self):
        message = self.conversation.messages.create(author=self.user,
                                                    content='yay')
        self.client.force_login(user=self.user)

        response = self.client.get('/api/conversations/{}/'.format(
            self.conversation.id),
                                   format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['seen_up_to'], None)

        data = {'seen_up_to': message.id}
        response = self.client.post('/api/conversations/{}/mark/'.format(
            self.conversation.id),
                                    data,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['seen_up_to'], message.id)

        self.participant.refresh_from_db()
        self.assertEqual(self.participant.seen_up_to, message)

    def test_mark_seen_up_to_fails_for_invalid_id(self):
        self.client.force_login(user=self.user)
        data = {'seen_up_to': 9817298172}
        response = self.client.post('/api/conversations/{}/mark/'.format(
            self.conversation.id),
                                    data,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(
            response.data['seen_up_to'][0],
            'Invalid pk "{}" - object does not exist.'.format(
                data['seen_up_to']))

    def test_mark_seen_up_to_fails_for_message_in_other_conversation(self):
        conversation = ConversationFactory()
        message = conversation.messages.create(author=self.user, content='yay')
        self.client.force_login(user=self.user)
        data = {'seen_up_to': message.id}
        response = self.client.post('/api/conversations/{}/mark/'.format(
            self.conversation.id),
                                    data,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(response.data['seen_up_to'][0],
                         'Must refer to a message in the conversation')
Beispiel #27
0
class TestConversationsAPI(APITestCase):
    def setUp(self):
        self.participant1 = UserFactory()
        self.participant2 = UserFactory()
        self.participant3 = UserFactory()
        self.not_participant1 = UserFactory()
        self.not_participant2 = UserFactory()
        self.not_participant3 = UserFactory()
        self.conversation1 = ConversationFactory()
        self.conversation1.sync_users(
            [self.participant1, self.participant2, self.participant3])
        self.conversation1.messages.create(author=self.participant1,
                                           content='hello')
        self.conversation2 = ConversationFactory()
        self.conversation2.sync_users([self.participant1])
        self.conversation2.messages.create(author=self.participant1,
                                           content='hello2')
        self.conversation3 = ConversationFactory()  # conversation noone is in

    def test_get_messages(self):
        self.client.force_login(user=self.participant1)
        response = self.client.get('/api/messages/?conversation={}'.format(
            self.conversation1.id),
                                   format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['results']), 1)
        self.assertEqual(response.data['results'][0]['content'], 'hello')

    def test_can_get_messages_for_all_conversations(self):
        self.client.force_login(user=self.participant1)
        response = self.client.get('/api/messages/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['results']), 2)
        self.assertEqual(response.data['results'][0]['content'], 'hello2')
        self.assertEqual(response.data['results'][1]['content'], 'hello')

    def test_cannot_get_messages_if_not_in_conversation(self):
        self.client.force_login(user=self.participant1)
        response = self.client.get('/api/messages/?conversation={}'.format(
            self.conversation3.id),
                                   format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_same_error_if_conversation_does_not_exist_as_if_you_are_just_not_in_it(
            self):
        self.client.force_login(user=self.participant1)
        response = self.client.get(
            '/api/messages/?conversation={}'.format(982398723), format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_create_message(self):
        conversation = ConversationFactory()
        conversation.join(self.participant1)
        self.client.force_login(user=self.participant1)
        data = {'conversation': conversation.id, 'content': 'a nice message'}
        response = self.client.post('/api/messages/', data, format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                         response.data)
        self.assertEqual(response.data['content'], data['content'])
        self.assertEqual(conversation.messages.first().content,
                         data['content'])
        self.assertEqual(conversation.messages.first().created_at,
                         parse(response.data['created_at']), response.data)
        self.assertEqual(conversation.messages.first().id, response.data['id'])
        self.assertEqual(conversation.messages.first().author.id,
                         response.data['author'])

    def test_cannot_create_message_without_specifying_conversation(self):
        self.client.force_login(user=self.participant1)
        data = {'content': 'a nice message'}
        response = self.client.post('/api/messages/', data, format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_cannot_create_message_if_not_in_conversation(self):
        self.client.force_login(user=self.participant1)
        data = {
            'conversation': self.conversation3.id,
            'content': 'a nice message'
        }
        response = self.client.post('/api/messages/', data, format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
Beispiel #28
0
    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,
                }
            })
 def test_message_create_requires_author(self):
     conversation = ConversationFactory()
     with self.assertRaises(IntegrityError):
         conversation.messages.create(content='ohno')
 def test_join(self):
     user = UserFactory()
     conversation = ConversationFactory()
     conversation.join(user)
     self.assertIn(user, conversation.participants.all())