Example #1
0
 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])
Example #2
0
 def test_receive_no_content(self):
     ws_client = WSClient()
     ws_client.send_and_consume(
         'websocket.receive',
         path='/commands',
     )
     self.assertIsNone(ws_client.receive())
Example #3
0
    def test_websockets_demultiplexer_custom_multiplexer(self):
        class MyWebsocketConsumer(websockets.JsonWebsocketConsumer):
            def connect(self, message, multiplexer=None, **kwargs):
                multiplexer.send({"THIS_SHOULD_BE_LOWERCASED": "1"})

        class MyMultiplexer(websockets.WebsocketMultiplexer):
            @classmethod
            def encode_json(cls, content):
                lowered = {
                    "stream":
                    content["stream"],
                    "payload":
                    dict((key.lower(), content["payload"][key])
                         for key in content["payload"])
                }
                return json.dumps(lowered)

        class Demultiplexer(websockets.WebsocketDemultiplexer):
            multiplexer_class = MyMultiplexer

            consumers = {"mystream": MyWebsocketConsumer}

        with apply_routes(
            [route_class(Demultiplexer, path='/path/(?P<ID>\d+)')]):
            client = WSClient()

            client.send_and_consume('websocket.connect', path='/path/1')
            self.assertEqual(
                client.receive(), {
                    "stream": "mystream",
                    "payload": {
                        "this_should_be_lowercased": "1"
                    },
                })
Example #4
0
    def test_trigger_outbound_create_non_auto_pk(self):

        class TestBinding(WebsocketBinding):
            model = models.TestUUIDModel
            stream = 'test'
            fields = ['name']

            @classmethod
            def group_names(cls, instance):
                return ["testuuidmodels"]

            def has_permission(self, user, action, pk):
                return True

        client = WSClient()
        client.join_group('testuuidmodels')

        instance = models.TestUUIDModel.objects.create(name='testname')

        received = client.receive()
        self.assertTrue('payload' in received)
        self.assertTrue('action' in received['payload'])
        self.assertTrue('data' in received['payload'])
        self.assertTrue('name' in received['payload']['data'])
        self.assertTrue('model' in received['payload'])
        self.assertTrue('pk' in received['payload'])

        self.assertEqual(received['payload']['action'], 'create')
        self.assertEqual(received['payload']['model'], 'tests.testuuidmodel')
        self.assertEqual(received['payload']['pk'], str(instance.pk))

        self.assertEqual(received['payload']['data']['name'], 'testname')

        received = client.receive()
        self.assertIsNone(received)
    def test_timer_slave_timeout(self):
        from threading import Timer
        webinterface = WSClient()
        webinterface.join_group('notifications')

        self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop)
        self.sched._Scheduler__script = self.script.id
        self.sched._Scheduler__state = SchedulerStatus.WAITING_FOR_SLAVES

        timer = Timer(
            1,
            self.sched.slave_timeout_callback,
        )

        timer.start()
        timer.join()

        self.assertEqual(
            self.sched._Scheduler__state,
            SchedulerStatus.ERROR,
        )

        self.assertEqual(
            self.sched._Scheduler__error_code,
            "Not all slaves connected within 5 minutes.",
        )
Example #6
0
 def test_get_params(self):
     client = WSClient()
     content = client._get_content(path='/my/path?test=1&token=2')
     self.assertTrue('path' in content)
     self.assertTrue('query_string' in content)
     self.assertEqual(content['path'], '/my/path')
     self.assertEqual(content['query_string'], 'test=1&token=2')
Example #7
0
 def test_get_params(self):
     client = WSClient()
     content = client._get_content(path='/my/path?test=1&token=2')
     self.assertTrue('path' in content)
     self.assertTrue('query_string' in content)
     self.assertEqual(content['path'], '/my/path')
     self.assertEqual(content['query_string'], 'test=1&token=2')
