Added websockets tests

* Moved websocket.py to users directory for easier understanding of integration.
This commit is contained in:
Andrew-Chen-Wang 2020-05-01 10:32:05 -04:00
parent a63278fb4e
commit f9122a55a8
7 changed files with 78 additions and 3 deletions

View File

@ -104,7 +104,9 @@ def remove_celery_files():
def remove_async_files():
file_names = [
os.path.join("config", "asgi.py"),
os.path.join("config", "websocket.py"),
os.path.join("{{cookiecutter.project_slug}}", "users", "websocket.py"),
os.path.join("{{cookiecutter.project_slug}}", "users", "tests", "async_server.py"),
os.path.join("{{cookiecutter.project_slug}}", "users", "tests", "test_socket.py"),
]
for file_name in file_names:
os.remove(file_name)

View File

@ -28,7 +28,8 @@ django_application = get_asgi_application()
# application = HelloWorldApplication(application)
# Import websocket application here, so apps from django_application are loaded first
from config.websocket import websocket_application # noqa isort:skip
# This is necessary since you may need to develop with your apps, but they need to be loaded first.
from {{ cookiecutter.project_slug }}.users.websocket import websocket_application # noqa isort:skip
async def application(scope, receive, send):

View File

@ -15,6 +15,11 @@ SECRET_KEY = env(
# https://docs.djangoproject.com/en/dev/ref/settings/#test-runner
TEST_RUNNER = "django.test.runner.DiscoverRunner"
{%- if cookiecutter.use_async == 'y' %}
# Needed for socket testing that also needs HTTP to go along with it
ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1"]
{%- endif %}
# CACHES
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#caches

View File

@ -0,0 +1,42 @@
import asyncio
import functools
import threading
import time
from contextlib import contextmanager
from uvicorn.config import Config
from uvicorn.main import ServerState
from uvicorn.protocols.http.h11_impl import H11Protocol
from uvicorn.protocols.websockets.websockets_impl import WebSocketProtocol
def run_loop(loop):
loop.run_forever()
loop.close()
@contextmanager
def run_server(path="/"):
asyncio.set_event_loop(None)
loop = asyncio.new_event_loop()
config = Config(
app="config.asgi:application", ws=WebSocketProtocol, http=H11Protocol
)
server_state = ServerState()
protocol = functools.partial(H11Protocol, config=config, server_state=server_state)
create_server_task = loop.create_server(protocol, host="127.0.0.1")
server = loop.run_until_complete(create_server_task)
port = server.sockets[0].getsockname()[1]
url = f"ws://127.0.0.1:{port}{path}"
try:
# Run the event loop in a new thread.
thread = threading.Thread(target=run_loop, args=[loop])
thread.start()
# Return the contextmanager state.
yield url
finally:
# Close the loop from our main thread.
while server_state.tasks:
time.sleep(0.01)
loop.call_soon_threadsafe(loop.stop)
thread.join()

View File

@ -0,0 +1,24 @@
"""
Refer to Uvicorn's tests to know how to write your own.
https://github.com/encode/uvicorn/blob/master/tests/protocols/test_websocket.py
"""
from asyncio import new_event_loop
from websockets import connect
from {{ cookiecutter.project_slug }}.users.tests.async_server import run_server
def test_accept_connection():
"""
If you want to communicate over HTTP, add live_server fixture
"""
async def open_connection(url):
async with connect(url) as websocket:
return websocket.open
with run_server() as url:
loop = new_event_loop()
is_open = loop.run_until_complete(open_connection(url))
assert is_open
loop.close()

View File

@ -3,6 +3,7 @@ async def websocket_application(scope, receive, send):
event = await receive()
if event["type"] == "websocket.connect":
# TODO Add authentication using DRF-SimpleJWT or other token methods
await send({"type": "websocket.accept"})
if event["type"] == "websocket.disconnect":
@ -10,4 +11,4 @@ async def websocket_application(scope, receive, send):
if event["type"] == "websocket.receive":
if event["text"] == "ping":
await send({"type": "websocket.send", "text": "pong!"})
await send({"type": "websocket.send", "text": "pong"})