mirror of
https://github.com/django/daphne.git
synced 2025-07-29 16:39:46 +03:00
Improvements for test client (#613)
* Tests for httpclient sending content * Testing ordered consumers * Added docs * Added testing for ordering * Added GET params at HttpClient * Remove blank line * Fix py3 bites * Test Client now support ChannelSocketException * Fix flake and isort * Conflict resolution
This commit is contained in:
parent
b7ea0b9287
commit
fa413af053
|
@ -12,6 +12,7 @@ from django.test.testcases import TestCase, TransactionTestCase
|
|||
from .. import DEFAULT_CHANNEL_LAYER
|
||||
from ..asgi import ChannelLayerWrapper, channel_layers
|
||||
from ..channel import Group
|
||||
from ..exceptions import ChannelSocketException
|
||||
from ..message import Message
|
||||
from ..routing import Router, include
|
||||
from ..signals import consumer_finished, consumer_started
|
||||
|
@ -134,6 +135,8 @@ class Client(object):
|
|||
try:
|
||||
consumer_started.send(sender=self.__class__)
|
||||
return consumer(message, **kwargs)
|
||||
except ChannelSocketException as e:
|
||||
e.run(message)
|
||||
finally:
|
||||
# Copy Django's workaround so we don't actually close DB conns
|
||||
consumer_finished.disconnect(close_old_connections)
|
||||
|
|
|
@ -20,11 +20,13 @@ class WSClient(Client):
|
|||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._ordered = kwargs.pop('ordered', False)
|
||||
super(WSClient, self).__init__(**kwargs)
|
||||
self._session = None
|
||||
self._headers = {}
|
||||
self._cookies = {}
|
||||
self._session_cookie = True
|
||||
self.order = 0
|
||||
|
||||
def set_cookie(self, key, value):
|
||||
"""
|
||||
|
@ -76,18 +78,38 @@ class WSClient(Client):
|
|||
Send a message to a channel.
|
||||
Adds reply_channel name and channel_session to the message.
|
||||
"""
|
||||
if to != 'websocket.connect' and '?' in path:
|
||||
path = path.split('?')[0]
|
||||
self.channel_layer.send(to, self._get_content(content, text, path))
|
||||
self._session_cookie = False
|
||||
|
||||
def _get_content(self, content={}, text=None, path='/'):
|
||||
content = copy.deepcopy(content)
|
||||
content.setdefault('reply_channel', self.reply_channel)
|
||||
content.setdefault('path', path)
|
||||
|
||||
if '?' in path:
|
||||
path, query_string = path.split('?')
|
||||
content.setdefault('path', path)
|
||||
content.setdefault('query_string', query_string)
|
||||
else:
|
||||
content.setdefault('path', path)
|
||||
|
||||
content.setdefault('headers', self.headers)
|
||||
|
||||
if self._ordered:
|
||||
if 'order' in content:
|
||||
raise ValueError('Do not use "order" manually with "ordered=True"')
|
||||
content['order'] = self.order
|
||||
self.order += 1
|
||||
|
||||
text = text or content.get('text', None)
|
||||
|
||||
if text is not None:
|
||||
if not isinstance(text, six.string_types):
|
||||
content['text'] = json.dumps(text)
|
||||
else:
|
||||
content['text'] = text
|
||||
self.channel_layer.send(to, content)
|
||||
self._session_cookie = False
|
||||
return content
|
||||
|
||||
def send_and_consume(self, channel, content={}, text=None, path='/', fail_on_none=True, check_accept=True):
|
||||
"""
|
||||
|
|
|
@ -187,6 +187,26 @@ may call ``WSClient.force_login`` (like at django client) with the user object.
|
|||
``receive`` method by default trying to deserialize json text content of a message,
|
||||
so if you need to pass decoding use ``receive(json=False)``, like in the example.
|
||||
|
||||
For testing consumers with ``enforce_ordering`` initialize ``HttpClient`` with ``ordered``
|
||||
flag, but if you wanna use your own order don't use it, use content::
|
||||
|
||||
client = HttpClient(ordered=True)
|
||||
client.send_and_consume('websocket.receive', text='1', path='/ws') # order = 0
|
||||
client.send_and_consume('websocket.receive', text='2', path='/ws') # order = 1
|
||||
client.send_and_consume('websocket.receive', text='3', path='/ws') # order = 2
|
||||
|
||||
# manually
|
||||
client = HttpClient()
|
||||
client.send('websocket.receive', content={'order': 0}, text='1')
|
||||
client.send('websocket.receive', content={'order': 2}, text='2')
|
||||
client.send('websocket.receive', content={'order': 1}, text='3')
|
||||
|
||||
# calling consume 4 time for `waiting` message with order 1
|
||||
client.consume('websocket.receive')
|
||||
client.consume('websocket.receive')
|
||||
client.consume('websocket.receive')
|
||||
client.consume('websocket.receive')
|
||||
|
||||
|
||||
Applying routes
|
||||
---------------
|
||||
|
|
|
@ -2,7 +2,11 @@ from __future__ import unicode_literals
|
|||
|
||||
from django.http.cookie import parse_cookie
|
||||
|
||||
from channels.test import ChannelTestCase, WSClient
|
||||
from channels import route
|
||||
from channels.exceptions import ChannelSocketException
|
||||
from channels.handler import AsgiRequest
|
||||
from channels.test import ChannelTestCase, WSClient, apply_routes
|
||||
from channels.sessions import enforce_ordering
|
||||
|
||||
|
||||
class WSClientTests(ChannelTestCase):
|
||||
|
@ -22,3 +26,98 @@ class WSClientTests(ChannelTestCase):
|
|||
'qux': 'qu;x',
|
||||
'sessionid': client.get_cookies()['sessionid']},
|
||||
cookie_dict)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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'])
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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')
|
||||
|
||||
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(), {})
|
||||
|
||||
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')
|
||||
|
|
Loading…
Reference in New Issue
Block a user