Skip to content

Commit 4c8d684

Browse files
committed
Add minimal testing for trusted publishing
1 parent 3d5de1d commit 4c8d684

File tree

4 files changed

+159
-0
lines changed

4 files changed

+159
-0
lines changed

django_mongodb_extensions/tests/__init__.py

Whitespace-only changes.
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import contextvars
2+
from typing import Optional
3+
4+
import html5lib
5+
from asgiref.local import Local
6+
from django.http import HttpResponse
7+
from django.test import (
8+
AsyncClient,
9+
AsyncRequestFactory,
10+
Client,
11+
RequestFactory,
12+
TestCase,
13+
TransactionTestCase,
14+
)
15+
16+
from debug_toolbar.panels import Panel
17+
from debug_toolbar.toolbar import DebugToolbar
18+
19+
data_contextvar = contextvars.ContextVar("djdt_toolbar_test_client")
20+
21+
22+
class ToolbarTestClient(Client):
23+
def request(self, **request):
24+
# Use a thread/async task context-local variable to guard against a
25+
# concurrent _created signal from a different thread/task.
26+
data = Local()
27+
data.toolbar = None
28+
29+
def handle_toolbar_created(sender, toolbar=None, **kwargs):
30+
data.toolbar = toolbar
31+
32+
DebugToolbar._created.connect(handle_toolbar_created)
33+
try:
34+
response = super().request(**request)
35+
finally:
36+
DebugToolbar._created.disconnect(handle_toolbar_created)
37+
response.toolbar = data.toolbar
38+
39+
return response
40+
41+
42+
class AsyncToolbarTestClient(AsyncClient):
43+
async def request(self, **request):
44+
# Use a thread/async task context-local variable to guard against a
45+
# concurrent _created signal from a different thread/task.
46+
# In cases testsuite will have both regular and async tests or
47+
# multiple async tests running in an eventloop making async_client calls.
48+
data_contextvar.set(None)
49+
50+
def handle_toolbar_created(sender, toolbar=None, **kwargs):
51+
data_contextvar.set(toolbar)
52+
53+
DebugToolbar._created.connect(handle_toolbar_created)
54+
try:
55+
response = await super().request(**request)
56+
finally:
57+
DebugToolbar._created.disconnect(handle_toolbar_created)
58+
response.toolbar = data_contextvar.get()
59+
60+
return response
61+
62+
63+
rf = RequestFactory()
64+
arf = AsyncRequestFactory()
65+
66+
67+
class BaseMixin:
68+
_is_async = False
69+
client_class = ToolbarTestClient
70+
async_client_class = AsyncToolbarTestClient
71+
72+
panel: Optional[Panel] = None
73+
panel_id = None
74+
75+
def setUp(self):
76+
super().setUp()
77+
self._get_response = lambda request: HttpResponse()
78+
self.request = rf.get("/")
79+
if self._is_async:
80+
self.request = arf.get("/")
81+
self.toolbar = DebugToolbar(self.request, self.get_response_async)
82+
else:
83+
self.toolbar = DebugToolbar(self.request, self.get_response)
84+
self.toolbar.stats = {}
85+
86+
if self.panel_id:
87+
self.panel = self.toolbar.get_panel_by_id(self.panel_id)
88+
self.panel.enable_instrumentation()
89+
else:
90+
self.panel = None
91+
92+
def tearDown(self):
93+
if self.panel:
94+
self.panel.disable_instrumentation()
95+
super().tearDown()
96+
97+
def get_response(self, request):
98+
return self._get_response(request)
99+
100+
async def get_response_async(self, request):
101+
return self._get_response(request)
102+
103+
def assertValidHTML(self, content):
104+
parser = html5lib.HTMLParser()
105+
parser.parseFragment(content)
106+
if parser.errors:
107+
msg_parts = ["Invalid HTML:"]
108+
lines = content.split("\n")
109+
for position, errorcode, datavars in parser.errors:
110+
msg_parts.append(f" {html5lib.constants.E[errorcode]}" % datavars)
111+
msg_parts.append(f" {lines[position[0] - 1]}")
112+
raise self.failureException("\n".join(msg_parts))
113+
114+
115+
class BaseTestCase(BaseMixin, TestCase):
116+
pass
117+
118+
119+
class BaseMultiDBTestCase(BaseMixin, TransactionTestCase):
120+
databases = {"default", "replica"}
121+
122+
123+
class IntegrationTestCase(TestCase):
124+
"""Base TestCase for tests involving clients making requests."""
125+
126+
def setUp(self):
127+
# The HistoryPanel keeps track of previous stores in memory.
128+
# This bleeds into other tests and violates their idempotency.
129+
# Clear the store before each test.
130+
for key in list(DebugToolbar._store.keys()):
131+
del DebugToolbar._store[key]
132+
super().setUp()

django_mongodb_extensions/tests/panels/__init__.py

Whitespace-only changes.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from django.contrib.auth.models import User
2+
3+
4+
from ..base import BaseTestCase
5+
6+
7+
class MQLPanelTestCase(BaseTestCase):
8+
panel_id = "MQLPanel"
9+
10+
def test_disabled(self):
11+
config = {
12+
"DISABLE_PANELS": {
13+
"django_mongodb_extensions.debug_toolbar.panels.mql.MQLPanel"
14+
}
15+
}
16+
self.assertTrue(self.panel.enabled)
17+
with self.settings(DEBUG_TOOLBAR_CONFIG=config):
18+
self.assertFalse(self.panel.enabled)
19+
20+
def test_not_insert_locals(self):
21+
"""
22+
Test that the panel does not insert locals() content.
23+
"""
24+
list(User.objects.filter(username="café"))
25+
response = self.panel.process_request(self.request)
26+
self.panel.generate_stats(self.request, response)
27+
self.assertNotIn("djdt-locals", self.panel.content)

0 commit comments

Comments
 (0)