@Tags(['integration', 'postgres']) library; import 'package:cyberhybridhub_server/trading/trading_config.dart'; import 'package:test/test.dart'; import '../helpers/fixture_loader.dart'; import '../helpers/test_db.dart'; void main() { TestDb? testDb; setUpAll(() async { testDb = await TestDb.open(); }); tearDown(() async { if (testDb != null) { await testDb!.truncateTradingTables(); } }); tearDownAll(() async { await testDb?.close(); }); test('resolveEffectiveConfig merges template and user override', () async { if (testDb == null) { markTestSkipped('Set DATABASE_URL or TEST_DATABASE_URL for integration tests'); return; } const String uid = 'trading-config-merge-uid'; await testDb!.seedUser(uid); final FixtureLoader fixtures = FixtureLoader(); final Map partialOverride = { 'rules': >[ { 'id': 'dip_confirm', 'threshold_pct': -2.5, }, ], 'data_inputs': >[ { 'id': 'primary_watchlist', 'symbols': ['SPY'], }, ], }; // Ensure fixture file is present (smoke for layout). await fixtures.loadJson('trading_config_default.json'); await testDb!.tradingConfigDb.upsertUserConfig( firebaseUid: uid, templateName: 'default_paper_watchlist', config: partialOverride, enabled: true, ); final EffectiveTradingConfig? effective = await testDb!.tradingConfigDb.resolveEffectiveConfig(uid); expect(effective, isNotNull); expect(effective!.enabled, isTrue); expect(effective.dataInputs.single.symbols, ['SPY']); expect(effective.dataInputs.single.metrics, containsAll(['last_trade', 'daily_bar', 'prev_close'])); final TradingRuleConfig rule = effective.rules.singleWhere((TradingRuleConfig r) => r.id == 'dip_confirm'); expect(rule.thresholdPct, -2.5); expect( rule.questionTemplate, contains('Swipe +10'), ); expect(effective.guardrails.maxOrdersPerDay, 3); }); }