d3ro-voice/server/supabase/tests/mobile-recording-lifecycle.integration.sql
2026-08-29 18:33:45 +09:00

141 lines
4.2 KiB
PL/PgSQL

\set ON_ERROR_STOP on
BEGIN;
CREATE OR REPLACE FUNCTION pg_temp.assert_true(condition boolean, message text)
RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
IF condition IS NOT TRUE THEN
RAISE EXCEPTION 'assertion_failed: %', message;
END IF;
END;
$$;
INSERT INTO auth.users (
id, aud, role, email, encrypted_password, email_confirmed_at,
raw_app_meta_data, raw_user_meta_data, created_at, updated_at
) VALUES
(
'71000000-0000-4000-8000-000000000001', 'authenticated', 'authenticated',
'recording-owner@example.invalid', crypt('fixture-password', gen_salt('bf')), now(),
'{"provider":"email","providers":["email"]}'::jsonb, '{}'::jsonb, now(), now()
),
(
'71000000-0000-4000-8000-000000000002', 'authenticated', 'authenticated',
'recording-other@example.invalid', crypt('fixture-password', gen_salt('bf')), now(),
'{"provider":"email","providers":["email"]}'::jsonb, '{}'::jsonb, now(), now()
);
INSERT INTO public.meetings (id, user_id, title, status)
VALUES (
'72000000-0000-4000-8000-000000000001',
'71000000-0000-4000-8000-000000000001',
'Foreground lifecycle fixture',
'recording'
);
INSERT INTO public.audio_files (
id, user_id, meeting_id, source, original_name, storage_key, mime_type,
size_bytes, duration_ms, sha256, upload_status
) VALUES (
'73000000-0000-4000-8000-000000000001',
'71000000-0000-4000-8000-000000000001',
'72000000-0000-4000-8000-000000000001',
'recording', 'fixture.wav',
'71000000-0000-4000-8000-000000000001/imports/fixture.wav',
'audio/wav', 32044, 1000, repeat('a', 64), 'uploaded'
);
SELECT pg_temp.assert_true(
NOT has_function_privilege('anon', 'public.mobile_begin_meeting_recording(uuid)', 'EXECUTE'),
'anonymous users must not mutate meeting recording state'
);
SET LOCAL ROLE authenticated;
SELECT set_config(
'request.jwt.claims',
'{"sub":"71000000-0000-4000-8000-000000000001","role":"authenticated"}',
true
);
SELECT public.mobile_begin_meeting_recording('72000000-0000-4000-8000-000000000001');
-- Reattach the uploaded fixture after begin_recording intentionally clears stale links.
RESET ROLE;
UPDATE public.audio_files
SET meeting_id = '72000000-0000-4000-8000-000000000001'
WHERE id = '73000000-0000-4000-8000-000000000001';
SET LOCAL ROLE authenticated;
SELECT set_config(
'request.jwt.claims',
'{"sub":"71000000-0000-4000-8000-000000000001","role":"authenticated"}',
true
);
SELECT public.mobile_queue_meeting_recording(
'72000000-0000-4000-8000-000000000001', 1000
);
SELECT public.mobile_begin_meeting_processing(
'72000000-0000-4000-8000-000000000001',
'73000000-0000-4000-8000-000000000001',
'mobile-meeting:fixture:aaaaaaaa'
);
SELECT public.mobile_complete_meeting_processing(
'72000000-0000-4000-8000-000000000001',
'73000000-0000-4000-8000-000000000001',
'mobile-meeting:fixture:aaaaaaaa',
'real mobile audio transcript', 'en', 'fixture-stt', 1000, 120
);
SELECT pg_temp.assert_true(
EXISTS (
SELECT 1 FROM public.meetings
WHERE id = '72000000-0000-4000-8000-000000000001'
AND status = 'completed'
AND raw_transcript = 'real mobile audio transcript'
AND audio_storage_key = '71000000-0000-4000-8000-000000000001/imports/fixture.wav'
),
'meeting completion links the transcript and audio atomically'
);
SELECT pg_temp.assert_true(
EXISTS (
SELECT 1 FROM public.transcripts
WHERE meeting_id = '72000000-0000-4000-8000-000000000001'
AND segment_index = 0
AND text = 'real mobile audio transcript'
),
'meeting transcript segment is persisted'
);
SELECT pg_temp.assert_true(
EXISTS (
SELECT 1 FROM public.processing_jobs
WHERE meeting_id = '72000000-0000-4000-8000-000000000001'
AND audio_file_id = '73000000-0000-4000-8000-000000000001'
AND status = 'succeeded'
AND progress = 100
),
'processing job reaches succeeded only after atomic completion'
);
DO $$
BEGIN
PERFORM set_config(
'request.jwt.claims',
'{"sub":"71000000-0000-4000-8000-000000000002","role":"authenticated"}',
true
);
BEGIN
PERFORM public.mobile_begin_meeting_recording(
'72000000-0000-4000-8000-000000000001'
);
RAISE EXCEPTION 'assertion_failed: another user changed the meeting';
EXCEPTION WHEN insufficient_privilege THEN
NULL;
END;
END;
$$;
RESET ROLE;
ROLLBACK;