cyberhybridhub/server/test/integration/question_source_preferences_test.dart
nathanAndrinoid 4459852f83
Some checks failed
Admin portal tests / test (push) Has been cancelled
spelling
2026-06-05 03:22:35 +00:00

187 lines
5.1 KiB
Dart

@Tags(<String>['integration', 'postgres'])
library;
import 'dart:convert';
import 'package:cyberhybridhub_server/firebase_auth.dart';
import 'package:cyberhybridhub_server/handlers/question_source_handler.dart';
import 'package:cyberhybridhub_server/question_source_preferences_db.dart';
import 'package:cyberhybridhub_server/questions_db.dart';
import 'package:postgres/postgres.dart';
import 'package:shelf/shelf.dart';
import 'package:test/test.dart';
import '../helpers/test_db.dart';
class _FakeAuthVerifier extends FirebaseAuthVerifier {
_FakeAuthVerifier() : super('test-key');
@override
Future<String?> verifyBearerToken(String? authorization) async {
if (authorization == null || !authorization.startsWith('Bearer ')) {
return null;
}
final String token = authorization.substring('Bearer '.length).trim();
return token.isEmpty ? null : token;
}
}
Future<Response> _get(
Handler handler, {
required String path,
String? bearer,
}) {
return Future<Response>.value(
handler(
Request(
'GET',
Uri.parse('http://localhost$path'),
headers: <String, String>{
if (bearer != null) 'Authorization': 'Bearer $bearer',
},
),
),
);
}
Future<Response> _put(
Handler handler, {
required String path,
required Map<String, dynamic> body,
String? bearer,
}) {
return Future<Response>.value(
handler(
Request(
'PUT',
Uri.parse('http://localhost$path'),
body: jsonEncode(body),
headers: <String, String>{
if (bearer != null) 'Authorization': 'Bearer $bearer',
'Content-Type': 'application/json',
},
),
),
);
}
void main() {
TestDb? testDb;
late Handler handler;
late QuestionSourcePreferencesDb preferencesDb;
setUpAll(() async {
testDb = await TestDb.open();
if (testDb == null) {
return;
}
preferencesDb = testDb!.questionSourcePreferencesDb;
handler = questionSourceHandler(
db: preferencesDb,
auth: _FakeAuthVerifier(),
);
});
tearDown(() async {
if (testDb != null) {
await testDb!.truncateTradingTables();
}
});
tearDownAll(() async {
await testDb?.close();
});
test('GET returns defaults for unknown user', () async {
if (testDb == null) {
markTestSkipped('Set DATABASE_URL or TEST_DATABASE_URL for integration tests');
return;
}
final Response response = await _get(
handler,
path: questionSourcesBasePath,
bearer: 'prefs-user',
);
expect(response.statusCode, 200);
final Map<String, dynamic> body =
jsonDecode(await response.readAsString()) as Map<String, dynamic>;
final List<dynamic> sources = body['sources'] as List<dynamic>;
expect(sources.length, 2);
expect(sources.first['id'], 'market_history');
});
test('PUT persists preferences and GET returns saved mix', () async {
if (testDb == null) {
markTestSkipped('Set DATABASE_URL or TEST_DATABASE_URL for integration tests');
return;
}
const String uid = 'prefs-save-user';
await testDb!.seedUser(uid);
final Response putResponse = await _put(
handler,
path: questionSourcesBasePath,
bearer: uid,
body: <String, dynamic>{
'sources': <Map<String, dynamic>>[
<String, dynamic>{'id': 'market_history', 'enabled': true, 'ratio': 80},
<String, dynamic>{'id': 'spelling', 'enabled': false, 'ratio': 20},
],
},
);
expect(putResponse.statusCode, 200);
final Response getResponse = await _get(
handler,
path: questionSourcesBasePath,
bearer: uid,
);
expect(getResponse.statusCode, 200);
final Map<String, dynamic> body =
jsonDecode(await getResponse.readAsString()) as Map<String, dynamic>;
final List<dynamic> sources = body['sources'] as List<dynamic>;
final Map<String, dynamic> market = sources.firstWhere(
(dynamic source) => source['id'] == 'market_history',
) as Map<String, dynamic>;
expect(market['ratio'], 80);
});
test('ensureProspectiveQuestionQueued skips batch when market_history disabled',
() async {
if (testDb == null) {
markTestSkipped('Set DATABASE_URL or TEST_DATABASE_URL for integration tests');
return;
}
const String uid = 'prefs-disabled-market-user';
await testDb!.seedUser(uid);
await preferencesDb.save(
uid,
<Map<String, dynamic>>[
<String, dynamic>{'id': 'market_history', 'enabled': false, 'ratio': 50},
<String, dynamic>{'id': 'spelling', 'enabled': false, 'ratio': 50},
],
);
final QuestionsDb questionsDb = testDb!.questionsDb;
final service = testDb!.questionService();
await questionsDb.ensureUserExists(uid);
await service.ensureProspectiveQuestionQueued(uid);
final Result rows = await testDb!.connection.execute(
Sql.named(
'''
SELECT COUNT(*)::int
FROM questions
WHERE assigned_user_id = @uid
''',
),
parameters: <String, dynamic>{'uid': uid},
);
expect(rows.first[0], 0);
});
}