예제 #1
0
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))
예제 #2
0
    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
            }
        })
예제 #3
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)
        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)
        )
예제 #4
0
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))
예제 #5
0
 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')
예제 #6
0
    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?'})
예제 #7
0
    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)
예제 #8
0
    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)
예제 #9
0
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)
예제 #10
0
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))
예제 #11
0
    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})
예제 #12
0
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))
예제 #13
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
            }
        })
예제 #14
0
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))
예제 #15
0
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))
예제 #16
0
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))
예제 #17
0
    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)
예제 #18
0
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)
예제 #19
0
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)
예제 #20
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,
                }
            })
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)