xtablo-source/supabase/tests/database/05_triggers.test.sql
2025-11-04 22:20:56 +01:00

303 lines
10 KiB
PL/PgSQL

begin;
select plan(28); -- Total number of tests
-- ============================================================================
-- Trigger Function Existence Tests
-- ============================================================================
SELECT has_function('public', 'create_tablo_access_for_owner',
'Function create_tablo_access_for_owner should exist');
SELECT has_function('public', 'create_last_signed_in_on_profiles',
'Function create_last_signed_in_on_profiles should exist');
SELECT has_function('public', 'update_tablo_invites_on_login',
'Function update_tablo_invites_on_login should exist');
SELECT has_function('public', 'update_profile_subscription_status',
'Function update_profile_subscription_status should exist');
-- ============================================================================
-- Trigger Existence Tests
-- ============================================================================
SELECT has_trigger('public', 'tablos', 'trigger_create_tablo_access',
'Trigger trigger_create_tablo_access should exist on tablos table');
SELECT has_trigger('auth', 'users', 'trigger_on_last_signed_in',
'Trigger trigger_on_last_signed_in should exist on auth.users table');
SELECT has_trigger('auth', 'users', 'trigger_update_tablo_invites_on_login',
'Trigger trigger_update_tablo_invites_on_login should exist on auth.users table');
-- Stripe triggers
SELECT ok(
(SELECT COUNT(*) FROM information_schema.triggers
WHERE trigger_name = 'update_profile_on_subscription_change'
AND event_object_schema = 'stripe') > 0,
'Trigger update_profile_on_subscription_change should exist on stripe schema'
);
-- ============================================================================
-- Tablo Access Trigger Tests
-- ============================================================================
-- Create test user and tablo to trigger auto-creation of tablo_access
DO $$
DECLARE
trigger_user_id uuid := gen_random_uuid();
trigger_tablo_id integer;
BEGIN
-- Insert test user
INSERT INTO auth.users (id, instance_id, aud, role, email, encrypted_password, email_confirmed_at, created_at, updated_at)
VALUES
(trigger_user_id, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', 'triggeruser@test.com', 'encrypted', now(), now(), now());
-- Insert test profile
INSERT INTO public.profiles (id, email, first_name, last_name)
VALUES
(trigger_user_id, 'triggeruser@test.com', 'Trigger', 'User');
-- Insert tablo (this should trigger auto-creation of tablo_access)
INSERT INTO public.tablos (owner_id, name, status, position)
VALUES
(trigger_user_id, 'Trigger Test Tablo', 'todo', 0)
RETURNING id INTO trigger_tablo_id;
-- Store test IDs
PERFORM set_config('test.trigger_user_id', trigger_user_id::text, true);
PERFORM set_config('test.trigger_tablo_id', trigger_tablo_id::text, true);
END $$;
-- Test: Verify tablo_access was auto-created
SELECT is(
(
SELECT count(*)::integer
FROM public.tablo_access
WHERE tablo_id = current_setting('test.trigger_tablo_id')::integer
AND user_id = current_setting('test.trigger_user_id')::uuid
),
1,
'Tablo access should be auto-created when tablo is created'
);
-- Test: Verify tablo_access has correct fields
SELECT is(
(
SELECT is_active
FROM public.tablo_access
WHERE tablo_id = current_setting('test.trigger_tablo_id')::integer
AND user_id = current_setting('test.trigger_user_id')::uuid
LIMIT 1
),
true,
'Auto-created tablo access should be active'
);
SELECT is(
(
SELECT is_admin
FROM public.tablo_access
WHERE tablo_id = current_setting('test.trigger_tablo_id')::integer
AND user_id = current_setting('test.trigger_user_id')::uuid
LIMIT 1
),
true,
'Auto-created tablo access should have admin privileges'
);
SELECT is(
(
SELECT granted_by
FROM public.tablo_access
WHERE tablo_id = current_setting('test.trigger_tablo_id')::integer
AND user_id = current_setting('test.trigger_user_id')::uuid
LIMIT 1
),
current_setting('test.trigger_user_id')::uuid,
'Auto-created tablo access should be granted by owner'
);
-- ============================================================================
-- Last Signed In Trigger Tests
-- ============================================================================
-- Create test user with last_sign_in_at
DO $$
DECLARE
signin_user_id uuid := gen_random_uuid();
test_signin_time timestamp with time zone := now();
BEGIN
-- Insert test user
INSERT INTO auth.users (id, instance_id, aud, role, email, encrypted_password, email_confirmed_at, last_sign_in_at, created_at, updated_at)
VALUES
(signin_user_id, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', 'signinuser@test.com', 'encrypted', now(), test_signin_time, now(), now());
-- Insert test profile
INSERT INTO public.profiles (id, email, first_name, last_name)
VALUES
(signin_user_id, 'signinuser@test.com', 'SignIn', 'User');
-- Store test IDs
PERFORM set_config('test.signin_user_id', signin_user_id::text, true);
PERFORM set_config('test.signin_time', test_signin_time::text, true);
END $$;
-- Test: Update last_sign_in_at on auth.users (simulating a sign-in)
DO $$
DECLARE
new_signin_time timestamp with time zone := now() + interval '1 hour';
BEGIN
UPDATE auth.users
SET last_sign_in_at = new_signin_time,
updated_at = now()
WHERE id = current_setting('test.signin_user_id')::uuid;
PERFORM set_config('test.new_signin_time', new_signin_time::text, true);
END $$;
-- Test: Verify last_signed_in was updated in profiles
SELECT ok(
(
SELECT last_signed_in
FROM public.profiles
WHERE id = current_setting('test.signin_user_id')::uuid
) IS NOT NULL,
'Profile last_signed_in should be updated after auth.users sign in'
);
-- ============================================================================
-- Tablo Invites Trigger Tests
-- ============================================================================
-- Create test temporary user and invite
DO $$
DECLARE
temp_user_id uuid := gen_random_uuid();
temp_user_email text := 'tempuser@test.com';
invite_tablo_id integer;
BEGIN
-- Insert test user (will be marked as temporary)
INSERT INTO auth.users (id, instance_id, aud, role, email, encrypted_password, email_confirmed_at, created_at, updated_at)
VALUES
(temp_user_id, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', temp_user_email, 'encrypted', now(), now(), now());
-- Insert test profile marked as temporary
INSERT INTO public.profiles (id, email, first_name, last_name, is_temporary)
VALUES
(temp_user_id, temp_user_email, 'Temp', 'User', true);
-- Create a tablo for invites
INSERT INTO public.tablos (owner_id, name, status, position)
VALUES
(temp_user_id, 'Invite Test Tablo', 'todo', 0)
RETURNING id INTO invite_tablo_id;
-- Create pending invite for this user's email
INSERT INTO public.tablo_invites (tablo_id, invited_email, invited_by, invite_token, is_pending)
VALUES
(invite_tablo_id, temp_user_email, temp_user_id, 'temp-user-token', true);
-- Store test IDs
PERFORM set_config('test.temp_user_id', temp_user_id::text, true);
PERFORM set_config('test.temp_user_email', temp_user_email, true);
END $$;
-- Test: Verify invite is initially pending
SELECT is(
(
SELECT is_pending
FROM public.tablo_invites
WHERE invited_email = current_setting('test.temp_user_email')
AND invite_token = 'temp-user-token'
LIMIT 1
),
true,
'Invite should be initially pending'
);
-- Test: Simulate sign-in to trigger invite update
DO $$
BEGIN
UPDATE auth.users
SET last_sign_in_at = now(),
updated_at = now()
WHERE id = current_setting('test.temp_user_id')::uuid;
END $$;
-- Test: Verify invite is_pending was set to false after sign-in
SELECT is(
(
SELECT is_pending
FROM public.tablo_invites
WHERE invited_email = current_setting('test.temp_user_email')
AND invite_token = 'temp-user-token'
LIMIT 1
),
false,
'Invite should be marked as not pending after temporary user signs in'
);
-- ============================================================================
-- Trigger Timing Tests
-- ============================================================================
-- Test that tablo access trigger fires AFTER INSERT
SELECT trigger_is(
'public', 'tablos', 'trigger_create_tablo_access',
'public', 'create_tablo_access_for_owner',
'Tablo access trigger should fire after insert'
);
-- ============================================================================
-- Security Tests
-- ============================================================================
-- Test that trigger functions are SECURITY DEFINER
SELECT is(
(
SELECT prosecdef
FROM pg_proc
WHERE proname = 'create_tablo_access_for_owner'
LIMIT 1
),
true,
'create_tablo_access_for_owner should be SECURITY DEFINER'
);
SELECT is(
(
SELECT prosecdef
FROM pg_proc
WHERE proname = 'create_last_signed_in_on_profiles'
LIMIT 1
),
true,
'create_last_signed_in_on_profiles should be SECURITY DEFINER'
);
SELECT is(
(
SELECT prosecdef
FROM pg_proc
WHERE proname = 'update_tablo_invites_on_login'
LIMIT 1
),
true,
'update_tablo_invites_on_login should be SECURITY DEFINER'
);
SELECT is(
(
SELECT prosecdef
FROM pg_proc
WHERE proname = 'update_profile_subscription_status'
LIMIT 1
),
true,
'update_profile_subscription_status should be SECURITY DEFINER'
);
select * from finish();
rollback;