Example #8
0
    def test_route_params_saved_in_kwargs(self):

        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', 'email', 'password', 'last_name']

            @classmethod
            def group_names(cls, instance):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        class Demultiplexer(WebsocketDemultiplexer):
            consumers = {
                'users': UserBinding.consumer,
            }

            groups = ['inbound']

        with apply_routes([Demultiplexer.as_route(path='/path/(?P<id>\d+)')]):
            client = WSClient()
            consumer = client.send_and_consume('websocket.connect', path='/path/789')
            self.assertEqual(consumer.kwargs['id'], '789')
Example #9
0
    def test_route_params_saved_in_kwargs(self):
        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', 'email', 'password', 'last_name']

            @classmethod
            def group_names(cls, instance):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        class Demultiplexer(WebsocketDemultiplexer):
            consumers = {
                'users': UserBinding.consumer,
            }

            groups = ['inbound']

        with apply_routes([Demultiplexer.as_route(path='/path/(?P<id>\d+)')]):
            client = WSClient()
            consumer = client.send_and_consume('websocket.connect',
                                               path='/path/789')
            self.assertEqual(consumer.kwargs['id'], '789')
Example #10
0
    def test_simple_content(self):
        client = WSClient()
        content = client._get_content(text={'key': 'value'}, path='/my/path')

        self.assertEqual(content['text'], '{"key": "value"}')
        self.assertEqual(content['path'], '/my/path')
        self.assertTrue('reply_channel' in content)
        self.assertTrue('headers' in content)
Example #11
0
    def test_path_in_content(self):
        client = WSClient()
        content = client._get_content(content={'path': '/my_path'}, text={'path': 'hi'}, path='/my/path')

        self.assertEqual(content['text'], '{"path": "hi"}')
        self.assertEqual(content['path'], '/my_path')
        self.assertTrue('reply_channel' in content)
        self.assertTrue('headers' in content)
Example #12
0
    def test_simple_content(self):
        client = WSClient()
        content = client._get_content(text={'key': 'value'}, path='/my/path')

        self.assertEqual(content['text'], '{"key": "value"}')
        self.assertEqual(content['path'], '/my/path')
        self.assertTrue('reply_channel' in content)
        self.assertTrue('headers' in content)
Example #13
0
    def test_path_in_content(self):
        client = WSClient()
        content = client._get_content(content={'path': '/my_path'}, text={'path': 'hi'}, path='/my/path')

        self.assertEqual(content['text'], '{"path": "hi"}')
        self.assertEqual(content['path'], '/my_path')
        self.assertTrue('reply_channel' in content)
        self.assertTrue('headers' in content)
Example #14
0
    def test_session_in_headers(self):
        client = WSClient()
        content = client._get_content()
        self.assertTrue('path' in content)
        self.assertEqual(content['path'], '/')

        self.assertTrue('headers' in content)
        self.assertTrue('cookie' in content['headers'])
        self.assertTrue(b'sessionid' in content['headers']['cookie'])
Example #15
0
    def test_session_in_headers(self):
        client = WSClient()
        content = client._get_content()
        self.assertTrue('path' in content)
        self.assertEqual(content['path'], '/')

        self.assertTrue('headers' in content)
        self.assertTrue('cookie' in content['headers'])
        self.assertTrue(b'sessionid' in content['headers']['cookie'])
Example #16
0
 def test_ordering_in_content(self):
     client = WSClient(ordered=True)
     content = client._get_content()
     self.assertTrue('order' in content)
     self.assertEqual(content['order'], 0)
     client.order = 2
     content = client._get_content()
     self.assertTrue('order' in content)
     self.assertEqual(content['order'], 2)
Example #17
0
 def test_ordering_in_content(self):
     client = WSClient(ordered=True)
     content = client._get_content()
     self.assertTrue('order' in content)
     self.assertEqual(content['order'], 0)
     client.order = 2
     content = client._get_content()
     self.assertTrue('order' in content)
     self.assertEqual(content['order'], 2)
