// Canned GraphQL responses for the smoke-test mock CMS. // // Every piece is typed with `satisfies` against the *fragment* types generated // by codegen (fragment masking makes the query types too weak — their // `$fragmentRefs` props are optional). When `npm run codegen` regenerates // after a schema change, `tsc --noEmit` fails here, flagging stale fixtures. import type { AllAssociationSlugsQuery, AllAssociationsQuery, AllGenericSlugsQuery, AllVenueSlugsQuery, AssociationBySlugQuery, AssociationFragment, AssociationIndexFragment, ContactIndexFragment, ContactsQuery, EventBySlugQuery, EventCategoryFragment, EventFragment, EventIndexFragment, EventIndexMetadataQuery, EventListItemFragment, EventOrganizerFragment, EventOverviewItemFragment, FutureEventsQuery, GenericFragment, GenericPageByUrlQuery, HomeFragment, HomeQuery, ImageFragment, NewsBySlugQuery, NewsFragment, NewsIndexFragment, NewsIndexMetadataQuery, NewsListItemFragment, NewsQuery, OpeningHoursSetFragment, OpeningHoursSetsQuery, PreviewPageQuery, SearchQuery, SponsorsPageFragment, SponsorsQuery, StudioFragment, StudioQuery, VenueBySlugQuery, VenueFragment, VenueIndexFragment, VenueIndexQuery, VenueRentalIndexFragment, VenueRentalIndexQuery, } from "@/gql/graphql"; export type MockState = { newsHeadlineVersion: "v1" | "v2"; }; export const SLUGS = { genericUrl: "praktisk", // served at /praktisk, wagtail urlPath /home/praktisk/ association: "testforening", venue: "storsalen", news: "test-artikkel", event: "testkonsert", } as const; export function newsTitle(state: MockState): string { return `Testartikkel (${state.newsHeadlineVersion})`; } type Resolver = (vars: Record, state: MockState) => unknown; export type Fixtures = Record; // Fragment masking types a fragment spread's slot as an opaque ref, but the // wire format is simply the fragment's fields. Each piece above proves its // shape with `satisfies `; this cast lets it slot into the masked // position of the enclosing query/fragment type. function mask(value: T): { " $fragmentRefs"?: undefined } { return value as never; } export function makeFixtures(cmsBaseUrl: string): Fixtures { const inAWeek = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000); const occurrenceStart = inAWeek.toISOString(); const occurrenceEnd = new Date( inAWeek.getTime() + 2 * 60 * 60 * 1000 ).toISOString(); const image = { id: "1", url: `${cmsBaseUrl}/media/pig.png`, width: 64, height: 64, alt: "En gris", attribution: null, } satisfies ImageFragment; const eventCategory = { __typename: "EventCategory", name: "Konsert", slug: "konsert", pig: "PIG_PINK", showInFilters: true, } satisfies EventCategoryFragment; const eventOrganizer = { __typename: "EventOrganizer", id: "1", name: "Testforeningen", slug: "testforeningen", externalUrl: null, association: null, } satisfies EventOrganizerFragment; const eventListItem = { __typename: "EventPage", id: "10", slug: SLUGS.event, title: "Testkonsert", subtitle: "En kveld med smoke tests", featuredImage: mask(image), occurrences: [ { __typename: "EventOccurrence", id: "100", start: occurrenceStart, end: occurrenceEnd, }, ], } satisfies EventListItemFragment; const venuePageRef = { __typename: "VenuePage" as const, id: "30", slug: SLUGS.venue, title: "Storsalen", preposition: "i", url: `/lokaler/${SLUGS.venue}/`, }; const eventOverviewItem = { ...eventListItem, categories: [mask(eventCategory)], occurrences: [ { __typename: "EventOccurrence", id: "100", start: occurrenceStart, end: occurrenceEnd, venueCustom: null, venue: venuePageRef, }, ], organizers: [mask(eventOrganizer)], } satisfies EventOverviewItemFragment; const eventPage = { ...eventOverviewItem, seoTitle: "Testkonsert", searchDescription: null, lead: "Bli med på testkonsert.", pig: "PIG_PINK", facebookUrl: null, ticketUrl: null, free: true, priceRegular: null, priceMember: null, priceStudent: null, body: [], } satisfies EventFragment; const eventIndex = { __typename: "EventIndex", id: "3", slug: "arrangementer", seoTitle: "Arrangementer", searchDescription: null, title: "Arrangementer", } satisfies EventIndexFragment; const newsListItem = (state: MockState) => ({ __typename: "NewsPage", id: "20", slug: SLUGS.news, title: newsTitle(state), firstPublishedAt: "2026-08-01T12:00:00+02:00", excerpt: "Et utdrag.", featuredImage: mask(image), }) satisfies NewsListItemFragment; const newsPage = (state: MockState) => ({ ...newsListItem(state), seoTitle: newsTitle(state), searchDescription: null, lead: "Ingressen.", body: [], }) satisfies NewsFragment; const newsIndex = { __typename: "NewsIndex", id: "2", slug: "aktuelt", seoTitle: "Aktuelt", searchDescription: null, title: "Aktuelt", lead: null, } satisfies NewsIndexFragment; const home = { __typename: "HomePage", featuredEvents: [], } satisfies HomeFragment; const genericPage = { __typename: "GenericPage", id: "40", urlPath: `/home/${SLUGS.genericUrl}/`, seoTitle: "Praktisk info", searchDescription: null, title: "Praktisk info", lead: "Alt du trenger å vite.", pig: "PIG_PINK", body: [], } satisfies GenericFragment; const association = { __typename: "AssociationPage", id: "50", slug: SLUGS.association, title: "Testforeningen", seoTitle: "Testforeningen", searchDescription: null, excerpt: "En forening for testing.", lead: null, associationType: "Kultur", websiteUrl: null, body: [], logo: null, } satisfies AssociationFragment; const associationIndex = { __typename: "AssociationIndex", title: "Foreninger", seoTitle: "Foreninger", searchDescription: null, lead: null, body: [], } satisfies AssociationIndexFragment; const venue = { __typename: "VenuePage", id: "30", slug: SLUGS.venue, title: "Storsalen", seoTitle: "Storsalen", searchDescription: null, showAsBookable: true, showInOverview: true, floor: "2", preposition: "i", usedFor: "Konserter", techSpecsUrl: null, capabilityAudio: null, capabilityAudioVideo: null, capabilityBar: null, capabilityLighting: null, capacityLegal: "450", capacityStanding: "450", capacitySitting: "200", images: [], body: [], featuredImage: null, } satisfies VenueFragment; const venueIndex = { __typename: "VenueIndex", title: "Lokaler", seoTitle: "Lokaler", searchDescription: null, lead: null, body: [], } satisfies VenueIndexFragment; const venueRentalIndex = { __typename: "VenueRentalIndex", title: "Utleie", seoTitle: "Utleie", searchDescription: null, lead: null, body: [], } satisfies VenueRentalIndexFragment; const contactIndex = { __typename: "ContactIndex", title: "Kontakt", seoTitle: "Kontakt", searchDescription: null, lead: null, body: [], } satisfies ContactIndexFragment; const sponsorsPage = { __typename: "SponsorsPage", title: "Sponsorer", seoTitle: "Sponsorer", searchDescription: null, lead: null, body: [], sponsors: [], } satisfies SponsorsPageFragment; const studioPage = { __typename: "StudioPage", id: "60", title: "Studio", seoTitle: "Studio", searchDescription: null, lead: null, pig: "PIG_PINK", logo: null, body: [], } satisfies StudioFragment; const openingHoursSet = { name: "Vanlige åpningstider", effectiveFrom: "2026-01-01", effectiveTo: null, announcement: null, items: [], } satisfies OpeningHoursSetFragment; return { // --- build time: generateStaticParams --- allGenericSlugs: () => ({ pages: [{ id: "40", urlPath: `/home/${SLUGS.genericUrl}/` }], }) satisfies AllGenericSlugsQuery, allAssociationSlugs: () => ({ pages: [{ id: "50", slug: SLUGS.association }], }) satisfies AllAssociationSlugsQuery, allVenueSlugs: () => ({ pages: [{ id: "30", slug: SLUGS.venue }], }) satisfies AllVenueSlugsQuery, // --- build time: static pages --- home: (_vars, state) => ({ events: { futureEvents: [mask(eventListItem)] }, home: mask(home), news: [mask(newsListItem(state))], }) satisfies HomeQuery, news: (_vars, state) => ({ index: mask(newsIndex), news: [mask(newsListItem(state))], }) satisfies NewsQuery, newsIndexMetadata: () => ({ index: mask(newsIndex) }) satisfies NewsIndexMetadataQuery, futureEvents: () => ({ index: mask(eventIndex), events: { futureEvents: [mask(eventOverviewItem)] }, eventCategories: [mask(eventCategory)], eventOrganizers: [mask(eventOrganizer)], venues: [ { id: "30", title: "Storsalen", slug: SLUGS.venue, preposition: "i", }, ], }) satisfies FutureEventsQuery, eventIndexMetadata: () => ({ index: mask(eventIndex) }) satisfies EventIndexMetadataQuery, allAssociations: () => ({ index: mask(associationIndex), associations: [mask(association)], }) satisfies AllAssociationsQuery, contacts: () => ({ index: mask(contactIndex) }) satisfies ContactsQuery, venueIndex: () => ({ index: mask(venueIndex), venues: [mask(venue)] }) satisfies VenueIndexQuery, venueRentalIndex: () => ({ index: mask(venueRentalIndex), venues: [mask(venue)], }) satisfies VenueRentalIndexQuery, sponsors: () => ({ page: mask(sponsorsPage) }) satisfies SponsorsQuery, studio: () => ({ page: mask(studioPage) }) satisfies StudioQuery, openingHoursSets: () => ({ openingHoursSets: [mask(openingHoursSet)] }) satisfies OpeningHoursSetsQuery, // --- build time: prerendered dynamic pages (null for unknown slugs → notFound) --- genericPageByUrl: (vars) => ({ page: vars.urlPath === `/home/${SLUGS.genericUrl}/` ? mask(genericPage) : null, }) satisfies GenericPageByUrlQuery, associationBySlug: (vars) => ({ association: vars.slug === SLUGS.association ? mask(association) : null, }) satisfies AssociationBySlugQuery, venueBySlug: (vars) => ({ venue: vars.slug === SLUGS.venue ? mask(venue) : null, }) satisfies VenueBySlugQuery, // --- runtime --- newsBySlug: (vars, state) => ({ news: vars.slug === SLUGS.news ? mask(newsPage(state)) : null, }) satisfies NewsBySlugQuery, eventBySlug: (vars) => ({ event: vars.slug === SLUGS.event ? mask(eventPage) : null, }) satisfies EventBySlugQuery, search: (vars) => ({ results: typeof vars.query === "string" && vars.query.length > 0 ? [ { __typename: "GenericPage", id: "40", title: "Praktisk info", url: `/${SLUGS.genericUrl}/`, lead: "Alt du trenger å vite.", }, ] : [], }) satisfies SearchQuery, previewPage: (_vars, state) => ({ page: { __typename: "NewsPage" as const, ...mask(newsPage(state)) }, }) satisfies PreviewPageQuery, }; }