Skip to content

Commit 016d896

Browse files
fix: changed resource type so that some fields could be optional (#29)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 4e5cb4d commit 016d896

5 files changed

Lines changed: 131 additions & 14 deletions

File tree

frontend/src/app/[locale]/generate-referrals/page.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,21 @@ export default function Page() {
127127
{r.description && (
128128
<div className="font-medium mb-2">{r.description}</div>
129129
)}
130-
{r.addresses?.length > 0 && (
130+
{r.addresses && r.addresses?.length > 0 && (
131131
<div className="mt-1">
132132
<span className="font-semibold">
133133
Address{r.addresses.length > 1 ? "es" : ""}:
134134
</span>{" "}
135135
{r.addresses.join(" | ")}
136136
</div>
137137
)}
138-
{r.phones?.length > 0 && (
138+
{r.phones && r.phones?.length > 0 && (
139139
<div className="mt-1">
140140
<span className="font-semibold">Phone:</span>{" "}
141141
{r.phones.join(" | ")}
142142
</div>
143143
)}
144-
{r.emails?.length > 0 && (
144+
{r.emails && r.emails?.length > 0 && (
145145
<div className="mt-1">
146146
<span className="font-semibold">Email:</span>{" "}
147147
{r.emails.join(" | ")}

frontend/src/types/resources.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { z } from "zod";
22

33
export const ResourceSchema = z.object({
4+
addresses: z.array(z.string().optional()).optional(),
5+
description: z.string().optional(),
6+
emails: z.array(z.string().email().optional()).optional(),
7+
justification: z.string().optional(),
48
name: z.string(),
5-
addresses: z.array(z.string()),
6-
phones: z.array(z.string()),
7-
emails: z.array(z.string().email()),
8-
website: z.string().url(),
9-
description: z.string(),
10-
justification: z.string(),
9+
phones: z.array(z.string().optional()).optional(),
10+
website: z.string().optional().or(z.literal("")),
1111
});
1212

1313
export const ResourcesSchema = z.object({

frontend/src/util/printReferrals.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,21 @@ export function PrintableReferralsReport({
4141
<div className="mb-2 text-slate-700">{r.description}</div>
4242
)}
4343

44-
{r.addresses?.length > 0 && (
44+
{r.addresses && r.addresses?.length > 0 && (
4545
<div className="text-slate-700">
4646
<span className="font-semibold">
4747
Address{r.addresses.length > 1 ? "es" : ""}:
4848
</span>{" "}
4949
{r.addresses.join(" | ")}
5050
</div>
5151
)}
52-
{r.phones?.length > 0 && (
52+
{r.phones && r.phones?.length > 0 && (
5353
<div className="text-slate-700">
5454
<span className="font-semibold">Phone:</span>{" "}
5555
{r.phones.join(" | ")}
5656
</div>
5757
)}
58-
{r.emails?.length > 0 && (
58+
{r.emails && r.emails?.length > 0 && (
5959
<div className="text-slate-700">
6060
<span className="font-semibold">Email:</span>{" "}
6161
{r.emails.join(" | ")}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// __tests__/resourceSchema.test.ts
2+
import { ResourceSchema } from "@/types/resources";
3+
4+
describe("ResourceSchema", () => {
5+
it("parses ok when all conditions met", () => {
6+
const resourceWithEverythingOK = {
7+
name: "Capital Metro",
8+
addresses: ["Austin, Texas"],
9+
phones: ["512-474-1200", "1-800-474-1201"],
10+
emails: ["info@capmetro.org", "capital@metro.org"],
11+
website: "http://www.capitalmetro.org",
12+
description:
13+
"Public transportation service provider in Austin. Offers route planning assistance and transit information services.",
14+
justification:
15+
"Can help plan reliable transportation routes to/from work using public transit system.",
16+
};
17+
18+
const result = ResourceSchema.safeParse(resourceWithEverythingOK);
19+
expect(result.success).toBe(true);
20+
expect(result?.data?.phones?.length).toBe(2);
21+
expect(result?.data?.emails?.[0]).toBe("info@capmetro.org");
22+
});
23+
24+
it("parses a resource with empty emails and empty website", () => {
25+
const resourceWithoutEmailsOrWebsite = {
26+
name: "Capital Metro",
27+
addresses: ["Austin, Texas"],
28+
phones: ["512-474-1200", "1-800-474-1201"],
29+
emails: [], // empty array is fine
30+
website: "",
31+
description:
32+
"Public transportation service provider in Austin. Offers route planning assistance and transit information services.",
33+
justification:
34+
"Can help plan reliable transportation routes to/from work using public transit system.",
35+
};
36+
37+
const result = ResourceSchema.safeParse(resourceWithoutEmailsOrWebsite);
38+
39+
expect(result.success).toBe(true);
40+
expect(result?.data?.website).toBeDefined();
41+
expect(result?.data?.website).toBe(""); // explicit empty string
42+
expect(Array.isArray(result?.data?.emails)).toBe(true);
43+
expect(result?.data?.emails?.length).toBe(0); // empty array preserved
44+
});
45+
46+
it("parses when website is omitted entirely", () => {
47+
const resourceWithoutWebsite = {
48+
name: "Capital Metro",
49+
addresses: ["Austin, Texas"],
50+
phones: ["512-474-1200", "1-800-474-1201"],
51+
emails: [],
52+
description:
53+
"Public transportation service provider in Austin. Offers route planning assistance and transit information services.",
54+
justification:
55+
"Can help plan reliable transportation routes to/from work using public transit system.",
56+
};
57+
58+
const result = ResourceSchema.safeParse(resourceWithoutWebsite);
59+
60+
expect(result.success).toBe(true);
61+
expect(result?.data?.website).toBeUndefined(); // missing field is fine
62+
});
63+
64+
it("parses when emails are omitted", () => {
65+
const resourceWithoutEmails = {
66+
name: "Capital Metro",
67+
website: "https://capmetro.org",
68+
};
69+
70+
const result = ResourceSchema.safeParse(resourceWithoutEmails);
71+
expect(result.success).toBe(true);
72+
expect(result?.data?.emails).toBeUndefined();
73+
});
74+
75+
it("fails when emails contain an invalid address", () => {
76+
const resourceWithInvalidEmail = {
77+
name: "Capital Metro",
78+
emails: ["not-an-email"],
79+
website: "https://capmetro.org",
80+
};
81+
82+
const result = ResourceSchema.safeParse(resourceWithInvalidEmail);
83+
expect(result.success).toBe(false);
84+
});
85+
86+
it("parses when emails array is valid", () => {
87+
const resourceWithValidEmails = {
88+
name: "Capital Metro",
89+
emails: ["info@capmetro.org", "support@capmetro.org"],
90+
website: "https://capmetro.org",
91+
};
92+
93+
const result = ResourceSchema.safeParse(resourceWithValidEmails);
94+
expect(result.success).toBe(true);
95+
expect(result?.data?.emails?.length).toBe(2);
96+
expect(result?.data?.emails?.[0]).toBe("info@capmetro.org");
97+
});
98+
99+
it("fails when name is missing", () => {
100+
const resourceWithNoName = {
101+
addresses: ["Austin, Texas"],
102+
phones: ["512-474-1200", "1-800-474-1201"],
103+
emails: [],
104+
description:
105+
"Public transportation service provider in Austin. Offers route planning assistance and transit information services.",
106+
justification:
107+
"Can help plan reliable transportation routes to/from work using public transit system.",
108+
};
109+
110+
const result = ResourceSchema.safeParse(resourceWithNoName);
111+
expect(result.success).toBe(false);
112+
});
113+
});

frontend/tests/util/printReferrals.test.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ describe("PrintableReferralsReport", () => {
5454
render(<PrintableReferralsReport resources={mockResources} />);
5555

5656
mockResources.forEach((resource) => {
57+
// @ts-expect-error resources will be populated in this test
5758
expect(screen.getByText(resource.description)).toBeInTheDocument();
5859
});
5960
});
@@ -62,7 +63,8 @@ describe("PrintableReferralsReport", () => {
6263
render(<PrintableReferralsReport resources={mockResources} />);
6364

6465
mockResources.forEach((resource) => {
65-
resource.addresses.forEach((address) => {
66+
resource.addresses?.forEach((address) => {
67+
// @ts-expect-error addresses will be populated in this test
6668
expect(screen.getByText(new RegExp(address))).toBeInTheDocument();
6769
});
6870
});
@@ -72,7 +74,8 @@ describe("PrintableReferralsReport", () => {
7274
render(<PrintableReferralsReport resources={mockResources} />);
7375

7476
mockResources.forEach((resource) => {
75-
resource.emails.forEach((email) => {
77+
resource.emails?.forEach((email) => {
78+
// @ts-expect-error emails will be populated in this test
7679
expect(screen.getByText(new RegExp(email))).toBeInTheDocument();
7780
});
7881
});
@@ -83,6 +86,7 @@ describe("PrintableReferralsReport", () => {
8386

8487
mockResources.forEach((resource) => {
8588
expect(
89+
// @ts-expect-error website will be populated in this test
8690
screen.getByText(new RegExp(resource.website)),
8791
).toBeInTheDocument();
8892
});

0 commit comments

Comments
 (0)