Introduces shared seams for paginated views, D-pad reorder, media control routing, async singletons and the device method channel, then points the open-coded copies at them. Also removes unused models and duplicated provider/server plumbing, folds the twice-implemented artifact store in the server, and factors the repeated Flutter toolchain prologue in CI into a composite action.
70 lines
2.5 KiB
Dart
70 lines
2.5 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:os_media_controls/os_media_controls.dart';
|
|
import 'package:plezy/services/media_control_router.dart';
|
|
|
|
void main() {
|
|
test('denied playback and media-item commands are consumed without mutation', () {
|
|
var canControl = false;
|
|
var canNavigate = false;
|
|
final calls = <String>[];
|
|
final router = _router(canControl: () => canControl, canNavigate: () => canNavigate, calls: calls);
|
|
|
|
final denied = <MediaControlEvent>[
|
|
const PlayEvent(),
|
|
const PauseEvent(),
|
|
const TogglePlayPauseEvent(),
|
|
const SeekEvent(Duration(seconds: 8)),
|
|
const SkipForwardEvent(Duration(seconds: 10)),
|
|
const SkipBackwardEvent(null),
|
|
const SetSpeedEvent(1.5),
|
|
const NextTrackEvent(),
|
|
const PreviousTrackEvent(),
|
|
];
|
|
for (final event in denied) {
|
|
expect(router.route(event), isTrue, reason: '$event must be consumed');
|
|
}
|
|
expect(calls, isEmpty);
|
|
|
|
expect(router.route(const StopEvent()), isTrue);
|
|
expect(calls, ['stop']);
|
|
|
|
canControl = true;
|
|
for (final event in denied) {
|
|
router.route(event);
|
|
}
|
|
expect(calls, ['stop', 'play', 'pause', 'toggle', 'seek:8', 'forward:10', 'backward:null', 'speed:1.5']);
|
|
|
|
canNavigate = true;
|
|
router.route(const NextTrackEvent());
|
|
router.route(const PreviousTrackEvent());
|
|
expect(calls.sublist(calls.length - 2), ['next', 'previous']);
|
|
});
|
|
|
|
test('unknown lifecycle events are left to the screen lifecycle handler', () {
|
|
final router = _router(canControl: () => false, canNavigate: () => false, calls: []);
|
|
expect(router.route(const AudioInterruptionBeganEvent()), isFalse);
|
|
expect(router.route(const AudioRouteOldDeviceUnavailableEvent()), isFalse);
|
|
});
|
|
}
|
|
|
|
MediaControlRouter _router({
|
|
required bool Function() canControl,
|
|
required bool Function() canNavigate,
|
|
required List<String> calls,
|
|
}) {
|
|
return MediaControlRouter(
|
|
canControlPlayback: canControl,
|
|
canNavigateMediaItems: canNavigate,
|
|
onPlay: () => calls.add('play'),
|
|
onPause: () => calls.add('pause'),
|
|
onTogglePlayPause: () => calls.add('toggle'),
|
|
onSeek: (position) => calls.add('seek:${position.inSeconds}'),
|
|
onNext: () => calls.add('next'),
|
|
onPrevious: () => calls.add('previous'),
|
|
onStop: () => calls.add('stop'),
|
|
onSkipForward: (interval) => calls.add('forward:${interval?.inSeconds}'),
|
|
onSkipBackward: (interval) => calls.add('backward:${interval?.inSeconds}'),
|
|
onSetSpeed: (speed) => calls.add('speed:$speed'),
|
|
);
|
|
}
|