Shuffle/supabase/tests/database/02_catalog.test.sql
cschlaefke 395816609f feat(db): enforce registration rules and add terms_version
Adds display name validation, terms_version, locale sync trigger and
pgTAP tests (KTO-01 criteria 1, 2, 10, 11). Includes GoTrue spike results.

Refs #1

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-02 22:36:21 +01:00

90 lines
5 KiB
PL/PgSQL

-- Katalog: öffentlich lesbar, private Spiele nur für den Ersteller, Pflege nur durch Admin.
begin;
select plan(19);
-- Beispieldaten aus seed.sql entfernen, damit die Zählungen unten stimmen (wird zurückgerollt)
delete from public.games;
delete from public.genres;
delete from public.mechanics;
delete from public.categories;
insert into auth.users (id, email, raw_user_meta_data) values
('11111111-1111-1111-1111-111111111111', 'anna@example.com', '{"age_confirmed":"true","terms_accepted":"true","terms_version":"test","display_name":"Anna"}'),
('22222222-2222-2222-2222-222222222222', 'ben@example.com', '{"age_confirmed":"true","terms_accepted":"true","terms_version":"test","display_name":"Ben"}');
insert into public.games (id, title, visibility, bgg_id) values
('a0000000-0000-0000-0000-000000000001', 'Catan', 'catalog', 13);
insert into public.games (id, title, visibility, owner_id) values
('a0000000-0000-0000-0000-000000000002', 'Annas Prototyp', 'private', '11111111-1111-1111-1111-111111111111');
insert into public.game_variants (game_id, name) values
('a0000000-0000-0000-0000-000000000001', 'Catan Jubiläum'),
('a0000000-0000-0000-0000-000000000002', 'Prototyp v2');
insert into public.genres (id, name_de, name_en) values
('b0000000-0000-0000-0000-000000000001', 'Strategie', 'Strategy');
-- Constraints (als Superuser)
select throws_ok(
$$insert into public.games (title, visibility, owner_id) values ('X', 'catalog', '11111111-1111-1111-1111-111111111111')$$,
'23514', null, 'Katalogspiel darf keinen Eigentümer haben');
select throws_ok(
$$insert into public.games (title, visibility) values ('X', 'private')$$,
'23514', null, 'Privates Spiel braucht einen Eigentümer');
select throws_ok(
$$insert into public.games (title, visibility, bgg_id) values ('Catan 2', 'catalog', 13)$$,
'23505', null, 'BGG-ID ist im Katalog einmalig');
select throws_ok(
$$insert into public.games (title, visibility, min_players, max_players) values ('Y', 'catalog', 4, 2)$$,
'23514', null, 'Maximale Spielerzahl nicht unter der minimalen');
-- Ohne Anmeldung
set local role anon;
select is((select count(*) from public.games), 1::bigint, 'Besucher sehen nur Katalogspiele');
select is((select count(*) from public.game_variants), 1::bigint, 'Besucher sehen nur Varianten sichtbarer Spiele');
select is((select count(*) from public.genres), 1::bigint, 'Besucher sehen Begriffe');
select throws_ok($$insert into public.games (title, visibility) values ('Z', 'catalog')$$,
'42501', null, 'Besucher können nichts anlegen');
reset role;
-- Anna
select set_config('request.jwt.claims', '{"sub":"11111111-1111-1111-1111-111111111111","role":"authenticated"}', true);
set local role authenticated;
select is((select count(*) from public.games), 2::bigint, 'Anna sieht Katalog und ihr privates Spiel');
select lives_ok(
$$insert into public.games (title, visibility, owner_id, bgg_id) values ('Noch ein Prototyp', 'private', '11111111-1111-1111-1111-111111111111', 13)$$,
'Anna darf ein privates Spiel anlegen, auch mit einer BGG-ID aus dem Katalog');
select throws_ok(
$$insert into public.games (title, visibility) values ('Eigenes Katalogspiel', 'catalog')$$,
'42501', null, 'Anna darf keine Katalogspiele anlegen');
select throws_ok(
$$insert into public.games (title, visibility, owner_id) values ('Fremd', 'private', '22222222-2222-2222-2222-222222222222')$$,
'42501', null, 'Anna darf kein privates Spiel für andere anlegen');
select throws_ok(
$$update public.games set visibility = 'catalog', owner_id = null where id = 'a0000000-0000-0000-0000-000000000002'$$,
'42501', null, 'Anna kann ihr privates Spiel nicht in den Katalog heben');
select is_empty($$update public.games set title = 'Gehackt' where id = 'a0000000-0000-0000-0000-000000000001' returning 1$$,
'Anna kann Katalogspiele nicht ändern');
select throws_ok($$insert into public.genres (name_de, name_en) values ('Neu', 'New')$$,
'42501', null, 'Anna darf keine Begriffe anlegen');
select lives_ok(
$$insert into public.game_genres (game_id, genre_id) values ('a0000000-0000-0000-0000-000000000002', 'b0000000-0000-0000-0000-000000000001')$$,
'Anna darf ihr privates Spiel einem Genre zuordnen');
reset role;
-- Ben
select set_config('request.jwt.claims', '{"sub":"22222222-2222-2222-2222-222222222222","role":"authenticated"}', true);
set local role authenticated;
select is((select count(*) from public.games where owner_id is not null), 0::bigint, 'Ben sieht keine privaten Spiele anderer');
select throws_ok(
$$insert into public.game_genres (game_id, genre_id) values ('a0000000-0000-0000-0000-000000000002', 'b0000000-0000-0000-0000-000000000001')$$,
'42501', null, 'Ben kann fremde private Spiele nicht zuordnen');
reset role;
-- Admin
select set_config('request.jwt.claims', '{"sub":"11111111-1111-1111-1111-111111111111","role":"authenticated","app_metadata":{"role":"admin"}}', true);
set local role authenticated;
select lives_ok($$insert into public.games (title, visibility) values ('Neues Katalogspiel', 'catalog')$$,
'Admin darf Katalogspiele anlegen');
reset role;
select * from finish();
rollback;