Some checks failed
Admin portal tests / test (push) Has been cancelled
- Replaced single Postgres Connection with Pool across the server to prevent runTx locking - Added _filterForEnabledSources to client's _fetchUnansweredForPanel to strictly enforce local configuration Co-authored-by: Cursor <cursoragent@cursor.com>
149 lines
4.6 KiB
Dart
149 lines
4.6 KiB
Dart
@Tags(<String>['integration', 'postgres'])
|
|
library;
|
|
|
|
import 'package:cyberhybridhub_server/question_dispatcher.dart';
|
|
import 'package:cyberhybridhub_server/questions_db.dart';
|
|
import 'package:test/test.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(
|
|
'listPanelQuestions excludes market when market_history enabled at ratio 0',
|
|
() async {
|
|
if (testDb == null) {
|
|
markTestSkipped('Set DATABASE_URL or TEST_DATABASE_URL for integration tests');
|
|
return;
|
|
}
|
|
|
|
// The critical scenario: user sets spelling=100%, market stays enabled but
|
|
// ratio=0. A stale market question is already in the DB. The dispatcher
|
|
// must never serve it.
|
|
const String uid = 'spelling-100-market-0-panel-uid';
|
|
await testDb!.seedUser(uid);
|
|
await testDb!.questionSourcePreferencesDb.save(
|
|
uid,
|
|
<Map<String, dynamic>>[
|
|
<String, dynamic>{'id': 'market_history', 'enabled': true, 'ratio': 0},
|
|
<String, dynamic>{'id': 'spelling', 'enabled': true, 'ratio': 100},
|
|
],
|
|
);
|
|
|
|
await testDb!.questionsDb.createQuestion(
|
|
assignedUserId: uid,
|
|
questionText: 'Stale market question',
|
|
correctAnswer: 10,
|
|
sourceTag: 'market_history:prospective',
|
|
pipelineKey: 'trading',
|
|
);
|
|
|
|
final QuestionDispatcher dispatcher = testDb!.questionDispatcher();
|
|
final List<Map<String, dynamic>> panel =
|
|
await dispatcher.listPanelQuestions(uid);
|
|
|
|
expect(panel, isNotEmpty);
|
|
for (final Map<String, dynamic> payload in panel) {
|
|
expect(payload['sourceId'], isNot('market_history'));
|
|
}
|
|
expect(panel.first['sourceId'], 'spelling');
|
|
expect(panel.first['presentation'], 'spelling_word');
|
|
});
|
|
|
|
test('nextQuestionAfterAnswer never returns market when spelling is 100%',
|
|
() async {
|
|
if (testDb == null) {
|
|
markTestSkipped('Set DATABASE_URL or TEST_DATABASE_URL for integration tests');
|
|
return;
|
|
}
|
|
|
|
const String uid = 'spelling-100-next-answer-uid';
|
|
await testDb!.seedUser(uid);
|
|
await testDb!.questionSourcePreferencesDb.save(
|
|
uid,
|
|
<Map<String, dynamic>>[
|
|
<String, dynamic>{'id': 'market_history', 'enabled': true, 'ratio': 0},
|
|
<String, dynamic>{'id': 'spelling', 'enabled': true, 'ratio': 100},
|
|
],
|
|
);
|
|
|
|
// Seed a stale market question that should never surface.
|
|
await testDb!.questionsDb.createQuestion(
|
|
assignedUserId: uid,
|
|
questionText: 'Old market question',
|
|
correctAnswer: 5,
|
|
sourceTag: 'market_history:prospective',
|
|
pipelineKey: 'trading',
|
|
);
|
|
|
|
final QuestionDispatcher dispatcher = testDb!.questionDispatcher();
|
|
|
|
// Simulate the context of "just answered a spelling question".
|
|
final Map<String, dynamic> fakeAnswered = <String, dynamic>{
|
|
'sourceTag': 'spelling:word_quiz',
|
|
'pipelineKey': 'spelling',
|
|
'pipelineStep': 'spelling_word_quiz',
|
|
};
|
|
|
|
final Map<String, dynamic>? next = await dispatcher.nextQuestionAfterAnswer(
|
|
firebaseUid: uid,
|
|
answeredQuestion: fakeAnswered,
|
|
);
|
|
|
|
expect(next, isNotNull);
|
|
expect(next!['sourceId'], isNot('market_history'));
|
|
expect(next['sourceId'], 'spelling');
|
|
});
|
|
|
|
test('listPanelQuestions excludes market when market_history disabled', () async {
|
|
if (testDb == null) {
|
|
markTestSkipped('Set DATABASE_URL or TEST_DATABASE_URL for integration tests');
|
|
return;
|
|
}
|
|
|
|
const String uid = 'spelling-only-panel-uid';
|
|
await testDb!.seedUser(uid);
|
|
await testDb!.questionSourcePreferencesDb.save(
|
|
uid,
|
|
<Map<String, dynamic>>[
|
|
<String, dynamic>{'id': 'market_history', 'enabled': false, 'ratio': 0},
|
|
<String, dynamic>{'id': 'spelling', 'enabled': true, 'ratio': 100},
|
|
],
|
|
);
|
|
|
|
await testDb!.questionsDb.createQuestion(
|
|
assignedUserId: uid,
|
|
questionText: 'Stale market question',
|
|
correctAnswer: 10,
|
|
sourceTag: 'market_history:prospective',
|
|
pipelineKey: 'trading',
|
|
);
|
|
|
|
final QuestionDispatcher dispatcher = testDb!.questionDispatcher();
|
|
final List<Map<String, dynamic>> panel =
|
|
await dispatcher.listPanelQuestions(uid);
|
|
|
|
expect(panel, isNotEmpty);
|
|
for (final Map<String, dynamic> payload in panel) {
|
|
expect(payload['sourceId'], isNot('market_history'));
|
|
}
|
|
expect(panel.first['sourceId'], 'spelling');
|
|
expect(panel.first['presentation'], 'spelling_word');
|
|
});
|
|
}
|