fix: validate mobile event drawer steps with schema
This commit is contained in:
@@ -1,73 +1,101 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import {
|
||||
getDefaultEventFormValues,
|
||||
getEventFormValuesFromEvent,
|
||||
validateEventFormValues,
|
||||
getDefaultEventFormValues,
|
||||
getEventFormValuesFromEvent,
|
||||
validateEventFormStep,
|
||||
validateEventFormValues,
|
||||
} from "@/lib/event-form";
|
||||
|
||||
describe("event form defaults and validation", () => {
|
||||
test("returns manual-create defaults with blank values", () => {
|
||||
expect(getDefaultEventFormValues()).toEqual({
|
||||
title: "",
|
||||
description: "",
|
||||
location: "",
|
||||
url: "",
|
||||
start: "",
|
||||
end: "",
|
||||
allDay: false,
|
||||
recurrenceRule: undefined,
|
||||
});
|
||||
});
|
||||
test("returns manual-create defaults with blank values", () => {
|
||||
expect(getDefaultEventFormValues()).toEqual({
|
||||
title: "",
|
||||
description: "",
|
||||
location: "",
|
||||
url: "",
|
||||
start: "",
|
||||
end: "",
|
||||
allDay: false,
|
||||
recurrenceRule: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
test("maps edit and AI-prefilled events into form values", () => {
|
||||
const values = getEventFormValuesFromEvent({
|
||||
title: "AI Draft",
|
||||
location: "Studio A",
|
||||
start: "2026-04-09T10:00:00.000Z",
|
||||
recurrenceRule: "FREQ=WEEKLY;INTERVAL=1;BYDAY=TH",
|
||||
});
|
||||
test("maps edit and AI-prefilled events into form values", () => {
|
||||
const values = getEventFormValuesFromEvent({
|
||||
title: "AI Draft",
|
||||
location: "Studio A",
|
||||
start: "2026-04-09T10:00:00.000Z",
|
||||
recurrenceRule: "FREQ=WEEKLY;INTERVAL=1;BYDAY=TH",
|
||||
});
|
||||
|
||||
expect(values.title).toBe("AI Draft");
|
||||
expect(values.location).toBe("Studio A");
|
||||
expect(values.start).toBe("2026-04-09T10:00:00.000Z");
|
||||
expect(values.recurrenceRule).toBe("FREQ=WEEKLY;INTERVAL=1;BYDAY=TH");
|
||||
});
|
||||
expect(values.title).toBe("AI Draft");
|
||||
expect(values.location).toBe("Studio A");
|
||||
expect(values.start).toBe("2026-04-09T10:00:00.000Z");
|
||||
expect(values.recurrenceRule).toBe("FREQ=WEEKLY;INTERVAL=1;BYDAY=TH");
|
||||
});
|
||||
|
||||
test("requires title and start values", () => {
|
||||
const result = validateEventFormValues(getDefaultEventFormValues());
|
||||
test("requires title and start values", () => {
|
||||
const result = validateEventFormValues(getDefaultEventFormValues());
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.flatten().fieldErrors.title?.[0]).toContain("Title is required");
|
||||
expect(result.error.flatten().fieldErrors.start?.[0]).toContain("Start date is required");
|
||||
}
|
||||
});
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.flatten().fieldErrors.title?.[0]).toContain("Title is required");
|
||||
expect(result.error.flatten().fieldErrors.start?.[0]).toContain("Start date is required");
|
||||
}
|
||||
});
|
||||
|
||||
test("requires end to be after start when present", () => {
|
||||
const result = validateEventFormValues({
|
||||
...getDefaultEventFormValues(),
|
||||
title: "Planning",
|
||||
start: "2026-04-09T10:00:00.000Z",
|
||||
end: "2026-04-09T09:30:00.000Z",
|
||||
});
|
||||
test("requires end to be after start when present", () => {
|
||||
const result = validateEventFormValues({
|
||||
...getDefaultEventFormValues(),
|
||||
title: "Planning",
|
||||
start: "2026-04-09T10:00:00.000Z",
|
||||
end: "2026-04-09T09:30:00.000Z",
|
||||
});
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.flatten().fieldErrors.end?.[0]).toContain("after the start date");
|
||||
}
|
||||
});
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.flatten().fieldErrors.end?.[0]).toContain("after the start date");
|
||||
}
|
||||
});
|
||||
|
||||
test("requires an optional URL to be valid when provided", () => {
|
||||
const result = validateEventFormValues({
|
||||
...getDefaultEventFormValues(),
|
||||
title: "Planning",
|
||||
start: "2026-04-09T10:00:00.000Z",
|
||||
url: "not-a-url",
|
||||
});
|
||||
test("requires an optional URL to be valid when provided", () => {
|
||||
const result = validateEventFormValues({
|
||||
...getDefaultEventFormValues(),
|
||||
title: "Planning",
|
||||
start: "2026-04-09T10:00:00.000Z",
|
||||
url: "not-a-url",
|
||||
});
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.flatten().fieldErrors.url?.[0]).toContain("valid URL");
|
||||
}
|
||||
});
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.flatten().fieldErrors.url?.[0]).toContain("valid URL");
|
||||
}
|
||||
});
|
||||
|
||||
test("validates only the requested mobile drawer step", () => {
|
||||
const values = {
|
||||
...getDefaultEventFormValues(),
|
||||
url: "not-a-url",
|
||||
end: "2026-04-09T09:30:00.000Z",
|
||||
};
|
||||
|
||||
const detailsResult = validateEventFormStep(values, ["title", "url"]);
|
||||
const scheduleResult = validateEventFormStep(values, ["start", "end"]);
|
||||
|
||||
expect(detailsResult.success).toBe(false);
|
||||
if (!detailsResult.success) {
|
||||
expect(detailsResult.fieldErrors.title?.[0]).toContain("Title is required");
|
||||
expect(detailsResult.fieldErrors.url?.[0]).toContain("valid URL");
|
||||
expect(detailsResult.fieldErrors.start).toBeUndefined();
|
||||
expect(detailsResult.fieldErrors.end).toBeUndefined();
|
||||
}
|
||||
|
||||
expect(scheduleResult.success).toBe(false);
|
||||
if (!scheduleResult.success) {
|
||||
expect(scheduleResult.fieldErrors.start?.[0]).toContain("Start date is required");
|
||||
expect(scheduleResult.fieldErrors.end?.[0]).toContain("valid");
|
||||
expect(scheduleResult.fieldErrors.title).toBeUndefined();
|
||||
expect(scheduleResult.fieldErrors.url).toBeUndefined();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user