123 lines
3.1 KiB
Dart
123 lines
3.1 KiB
Dart
@Tags(['integration', 'postgres'])
|
|
library;
|
|
|
|
import 'package:cyberhybridhub_server/trading/trade_orders_db.dart';
|
|
import 'package:postgres/postgres.dart';
|
|
import 'package:test/test.dart';
|
|
import 'package:uuid/uuid.dart';
|
|
|
|
import '../helpers/test_db.dart';
|
|
|
|
void main() {
|
|
const Uuid uuid = Uuid();
|
|
TestDb? testDb;
|
|
|
|
setUpAll(() async {
|
|
testDb = await TestDb.open();
|
|
});
|
|
|
|
tearDown(() async {
|
|
if (testDb != null) {
|
|
await testDb!.truncateTradingTables();
|
|
}
|
|
});
|
|
|
|
tearDownAll(() async {
|
|
await testDb?.close();
|
|
});
|
|
|
|
test('duplicate client_order_id returns existing row without second insert',
|
|
() async {
|
|
if (testDb == null) {
|
|
markTestSkipped('Set DATABASE_URL or TEST_DATABASE_URL for integration tests');
|
|
return;
|
|
}
|
|
|
|
const String uid = 'trade-orders-idempotency-uid';
|
|
await testDb!.seedUser(uid);
|
|
final String clientOrderId = 'test-${uuid.v4()}';
|
|
|
|
final TradeOrder first = await testDb!.tradeOrdersDb.insertOrder(
|
|
firebaseUid: uid,
|
|
clientOrderId: clientOrderId,
|
|
symbol: 'SPY',
|
|
side: 'buy',
|
|
orderType: 'market',
|
|
status: 'pending',
|
|
notionalUsd: 10,
|
|
ruleId: 'dip_confirm',
|
|
);
|
|
|
|
final TradeOrder second = await testDb!.tradeOrdersDb.insertOrder(
|
|
firebaseUid: uid,
|
|
clientOrderId: clientOrderId,
|
|
symbol: 'SPY',
|
|
side: 'buy',
|
|
orderType: 'market',
|
|
status: 'pending',
|
|
notionalUsd: 99,
|
|
);
|
|
|
|
expect(second.id, first.id);
|
|
expect(second.notionalUsd, 10);
|
|
|
|
final Result count = await testDb!.connection.execute(
|
|
Sql.named(
|
|
'SELECT COUNT(*)::int FROM trade_orders WHERE client_order_id = @id',
|
|
),
|
|
parameters: <String, dynamic>{'id': clientOrderId},
|
|
);
|
|
expect((count.first[0]! as num).toInt(), 1);
|
|
});
|
|
|
|
test('raw insert with duplicate client_order_id raises unique violation',
|
|
() async {
|
|
if (testDb == null) {
|
|
markTestSkipped('Set DATABASE_URL or TEST_DATABASE_URL for integration tests');
|
|
return;
|
|
}
|
|
|
|
const String uid = 'trade-orders-unique-uid';
|
|
await testDb!.seedUser(uid);
|
|
final String clientOrderId = 'dup-${uuid.v4()}';
|
|
final String orderId = uuid.v4();
|
|
|
|
await testDb!.connection.execute(
|
|
Sql.named(
|
|
'''
|
|
INSERT INTO trade_orders (
|
|
id, firebase_uid, client_order_id, symbol, side, order_type, status
|
|
) VALUES (
|
|
@id::uuid, @uid, @client_order_id, 'SPY', 'buy', 'market', 'pending'
|
|
)
|
|
''',
|
|
),
|
|
parameters: <String, dynamic>{
|
|
'id': orderId,
|
|
'uid': uid,
|
|
'client_order_id': clientOrderId,
|
|
},
|
|
);
|
|
|
|
await expectLater(
|
|
testDb!.connection.execute(
|
|
Sql.named(
|
|
'''
|
|
INSERT INTO trade_orders (
|
|
id, firebase_uid, client_order_id, symbol, side, order_type, status
|
|
) VALUES (
|
|
@id::uuid, @uid, @client_order_id, 'SPY', 'buy', 'market', 'pending'
|
|
)
|
|
''',
|
|
),
|
|
parameters: <String, dynamic>{
|
|
'id': uuid.v4(),
|
|
'uid': uid,
|
|
'client_order_id': clientOrderId,
|
|
},
|
|
),
|
|
throwsA(isA<ServerException>()),
|
|
);
|
|
});
|
|
}
|