Files
SpotiFLAC-Mobile/test/audio_info_sheet_test.dart
T

164 lines
5.4 KiB
Dart

import 'dart:async';
import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:spotiflac_android/controllers/player_metadata_controller.dart';
import 'package:spotiflac_android/l10n/app_localizations.dart';
import 'package:spotiflac_android/services/audio_route_info.dart';
import 'package:spotiflac_android/widgets/audio_info_sheet.dart';
const _route = MethodChannel('com.zarz.spotiflac/audio_route');
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
tearDown(() {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(_route, null);
});
test('route info tolerates partial platform maps', () {
final info = AudioRouteInfo.fromMap({
'mixerSampleRate': 48000,
'framesPerBuffer': 192,
'device': {
'type': 'usb',
'sampleRates': [48000, 44100, 0],
'mixer': {'sampleRate': 96000, 'bitPerfect': true},
},
'spatializer': {'available': false},
});
expect(info.bufferMs, 4);
expect(info.device?.sampleRates, [48000, 44100]);
expect(info.device?.mixerSampleRate, 96000);
expect(info.device?.mixerBitPerfect, isTrue);
expect(info.spatialAvailable, isFalse);
expect(info.stream, isNull);
});
testWidgets('shows source, signal and resampling to the output device', (
tester,
) async {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(
_route,
(call) async => {
'platform': 'android',
'mixerSampleRate': 48000,
'framesPerBuffer': 96,
'device': {
'type': 'usb',
'name': 'Example DAC',
// A leftover preference must not claim bit-perfect playback.
'mixer': {'sampleRate': 48000, 'bitPerfect': true},
},
},
);
final metadata = PlayerMetadataController();
addTearDown(metadata.dispose);
await metadata.load(
const MediaItem(
id: 'track',
title: 'Track',
extras: {
'source': 'https://example.com/track.flac',
'format': 'flac',
'bit_depth': 24,
'sample_rate': 96000,
},
),
);
await tester.pumpWidget(
MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Builder(
builder: (context) => TextButton(
onPressed: () => showAudioInfoSheet(context, metadata: metadata),
child: const Text('open'),
),
),
),
);
await tester.tap(find.text('open'));
await tester.pumpAndSettle();
expect(find.text('Audio info'), findsOneWidget);
expect(find.text('Hi-Res Lossless'), findsOneWidget);
expect(find.text('96 kHz'), findsOneWidget);
expect(find.text('Up to 48 kHz (Nyquist)'), findsOneWidget);
expect(find.text('144 dB'), findsOneWidget);
expect(find.text('No ReplayGain tags'), findsOneWidget);
await tester.scrollUntilVisible(find.text('96 kHz → 48 kHz'), 200);
expect(find.text('96 kHz → 48 kHz'), findsOneWidget);
expect(find.text('Yes, unaltered samples'), findsNothing);
await tester.scrollUntilVisible(find.text('USB audio · Example DAC'), 200);
await tester.scrollUntilVisible(find.text('2.0 ms · 96 frames'), 200);
expect(find.text('2.0 ms · 96 frames'), findsOneWidget);
});
testWidgets('late route replies cannot replace the latest track snapshot', (
tester,
) async {
final replies = <Completer<Map<String, dynamic>>>[];
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(_route, (call) {
final reply = Completer<Map<String, dynamic>>();
replies.add(reply);
return reply.future;
});
final metadata = PlayerMetadataController();
addTearDown(metadata.dispose);
Future<void> load(String id) => metadata.load(
MediaItem(
id: id,
title: id,
extras: {
'source': 'https://example.test/$id.flac',
'format': 'flac',
'bit_depth': 24,
'sample_rate': 96000,
},
),
);
await load('a');
await tester.pumpWidget(
MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Builder(
builder: (context) => TextButton(
onPressed: () => showAudioInfoSheet(context, metadata: metadata),
child: const Text('open'),
),
),
),
);
await tester.tap(find.text('open'));
await tester.pumpAndSettle();
await load('b');
await tester.pump();
await load('a');
await tester.pump();
expect(replies, hasLength(3));
replies.last.complete({
'mixerSampleRate': 96000,
'device': {'type': 'usb', 'name': 'Current DAC'},
});
await tester.pumpAndSettle();
for (final reply in replies.take(2)) {
reply.complete({
'mixerSampleRate': 48000,
'device': {'type': 'usb', 'name': 'Stale DAC'},
});
}
await tester.pumpAndSettle();
await tester.scrollUntilVisible(find.text('USB audio · Current DAC'), 200);
expect(find.text('USB audio · Stale DAC'), findsNothing);
});
}