Example #18
0
    def test_session_in_headers(self):
        client = WSClient()
        content = client._get_content()
        self.assertTrue('path' in content)
        self.assertEqual(content['path'], '/')

        self.assertTrue('headers' in content)
        self.assertIn(b'cookie', [x[0] for x in content['headers']])
        self.assertIn(b'sessionid', [x[1] for x in content['headers'] if x[0] == b'cookie'][0])
    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_authentication_with_wrong_token_failed(self):
        client = WSClient()

        client.send_and_consume('websocket.connect',
                                path='/accounts/user/wrong/',
                                check_accept=False)

        received = client.receive(json=False)
        self.assertEqual(received, {"close": True})
Example #21
0
    def test_create_contestant_valid_room(self):
        """
        Attempt to create a contestant in a valid room
        """
        room = Room.objects.last()

        client = WSClient()
        client.send_and_consume('websocket.connect')
        client.send_and_consume(
            'quiz.receive', {
                'command': 'new_contestant',
                'room_code': room.code,
                'contestant_name': 'Joe Bloggs'
            })

        response = client.receive()

        # Verify server responded with correct status code
        self.assertEqual(response['status_code'], StatusCode.OK)
        # Verify room contestant count is one
        self.assertEquals(room.contestant_set.count(), 1)
        # Verify it is indeed Joe Bloggs in the room
        self.assertEquals(room.contestant_set.last().handle, 'Joe Bloggs')

        client.send_and_consume('websocket.disconnect')
Example #22
0
    def test_receive_filesystem_restore_with_error_code(self):
        filesystem = MovedFileFactory()

        error_code = 'any kind of string'

        error_status = Status.err({
            'method': 'filesystem_restore',
            'result': error_code,
        })

        error_status.uuid = filesystem.command_uuid

        #  connect webinterface
        webinterface = WSClient()
        webinterface.join_group('notifications')

        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': error_status.to_json()},
        )

        query = FilesystemModel.objects.get(id=filesystem.id)
        self.assertEqual(query.error_code, error_code)

        self.assertEqual(
            Status.ok({
                'filesystem_status': 'error',
                'fid': str(filesystem.id),
                'error_code': error_code,
            }),
            Status.from_json(json.dumps(webinterface.receive())),
        )
Example #23
0
    def test_receive_online_with_error_status(self):
        slave = SlaveOnlineFactory(online=False)

        error_status = Status.err({
            'method': 'online',
            'result': str(Exception('foobar'))
        })

        error_status.uuid = slave.command_uuid

        # connect webinterface on /notifications
        webinterface = WSClient()
        webinterface.join_group('notifications')

        # send online answer
        ws_client = WSClient()
        ws_client.send_and_consume('websocket.receive',
                                   path='/commands',
                                   content={'text': error_status.to_json()})

        self.assertFalse(SlaveModel.objects.get(id=slave.id).is_online)

        # test if a connected message was send on /notifications
        self.assertEqual(
            Status.err(
                'An error occurred while connecting to client {}!'.format(
                    slave.name)),
            Status.from_json(json.dumps(webinterface.receive())),
        )
Example #24
0
    def test_receive_online_success(self):
        slave = SlaveOnlineFactory(online=False)

        expected_status = Status.ok({'method': 'online'})
        expected_status.uuid = slave.command_uuid

        # connect webinterface on /notifications
        webinterface = WSClient()
        webinterface.join_group('notifications')

        # send online answer
        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': expected_status.to_json()},
        )

        self.assertTrue(SlaveModel.objects.get(id=slave.id).is_online)

        # test if a connected message was send on /notifications
        self.assertEqual(
            Status.ok({
                'slave_status': 'connected',
                'sid': str(slave.id),
            }),
            Status.from_json(json.dumps(webinterface.receive())),
        )
Example #25
0
    def test_receive_execute_slave_not_exists(self):
        program_status = ProgramStatusFactory(running=True)
        program = program_status.program

        expected_status = Status.ok({'method': 'execute', 'result': 0})
        expected_status.uuid = program_status.command_uuid

        #  connect webinterface
        webinterface = WSClient()
        webinterface.send_and_consume(
            'websocket.connect',
            path='/notifications',
        )

        program.delete()

        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': expected_status.to_json()},
        )

        self.assertFalse(
            ProgramStatusModel.objects.filter(program=program).exists())

        #  test if the webinterface gets the "finished" message
        self.assertIsNone(webinterface.receive())
