import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:halkyon_app/halkyon_app.dart'; /// The device's speech recognition through `speech_to_text`, its platform /// channel answering as Android does: a phone without a recogniser /// installed (GrapheneOS has none) fails with a PlatformException, which /// left the microphone doing nothing and stuck listening (4 Nov 2026). void main() { TestWidgetsFlutterBinding.ensureInitialized(); const channel = MethodChannel('plugin.csdcorp.com/speech_to_text'); late List calls; void answer(Object? Function(MethodCall call) answers) { calls = []; TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMethodCallHandler(channel, (call) async { calls.add(call); return answers(call); }); } tearDown( () => TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMethodCallHandler(channel, null), ); Future listen() => DeviceSpeechInput().listen( language: 'en', onWords: (_) {}, onDone: () => fail('nothing was heard'), ); test('without a recogniser installed, it says so, asking for no ' 'Bluetooth permission', () async { answer( (call) => throw PlatformException( code: 'recognizerNotAvailable', message: 'Speech recognition not available on this device', ), ); expect(await listen(), SpeechStart.noRecognizer); final initialize = calls.single; expect(initialize.method, 'initialize'); expect( (initialize.arguments as Map)['noBluetooth'], isTrue, ); }); test('any other failure, it says it cannot listen now', () async { answer((call) => throw PlatformException(code: 'missingContext')); expect(await listen(), SpeechStart.unavailable); }); test('the microphone refused, it says it cannot listen now', () async { answer((call) => call.method == 'initialize' ? false : null); expect(await listen(), SpeechStart.unavailable); }); // Last: `speech_to_text` keeps one instance, initialised from here on. test('a listen that fails to start says it cannot listen now', () async { answer( (call) => switch (call.method) { 'initialize' => true, 'locales' => [], 'listen' => throw PlatformException(code: 'listenFailed'), _ => null, }, ); expect(await listen(), SpeechStart.unavailable); }); }