feat(realtime): Fase 2b.0 infra + first R-series tests green
Enable postgres_changes broadcasts on shopping_items / shopping_lists and prove the path end-to-end with Vitest Realtime tests and a pgTAP configuration check. Infra changes that were silently blocking events - Migration 007: shopping_items + shopping_lists added to supabase_realtime publication with REPLICA IDENTITY FULL (UPDATE/DELETE payloads need the full row so list_id-based filters work and RLS can evaluate DELETE against OLD) - Realtime service: DB_USER=supabase_admin (superuser; supabase_replication_admin lacks CREATE on the `realtime` schema that the service auto-creates per tenant) - Realtime service: SELF_HOST_TENANT_NAME=realtime so the seed tenant name matches the default supabase-js resolves for localhost URLs (was realtime-dev → TenantNotFound) Tests - pgTAP 004_realtime_publication.sql — P-01..P-04: publication membership and REPLICA IDENTITY FULL for both shopping tables - Vitest realtime-postgres-changes.test.ts — R-01 INSERT broadcast, R-02 UPDATE carries full row, R-03 list_id filter isolates events - test-utils realtime-helpers.ts — subscribePostgresChanges() returns a waitFor(predicate, timeout) helper that captures the SUBSCRIBED handshake before returning so mutations issued right after are not lost - createClientAs now calls realtime.setAuth(token) so the server evaluates RLS against the test user's JWT - Justfile test-db now globs supabase/tests/*.sql so new pgTAP files are picked up automatically Totals: 54→57 Vitest, 12→16 pgTAP, 15 Playwright = 88 tests green. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
55
supabase/tests/004_realtime_publication.sql
Normal file
55
supabase/tests/004_realtime_publication.sql
Normal file
@@ -0,0 +1,55 @@
|
||||
-- pgTAP: Realtime publication + replica identity — Fase 2b prep
|
||||
-- Run with: psql -U postgres -d postgres -f supabase/tests/004_realtime_publication.sql
|
||||
--
|
||||
-- These invariants must hold for Supabase Realtime to forward Postgres Changes
|
||||
-- events for shopping_items / shopping_lists to subscribed clients with the
|
||||
-- correct row payloads. Breaking any of them silently drops events.
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS pgtap;
|
||||
|
||||
BEGIN;
|
||||
SELECT plan(4);
|
||||
|
||||
-- P-01: shopping_items is in the supabase_realtime publication
|
||||
SELECT ok(
|
||||
EXISTS (
|
||||
SELECT 1 FROM pg_publication_tables
|
||||
WHERE pubname = 'supabase_realtime'
|
||||
AND schemaname = 'public'
|
||||
AND tablename = 'shopping_items'
|
||||
),
|
||||
'P-01: shopping_items is part of the supabase_realtime publication'
|
||||
);
|
||||
|
||||
-- P-02: shopping_lists is in the supabase_realtime publication
|
||||
SELECT ok(
|
||||
EXISTS (
|
||||
SELECT 1 FROM pg_publication_tables
|
||||
WHERE pubname = 'supabase_realtime'
|
||||
AND schemaname = 'public'
|
||||
AND tablename = 'shopping_lists'
|
||||
),
|
||||
'P-02: shopping_lists is part of the supabase_realtime publication'
|
||||
);
|
||||
|
||||
-- P-03: shopping_items has REPLICA IDENTITY FULL so UPDATE/DELETE events
|
||||
-- carry the full row (needed for list_id-based client filtering and RLS on DELETE)
|
||||
SELECT results_eq(
|
||||
$$ SELECT relreplident::text FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE n.nspname = 'public' AND c.relname = 'shopping_items' $$,
|
||||
$$ VALUES ('f') $$,
|
||||
'P-03: shopping_items has REPLICA IDENTITY FULL'
|
||||
);
|
||||
|
||||
-- P-04: same for shopping_lists
|
||||
SELECT results_eq(
|
||||
$$ SELECT relreplident::text FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE n.nspname = 'public' AND c.relname = 'shopping_lists' $$,
|
||||
$$ VALUES ('f') $$,
|
||||
'P-04: shopping_lists has REPLICA IDENTITY FULL'
|
||||
);
|
||||
|
||||
SELECT * FROM finish();
|
||||
ROLLBACK;
|
||||
Reference in New Issue
Block a user