Example #26
0
    def test_receive_execute_success(self):
        program_status = ProgramStatusFactory(running=True)
        program = program_status.program

        expected_status = Status.ok({'method': 'execute', 'result': 0})
        expected_status.uuid = program_status.command_uuid

        #  connect webinterface
        webinterface = WSClient()
        webinterface.send_and_consume(
            'websocket.connect',
            path='/notifications',
        )

        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': expected_status.to_json()},
        )

        query = ProgramStatusModel.objects.filter(program=program, code=0)
        self.assertTrue(query.count() == 1)
        self.assertFalse(query.first().running)

        #  test if the webinterface gets the "finished" message
        self.assertEqual(
            Status.ok({
                'program_status': 'finished',
                'pid': str(program.id),
                'code': 0,
            }),
            Status.from_json(json.dumps(webinterface.receive())),
        )
Example #27
0
    def test_receive_get_log_success(self):
        program_status = ProgramStatusFactory(running=True)
        program = program_status.program

        error_status = Status.ok({
            'method': 'get_log',
            'result': {
                'log': 'this is the content of a logfile',
                'uuid': program_status.command_uuid,
            },
        })

        #  connect webinterface
        webinterface = WSClient()
        webinterface.join_group('notifications')

        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': error_status.to_json()},
        )

        #  test if the webinterface gets the error message
        self.assertEqual(
            Status.ok({
                'log': 'this is the content of a logfile',
                'pid': str(program.id),
            }),
            Status.from_json(json.dumps(webinterface.receive())),
        )
Example #28
0
    def test_receive_execute_with_error_status(self):
        program_status = ProgramStatusFactory(running=True)
        program = program_status.program

        error_status = Status.err({
            'method': 'execute',
            'result': str(Exception('foobar')),
        })
        error_status.uuid = program_status.command_uuid

        #  connect webinterface
        webinterface = WSClient()
        webinterface.join_group('notifications')

        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': error_status.to_json()},
        )

        query = ProgramStatusModel.objects.get(program=program)
        self.assertFalse(query.running)
        self.assertEqual(query.code, 'foobar')

        #  test if the webinterface gets the error message
        self.assertEqual(
            Status.ok({
                'program_status': 'finished',
                'pid': str(program.id),
                'code': 'foobar',
            }),
            Status.from_json(json.dumps(webinterface.receive())),
        )
Example #29
0
    def test_submit_card(self):
        client = WSClient()

        client.send_and_consume(
            'websocket.connect', path='/game/'
        )  # Connect is forwarded to ALL multiplexed consumers under this demultiplexer
        while client.receive():
            pass  # Grab connection success message from each consumer

        # Invalid Test
        client.send_and_consume(
            'websocket.receive',
            path='/game/',
            text={
                'stream': 'submit_card',
                'payload': {
                    'game_code': '1234'
                }
            })  # Text arg is JSON as if it came from browser
        receive_reply = client.receive(
        )  # receive() grabs the content of the next message off of the client's reply_channel
        self.assertEqual(receive_reply.get('stream'), 'submit_card')
        self.assertFalse(receive_reply.get('payload').get('data').get('valid'))

        disconnect_consumer = client.send_and_consume('websocket.disconnect',
                                                      path='/game/')
        disconnect_consumer.close()
Example #30
0
    def test_receive_get_log_program_not_exists(self):
        error_status = Status.ok({
            'method': 'get_log',
            'result': {
                'log': '',
                'uuid': '0'
            },
        })

        #  connect webinterface
        webinterface = WSClient()
        webinterface.join_group('notifications')

        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': error_status.to_json()},
        )

        #  test if the webinterface gets the error message
        self.assertEqual(
            Status.err('Received log from unknown program!'),
            Status.from_json(json.dumps(webinterface.receive())),
        )
