diff --git a/kouyu_english/test/live_endpoint_test.dart b/kouyu_english/test/live_endpoint_test.dart index 165e232..f838fb6 100644 --- a/kouyu_english/test/live_endpoint_test.dart +++ b/kouyu_english/test/live_endpoint_test.dart @@ -11,56 +11,74 @@ class RealHttpOverrides extends HttpOverrides { } } +/// 读取联网测试用的配置。密钥只来自环境变量,不写进仓库。 +/// +/// 运行方式: +/// KOUYU_AI_API_KEY=sk-xxx flutter test test/live_endpoint_test.dart +/// 可选:KOUYU_AI_BASE_URL(默认 https://codex.slcydia.fun)、KOUYU_AI_MODEL。 +/// 未设置密钥时整组测试自动跳过,不会误报成功。 +String? _env(String name) { + final value = Platform.environment[name]; + return (value == null || value.trim().isEmpty) ? null : value.trim(); +} + void main() { TestWidgetsFlutterBinding.ensureInitialized(); HttpOverrides.global = RealHttpOverrides(); - const testKey = '***REMOVED***'; - AiService.instance.setFallbackApiKey(testKey); + + final apiKey = _env('KOUYU_AI_API_KEY'); + final baseUrl = _env('KOUYU_AI_BASE_URL') ?? 'https://codex.slcydia.fun'; + final model = _env('KOUYU_AI_MODEL') ?? 'gemini-3.7-flash-high'; + final skipReason = apiKey == null + ? '未设置 KOUYU_AI_API_KEY,跳过联网测试。' + : null; + if (apiKey != null) { + AiService.instance.setFallbackApiKey(apiKey); + } test('Live test: /v1/responses endpoint testConnection', () async { try { final resResponses = await AiService.instance.testConnection( provider: AiProviderType.compatible, - endpoint: 'https://codex.slcydia.fun/v1/responses', - model: 'gemini-3.7-flash-high', - explicitApiKey: testKey, + endpoint: '$baseUrl/v1/responses', + model: model, + explicitApiKey: apiKey, ); print('Responses API result: ok=${resResponses.ok}, msg=${resResponses.message}'); } catch (e) { print('Network test skipped: $e'); } - }); + }, skip: skipReason); test('Live test: /v1 (Chat Completions) endpoint testConnection', () async { try { final resChat = await AiService.instance.testConnection( provider: AiProviderType.compatible, - endpoint: 'https://codex.slcydia.fun/v1', - model: 'gemini-3.7-flash-high', - explicitApiKey: testKey, + endpoint: '$baseUrl/v1', + model: model, + explicitApiKey: apiKey, ); print('Chat Completions API result: ok=${resChat.ok}, msg=${resChat.message}'); } catch (e) { print('Network test skipped: $e'); } - }); + }, skip: skipReason); test('Live test: /v1/responses dialogueReply', timeout: const Timeout(Duration(seconds: 60)), () async { - try { final reply = await AiService.instance.dialogueReply( provider: AiProviderType.compatible, - endpoint: 'https://codex.slcydia.fun/v1/responses', - model: 'gemini-3.7-flash-high', + endpoint: '$baseUrl/v1/responses', + model: model, history: [ {'role': 'user', 'content': 'Hello, my name is Alex.'} ], aiGoal: 'Greet the learner and ask their name', learnerTask: 'say their own name', ); - print('Dialogue reply from /v1/responses: reply="${reply?.reply}", slots=${reply?.slots}, suggestsComplete=${reply?.suggestsComplete}'); + print('Dialogue reply from /v1/responses: reply="${reply?.reply}", translation="${reply?.translation}", feedback="${reply?.feedback}"'); } catch (e) { print('Network test skipped: $e'); } - }); + }, skip: skipReason); }