toBeTrue(); expect(Schema::hasColumns('client_tg_campaigns', [ 'tenant_id', 'status', 'ad_text', 'ad_link', 'media_path', 'ord_category', 'budget_cap_rub', 'audience_kind', 'audience_params', 'matched_count', 'created_by', ]))->toBeTrue(); }); it('creates client_tg_campaign_phones with expected columns', function () { expect(Schema::hasTable('client_tg_campaign_phones'))->toBeTrue(); expect(Schema::hasColumns('client_tg_campaign_phones', [ 'tenant_id', 'campaign_id', 'phone', 'expires_at', ]))->toBeTrue(); }); it('creates client_tg_optouts with expected columns', function () { expect(Schema::hasTable('client_tg_optouts'))->toBeTrue(); expect(Schema::hasColumns('client_tg_optouts', [ 'tenant_id', 'phone', ]))->toBeTrue(); }); it('creates client_tg_contacts with expected columns', function () { expect(Schema::hasTable('client_tg_contacts'))->toBeTrue(); expect(Schema::hasColumns('client_tg_contacts', [ 'tenant_id', 'phone', 'name', 'operator', ]))->toBeTrue(); }); it('creates client_tg_tariffs with expected columns and seeds exactly 5 rows', function () { expect(Schema::hasTable('client_tg_tariffs'))->toBeTrue(); expect(Schema::hasColumns('client_tg_tariffs', [ 'min_qty', 'price_rub', ]))->toBeTrue(); expect(DB::table('client_tg_tariffs')->count())->toBe(5); }); it('enables row level security on client_tg_campaigns with a tenant_isolation policy', function () { $rls = DB::selectOne("SELECT relrowsecurity FROM pg_class WHERE relname = 'client_tg_campaigns'"); expect((bool) $rls->relrowsecurity)->toBeTrue(); $policyExists = DB::table('pg_policies') ->where('tablename', 'client_tg_campaigns') ->where('policyname', 'tenant_isolation') ->exists(); expect($policyExists)->toBeTrue(); });