Example #31
0
    def test_receive_filesystem_moved_success(self):
        filesystem = FileFactory()

        moved = MovedFileFactory.build()

        error_status = Status.ok({
            'method': 'filesystem_move',
            'result': moved.hash_value,
        })
        error_status.uuid = filesystem.command_uuid

        #  connect webinterface
        webinterface = WSClient()
        webinterface.join_group('notifications')

        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': error_status.to_json()},
        )

        query = FilesystemModel.objects.get(id=filesystem.id)
        self.assertEqual(query.hash_value, moved.hash_value)
        self.assertEqual(query.error_code, "")

        self.assertEqual(
            Status.ok({
                'filesystem_status': 'moved',
                'fid': str(filesystem.id),
            }),
            Status.from_json(json.dumps(webinterface.receive())),
        )
Example #32
0
    def test_receive_unknown_message_type(self):
        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': Status.ok({
                'method': ''
            }).to_json()},
        )

        self.assertIsNone(ws_client.receive())
Example #33
0
    def test_ws_message(self):
        client = WSClient()
        client.send_and_consume('websocket.receive', text={'event': 'ConnectionEstablished', 'socketId': '54'})
        self.assertIsNone(client.receive())

        client.send_and_consume('websocket.receive', text={'event': 'fetchCurrentPort'})
        receive = client.receive()["data"]
        self.assertEqual(receive, settings.PORT)

        client.send_and_consume('websocket.receive', text={'event': 'getPublicIPaddress'})
        receive = client.receive()["data"]
        self.assertEqual(receive, settings.HOST_NAME)
    def test_authentication_with_token_success(self):
        client = WSClient()

        resident = ResidentFactory.create()
        token = TokenFactory.create(user=resident)

        client.send_and_consume('websocket.connect',
                                path='/accounts/user/{0}/'.format(token.key),
                                check_accept=False)

        received = client.receive(json=False)
        self.assertEqual(received, {"accept": True})
Example #35
0
    def test_websocket_close_exception_close_code(self):
        def consumer(message):
            raise WebsocketCloseException(3001)

        client = WSClient(reply_channel='daphne.response.1')

        with apply_routes(route('websocket.receive', consumer)):
            client.send_and_consume('websocket.receive')

        self.assertEqual(
            client.get_next_message(client.reply_channel).content,
            {'close': 3001})
Example #36
0
 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()
Example #37
0
    def test_channel_socket_exception(self):
        class MyChannelSocketException(ChannelSocketException):
            def run(self, message):
                message.reply_channel.send({'text': 'error'})

        def consumer(message):
            raise MyChannelSocketException

        client = WSClient()
        with apply_routes(route('websocket.receive', consumer)):
            client.send_and_consume('websocket.receive')

            self.assertEqual(client.receive(json=False), 'error')
    def test_receive_for_authenticated_success(self):
        client = WSClient()

        resident = ResidentFactory.create()
        token = TokenFactory.create(user=resident)

        client.send_and_consume(
            'websocket.connect',
            path='/accounts/user/{0}/'.format(token.key),
        )

        Group('user-{0}'.format(resident.pk)).send({'text': 'ok'},
                                                   immediately=True)
        self.assertEqual(client.receive(json=False), 'ok')
Example #39
0
    def test_channel_socket_exception(self):

        class MyChannelSocketException(ChannelSocketException):

            def run(self, message):
                message.reply_channel.send({'text': 'error'})

        def consumer(message):
            raise MyChannelSocketException

        client = WSClient()
        with apply_routes(route('websocket.receive', consumer)):
            client.send_and_consume('websocket.receive')

            self.assertEqual(client.receive(json=False), 'error')
