-- pgTAP: restore_list / hard_delete_list RPCs — Fase 10.4 -- Run with: psql -U postgres -d postgres -f supabase/tests/012_trash_rpcs.sql CREATE EXTENSION IF NOT EXISTS pgtap; BEGIN; SELECT plan(8); -- ── Existence ──────────────────────────────────────────────────────────────── SELECT has_function( 'public', 'restore_list', ARRAY['uuid'], 'public.restore_list(uuid) RPC exists' ); SELECT has_function( 'public', 'hard_delete_list', ARRAY['uuid'], 'public.hard_delete_list(uuid) RPC exists' ); -- ── Setup: a soft-deleted list in the seed collective ──────────────────────── -- Owned by Borja so it has a valid created_by (RESTRICT FK). INSERT INTO public.shopping_lists (id, collective_id, name, status, created_by, deleted_at) VALUES ('cccccccc-4444-4444-4444-4444deadbeef', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'Trash test list', 'active', '22222222-2222-2222-2222-222222222222', now() - interval '1 hour'); INSERT INTO public.shopping_lists (id, collective_id, name, status, created_by) VALUES ('cccccccc-4444-4444-4444-4444cafebabe', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'Active list', 'active', '22222222-2222-2222-2222-222222222222'); -- ── Case 1: restore as Borja (member) ──────────────────────────────────────── SELECT set_config('request.jwt.claim.sub', '22222222-2222-2222-2222-222222222222', true); SELECT lives_ok( $$ SELECT public.restore_list('cccccccc-4444-4444-4444-4444deadbeef') $$, 'T-01: member can restore a soft-deleted list in their collective' ); SELECT is( (SELECT deleted_at FROM public.shopping_lists WHERE id = 'cccccccc-4444-4444-4444-4444deadbeef'), NULL, 'T-01: deleted_at cleared after restore' ); -- ── Case 2: restore by non-member (Eva) → reject ───────────────────────────── -- Soft-delete it again first UPDATE public.shopping_lists SET deleted_at = now() - interval '1 hour' WHERE id = 'cccccccc-4444-4444-4444-4444deadbeef'; SELECT set_config('request.jwt.claim.sub', '55555555-5555-5555-5555-555555555555', true); -- Eva SELECT throws_ok( $$ SELECT public.restore_list('cccccccc-4444-4444-4444-4444deadbeef') $$, NULL, NULL, 'T-02: non-member rejected' ); -- ── Case 3: hard delete a soft-deleted list (Borja) ────────────────────────── SELECT set_config('request.jwt.claim.sub', '22222222-2222-2222-2222-222222222222', true); SELECT lives_ok( $$ SELECT public.hard_delete_list('cccccccc-4444-4444-4444-4444deadbeef') $$, 'T-03: member can hard-delete a soft-deleted list' ); SELECT is( (SELECT count(*)::int FROM public.shopping_lists WHERE id = 'cccccccc-4444-4444-4444-4444deadbeef'), 0, 'T-03: row gone after hard delete' ); -- ── Case 4: hard delete an active list → rejected (guard) ──────────────────── SELECT throws_ok( $$ SELECT public.hard_delete_list('cccccccc-4444-4444-4444-4444cafebabe') $$, NULL, NULL, 'T-04: hard delete of non-trashed list rejected' ); SELECT * FROM finish(); ROLLBACK;