-- pgTAP: accept_invitation() function — B-series edge cases -- Run with: psql -U postgres -d postgres -f supabase/tests/001_accept_invitation.sql CREATE EXTENSION IF NOT EXISTS pgtap; BEGIN; SELECT plan(6); -- Setup: three invitations (valid, already-used, expired). -- NOTE: accept_invitation() looks up by `token`, not by `id`. DO $$ BEGIN INSERT INTO public.collective_invitations (id, collective_id, token, created_by, role, expires_at) VALUES ('ffffffff-0001-0001-0001-000000000001', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ffffffff-0001-0001-0001-000000000001', -- token = same UUID for convenience '11111111-1111-1111-1111-111111111111', 'member', now() + INTERVAL '7 days'), ('ffffffff-0002-0002-0002-000000000002', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ffffffff-0002-0002-0002-000000000002', '11111111-1111-1111-1111-111111111111', 'member', now() + INTERVAL '7 days'), ('ffffffff-0003-0003-0003-000000000003', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ffffffff-0003-0003-0003-000000000003', '11111111-1111-1111-1111-111111111111', 'member', now() - INTERVAL '1 day') ON CONFLICT (id) DO NOTHING; -- Mark the second one as already used UPDATE public.collective_invitations SET accepted_at = now(), accepted_by = '22222222-2222-2222-2222-222222222222' WHERE id = 'ffffffff-0002-0002-0002-000000000002'; END $$; -- Make auth.uid() resolve to Eva. set_config() is more reliable than `SET LOCAL`. SELECT set_config('request.jwt.claim.sub', '55555555-5555-5555-5555-555555555555', true); -- B-10: Accept valid invitation SELECT results_eq( $$ SELECT (public.accept_invitation('ffffffff-0001-0001-0001-000000000001'::uuid) ->> 'ok')::boolean $$, $$ VALUES (true) $$, 'B-10: valid invitation accepted' ); SELECT ok( EXISTS ( SELECT 1 FROM public.collective_members WHERE collective_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' AND user_id = '55555555-5555-5555-5555-555555555555' ), 'B-10: Eva added to collective_members after acceptance' ); -- B-11: Already-used invitation returns already_used SELECT results_eq( $$ SELECT public.accept_invitation('ffffffff-0002-0002-0002-000000000002'::uuid) ->> 'error' $$, $$ VALUES ('already_used') $$, 'B-11: already-used invitation returns already_used error' ); -- B-12: Expired invitation returns expired SELECT results_eq( $$ SELECT public.accept_invitation('ffffffff-0003-0003-0003-000000000003'::uuid) ->> 'error' $$, $$ VALUES ('expired') $$, 'B-12: expired invitation returns expired error' ); -- B-12b: Non-existent token returns not_found SELECT results_eq( $$ SELECT public.accept_invitation('00000000-0000-0000-0000-000000000000'::uuid) ->> 'error' $$, $$ VALUES ('not_found') $$, 'B-12b: non-existent token returns not_found error' ); -- B-12c: Accepting the same token twice — already-used takes precedence over -- already_member (the function checks accepted_at before membership). SELECT results_eq( $$ SELECT public.accept_invitation('ffffffff-0001-0001-0001-000000000001'::uuid) ->> 'error' $$, $$ VALUES ('already_used') $$, 'B-12c: re-using a consumed invitation returns already_used' ); SELECT * FROM finish(); ROLLBACK;