Example #40
0
    def test_trigger_outbound_update(self):
        class TestBinding(WebsocketBinding):
            model = User
            stream = 'test'
            fields = ['__all__']

            @classmethod
            def group_names(cls, instance):
                return ["users2"]

            def has_permission(self, user, action, pk):
                return True

        # Make model and clear out pending sends
        user = User.objects.create(username='******', email='*****@*****.**')

        client = WSClient()
        client.join_group('users2')

        user.username = '******'
        user.save()

        received = client.receive()
        self.assertTrue('payload' in received)
        self.assertTrue('action' in received['payload'])
        self.assertTrue('data' in received['payload'])
        self.assertTrue('username' in received['payload']['data'])
        self.assertTrue('email' in received['payload']['data'])
        self.assertTrue('password' in received['payload']['data'])
        self.assertTrue('last_name' in received['payload']['data'])
        self.assertTrue('model' in received['payload'])
        self.assertTrue('pk' in received['payload'])

        self.assertEqual(received['payload']['action'], 'update')
        self.assertEqual(received['payload']['model'], 'auth.user')
        self.assertEqual(received['payload']['pk'], user.pk)

        self.assertEqual(received['payload']['data']['email'], '*****@*****.**')
        self.assertEqual(received['payload']['data']['username'], 'test_new')
        self.assertEqual(received['payload']['data']['password'], '')
        self.assertEqual(received['payload']['data']['last_name'], '')

        received = client.receive()
        self.assertIsNone(received)
Example #41
0
    def test_notification(self):
        client = WSClient()

        client.send_and_consume('websocket.connect', path='/knocker/en/')
        post = Post.objects.create(
            title='first post',
            slug='first-post',
        )
        notification = client.receive()
        self.assertEqual(notification['title'], 'new {0}'.format(post._meta.verbose_name))
        self.assertEqual(notification['message'], post.title)
        self.assertEqual(notification['url'], post.get_absolute_url())

        # This model does not send notifications
        NoKnockPost.objects.create(
            title='first post',
            slug='first-post',
        )
        self.assertIsNone(client.receive())
Example #42
0
    def test_cookies(self):
        client = WSClient()
        client.set_cookie('foo', 'not-bar')
        client.set_cookie('foo', 'bar')
        client.set_cookie('qux', 'qu;x')

        # Django's interpretation of the serialized cookie.
        cookie_dict = parse_cookie(client.headers['cookie'].decode('ascii'))

        self.assertEqual(client.get_cookies(),
                         cookie_dict)

        self.assertEqual({'foo': 'bar',
                          'qux': 'qu;x',
                          'sessionid': client.get_cookies()['sessionid']},
                         cookie_dict)
Example #43
0
    def test_trigger_outbound_create_exclude(self):
        class TestBinding(WebsocketBinding):
            model = User
            stream = 'test'
            exclude = ['first_name', 'last_name']

            @classmethod
            def group_names(cls, instance):
                return ["users_exclude"]

            def has_permission(self, user, action, pk):
                return True

        with apply_routes([route('test', TestBinding.consumer)]):
            client = WSClient()
            client.join_group('users_exclude')

            user = User.objects.create(username='******', email='*****@*****.**')
            received = client.receive()

            self.assertTrue('payload' in received)
            self.assertTrue('action' in received['payload'])
            self.assertTrue('data' in received['payload'])
            self.assertTrue('username' in received['payload']['data'])
            self.assertTrue('email' in received['payload']['data'])
            self.assertTrue('password' in received['payload']['data'])
            self.assertTrue('model' in received['payload'])
            self.assertTrue('pk' in received['payload'])

            self.assertFalse('last_name' in received['payload']['data'])
            self.assertFalse('first_name' in received['payload']['data'])

            self.assertEqual(received['payload']['action'], 'create')
            self.assertEqual(received['payload']['model'], 'auth.user')
            self.assertEqual(received['payload']['pk'], user.pk)

            self.assertEqual(received['payload']['data']['email'], '*****@*****.**')
            self.assertEqual(received['payload']['data']['username'], 'test')
            self.assertEqual(received['payload']['data']['password'], '')

            received = client.receive()
            self.assertIsNone(received)
Example #44
0
    def test_inbound_delete(self):
        user = User.objects.create(username='******', email='*****@*****.**')

        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', ]

            @classmethod
            def group_names(cls, instance):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        class Demultiplexer(WebsocketDemultiplexer):
            consumers = {
                'users': UserBinding.consumer,
            }

            groups = ['inbound']

        with apply_routes([Demultiplexer.as_route(path='/')]):
            client = WSClient()
            client.send_and_consume('websocket.connect', path='/')
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {'action': DELETE, 'pk': user.pk}
            })

        self.assertIsNone(User.objects.filter(pk=user.pk).first())
        self.assertIsNone(client.receive())
