73 lines
2.5 KiB
Dart
73 lines
2.5 KiB
Dart
|
|
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<MethodCall> 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<SpeechStart> 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<Object?, Object?>)['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' => <Object?>[],
|
||
|
|
'listen' => throw PlatformException(code: 'listenFailed'),
|
||
|
|
_ => null,
|
||
|
|
},
|
||
|
|
);
|
||
|
|
expect(await listen(), SpeechStart.unavailable);
|
||
|
|
});
|
||
|
|
}
|