mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-22 08:51:09 -05:00
okay fine
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
from asgiref.testing import ApplicationCommunicator # noqa
|
||||
|
||||
from .http import HttpCommunicator # noqa
|
||||
from .live import ChannelsLiveServerTestCase # noqa
|
||||
from .websocket import WebsocketCommunicator # noqa
|
||||
|
||||
__all__ = [
|
||||
"ApplicationCommunicator",
|
||||
"HttpCommunicator",
|
||||
"ChannelsLiveServerTestCase",
|
||||
"WebsocketCommunicator",
|
||||
]
|
||||
56
.venv/lib/python3.12/site-packages/channels/testing/http.py
Normal file
56
.venv/lib/python3.12/site-packages/channels/testing/http.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from urllib.parse import unquote, urlparse
|
||||
|
||||
from asgiref.testing import ApplicationCommunicator
|
||||
|
||||
|
||||
class HttpCommunicator(ApplicationCommunicator):
|
||||
"""
|
||||
ApplicationCommunicator subclass that has HTTP shortcut methods.
|
||||
|
||||
It will construct the scope for you, so you need to pass the application
|
||||
(uninstantiated) along with HTTP parameters.
|
||||
|
||||
This does not support full chunking - for that, just use ApplicationCommunicator
|
||||
directly.
|
||||
"""
|
||||
|
||||
def __init__(self, application, method, path, body=b"", headers=None):
|
||||
parsed = urlparse(path)
|
||||
self.scope = {
|
||||
"type": "http",
|
||||
"http_version": "1.1",
|
||||
"method": method.upper(),
|
||||
"path": unquote(parsed.path),
|
||||
"query_string": parsed.query.encode("utf-8"),
|
||||
"headers": headers or [],
|
||||
}
|
||||
assert isinstance(body, bytes)
|
||||
self.body = body
|
||||
self.sent_request = False
|
||||
super().__init__(application, self.scope)
|
||||
|
||||
async def get_response(self, timeout=1):
|
||||
"""
|
||||
Get the application's response. Returns a dict with keys of
|
||||
"body", "headers" and "status".
|
||||
"""
|
||||
# If we've not sent the request yet, do so
|
||||
if not self.sent_request:
|
||||
self.sent_request = True
|
||||
await self.send_input({"type": "http.request", "body": self.body})
|
||||
# Get the response start
|
||||
response_start = await self.receive_output(timeout)
|
||||
assert response_start["type"] == "http.response.start"
|
||||
# Get all body parts
|
||||
response_start["body"] = b""
|
||||
while True:
|
||||
chunk = await self.receive_output(timeout)
|
||||
assert chunk["type"] == "http.response.body"
|
||||
assert isinstance(chunk["body"], bytes)
|
||||
response_start["body"] += chunk["body"]
|
||||
if not chunk.get("more_body", False):
|
||||
break
|
||||
# Return structured info
|
||||
del response_start["type"]
|
||||
response_start.setdefault("headers", [])
|
||||
return response_start
|
||||
76
.venv/lib/python3.12/site-packages/channels/testing/live.py
Normal file
76
.venv/lib/python3.12/site-packages/channels/testing/live.py
Normal file
@@ -0,0 +1,76 @@
|
||||
from functools import partial
|
||||
|
||||
from daphne.testing import DaphneProcess
|
||||
from django.contrib.staticfiles.handlers import ASGIStaticFilesHandler
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import connections
|
||||
from django.test.testcases import TransactionTestCase
|
||||
from django.test.utils import modify_settings
|
||||
|
||||
from channels.routing import get_default_application
|
||||
|
||||
|
||||
def make_application(*, static_wrapper):
|
||||
# Module-level function for pickle-ability
|
||||
application = get_default_application()
|
||||
if static_wrapper is not None:
|
||||
application = static_wrapper(application)
|
||||
return application
|
||||
|
||||
|
||||
class ChannelsLiveServerTestCase(TransactionTestCase):
|
||||
"""
|
||||
Does basically the same as TransactionTestCase but also launches a
|
||||
live Daphne server in a separate process, so
|
||||
that the tests may use another test framework, such as Selenium,
|
||||
instead of the built-in dummy client.
|
||||
"""
|
||||
|
||||
host = "localhost"
|
||||
ProtocolServerProcess = DaphneProcess
|
||||
static_wrapper = ASGIStaticFilesHandler
|
||||
serve_static = True
|
||||
|
||||
@property
|
||||
def live_server_url(self):
|
||||
return "http://%s:%s" % (self.host, self._port)
|
||||
|
||||
@property
|
||||
def live_server_ws_url(self):
|
||||
return "ws://%s:%s" % (self.host, self._port)
|
||||
|
||||
def _pre_setup(self):
|
||||
for connection in connections.all():
|
||||
if self._is_in_memory_db(connection):
|
||||
raise ImproperlyConfigured(
|
||||
"ChannelLiveServerTestCase can not be used with in memory databases"
|
||||
)
|
||||
|
||||
super(ChannelsLiveServerTestCase, self)._pre_setup()
|
||||
|
||||
self._live_server_modified_settings = modify_settings(
|
||||
ALLOWED_HOSTS={"append": self.host}
|
||||
)
|
||||
self._live_server_modified_settings.enable()
|
||||
|
||||
get_application = partial(
|
||||
make_application,
|
||||
static_wrapper=self.static_wrapper if self.serve_static else None,
|
||||
)
|
||||
self._server_process = self.ProtocolServerProcess(self.host, get_application)
|
||||
self._server_process.start()
|
||||
self._server_process.ready.wait()
|
||||
self._port = self._server_process.port.value
|
||||
|
||||
def _post_teardown(self):
|
||||
self._server_process.terminate()
|
||||
self._server_process.join()
|
||||
self._live_server_modified_settings.disable()
|
||||
super(ChannelsLiveServerTestCase, self)._post_teardown()
|
||||
|
||||
def _is_in_memory_db(self, connection):
|
||||
"""
|
||||
Check if DatabaseWrapper holds in memory database.
|
||||
"""
|
||||
if connection.vendor == "sqlite":
|
||||
return connection.is_in_memory_db()
|
||||
102
.venv/lib/python3.12/site-packages/channels/testing/websocket.py
Normal file
102
.venv/lib/python3.12/site-packages/channels/testing/websocket.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import json
|
||||
from urllib.parse import unquote, urlparse
|
||||
|
||||
from asgiref.testing import ApplicationCommunicator
|
||||
|
||||
|
||||
class WebsocketCommunicator(ApplicationCommunicator):
|
||||
"""
|
||||
ApplicationCommunicator subclass that has WebSocket shortcut methods.
|
||||
|
||||
It will construct the scope for you, so you need to pass the application
|
||||
(uninstantiated) along with the initial connection parameters.
|
||||
"""
|
||||
|
||||
def __init__(self, application, path, headers=None, subprotocols=None):
|
||||
if not isinstance(path, str):
|
||||
raise TypeError("Expected str, got {}".format(type(path)))
|
||||
parsed = urlparse(path)
|
||||
self.scope = {
|
||||
"type": "websocket",
|
||||
"path": unquote(parsed.path),
|
||||
"query_string": parsed.query.encode("utf-8"),
|
||||
"headers": headers or [],
|
||||
"subprotocols": subprotocols or [],
|
||||
}
|
||||
super().__init__(application, self.scope)
|
||||
|
||||
async def connect(self, timeout=1):
|
||||
"""
|
||||
Trigger the connection code.
|
||||
|
||||
On an accepted connection, returns (True, <chosen-subprotocol>)
|
||||
On a rejected connection, returns (False, <close-code>)
|
||||
"""
|
||||
await self.send_input({"type": "websocket.connect"})
|
||||
response = await self.receive_output(timeout)
|
||||
if response["type"] == "websocket.close":
|
||||
return (False, response.get("code", 1000))
|
||||
else:
|
||||
return (True, response.get("subprotocol", None))
|
||||
|
||||
async def send_to(self, text_data=None, bytes_data=None):
|
||||
"""
|
||||
Sends a WebSocket frame to the application.
|
||||
"""
|
||||
# Make sure we have exactly one of the arguments
|
||||
assert bool(text_data) != bool(
|
||||
bytes_data
|
||||
), "You must supply exactly one of text_data or bytes_data"
|
||||
# Send the right kind of event
|
||||
if text_data:
|
||||
assert isinstance(text_data, str), "The text_data argument must be a str"
|
||||
await self.send_input({"type": "websocket.receive", "text": text_data})
|
||||
else:
|
||||
assert isinstance(
|
||||
bytes_data, bytes
|
||||
), "The bytes_data argument must be bytes"
|
||||
await self.send_input({"type": "websocket.receive", "bytes": bytes_data})
|
||||
|
||||
async def send_json_to(self, data):
|
||||
"""
|
||||
Sends JSON data as a text frame
|
||||
"""
|
||||
await self.send_to(text_data=json.dumps(data))
|
||||
|
||||
async def receive_from(self, timeout=1):
|
||||
"""
|
||||
Receives a data frame from the view. Will fail if the connection
|
||||
closes instead. Returns either a bytestring or a unicode string
|
||||
depending on what sort of frame you got.
|
||||
"""
|
||||
response = await self.receive_output(timeout)
|
||||
# Make sure this is a send message
|
||||
assert response["type"] == "websocket.send"
|
||||
# Make sure there's exactly one key in the response
|
||||
assert ("text" in response) != (
|
||||
"bytes" in response
|
||||
), "The response needs exactly one of 'text' or 'bytes'"
|
||||
# Pull out the right key and typecheck it for our users
|
||||
if "text" in response:
|
||||
assert isinstance(response["text"], str), "Text frame payload is not str"
|
||||
return response["text"]
|
||||
else:
|
||||
assert isinstance(
|
||||
response["bytes"], bytes
|
||||
), "Binary frame payload is not bytes"
|
||||
return response["bytes"]
|
||||
|
||||
async def receive_json_from(self, timeout=1):
|
||||
"""
|
||||
Receives a JSON text frame payload and decodes it
|
||||
"""
|
||||
payload = await self.receive_from(timeout)
|
||||
assert isinstance(payload, str), "JSON data is not a text frame"
|
||||
return json.loads(payload)
|
||||
|
||||
async def disconnect(self, code=1000, timeout=1):
|
||||
"""
|
||||
Closes the socket
|
||||
"""
|
||||
await self.send_input({"type": "websocket.disconnect", "code": code})
|
||||
await self.wait(timeout)
|
||||
Reference in New Issue
Block a user