From 3dd964e7b39c71a8520c166e6021a9cf73e5a844 Mon Sep 17 00:00:00 2001 From: janiceelamm Date: Fri, 21 Nov 2025 14:32:02 -0500 Subject: [PATCH] implement filter-general function Resolved comments from PR completed unit tests fixing vercel issue fixing vercel issue1 fixing vercel issue3 fixing vercel issue3 fixing vercel issue2 fixing vercel issue resolving integration test fixed the test resolved comments Implement filter-general function changed to real database cleaned up mock tests --- src/lib/api/getVolunteerByGeneralInfo.ts | 55 ++++++++++++ .../lib/api/getVolunteerByGeneralInfo.test.ts | 83 +++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 src/lib/api/getVolunteerByGeneralInfo.ts create mode 100644 tests/lib/api/getVolunteerByGeneralInfo.test.ts diff --git a/src/lib/api/getVolunteerByGeneralInfo.ts b/src/lib/api/getVolunteerByGeneralInfo.ts new file mode 100644 index 0000000..606883d --- /dev/null +++ b/src/lib/api/getVolunteerByGeneralInfo.ts @@ -0,0 +1,55 @@ +import { createClient } from "../client/supabase/server"; +import type { Database } from "@/lib/client/supabase/types"; + +type LogicalOp = "AND" | "OR"; + +type VolunteerRow = Database["public"]["Tables"]["Volunteers"]["Row"]; + +export async function getVolunteerByGeneralInfo( + op: LogicalOp, + column: keyof VolunteerRow & string, + values: string[] +): Promise<{ + data: VolunteerRow[] | null; + error: Error | null; +}> { + if (values.length === 0) { + return { data: null, error: new Error("No values provided.") }; + } + + const client = await createClient(); + + if (op === "AND") { + const uniqueValues = [...new Set(values)]; + + if (uniqueValues.length > 1) { + return { data: [], error: null }; // Return empty result if there are multiple unique values + } + const value = uniqueValues[0]!; + + const { data, error } = await client + .from("Volunteers") + .select() + .eq(column, value); + + return { + data, + error: error ?? null, + }; + } + if (op === "OR") { + const { data, error } = await client + .from("Volunteers") + .select() + .in(column, values); + + return { + data, + error: error ?? null, + }; + } + return { + data: null, + error: new Error(`Unsupported operator: ${op}`), + }; +} diff --git a/tests/lib/api/getVolunteerByGeneralInfo.test.ts b/tests/lib/api/getVolunteerByGeneralInfo.test.ts new file mode 100644 index 0000000..6b5d40d --- /dev/null +++ b/tests/lib/api/getVolunteerByGeneralInfo.test.ts @@ -0,0 +1,83 @@ +import { describe, it, expect, beforeEach, afterEach } from "vitest"; +import { getVolunteerByGeneralInfo } from "../../../src/lib/api/getVolunteerByGeneralInfo"; +import { createServiceTestClient, deleteWhere } from "../support/helpers"; +import { makeTestVolunteerInsert } from "../support/factories"; +import type { Tables } from "@/lib/client/supabase/types"; + +describe("db: getVolunteerByGeneralInfo(integration)", () => { + const client = createServiceTestClient(); + + beforeEach(async () => { + await deleteWhere(client, "Volunteers", "name_org", "TEST_%"); + const { error } = await client.from("Volunteers").insert([ + makeTestVolunteerInsert({ + name_org: "TEST_OR_A", + email: "a@test.com", + }), + makeTestVolunteerInsert({ + name_org: "TEST_OR_B", + email: "b@test.com", + }), + makeTestVolunteerInsert({ + name_org: "TEST_OR_C", + email: "other@test.com", + }), + ]); + + if (error) { + throw new Error(`Setup failed: ${error.message}`); + } + }); + + afterEach(async () => { + // Cleanup test data + await deleteWhere(client, "Volunteers", "name_org", "TEST_%"); + }); + + it("returns error if values are empty", async () => { + const result = await getVolunteerByGeneralInfo("AND", "name_org", []); + expect(result.data).toBeNull(); + expect(result.error).toBeInstanceOf(Error); + expect(result.error?.message).toBe("No values provided."); + }); + + it("returns volunteers matching ANY email (OR)", async () => { + const result = await getVolunteerByGeneralInfo("OR", "email", [ + "a@test.com", + "b@test.com", + ]); + + expect(result.error).toBeNull(); + expect(result.data).toHaveLength(2); + + type VolunteerRow = Tables<"Volunteers">; + const volunteers: VolunteerRow[] = result.data ?? []; + const emails = volunteers.map((v) => v.email); + + expect(emails).toContain("a@test.com"); + expect(emails).toContain("b@test.com"); + }); + + it("returns volunteer when AND matches single value", async () => { + const result = await getVolunteerByGeneralInfo("AND", "email", [ + "a@test.com", + ]); + + expect(result.error).toBeNull(); + if (!result.data || result.data.length !== 1) { + throw new Error("Expected exactly one volunteer"); + } + + const volunteer = result.data[0]!; + expect(volunteer.email).toBe("a@test.com"); + }); + + it("returns empty data if AND has multiple unique values", async () => { + const result = await getVolunteerByGeneralInfo("AND", "email", [ + "a@mail.com", + "b@mail.com", + ]); + expect(result.data).toEqual([]); + expect(result.error).toBeNull(); + }); +});