dnscms: add more tests
This commit is contained in:
@@ -5,10 +5,35 @@ import pytest
|
||||
import wagtail_factories
|
||||
from wagtail.models import Page
|
||||
|
||||
from associations.models import AssociationIndex, AssociationPage
|
||||
from events.models import EventIndex, EventPage
|
||||
from generic.models import GenericPage
|
||||
from images.models import CustomImage
|
||||
from news.models import NewsIndex, NewsPage
|
||||
from venues.models import VenueIndex, VenuePage
|
||||
|
||||
|
||||
class CustomImageFactory(wagtail_factories.ImageFactory):
|
||||
class Meta:
|
||||
model = CustomImage
|
||||
|
||||
|
||||
class AssociationIndexFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"Associations {n}")
|
||||
lead = "<p>Foreninger og utvalg.</p>"
|
||||
|
||||
class Meta:
|
||||
model = AssociationIndex
|
||||
|
||||
|
||||
class AssociationPageFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"Association {n}")
|
||||
excerpt = "Et utdrag."
|
||||
|
||||
class Meta:
|
||||
model = AssociationPage
|
||||
|
||||
|
||||
class EventIndexFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"Events {n}")
|
||||
|
||||
@@ -23,6 +48,29 @@ class EventPageFactory(wagtail_factories.PageFactory):
|
||||
model = EventPage
|
||||
|
||||
|
||||
class GenericPageFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"Page {n}")
|
||||
lead = "<p>Ingress.</p>"
|
||||
|
||||
class Meta:
|
||||
model = GenericPage
|
||||
|
||||
|
||||
class NewsIndexFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"News {n}")
|
||||
|
||||
class Meta:
|
||||
model = NewsIndex
|
||||
|
||||
|
||||
class NewsPageFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"Article {n}")
|
||||
excerpt = "Et utdrag."
|
||||
|
||||
class Meta:
|
||||
model = NewsPage
|
||||
|
||||
|
||||
class VenueIndexFactory(wagtail_factories.PageFactory):
|
||||
title = factory.Sequence(lambda n: f"Venues {n}")
|
||||
|
||||
@@ -56,6 +104,16 @@ def event_index(home_page):
|
||||
return EventIndexFactory(parent=home_page)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def news_index(home_page):
|
||||
return NewsIndexFactory(parent=home_page)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def association_index(home_page):
|
||||
return AssociationIndexFactory(parent=home_page)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def venue(home_page):
|
||||
venue_index = VenueIndexFactory(parent=home_page)
|
||||
|
||||
+319
-18
@@ -1,16 +1,21 @@
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytest
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils import timezone
|
||||
|
||||
from events.models import (
|
||||
EventCategory,
|
||||
EventOccurrence,
|
||||
EventOrganizer,
|
||||
EventOrganizerLink,
|
||||
EventPage,
|
||||
)
|
||||
from tests.conftest import EventPageFactory
|
||||
from tests.conftest import (
|
||||
AssociationPageFactory,
|
||||
CustomImageFactory,
|
||||
EventPageFactory,
|
||||
)
|
||||
|
||||
|
||||
def test_eventpage_clean_unsets_specific_pricing_when_free():
|
||||
@@ -30,6 +35,58 @@ def test_eventpage_clean_unsets_specific_pricing_when_free():
|
||||
assert page.price_member == ""
|
||||
|
||||
|
||||
def test_eventpage_clean_keeps_specific_pricing_when_not_free():
|
||||
page = EventPage(
|
||||
title="Paid event",
|
||||
slug="paid-event",
|
||||
free=False,
|
||||
price_regular="100",
|
||||
price_student="50",
|
||||
price_member="25",
|
||||
)
|
||||
|
||||
page.clean()
|
||||
|
||||
assert page.price_regular == "100"
|
||||
assert page.price_student == "50"
|
||||
assert page.price_member == "25"
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
def test_eventpage_clean_dedupes_three_duplicates_and_keeps_distinct(event_index):
|
||||
dup_1 = EventOrganizer.objects.create(name="DNS", slug="dns-1")
|
||||
dup_2 = EventOrganizer.objects.create(name="DNS", slug="dns-2")
|
||||
dup_3 = EventOrganizer.objects.create(name="DNS", slug="dns-3")
|
||||
distinct = EventOrganizer.objects.create(name="Studentersamfundet", slug="ss")
|
||||
|
||||
event = EventPageFactory(parent=event_index)
|
||||
for organizer in (dup_1, dup_2, dup_3, distinct):
|
||||
EventOrganizerLink.objects.create(event=event, organizer=organizer)
|
||||
|
||||
event = EventPage.objects.get(pk=event.pk)
|
||||
assert event.organizer_links.count() == 4
|
||||
|
||||
event.clean()
|
||||
|
||||
names = sorted(link.organizer.name for link in event.organizer_links.all())
|
||||
assert names == ["DNS", "Studentersamfundet"]
|
||||
|
||||
|
||||
def test_eventoccurrence_clean_rejects_both_venue_and_venue_custom(event_index, venue):
|
||||
event = EventPageFactory(parent=event_index)
|
||||
occurrence = EventOccurrence(
|
||||
@@ -57,14 +114,10 @@ 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"
|
||||
)
|
||||
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"
|
||||
)
|
||||
EventOccurrence.objects.create(event=future, start=now + timedelta(days=7), venue_custom="New")
|
||||
|
||||
results = list(EventPage.objects.live().future().order_by("next_occurrence"))
|
||||
|
||||
@@ -72,17 +125,265 @@ def test_eventpage_manager_future_filters_past_and_annotates(event_index):
|
||||
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")
|
||||
def test_future_includes_occurrence_late_today(event_index):
|
||||
today_start = timezone.localtime(timezone.now()).replace(
|
||||
hour=0, minute=0, second=0, microsecond=0
|
||||
)
|
||||
late_today = today_start + timedelta(hours=23, minutes=59)
|
||||
|
||||
event = EventPageFactory(parent=event_index)
|
||||
EventOrganizerLink.objects.create(event=event, organizer=org_a)
|
||||
EventOrganizerLink.objects.create(event=event, organizer=org_b)
|
||||
event = EventPageFactory(parent=event_index, title="Late today")
|
||||
EventOccurrence.objects.create(event=event, start=late_today, venue_custom="X")
|
||||
|
||||
event = EventPage.objects.get(pk=event.pk)
|
||||
assert event.organizer_links.count() == 2
|
||||
assert event.pk in EventPage.objects.future().values_list("pk", flat=True)
|
||||
|
||||
event.clean()
|
||||
|
||||
assert event.organizer_links.count() == 1
|
||||
def test_future_excludes_occurrence_just_before_today(event_index):
|
||||
today_start = timezone.localtime(timezone.now()).replace(
|
||||
hour=0, minute=0, second=0, microsecond=0
|
||||
)
|
||||
just_before_today = today_start - timedelta(seconds=1)
|
||||
|
||||
event = EventPageFactory(parent=event_index, title="Just past")
|
||||
EventOccurrence.objects.create(event=event, start=just_before_today, venue_custom="X")
|
||||
|
||||
assert event.pk not in EventPage.objects.future().values_list("pk", flat=True)
|
||||
|
||||
|
||||
def test_future_next_occurrence_picks_earliest_future_ignoring_past(event_index):
|
||||
now = timezone.now()
|
||||
soonest_future = now + timedelta(days=3)
|
||||
|
||||
event = EventPageFactory(parent=event_index, title="With history")
|
||||
EventOccurrence.objects.create(event=event, start=now - timedelta(days=30), venue_custom="X")
|
||||
EventOccurrence.objects.create(event=event, start=soonest_future, venue_custom="X")
|
||||
EventOccurrence.objects.create(event=event, start=now + timedelta(days=10), venue_custom="X")
|
||||
|
||||
annotated = EventPage.objects.future().filter(pk=event.pk).first()
|
||||
assert annotated is not None
|
||||
assert abs((annotated.next_occurrence - soonest_future).total_seconds()) < 1
|
||||
|
||||
|
||||
def test_graphql_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
|
||||
|
||||
|
||||
def test_graphql_event_index_future_events_ordered_by_next_occurrence(event_index, graphql_post):
|
||||
now = timezone.now()
|
||||
|
||||
later = EventPageFactory(parent=event_index, title="Later gig")
|
||||
EventOccurrence.objects.create(event=later, start=now + timedelta(days=10), venue_custom="X")
|
||||
|
||||
sooner = EventPageFactory(parent=event_index, title="Sooner gig")
|
||||
EventOccurrence.objects.create(event=sooner, start=now + timedelta(days=3), venue_custom="X")
|
||||
|
||||
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 titles.index("Sooner gig") < titles.index("Later gig")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def comprehensive_event(event_index, venue, association_index):
|
||||
"""A fully-populated paid EventPage exercising every field exposed via GraphQL."""
|
||||
image = CustomImageFactory(
|
||||
title="Cover",
|
||||
alt="Et fotografi av en gris med solbriller",
|
||||
attribution="Foto: Test",
|
||||
)
|
||||
|
||||
konsert = EventCategory.objects.create(
|
||||
name="Konsert", slug="konsert", show_in_filters=True, pig="pigHeadLogo"
|
||||
)
|
||||
klubb = EventCategory.objects.create(name="Klubb", slug="klubb")
|
||||
|
||||
association = AssociationPageFactory(
|
||||
parent=association_index,
|
||||
title="Internal",
|
||||
association_type="forening",
|
||||
)
|
||||
internal_org = EventOrganizer.objects.create(
|
||||
name="Internal", slug="internal", association=association
|
||||
)
|
||||
external_org = EventOrganizer.objects.create(
|
||||
name="External",
|
||||
slug="external",
|
||||
external_url="https://external.example.com",
|
||||
)
|
||||
|
||||
event = EventPageFactory(
|
||||
parent=event_index,
|
||||
title="Et arrangement",
|
||||
slug="et-arrangement",
|
||||
subtitle="En undertekst",
|
||||
lead="<p>Ingress.</p>",
|
||||
body=[("paragraph", "<p>Body content.</p>")],
|
||||
pig="automatic",
|
||||
free=False,
|
||||
price_regular="150",
|
||||
price_student="100",
|
||||
price_member="75",
|
||||
ticket_url="https://example.com/tickets",
|
||||
facebook_url="https://facebook.com/example",
|
||||
featured_image=image,
|
||||
)
|
||||
event.categories.add(konsert, klubb)
|
||||
EventOrganizerLink.objects.create(event=event, organizer=internal_org)
|
||||
EventOrganizerLink.objects.create(event=event, organizer=external_org)
|
||||
|
||||
now = timezone.now()
|
||||
EventOccurrence.objects.create(
|
||||
event=event,
|
||||
start=now + timedelta(days=5),
|
||||
end=now + timedelta(days=5, hours=3),
|
||||
venue=venue,
|
||||
)
|
||||
EventOccurrence.objects.create(
|
||||
event=event,
|
||||
start=now + timedelta(days=12),
|
||||
end=now + timedelta(days=12, hours=2),
|
||||
venue_custom="Frederikkeplassen",
|
||||
)
|
||||
|
||||
event.save()
|
||||
return event
|
||||
|
||||
|
||||
def test_graphql_event_index_returns_all_fields_for_comprehensive_event(
|
||||
comprehensive_event, graphql_post
|
||||
):
|
||||
response, body = graphql_post(
|
||||
"""
|
||||
query {
|
||||
eventIndex {
|
||||
futureEvents {
|
||||
title
|
||||
slug
|
||||
subtitle
|
||||
lead
|
||||
body {
|
||||
blockType
|
||||
field
|
||||
... on RichTextBlock {
|
||||
value
|
||||
}
|
||||
}
|
||||
pig
|
||||
free
|
||||
priceRegular
|
||||
priceStudent
|
||||
priceMember
|
||||
ticketUrl
|
||||
facebookUrl
|
||||
featuredImage {
|
||||
alt
|
||||
attribution
|
||||
}
|
||||
categories {
|
||||
name
|
||||
slug
|
||||
showInFilters
|
||||
pig
|
||||
}
|
||||
organizers {
|
||||
name
|
||||
slug
|
||||
externalUrl
|
||||
association {
|
||||
title
|
||||
}
|
||||
}
|
||||
occurrences {
|
||||
start
|
||||
end
|
||||
venueCustom
|
||||
venue {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "errors" not in body, body
|
||||
|
||||
events = body["data"]["eventIndex"]["futureEvents"]
|
||||
event = next(e for e in events if e["title"] == "Et arrangement")
|
||||
|
||||
assert event["slug"] == "et-arrangement"
|
||||
assert event["subtitle"] == "En undertekst"
|
||||
assert "Ingress." in event["lead"]
|
||||
assert event["pig"] == "automatic"
|
||||
assert event["free"] is False
|
||||
assert event["priceRegular"] == "150"
|
||||
assert event["priceStudent"] == "100"
|
||||
assert event["priceMember"] == "75"
|
||||
assert event["ticketUrl"] == "https://example.com/tickets"
|
||||
assert event["facebookUrl"] == "https://facebook.com/example"
|
||||
|
||||
assert event["featuredImage"]["alt"] == "Et fotografi av en gris med solbriller"
|
||||
assert event["featuredImage"]["attribution"] == "Foto: Test"
|
||||
|
||||
assert event["body"][0]["blockType"] == "RichTextBlock"
|
||||
assert "Body content." in event["body"][0]["value"]
|
||||
|
||||
categories_by_name = {c["name"]: c for c in event["categories"]}
|
||||
assert set(categories_by_name) == {"Konsert", "Klubb"}
|
||||
assert categories_by_name["Konsert"]["slug"] == "konsert"
|
||||
assert categories_by_name["Konsert"]["showInFilters"] is True
|
||||
assert categories_by_name["Konsert"]["pig"] == "pigHeadLogo"
|
||||
assert categories_by_name["Klubb"]["showInFilters"] is False
|
||||
|
||||
organizers_by_name = {o["name"]: o for o in event["organizers"]}
|
||||
assert set(organizers_by_name) == {"Internal", "External"}
|
||||
assert organizers_by_name["Internal"]["association"]["title"] == "Internal"
|
||||
assert organizers_by_name["Internal"]["externalUrl"] == ""
|
||||
assert organizers_by_name["External"]["association"] is None
|
||||
assert organizers_by_name["External"]["externalUrl"] == "https://external.example.com"
|
||||
|
||||
assert len(event["occurrences"]) == 2
|
||||
venue_occ = next(o for o in event["occurrences"] if o["venue"] is not None)
|
||||
custom_occ = next(o for o in event["occurrences"] if o["venueCustom"])
|
||||
assert venue_occ["venueCustom"] == ""
|
||||
assert venue_occ["venue"]["title"]
|
||||
assert custom_occ["venue"] is None
|
||||
assert custom_occ["venueCustom"] == "Frederikkeplassen"
|
||||
|
||||
venue_occ_db = comprehensive_event.occurrences.exclude(venue=None).get()
|
||||
custom_occ_db = comprehensive_event.occurrences.exclude(venue_custom="").get()
|
||||
assert datetime.fromisoformat(venue_occ["start"]) == venue_occ_db.start
|
||||
assert datetime.fromisoformat(venue_occ["end"]) == venue_occ_db.end
|
||||
assert datetime.fromisoformat(custom_occ["start"]) == custom_occ_db.start
|
||||
assert datetime.fromisoformat(custom_occ["end"]) == custom_occ_db.end
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
from generic.models import GenericPage
|
||||
from tests.conftest import GenericPageFactory
|
||||
|
||||
|
||||
def test_generic_page_persists_via_factory(home_page):
|
||||
page = GenericPageFactory(
|
||||
parent=home_page,
|
||||
title="Om oss",
|
||||
slug="om-oss",
|
||||
lead="<p>Ingress.</p>",
|
||||
body=[("paragraph", "<p>Body content.</p>")],
|
||||
pig="drink",
|
||||
)
|
||||
|
||||
reloaded = GenericPage.objects.get(pk=page.pk)
|
||||
assert reloaded.title == "Om oss"
|
||||
assert reloaded.slug == "om-oss"
|
||||
assert "Ingress." in reloaded.lead
|
||||
assert reloaded.pig == "drink"
|
||||
assert reloaded.body[0].block_type == "paragraph"
|
||||
|
||||
|
||||
def test_generic_page_allows_recursive_children(home_page):
|
||||
parent = GenericPageFactory(parent=home_page, title="Parent", slug="parent")
|
||||
child = GenericPageFactory(parent=parent, title="Child", slug="child")
|
||||
|
||||
assert child.get_parent().specific == parent
|
||||
assert list(parent.get_children().specific()) == [child]
|
||||
|
||||
|
||||
def test_graphql_generic_page_query(home_page, graphql_post):
|
||||
GenericPageFactory(
|
||||
parent=home_page,
|
||||
title="Om oss",
|
||||
slug="om-oss",
|
||||
lead="<p>Ingress text.</p>",
|
||||
body=[("paragraph", "<p>Body content.</p>")],
|
||||
pig="drink",
|
||||
)
|
||||
|
||||
response, body = graphql_post(
|
||||
"""
|
||||
query {
|
||||
page(slug: "om-oss", contentType: "generic.GenericPage") {
|
||||
title
|
||||
slug
|
||||
... on GenericPage {
|
||||
lead
|
||||
pig
|
||||
body {
|
||||
blockType
|
||||
field
|
||||
... on RichTextBlock {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "errors" not in body, body
|
||||
data = body["data"]["page"]
|
||||
assert data["title"] == "Om oss"
|
||||
assert data["slug"] == "om-oss"
|
||||
assert "Ingress text." in data["lead"]
|
||||
assert data["pig"] == "drink"
|
||||
assert data["body"][0]["blockType"] == "RichTextBlock"
|
||||
assert "Body content." in data["body"][0]["value"]
|
||||
@@ -1,38 +1,6 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
from news.models import NewsPage
|
||||
from tests.conftest import NewsPageFactory
|
||||
|
||||
|
||||
def test_news_page_persists_via_factory(news_index):
|
||||
page = NewsPageFactory(parent=news_index, title="Big news", excerpt="Short summary")
|
||||
|
||||
reloaded = NewsPage.objects.get(pk=page.pk)
|
||||
assert reloaded.title == "Big news"
|
||||
assert reloaded.excerpt == "Short summary"
|
||||
|
||||
|
||||
def test_graphql_news_index_query(news_index, graphql_post):
|
||||
response, body = graphql_post(
|
||||
"""
|
||||
query {
|
||||
newsIndex {
|
||||
title
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "errors" not in body, body
|
||||
assert body["data"]["newsIndex"]["title"] == news_index.title
|
||||
@@ -0,0 +1,91 @@
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from openinghours.models import OpeningHoursItem, OpeningHoursSet
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def opening_hours_set(db):
|
||||
return OpeningHoursSet.objects.create(
|
||||
name="Vanlige åpningstider",
|
||||
effective_from=datetime.date(2025, 1, 1),
|
||||
)
|
||||
|
||||
|
||||
def test_opening_hours_set_str_with_end_date():
|
||||
ohs = OpeningHoursSet(
|
||||
name="Sommer",
|
||||
effective_from=datetime.date(2025, 6, 1),
|
||||
effective_to=datetime.date(2025, 8, 31),
|
||||
)
|
||||
assert str(ohs) == "Sommer (2025-06-01 - 2025-08-31)"
|
||||
|
||||
|
||||
def test_opening_hours_set_str_uses_infinity_when_open_ended():
|
||||
ohs = OpeningHoursSet(
|
||||
name="Forever",
|
||||
effective_from=datetime.date(2025, 1, 1),
|
||||
effective_to=None,
|
||||
)
|
||||
assert str(ohs) == "Forever (2025-01-01 - ∞)"
|
||||
|
||||
|
||||
def test_opening_hours_streamfield_week_roundtrip(opening_hours_set):
|
||||
OpeningHoursItem.objects.create(
|
||||
opening_hours_set=opening_hours_set,
|
||||
function="glassbaren",
|
||||
week=[
|
||||
(
|
||||
"week",
|
||||
{
|
||||
"monday": {
|
||||
"time_from": datetime.time(15, 0),
|
||||
"time_to": datetime.time(23, 0),
|
||||
"custom": "",
|
||||
},
|
||||
"tuesday": {"time_from": None, "time_to": None, "custom": "Stengt"},
|
||||
"wednesday": {"time_from": None, "time_to": None, "custom": ""},
|
||||
"thursday": {"time_from": None, "time_to": None, "custom": ""},
|
||||
"friday": {"time_from": None, "time_to": None, "custom": ""},
|
||||
"saturday": {"time_from": None, "time_to": None, "custom": ""},
|
||||
"sunday": {"time_from": None, "time_to": None, "custom": ""},
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
reloaded = OpeningHoursSet.objects.get(pk=opening_hours_set.pk)
|
||||
item = reloaded.items.get()
|
||||
assert item.function == "glassbaren"
|
||||
|
||||
week_block = item.week[0]
|
||||
assert week_block.block_type == "week"
|
||||
assert week_block.value["monday"]["time_from"] == datetime.time(15, 0)
|
||||
assert week_block.value["monday"]["time_to"] == datetime.time(23, 0)
|
||||
assert week_block.value["tuesday"]["custom"] == "Stengt"
|
||||
|
||||
|
||||
def test_graphql_opening_hours_sets_query(db, graphql_post):
|
||||
OpeningHoursSet.objects.create(
|
||||
name="Sommer 2025",
|
||||
effective_from=datetime.date(2025, 6, 1),
|
||||
effective_to=datetime.date(2025, 8, 31),
|
||||
)
|
||||
|
||||
response, body = graphql_post(
|
||||
"""
|
||||
query {
|
||||
openingHoursSets {
|
||||
name
|
||||
effectiveFrom
|
||||
effectiveTo
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "errors" not in body, body
|
||||
names = [s["name"] for s in body["data"]["openingHoursSets"]]
|
||||
assert "Sommer 2025" in names
|
||||
Reference in New Issue
Block a user