-- pgTAP: item_frequency.weight + set_item_frequency_weight + purge_item_frequency -- (Fase 15.1) -- Run with: psql -U postgres -d postgres -f supabase/tests/018_item_frequency_weight.sql -- -- Schema invariants for the new weight column and the two SECURITY DEFINER -- RPCs that gate writes (admin-only). Behavioural denial-for-non-admin runs -- via the postgres superuser here, so we cannot exercise the role gate from -- inside pgTAP (postgres bypasses the function's `auth.uid()` check by -- returning NULL); the role-gate behaviour for member / guest is covered by -- the Vitest integration suite (common-items.test.ts). CREATE EXTENSION IF NOT EXISTS pgtap; BEGIN; SELECT plan(11); -- ── Schema invariants ─────────────────────────────────────────────────────── SELECT has_column( 'public', 'item_frequency', 'weight', 'IFW-T01: item_frequency.weight column exists' ); SELECT col_type_is( 'public', 'item_frequency', 'weight', 'integer', 'IFW-T02: item_frequency.weight is integer' ); SELECT col_not_null( 'public', 'item_frequency', 'weight', 'IFW-T03: item_frequency.weight is NOT NULL' ); SELECT col_default_is( 'public', 'item_frequency', 'weight', '0', 'IFW-T04: item_frequency.weight defaults to 0' ); -- IFW-T05: the suggestion ordering index includes weight first. SELECT ok( EXISTS ( SELECT 1 FROM pg_indexes WHERE schemaname = 'public' AND tablename = 'item_frequency' AND indexname = 'item_frequency_collective_order_idx' ), 'IFW-T05: item_frequency_collective_order_idx exists' ); -- IFW-T06: the old index name is gone (replaced by the order-idx above). SELECT ok( NOT EXISTS ( SELECT 1 FROM pg_indexes WHERE schemaname = 'public' AND tablename = 'item_frequency' AND indexname = 'item_frequency_collective_count_idx' ), 'IFW-T06: old item_frequency_collective_count_idx was dropped' ); -- ── RPC existence + SECURITY DEFINER posture ─────────────────────────────── SELECT has_function( 'public', 'set_item_frequency_weight', ARRAY['uuid', 'text', 'integer'], 'IFW-T07: set_item_frequency_weight(uuid, text, integer) exists' ); SELECT has_function( 'public', 'purge_item_frequency', ARRAY['uuid', 'text'], 'IFW-T08: purge_item_frequency(uuid, text) exists' ); SELECT ok( (SELECT prosecdef FROM pg_proc WHERE proname = 'set_item_frequency_weight' AND pronamespace = 'public'::regnamespace), 'IFW-T09: set_item_frequency_weight is SECURITY DEFINER' ); SELECT ok( (SELECT prosecdef FROM pg_proc WHERE proname = 'purge_item_frequency' AND pronamespace = 'public'::regnamespace), 'IFW-T10: purge_item_frequency is SECURITY DEFINER' ); -- ── Behaviour: trigger-inserted row gets weight=0 default ─────────────────── -- The existing trigger only writes (collective_id, name, use_count, last_used_at) -- so the new weight column must take the column default. INSERT INTO public.shopping_items (list_id, name, sort_order, created_by) VALUES ( 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'IFW-trigger-default-item', 9001, '11111111-1111-1111-1111-111111111111' ); SELECT is( (SELECT weight FROM public.item_frequency WHERE collective_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' AND name = 'ifw-trigger-default-item'), 0, 'IFW-T11: trigger-inserted item_frequency row gets weight=0 default' ); SELECT * FROM finish(); ROLLBACK;