80 lines
2.1 KiB
Dart
80 lines
2.1 KiB
Dart
@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<String, dynamic> partialOverride = <String, dynamic>{
|
|
'rules': <Map<String, dynamic>>[
|
|
<String, dynamic>{
|
|
'id': 'dip_confirm',
|
|
'threshold_pct': -2.5,
|
|
},
|
|
],
|
|
'data_inputs': <Map<String, dynamic>>[
|
|
<String, dynamic>{
|
|
'id': 'primary_watchlist',
|
|
'symbols': <String>['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, <String>['SPY']);
|
|
expect(effective.dataInputs.single.metrics,
|
|
containsAll(<String>['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);
|
|
});
|
|
}
|