Files
plezy/test/widgets/video_controls_header_test.dart
T
edde746 f0debe2c32 feat(ui): show a system-format clock on TV home and in the player
The clock renders through the existing formatClockTime helper driven by
MediaQuery.alwaysUse24HourFormatOf, so it follows the OS 12/24-hour
setting instead of introducing an app preference. It re-arms a one-shot
timer onto each wall-clock minute boundary rather than polling, and
resyncs on resume because a suspended process runs no timers.

The player header is shared by the mobile and desktop/TV controls, so one
insertion point covers every form factor: the player is fullscreen
everywhere, so it never has an OS clock to defer to. Home is the
exception and only gets one on TV, where a leanback app hides the system
clock; a phone status bar and a desktop menu bar already show the time.
2026-08-08 10:58:59 +02:00

105 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:plezy/i18n/strings.g.dart';
import 'package:plezy/media/ids.dart';
import 'package:plezy/media/media_item.dart';
import 'package:plezy/services/jellyfin_mappers.dart';
import 'package:plezy/watch_together/providers/watch_together_provider.dart';
import 'package:plezy/widgets/video_controls/widgets/video_controls_header.dart';
import 'package:provider/provider.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
setUpAll(() async {
LocaleSettings.setLocaleSync(AppLocale.en);
await initializeDateFormatting('en');
});
testWidgets('title-less mapped movie builds with localized fallback in both layouts', (tester) async {
final item = _mappedItem({'Id': 'movie-without-name', 'Type': 'Movie'});
for (final style in VideoHeaderStyle.values) {
await _pumpHeader(tester, metadata: item, style: style);
expect(find.text(t.common.unknown), findsOneWidget, reason: style.name);
expect(tester.takeException(), isNull, reason: style.name);
}
});
testWidgets('title-less mapped episode keeps series identity and uses fallback in both layouts', (tester) async {
final item = _mappedItem({
'Id': 'episode-without-name',
'Type': 'Episode',
'SeriesName': 'Mapped Series',
'ParentIndexNumber': 2,
'IndexNumber': 3,
});
for (final style in VideoHeaderStyle.values) {
await _pumpHeader(tester, metadata: item, style: style);
final expectedEpisodeLine = switch (style) {
VideoHeaderStyle.singleLine => 'Mapped Series · S2E3 · ${t.common.unknown}',
VideoHeaderStyle.multiLine => 'S2 · E3 · ${t.common.unknown}',
};
expect(find.text(expectedEpisodeLine), findsOneWidget, reason: style.name);
expect(tester.takeException(), isNull, reason: style.name);
}
});
testWidgets('ordinary mapped episode wording remains unchanged in both layouts', (tester) async {
final item = _mappedItem({
'Id': 'titled-episode',
'Type': 'Episode',
'Name': 'The Arrival',
'SeriesName': 'Mapped Series',
'ParentIndexNumber': 1,
'IndexNumber': 4,
});
for (final style in VideoHeaderStyle.values) {
await _pumpHeader(tester, metadata: item, style: style);
final expectedEpisodeLine = switch (style) {
VideoHeaderStyle.singleLine => 'Mapped Series · S1E4 · The Arrival',
VideoHeaderStyle.multiLine => 'S1 · E4 · The Arrival',
};
expect(find.text(expectedEpisodeLine), findsOneWidget, reason: style.name);
expect(find.text(t.common.unknown), findsNothing, reason: style.name);
}
});
}
MediaItem _mappedItem(Map<String, dynamic> json) {
return JellyfinMappers.mediaItem(
json,
serverId: ServerId('header-test-server'),
serverName: 'Test Server',
absolutizer: null,
)!;
}
Future<void> _pumpHeader(WidgetTester tester, {required MediaItem metadata, required VideoHeaderStyle style}) async {
final watchTogether = WatchTogetherProvider();
addTearDown(watchTogether.dispose);
await tester.pumpWidget(
TranslationProvider(
child: ChangeNotifierProvider<WatchTogetherProvider>.value(
value: watchTogether,
child: MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
body: SizedBox(
width: 900,
child: VideoControlsHeader(metadata: metadata, style: style, onBack: () {}),
),
),
),
),
),
);
}