import 'package:halkyon_llm/halkyon_llm.dart'; import 'package:halkyon_llm/testing.dart'; import 'package:test/test.dart'; final _endpoint = LlmEndpoint( protocol: LlmProtocol.openai, model: 'm', apiKey: 'k', ); final _request = LlmRequest( messages: [ LlmMessage.user([const LlmText('?')]), ], maxOutputTokens: 10, ); void main() { group('FakeLlmClient', () { test('answers with the text scripted, in pieces, and keeps what it was ' 'sent', () async { final client = FakeLlmClient()..replyText('Hallo Welt'); final events = await client.send(_endpoint, _request).toList(); expect( events.whereType().map((delta) => delta.text).join(), 'Hallo Welt', ); expect((events.last as LlmFinished).message.text, 'Hallo Welt'); expect(client.sent.single, (_endpoint, _request)); expect(client.allReplied, isTrue); }); test('fails as scripted, with what was counted', () { final client = FakeLlmClient() ..fail( LlmFailureKind.rateLimited, usage: const LlmUsage(inputTokens: 5, outputTokens: 0), ); expect( client.send(_endpoint, _request).toList(), throwsA( isA() .having((f) => f.kind, 'kind', LlmFailureKind.rateLimited) .having((f) => f.usage.inputTokens, 'input', 5), ), ); }); test('counts answers cancelled before they ended', () async { final client = FakeLlmClient()..replyText('Hallo Welt'); await client.send(_endpoint, _request).first; expect(client.cancelled, 1); }); test('refuses a request nothing was scripted for', () { expect( () => FakeLlmClient().send(_endpoint, _request), throwsStateError, ); }); test("refuses an effort the endpoint's host takes not, as HTTP's does", () { final client = FakeLlmClient()..replyText('Hallo'); expect( () => client.send( LlmEndpoint( protocol: LlmProtocol.openai, model: 'm', apiKey: 'k', baseUrl: 'https://api.mistral.ai/v1', ), LlmRequest( messages: _request.messages, maxOutputTokens: 10, effort: LlmEffort.low, ), ), throwsArgumentError, ); expect(client.sent, isEmpty); }); }); }