Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@
"src/ui/templates/public/reservations.tsx",
"test/lib/server-attendees.test.ts",
"test/lib/server-listing-parents.test.ts",
"test/lib/server-parents-gate.test.ts",
"test/lib/server-payments.test.ts",
"test/lib/square.test.ts",
"test/lib/stripe.test.ts"
Expand Down
21 changes: 6 additions & 15 deletions test/lib/server-booking-preserve.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@ import { expect } from "@std/expect";
import { it as test } from "@std/testing/bdd";
import { handleRequest } from "#routes";
import { addDays } from "#shared/dates.ts";
import {
answersTable,
questionsTable,
setListingQuestions,
} from "#shared/db/questions.ts";
import { settings } from "#shared/db/settings.ts";
import { todayInTz } from "#shared/timezone.ts";
import { assignQuestion } from "#test/shared/db/questions/helpers.ts";
import {
createTestListing,
describeWithEnv,
Expand Down Expand Up @@ -131,16 +127,11 @@ describeWithEnv("server (booking input preservation)", { db: true }, () => {
test("re-fills a question answer", async () => {
await settings.update.terms(TERMS);
const listing = await createTestListing({ maxQuantity: 5, name: "Ticket" });
const question = await questionsTable.insert({
displayType: "radio",
text: "Size?",
});
const answer = await answersTable.insert({
questionId: question.id,
sortOrder: 0,
text: "Large",
});
await setListingQuestions(listing.id, [question.id]);
const { question, answer } = await assignQuestion(
listing.id,
"Size?",
"Large",
);

const html = await submitAndRefill(listing.slug, {
email: "jane@example.com",
Expand Down
14 changes: 2 additions & 12 deletions test/lib/server-parents-booking/api-book-payments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
bookParentChild,
describeWithEnv,
enablePublicApi,
makeCustomisableDailyParent,
makeParent,
setupStripe,
} from "#test-utils";
Expand Down Expand Up @@ -108,18 +109,7 @@ describeWithEnv(
// webhook reprices the child at a 1-day span (£10) and refunds the gap.
await setupStripe();

const { parent, child } = await makeParent({
children: [
{
customisableDays: true,
dayPrices: { 1: 1000, 3: 3000 },
durationDays: 3,
maxPrice: 0,
unitPrice: 0,
},
],
parent: { daily: true, durationDays: 3 },
});
const { parent, child } = await makeCustomisableDailyParent();

const date = (await bookableStartDates(parent.id))[0]!;

Expand Down
21 changes: 2 additions & 19 deletions test/lib/server-parents-discovery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
deactivateTestListing,
describeWithEnv,
makeParent,
makeRoomySharedChild,
mockRequest,
publicBody,
ticketPageStatus,
Expand Down Expand Up @@ -289,25 +290,7 @@ describeWithEnv(
// (B = 1): one parent+child order needs two of A's ten spots, so it fits and
// the parent keeps its Book link. The pre-fix code took the child's
// per-listing minimum (1) and marked the parent sold out.
const groupA = await createTestGroup({
maxAttendees: 10,
name: "Shared",
});
const groupB = await createTestGroup({
maxAttendees: 1,
name: "Tighter",
});
const parent = await createTestListing({
groupIds: [groupA.id],
maxAttendees: 100,
name: "Base unit",
});
const child = await createTestListing({
groupIds: [groupA.id, groupB.id],
maxAttendees: 100,
name: "Add-on",
});
await listingChildren.setIds(parent.id, [child.id]);
const { parent } = await makeRoomySharedChild();
await assertBookable(parent.slug);
});

Expand Down
78 changes: 30 additions & 48 deletions test/lib/server-parents-e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,24 @@ import { listingChildren } from "#shared/db/listing-parents.ts";
import type { Listing } from "#shared/types.ts";
import {
bookingPageHtml,
bookParent,
childField,
createDailyTestListing,
createTestGroup,
createTestListing,
describeWithEnv,
expectFlash,
expectPackageBookingAccepted,
expectRejectedBooking,
expectReserved,
makeParent,
parentField,
postBooking,
postCalculate,
submitPackageBooking,
ticketPageStatus,
} from "#test-utils";
import { firstBookableDate } from "./server-parents-gate/helpers.ts";

/**
* End-to-end journey for the parent/child (per-unit) booking flow: a daily
Expand Down Expand Up @@ -65,11 +70,7 @@ const setupParentWithTwoChildren = async (): Promise<{
});
const [childA, childB] = children;

const { getBookableStartDates } = await import("#shared/dates.ts");
const { getActiveHolidays } = await import("#shared/db/holidays.ts");
const { getListingWithCount } = await import("#shared/db/listings.ts");
const parentRow = (await getListingWithCount(parent.id))!;
const date = getBookableStartDates(parentRow, await getActiveHolidays())[0]!;
const date = await firstBookableDate(parent.id);

return { childA: childA!, childB: childB!, date, parent };
};
Expand Down Expand Up @@ -102,29 +103,6 @@ const bookingRowsFor = async (
);
};

/** Quick booking with email "a@b.com"/name "Ada" — validation tests. */
const adaBook = (
parent: Listing,
date: string,
extra: Record<string, string>,
) =>
postBooking(parent.slug, {
date,
email: "a@b.com",
name: "Ada",
...extra,
});

/** Build the parent-qty form field for a booking or calculate call. */
const parentField = (p: Listing, qty: string) => ({
[`quantity_${p.id}`]: qty,
});

/** Build a child-qty form field for a booking or calculate call. */
const childField = (p: Listing, c: Listing, qty: string) => ({
[`child_qty_${p.id}_${c.id}`]: qty,
});

/** "Ada Lovelace" booking; asserts reserved. */
const adaLoveBook = async (
parent: Listing,
Expand All @@ -141,13 +119,6 @@ const adaLoveBook = async (
return res;
};

/** Asserts a "choose 1 more" rejection: 302, flash, no attendee row written. */
const assertChoose1More = async (res: Response, parent: Listing) => {
expect(res.status).toBe(302);
expectFlash(res, `Choose 1 more add-on for ${parent.name}.`, false);
expect((await getAttendeesRaw(parent.id)).length).toBe(0);
};

/** Asserts one attendee row per child with qty 1; returns rows for extra checks. */
const assertOneEachPersisted = async (childA: Listing, childB: Listing) => {
const rowsA = await getAttendeesRaw(childA.id);
Expand Down Expand Up @@ -216,11 +187,7 @@ const setupStandalone = async (): Promise<{
thankYouUrl: "",
unitPrice: 0,
});
const { getBookableStartDates } = await import("#shared/dates.ts");
const { getActiveHolidays } = await import("#shared/db/holidays.ts");
const { getListingWithCount } = await import("#shared/db/listings.ts");
const row = (await getListingWithCount(standalone.id))!;
const date = getBookableStartDates(row, await getActiveHolidays())[0]!;
const date = await firstBookableDate(standalone.id);
const res = await postBooking(standalone.slug, {
date,
email: "ada@example.com",
Expand Down Expand Up @@ -252,14 +219,22 @@ describeWithEnv(

test("parent qty 1 with no child chosen is rejected (choose 1 more)", async () => {
const { parent, date } = await setupParentWithTwoChildren();
const res = await adaBook(parent, date, parentField(parent, "1"));
await assertChoose1More(res, parent);
const res = await bookParent(parent.slug, {
date,
...parentField(parent, "1"),
});
await expectRejectedBooking(
res,
parent.id,
`Choose 1 more add-on for ${parent.name}.`,
);
});

test("parent qty 1 with one child unit is accepted", async () => {
const { parent, childA, childB, date } =
await setupParentWithTwoChildren();
const res = await adaBook(parent, date, {
const res = await bookParent(parent.slug, {
date,
...parentField(parent, "1"),
...childField(parent, childA, "1"),
});
Expand All @@ -273,7 +248,7 @@ describeWithEnv(
test("parent qty 2 with two of one child is accepted and folds a single line", async () => {
const { parent, childA, childB, date, baseFields } =
await setupTwoChildrenBase();
const res = await adaBook(parent, date, baseFields);
const res = await bookParent(parent.slug, { date, ...baseFields });
expectReserved(res);
const rowsA = await getAttendeesRaw(childA.id);
expect(rowsA.length).toBe(1);
Expand All @@ -285,7 +260,8 @@ describeWithEnv(
test("parent qty 2 with one of each child is accepted and folds two lines", async () => {
const { parent, childA, childB, date } =
await setupParentWithTwoChildren();
const res = await adaBook(parent, date, {
const res = await bookParent(parent.slug, {
date,
...parentField(parent, "2"),
...childField(parent, childA, "1"),
...childField(parent, childB, "1"),
Expand All @@ -296,16 +272,22 @@ describeWithEnv(

test("parent qty 2 with only one child unit is rejected (too few)", async () => {
const { parent, childA, date } = await setupParentWithTwoChildren();
const res = await adaBook(parent, date, {
const res = await bookParent(parent.slug, {
date,
...parentField(parent, "2"),
...childField(parent, childA, "1"),
});
await assertChoose1More(res, parent);
await expectRejectedBooking(
res,
parent.id,
`Choose 1 more add-on for ${parent.name}.`,
);
});

test("parent qty 2 with three child units is rejected (too many)", async () => {
const { parent, childB, date, baseFields } = await setupTwoChildrenBase();
const res = await adaBook(parent, date, {
const res = await bookParent(parent.slug, {
date,
...baseFields,
...childField(parent, childB, "1"),
});
Expand Down
Loading