Example #45
0
    def test_inbound_update(self):
        user = User.objects.create(username='******', email='*****@*****.**')

        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', ]

            @classmethod
            def group_names(cls, instance):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        class Demultiplexer(WebsocketDemultiplexer):
            consumers = {
                'users': UserBinding.consumer,
            }

            groups = ['inbound']

        with apply_routes([Demultiplexer.as_route(path='/')]):
            client = WSClient()
            client.send_and_consume('websocket.connect', path='/')
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {'action': UPDATE, 'pk': user.pk, 'data': {'username': '******'}}
            })

            user = User.objects.get(pk=user.pk)
            self.assertEqual(user.username, 'test_inbound')
            self.assertEqual(user.email, '*****@*****.**')

            # trying change field that not in binding fields
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {'action': UPDATE, 'pk': user.pk, 'data': {'email': '*****@*****.**'}}
            })

            user = User.objects.get(pk=user.pk)
            self.assertEqual(user.username, 'test_inbound')
            self.assertEqual(user.email, '*****@*****.**')

            self.assertIsNone(client.receive())
Example #46
0
    def test_get_params_with_consumer(self):
        client = WSClient(ordered=True)

        def consumer(message):
            message.content['method'] = 'FAKE'
            message.reply_channel.send({'text': dict(AsgiRequest(message).GET)})

        with apply_routes([route('websocket.receive', consumer, path=r'^/test'),
                           route('websocket.connect', consumer, path=r'^/test')]):
            path = '/test?key1=val1&key2=val2&key1=val3'
            client.send_and_consume('websocket.connect', path=path, check_accept=False)
            self.assertDictEqual(client.receive(), {'key2': ['val2'], 'key1': ['val1', 'val3']})

            client.send_and_consume('websocket.receive', path=path)
            self.assertDictEqual(client.receive(), {})
Example #47
0
    def test_ordering(self):

        client = WSClient(ordered=True)

        @enforce_ordering
        def consumer(message):
            message.reply_channel.send({'text': message['text']})

        with apply_routes(route('websocket.receive', consumer)):
            client.send_and_consume('websocket.receive', text='1')  # order = 0
            client.send_and_consume('websocket.receive', text='2')  # order = 1
            client.send_and_consume('websocket.receive', text='3')  # order = 2

            self.assertEqual(client.receive(), 1)
            self.assertEqual(client.receive(), 2)
            self.assertEqual(client.receive(), 3)
Example #48
0
    def test_inbound_create(self):
        self.assertEqual(User.objects.all().count(), 0)

        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', 'email', 'password', 'last_name']

            @classmethod
            def group_names(cls, instance):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        class Demultiplexer(WebsocketDemultiplexer):
            consumers = {
                'users': UserBinding.consumer,
            }

            groups = ['inbound']

        with apply_routes([Demultiplexer.as_route(path='/')]):
            client = WSClient()
            client.send_and_consume('websocket.connect', path='/')
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {
                    'action': CREATE,
                    'data': {'username': '******', 'email': 'test@user_steam.com'},
                },
            })

        self.assertEqual(User.objects.all().count(), 1)
        user = User.objects.all().first()
        self.assertEqual(user.username, 'test_inbound')
        self.assertEqual(user.email, 'test@user_steam.com')

        self.assertIsNone(client.receive())
Example #49
0
 def test_ws_connect(self):
     client = WSClient()
     client.send_and_consume('websocket.connect')
     self.assertIsNone(client.receive())
Example #50
0
 def setUp(self):
     super(ResourceBindingTestCase, self).setUp()
     self.client = WSClient()
Example #51
0
    def test_connect(self):
        client = WSClient()

        client.send_and_consume('websocket.connect', path='/knocker/en/')
        self.assertIsNone(client.receive())
Example #52
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)