dnscms: add some basic tests
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,23 @@
|
||||
from .base import * # noqa: F401, F403
|
||||
|
||||
SECRET_KEY = "test-secret-key"
|
||||
DEBUG = False
|
||||
ALLOWED_HOSTS = ["*"]
|
||||
|
||||
DATABASES = {
|
||||
"default": {
|
||||
"ENGINE": "django.db.backends.sqlite3",
|
||||
"NAME": ":memory:",
|
||||
}
|
||||
}
|
||||
|
||||
STORAGES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||
},
|
||||
"staticfiles": {
|
||||
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
||||
},
|
||||
}
|
||||
|
||||
PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"]
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
# Create your tests here.
|
||||
@@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -18,6 +18,9 @@ dependencies = [
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"ruff>=0.15.1",
|
||||
"pytest>=8.3",
|
||||
"pytest-django>=4.9",
|
||||
"wagtail-factories>=4.2",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
@@ -34,3 +37,8 @@ line-length = 99
|
||||
select = ["F", "E", "W", "Q", "UP", "DJ"]
|
||||
ignore = []
|
||||
exclude = ["**/migrations/*.py"]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
DJANGO_SETTINGS_MODULE = "dnscms.settings.test"
|
||||
python_files = ["test_*.py"]
|
||||
testpaths = ["tests"]
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import json
|
||||
|
||||
import factory
|
||||
import pytest
|
||||
import wagtail_factories
|
||||
from wagtail.models import Page
|
||||
|
||||
from events.models import EventIndex, EventPage
|
||||
from venues.models import VenueIndex, VenuePage
|
||||
|
||||
|
||||
class EventIndexFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"Events {n}")
|
||||
|
||||
class Meta:
|
||||
model = EventIndex
|
||||
|
||||
|
||||
class EventPageFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"Event {n}")
|
||||
|
||||
class Meta:
|
||||
model = EventPage
|
||||
|
||||
|
||||
class VenueIndexFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"Venues {n}")
|
||||
|
||||
class Meta:
|
||||
model = VenueIndex
|
||||
|
||||
|
||||
class VenuePageFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"Venue {n}")
|
||||
|
||||
class Meta:
|
||||
model = VenuePage
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def root_page(db):
|
||||
return Page.objects.get(depth=1)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def home_page(root_page):
|
||||
# Wagtail's initial migration creates a default "Welcome" page at depth=2.
|
||||
# Reuse it so we don't fight slug collisions across tests.
|
||||
return root_page.get_children().first() or root_page.add_child(
|
||||
instance=Page(title="Home", slug="home")
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def event_index(home_page):
|
||||
return EventIndexFactory(parent=home_page)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def venue(home_page):
|
||||
venue_index = VenueIndexFactory(parent=home_page)
|
||||
return VenuePageFactory(parent=venue_index)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def graphql_post(client):
|
||||
def _post(query, variables=None):
|
||||
payload = {"query": query}
|
||||
if variables is not None:
|
||||
payload["variables"] = variables
|
||||
response = client.post(
|
||||
"/api/graphql/",
|
||||
data=json.dumps(payload),
|
||||
content_type="application/json",
|
||||
)
|
||||
return response, response.json()
|
||||
|
||||
return _post
|
||||
@@ -0,0 +1,88 @@
|
||||
from datetime import timedelta
|
||||
|
||||
import pytest
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils import timezone
|
||||
|
||||
from events.models import (
|
||||
EventOccurrence,
|
||||
EventOrganizer,
|
||||
EventOrganizerLink,
|
||||
EventPage,
|
||||
)
|
||||
from tests.conftest import EventPageFactory
|
||||
|
||||
|
||||
def test_eventpage_clean_unsets_specific_pricing_when_free():
|
||||
page = EventPage(
|
||||
title="Free event",
|
||||
slug="free-event",
|
||||
free=True,
|
||||
price_regular="100",
|
||||
price_student="50",
|
||||
price_member="25",
|
||||
)
|
||||
|
||||
page.clean()
|
||||
|
||||
assert page.price_regular == ""
|
||||
assert page.price_student == ""
|
||||
assert page.price_member == ""
|
||||
|
||||
|
||||
def test_eventoccurrence_clean_rejects_both_venue_and_venue_custom(event_index, venue):
|
||||
event = EventPageFactory(parent=event_index)
|
||||
occurrence = EventOccurrence(
|
||||
event=event,
|
||||
start=timezone.now(),
|
||||
venue=venue,
|
||||
venue_custom="Frederikkeplassen",
|
||||
)
|
||||
|
||||
with pytest.raises(ValidationError) as exc:
|
||||
occurrence.clean()
|
||||
assert "venue_custom" in exc.value.message_dict
|
||||
|
||||
|
||||
def test_eventoccurrence_clean_requires_venue_or_venue_custom(event_index):
|
||||
event = EventPageFactory(parent=event_index)
|
||||
occurrence = EventOccurrence(event=event, start=timezone.now())
|
||||
|
||||
with pytest.raises(ValidationError) as exc:
|
||||
occurrence.clean()
|
||||
assert "venue" in exc.value.message_dict
|
||||
|
||||
|
||||
def test_eventpage_manager_future_filters_past_and_annotates(event_index):
|
||||
now = timezone.now()
|
||||
|
||||
past = EventPageFactory(parent=event_index, title="Past")
|
||||
EventOccurrence.objects.create(
|
||||
event=past, start=now - timedelta(days=7), venue_custom="Old"
|
||||
)
|
||||
|
||||
future = EventPageFactory(parent=event_index, title="Future")
|
||||
EventOccurrence.objects.create(
|
||||
event=future, start=now + timedelta(days=7), venue_custom="New"
|
||||
)
|
||||
|
||||
results = list(EventPage.objects.live().future().order_by("next_occurrence"))
|
||||
|
||||
assert [p.pk for p in results] == [future.pk]
|
||||
assert results[0].next_occurrence is not None
|
||||
|
||||
|
||||
def test_eventpage_clean_dedupes_organizers_by_name(event_index):
|
||||
org_a = EventOrganizer.objects.create(name="DNS", slug="dns-a")
|
||||
org_b = EventOrganizer.objects.create(name="DNS", slug="dns-b")
|
||||
|
||||
event = EventPageFactory(parent=event_index)
|
||||
EventOrganizerLink.objects.create(event=event, organizer=org_a)
|
||||
EventOrganizerLink.objects.create(event=event, organizer=org_b)
|
||||
|
||||
event = EventPage.objects.get(pk=event.pk)
|
||||
assert event.organizer_links.count() == 2
|
||||
|
||||
event.clean()
|
||||
|
||||
assert event.organizer_links.count() == 1
|
||||
@@ -0,0 +1,38 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
from events.models import EventOccurrence
|
||||
from tests.conftest import EventPageFactory
|
||||
|
||||
|
||||
def test_graphql_endpoint_responds(db, graphql_post):
|
||||
response, body = graphql_post("{ __schema { queryType { name } } }")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "errors" not in body
|
||||
assert body["data"]["__schema"]["queryType"]["name"] == "Query"
|
||||
|
||||
|
||||
def test_event_index_future_events_query(event_index, graphql_post):
|
||||
upcoming = EventPageFactory(parent=event_index, title="Upcoming gig")
|
||||
EventOccurrence.objects.create(
|
||||
event=upcoming,
|
||||
start=timezone.now() + timedelta(days=3),
|
||||
venue_custom="Storsalen",
|
||||
)
|
||||
|
||||
response, body = graphql_post(
|
||||
"""
|
||||
query {
|
||||
eventIndex {
|
||||
futureEvents { title }
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "errors" not in body, body
|
||||
titles = [e["title"] for e in body["data"]["eventIndex"]["futureEvents"]]
|
||||
assert "Upcoming gig" in titles
|
||||
Generated
+110
-1
@@ -62,6 +62,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defusedxml"
|
||||
version = "0.7.1"
|
||||
@@ -212,7 +221,10 @@ dependencies = [
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-django" },
|
||||
{ name = "ruff" },
|
||||
{ name = "wagtail-factories" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
@@ -227,7 +239,12 @@ requires-dist = [
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [{ name = "ruff", specifier = ">=0.15.1" }]
|
||||
dev = [
|
||||
{ name = "pytest", specifier = ">=8.3" },
|
||||
{ name = "pytest-django", specifier = ">=4.9" },
|
||||
{ name = "ruff", specifier = ">=0.15.1" },
|
||||
{ name = "wagtail-factories", specifier = ">=4.2" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "draftjs-exporter"
|
||||
@@ -247,6 +264,30 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059, upload-time = "2024-10-25T17:25:39.051Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "factory-boy"
|
||||
version = "3.3.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "faker" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ba/98/75cacae9945f67cfe323829fc2ac451f64517a8a330b572a06a323997065/factory_boy-3.3.3.tar.gz", hash = "sha256:866862d226128dfac7f2b4160287e899daf54f2612778327dd03d0e2cb1e3d03", size = 164146, upload-time = "2025-02-03T09:49:04.433Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/27/8d/2bc5f5546ff2ccb3f7de06742853483ab75bf74f36a92254702f8baecc79/factory_boy-3.3.3-py2.py3-none-any.whl", hash = "sha256:1c39e3289f7e667c4285433f305f8d506efc2fe9c73aaea4151ebd5cdea394fc", size = 37036, upload-time = "2025-02-03T09:49:01.659Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "faker"
|
||||
version = "40.18.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/06/70886e82d8f1d2b73454f3a7c1b7405300128df22e70d85a828951366932/faker-40.18.0.tar.gz", hash = "sha256:2207575c0e8f90e6ccd6dbef764de875c614d16d3db4eee9712d9a00087f2e70", size = 1968243, upload-time = "2026-05-14T16:43:04.834Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/84/0b/5c0b2d3a4b7a715f1835dd3f963bfbe841a02ae5cad1df8ee0325dfad235/faker-40.18.0-py3-none-any.whl", hash = "sha256:61a6b94b74605ddb090a065deb197a1c585ae7a874c094cf6693671d271e6083", size = 2006355, upload-time = "2026-05-14T16:43:02.489Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetype"
|
||||
version = "1.2.0"
|
||||
@@ -330,6 +371,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "laces"
|
||||
version = "0.1.2"
|
||||
@@ -424,6 +474,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/3c/63cbbe3a6a54e3ec925d2433bb431a4bf61695f34b5f1e689db642fb20c1/pillow_heif-1.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:514c856230995dc2f918fb12d83906885d42829e911868e23035e2d916c4c7c5", size = 5573890, upload-time = "2025-08-02T09:58:05.049Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "promise"
|
||||
version = "2.3"
|
||||
@@ -452,6 +511,43 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/36/9c0c326fe3a4227953dfb29f5d0c8ae3b8eb8c1cd2967aa569f50cb3c61f/psycopg2_binary-2.9.11-cp314-cp314-win_amd64.whl", hash = "sha256:4012c9c954dfaccd28f94e84ab9f94e12df76b4afb22331b1f0d3154893a6316", size = 2803913, upload-time = "2025-10-10T11:13:57.058Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.20.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "9.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "iniconfig" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pluggy" },
|
||||
{ name = "pygments" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-django"
|
||||
version = "4.12.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/13/2b/db9a193df89e5660137f5428063bcc2ced7ad790003b26974adf5c5ceb3b/pytest_django-4.12.0.tar.gz", hash = "sha256:df94ec819a83c8979c8f6de13d9cdfbe76e8c21d39473cfe2b40c9fc9be3c758", size = 91156, upload-time = "2026-02-14T18:40:49.235Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/83/a5/41d091f697c09609e7ef1d5d61925494e0454ebf51de7de05f0f0a728f1d/pytest_django-4.12.0-py3-none-any.whl", hash = "sha256:3ff300c49f8350ba2953b90297d23bf5f589db69545f56f1ec5f8cff5da83e85", size = 26123, upload-time = "2026-02-14T18:40:47.381Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
version = "2.9.0.post0"
|
||||
@@ -605,6 +701,19 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/0e/5efc903966b966df2261a66cce8cb88909e4ade86f1173a156aadbbd1a06/wagtail-7.3.1-py3-none-any.whl", hash = "sha256:eab131e15ab9edc7ed24143d44271e92af79239e105bc3e173d26c95d2b489b3", size = 9479191, upload-time = "2026-03-03T15:54:42.644Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wagtail-factories"
|
||||
version = "4.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "factory-boy" },
|
||||
{ name = "wagtail" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/42/8c/2ece22c2757bb3f6ef34f36cf185246b136134cf594b7b1dde92cb0a331f/wagtail_factories-4.4.0.tar.gz", hash = "sha256:c77c13d438a2e999a9220ff1829f060116013aa519a81944577353f460ba8cba", size = 9939, upload-time = "2026-02-10T15:14:13.7Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/85/bd5aeaa54a10b6defca927f75bc3890acb7c3a9a23df8e10f3aa42e75807/wagtail_factories-4.4.0-py2.py3-none-any.whl", hash = "sha256:be0abb96d36bf0e3c733d7520fc1944441a379ab06d93af447fc4e71b67e2a01", size = 10754, upload-time = "2026-02-10T15:14:12.773Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wagtail-grapple"
|
||||
version = "0.29.0"
|
||||
|
||||
Reference in New Issue
Block a user