const fs = require('fs'); const path = require('path'); const sql = fs.readFileSync( path.join(__dirname, '../../supabase/migrations/004_affiliate_tables.sql'), 'utf8' ); describe('Migration 004 — Affiliate Tables', () => { test('creates referral_codes table', () => { expect(sql).toContain('CREATE TABLE IF NOT EXISTS referral_codes'); }); test('creates wallet_addresses table', () => { expect(sql).toContain('CREATE TABLE IF NOT EXISTS wallet_addresses'); }); test('creates referral_conversions table', () => { expect(sql).toContain('CREATE TABLE IF NOT EXISTS referral_conversions'); }); test('creates affiliate_payouts table', () => { expect(sql).toContain('CREATE TABLE IF NOT EXISTS affiliate_payouts'); }); test('referral_codes has unique code constraint', () => { expect(sql).toMatch(/code TEXT NOT NULL UNIQUE/); }); test('referral_codes has affiliate_tier constraint', () => { expect(sql).toMatch(/affiliate_tier.*CHECK.*\(affiliate_tier IN/); }); test('referral_conversions has conversion_type constraint', () => { expect(sql).toMatch(/conversion_type.*CHECK.*\(conversion_type IN.*'signup'.*'upgrade'.*'renewal'/); }); test('referral_conversions has status constraint', () => { expect(sql).toMatch(/status.*CHECK.*\(status IN.*'pending'.*'confirmed'.*'paid'/); }); test('affiliate_payouts has payout_method constraint', () => { expect(sql).toMatch(/payout_method.*CHECK.*\(payout_method IN.*'crypto'.*'paypal'/); }); test('wallet_addresses has chain constraint', () => { expect(sql).toMatch(/chain.*CHECK.*\(chain IN.*'ethereum'.*'solana'/); }); test('RLS enabled on all four tables', () => { expect(sql).toContain('ALTER TABLE referral_codes ENABLE ROW LEVEL SECURITY'); expect(sql).toContain('ALTER TABLE referral_conversions ENABLE ROW LEVEL SECURITY'); expect(sql).toContain('ALTER TABLE affiliate_payouts ENABLE ROW LEVEL SECURITY'); expect(sql).toContain('ALTER TABLE wallet_addresses ENABLE ROW LEVEL SECURITY'); }); test('referral_codes has public read policy', () => { expect(sql).toContain('referral_codes_public_read'); expect(sql).toContain('FOR SELECT USING (true)'); }); test('service role has full access on all tables', () => { expect(sql).toContain('referral_codes_service_write'); expect(sql).toContain('referral_conversions_service_access'); expect(sql).toContain('affiliate_payouts_service_access'); expect(sql).toContain('wallet_addresses_service_access'); }); test('wallet_addresses is created before affiliate_payouts (FK dependency)', () => { const walletPos = sql.indexOf('CREATE TABLE IF NOT EXISTS wallet_addresses'); const payoutsPos = sql.indexOf('CREATE TABLE IF NOT EXISTS affiliate_payouts'); expect(walletPos).toBeLessThan(payoutsPos); }); test('affiliate_payouts references wallet_addresses', () => { expect(sql).toMatch(/wallet_address_id UUID REFERENCES wallet_addresses\(id\)/); }); test('indexes created for key lookup columns', () => { expect(sql).toContain('idx_referral_codes_owner'); expect(sql).toContain('idx_referral_codes_code'); expect(sql).toContain('idx_referral_conversions_code'); expect(sql).toContain('idx_affiliate_payouts_user'); expect(sql).toContain('idx_wallet_addresses_user'); }); });