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(); + }); +});