BEGIN; SELECT plan(15); -- ============================================================================ -- Setup Test Data -- ============================================================================ DO $$ DECLARE test_user_id uuid := gen_random_uuid(); tablo_no_etapes text; tablo_all_done text; tablo_in_progress text; tablo_mixed text; tablo_empty_etapes text; etape1_id text; etape2_id text; etape3_id text; etape4_id text; etape5_id text; BEGIN -- Insert test user INSERT INTO auth.users (id, instance_id, aud, role, email, encrypted_password, email_confirmed_at, created_at, updated_at) VALUES (test_user_id, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', 'status_test_' || test_user_id::text || '@test.com', 'encrypted', now(), now(), now()) ON CONFLICT DO NOTHING; -- Insert test profile INSERT INTO public.profiles (id, email, first_name, last_name, short_user_id) VALUES (test_user_id, 'status_test_' || test_user_id::text || '@test.com', 'Status', 'Test', substring(test_user_id::text from 1 for 8)) ON CONFLICT DO NOTHING; -- Set JWT context PERFORM set_config('request.jwt.claims', json_build_object('sub', test_user_id::text)::text, true); -- Create test tablos -- Tablo 1: No etapes INSERT INTO public.tablos (owner_id, name, position) VALUES (test_user_id, 'Tablo No Etapes', 0) RETURNING id INTO tablo_no_etapes; -- Tablo 2: All etapes done INSERT INTO public.tablos (owner_id, name, position) VALUES (test_user_id, 'Tablo All Done', 1) RETURNING id INTO tablo_all_done; -- Tablo 3: Has in_progress tasks INSERT INTO public.tablos (owner_id, name, position) VALUES (test_user_id, 'Tablo In Progress', 2) RETURNING id INTO tablo_in_progress; -- Tablo 4: Mixed statuses INSERT INTO public.tablos (owner_id, name, position) VALUES (test_user_id, 'Tablo Mixed', 3) RETURNING id INTO tablo_mixed; -- Tablo 5: Etapes without child tasks INSERT INTO public.tablos (owner_id, name, position) VALUES (test_user_id, 'Tablo Empty Etapes', 4) RETURNING id INTO tablo_empty_etapes; -- Setup Tablo 2: All etapes done -- Etape 1 with all tasks done INSERT INTO public.tasks (tablo_id, title, status, position, is_parent) VALUES (tablo_all_done, 'Etape 1', 'done', 0, true) RETURNING id INTO etape1_id; INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id) VALUES (tablo_all_done, 'Task 1.1', 'done', 0, false, etape1_id), (tablo_all_done, 'Task 1.2', 'done', 1, false, etape1_id); -- Etape 2 with all tasks done INSERT INTO public.tasks (tablo_id, title, status, position, is_parent) VALUES (tablo_all_done, 'Etape 2', 'done', 1, true) RETURNING id INTO etape2_id; INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id) VALUES (tablo_all_done, 'Task 2.1', 'done', 0, false, etape2_id); -- Setup Tablo 3: Has in_progress tasks -- Etape 1 with in_progress task INSERT INTO public.tasks (tablo_id, title, status, position, is_parent) VALUES (tablo_in_progress, 'Etape 1', 'in_progress', 0, true) RETURNING id INTO etape3_id; INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id) VALUES (tablo_in_progress, 'Task 1.1', 'in_progress', 0, false, etape3_id), (tablo_in_progress, 'Task 1.2', 'done', 1, false, etape3_id); -- Setup Tablo 4: Mixed statuses -- Etape 1: all done INSERT INTO public.tasks (tablo_id, title, status, position, is_parent) VALUES (tablo_mixed, 'Etape 1', 'done', 0, true) RETURNING id INTO etape4_id; INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id) VALUES (tablo_mixed, 'Task 1.1', 'done', 0, false, etape4_id); -- Etape 2: has todo tasks (not started) INSERT INTO public.tasks (tablo_id, title, status, position, is_parent) VALUES (tablo_mixed, 'Etape 2', 'todo', 1, true) RETURNING id INTO etape5_id; INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id) VALUES (tablo_mixed, 'Task 2.1', 'todo', 0, false, etape5_id); -- Setup Tablo 5: Empty etapes (no child tasks) INSERT INTO public.tasks (tablo_id, title, status, position, is_parent) VALUES (tablo_empty_etapes, 'Empty Etape 1', 'todo', 0, true), (tablo_empty_etapes, 'Empty Etape 2', 'todo', 1, true); -- Store test IDs PERFORM set_config('test.user_id', test_user_id::text, true); PERFORM set_config('test.tablo_no_etapes', tablo_no_etapes, true); PERFORM set_config('test.tablo_all_done', tablo_all_done, true); PERFORM set_config('test.tablo_in_progress', tablo_in_progress, true); PERFORM set_config('test.tablo_mixed', tablo_mixed, true); PERFORM set_config('test.tablo_empty_etapes', tablo_empty_etapes, true); END $$; -- ============================================================================ -- Test 1: Function exists and is accessible -- ============================================================================ SELECT has_function( 'public', 'compute_tablo_status', ARRAY['text'], 'compute_tablo_status function should exist' ); SELECT function_returns( 'public', 'compute_tablo_status', ARRAY['text'], 'text', 'compute_tablo_status should return text' ); -- ============================================================================ -- Test 2: Tablo with no etapes should return 'todo' -- ============================================================================ SELECT is( public.compute_tablo_status(current_setting('test.tablo_no_etapes')), 'todo', 'Tablo with no etapes should have status "todo"' ); -- ============================================================================ -- Test 3: Tablo with all etapes done should return 'done' -- ============================================================================ SELECT is( public.compute_tablo_status(current_setting('test.tablo_all_done')), 'done', 'Tablo with all etapes completed should have status "done"' ); -- ============================================================================ -- Test 4: Tablo with in_progress tasks should return 'in_progress' -- ============================================================================ SELECT is( public.compute_tablo_status(current_setting('test.tablo_in_progress')), 'in_progress', 'Tablo with tasks in progress should have status "in_progress"' ); -- ============================================================================ -- Test 5: Tablo with mixed etapes (some done, some todo) should return 'in_progress' -- ============================================================================ SELECT is( public.compute_tablo_status(current_setting('test.tablo_mixed')), 'in_progress', 'Tablo with mixed etapes (some done, some todo) should have status "in_progress"' ); -- ============================================================================ -- Test 6: Tablo with empty etapes (no child tasks) should return 'done' -- ============================================================================ SELECT is( public.compute_tablo_status(current_setting('test.tablo_empty_etapes')), 'done', 'Tablo with etapes that have no child tasks should have status "done"' ); -- ============================================================================ -- Test 6.5: Tablo with partial progress (some tasks done, some todo) should return 'in_progress' -- ============================================================================ DO $$ DECLARE partial_tablo_id text; partial_etape_id text; BEGIN -- Create a tablo with partial progress INSERT INTO public.tablos (owner_id, name, position) VALUES (current_setting('test.user_id')::uuid, 'Partial Progress Tablo', 7) RETURNING id INTO partial_tablo_id; -- Create an etape INSERT INTO public.tasks (tablo_id, title, status, position, is_parent) VALUES (partial_tablo_id, 'Partial Etape', 'in_progress', 0, true) RETURNING id INTO partial_etape_id; -- Create multiple tasks with mixed statuses INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id) VALUES (partial_tablo_id, 'Done Task 1', 'done', 0, false, partial_etape_id), (partial_tablo_id, 'Done Task 2', 'done', 1, false, partial_etape_id), (partial_tablo_id, 'Todo Task 1', 'todo', 2, false, partial_etape_id), (partial_tablo_id, 'Todo Task 2', 'todo', 3, false, partial_etape_id); PERFORM set_config('test.partial_tablo', partial_tablo_id, true); END $$; SELECT is( public.compute_tablo_status(current_setting('test.partial_tablo')), 'in_progress', 'Tablo with some tasks done and some todo should have status "in_progress"' ); -- ============================================================================ -- Test 7: Verify status computation in user_tablos view -- ============================================================================ SELECT is( (SELECT status FROM public.user_tablos WHERE id = current_setting('test.tablo_no_etapes')), 'todo', 'user_tablos view should show computed status for tablo with no etapes' ); SELECT is( (SELECT status FROM public.user_tablos WHERE id = current_setting('test.tablo_all_done')), 'done', 'user_tablos view should show computed status for tablo with all done' ); SELECT is( (SELECT status FROM public.user_tablos WHERE id = current_setting('test.tablo_in_progress')), 'in_progress', 'user_tablos view should show computed status for tablo in progress' ); -- ============================================================================ -- Test 8: Test status changes when tasks are updated -- ============================================================================ DO $$ DECLARE test_tablo_id text; test_etape_id text; test_task_id text; BEGIN -- Create a new tablo for dynamic testing INSERT INTO public.tablos (owner_id, name, position) VALUES (current_setting('test.user_id')::uuid, 'Dynamic Test Tablo', 5) RETURNING id INTO test_tablo_id; -- Create an etape INSERT INTO public.tasks (tablo_id, title, status, position, is_parent) VALUES (test_tablo_id, 'Dynamic Etape', 'todo', 0, true) RETURNING id INTO test_etape_id; -- Create a todo task INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id) VALUES (test_tablo_id, 'Dynamic Task', 'todo', 0, false, test_etape_id) RETURNING id INTO test_task_id; -- Store IDs for testing PERFORM set_config('test.dynamic_tablo', test_tablo_id, true); PERFORM set_config('test.dynamic_task', test_task_id, true); END $$; -- Initially should be 'todo' SELECT is( public.compute_tablo_status(current_setting('test.dynamic_tablo')), 'todo', 'New tablo with todo task should have status "todo"' ); -- Update task to in_progress DO $$ BEGIN UPDATE public.tasks SET status = 'in_progress' WHERE id = current_setting('test.dynamic_task'); END $$; SELECT is( public.compute_tablo_status(current_setting('test.dynamic_tablo')), 'in_progress', 'Tablo should change to "in_progress" when task is updated' ); -- Update task to done DO $$ BEGIN UPDATE public.tasks SET status = 'done' WHERE id = current_setting('test.dynamic_task'); END $$; SELECT is( public.compute_tablo_status(current_setting('test.dynamic_tablo')), 'done', 'Tablo should change to "done" when all tasks are completed' ); -- ============================================================================ -- Test 9: Test with tasks in 'in_review' status (should count as in_progress) -- ============================================================================ DO $$ DECLARE review_tablo_id text; review_etape_id text; BEGIN -- Create a tablo with in_review tasks INSERT INTO public.tablos (owner_id, name, position) VALUES (current_setting('test.user_id')::uuid, 'Review Test Tablo', 6) RETURNING id INTO review_tablo_id; -- Create an etape INSERT INTO public.tasks (tablo_id, title, status, position, is_parent) VALUES (review_tablo_id, 'Review Etape', 'in_review', 0, true) RETURNING id INTO review_etape_id; -- Create an in_review task INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id) VALUES (review_tablo_id, 'Review Task', 'in_review', 0, false, review_etape_id); PERFORM set_config('test.review_tablo', review_tablo_id, true); END $$; SELECT is( public.compute_tablo_status(current_setting('test.review_tablo')), 'in_progress', 'Tablo with in_review tasks should have status "in_progress"' ); SELECT * FROM finish(); ROLLBACK;