import 'dart:math'; import 'package:cyberhybridhub_server/question_source_mix.dart'; import 'package:cyberhybridhub_server/questions_db.dart'; import 'package:test/test.dart'; void main() { group('QuestionSourceMix.pickNextSourceId', () { test('weighted random selection works deterministically with seeded random', () { final Map mix = { 'market_history': 70, 'spelling': 30, }; var marketCount = 0; var spellingCount = 0; final Random random = Random(42); for (var i = 0; i < 200; i++) { final String pick = QuestionSourceMix.pickNextSourceId( effectiveMixPercent: mix, deliveredCounts: {}, random: random, ); if (pick == 'market_history') { marketCount++; } else if (pick == 'spelling') { spellingCount++; } } expect(marketCount, greaterThan(120)); expect(spellingCount, greaterThan(40)); expect(marketCount + spellingCount, 200); }); test('always picks the only active source', () { expect( QuestionSourceMix.pickNextSourceId( effectiveMixPercent: {'spelling': 100}, deliveredCounts: {}, ), 'spelling', ); }); }); group('QuestionSourceMix.orderUnansweredByPreferredSource', () { test('puts preferred source first preserving FIFO within source', () { final List> ordered = QuestionSourceMix.orderUnansweredByPreferredSource( >[ { 'id': 'm1', 'sourceTag': 'market_history:prospective', 'createdAt': '2026-01-01T00:00:00Z', }, { 'id': 's1', 'sourceTag': 'spelling:word_quiz', 'pipelineKey': 'spelling', 'createdAt': '2026-01-02T00:00:00Z', }, { 'id': 'm2', 'sourceTag': 'market_history:prospective', 'createdAt': '2026-01-03T00:00:00Z', }, ], preferredSourceId: 'spelling', ); expect(ordered.map((Map r) => r['id']).toList(), [ 's1', 'm1', 'm2', ]); expect( QuestionsDb.resolveSourceId(ordered.first), 'spelling', ); }); }); }