Files
plezy/test/widgets/setting_tile_test.dart
T
edde746 15b54e2ec6 fix(settings): restore the shared compact row size
Settings rows carried their own platform-conditional typography and
density, so on desktop and TV they rendered a 16px title, 14px subtitle
and 80px row while every other row in the app — the Focusable*ListTile
defaults plus ThemeData.listTileTheme's `dense: true` — renders 13/12
in 61px.

Drop the overrides instead of re-tuning them: the tile defaults already
encode the app's row style, and the explicit title styles were redundant
under a dense ListTile (they also masked the disabled/selected title
color). settingsOptionTitleStyle now only serves group children that are
not ListTiles, and matches the dense title unconditionally.

SettingsGroup hands its children that same compact density, so the plain
ListTiles used as non-interactive info rows stop standing 11px taller
than their interactive siblings.
2026-07-26 21:04:53 +02:00

95 lines
3.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:plezy/theme/mono_theme.dart';
import 'package:plezy/widgets/focusable_list_tile.dart';
import 'package:plezy/widgets/setting_tile.dart';
import 'package:plezy/widgets/settings_section.dart';
/// Settings rows must render exactly like every other row in the app on every
/// platform. Each row type is measured against an untouched [FocusableListTile]
/// — the app-wide reference row — rather than against a hard-coded size, so the
/// assertions still hold if the app's row density is ever retuned.
void main() {
for (final platform in [TargetPlatform.android, TargetPlatform.macOS]) {
testWidgets('settings rows match the standard app row on $platform', (tester) async {
await tester.pumpWidget(_harness(platform));
final referenceTitle = _titleFontSize(tester, 'Clear Cache');
final referenceSubtitle = _subtitleFontSize(tester, 'Clear cached data');
final referenceHeight = tester.getSize(find.byKey(const ValueKey('reference'))).height;
// The dense ListTile title/subtitle sizes; spelled out so a silent
// theme-wide inflation can't make every side of the comparison agree.
expect(referenceTitle, 13);
expect(referenceSubtitle, 12);
for (final title in ['View Logs', 'Enable Thing', 'View Mode', 'Account']) {
expect(_titleFontSize(tester, title), referenceTitle, reason: '$title title size');
}
for (final subtitle in ['View application logs', 'Toggles the thing', 'signed in']) {
expect(_subtitleFontSize(tester, subtitle), referenceSubtitle, reason: '$subtitle subtitle size');
}
for (final key in ['navigation', 'switch', 'plain']) {
expect(tester.getSize(find.byKey(ValueKey(key))).height, referenceHeight, reason: '$key row height');
}
});
}
}
double? _titleFontSize(WidgetTester tester, String text) {
final finder = find.text(text);
final inherited = DefaultTextStyle.of(tester.element(finder)).style;
return inherited.merge(tester.widget<Text>(finder).style).fontSize;
}
double? _subtitleFontSize(WidgetTester tester, String text) =>
DefaultTextStyle.of(tester.element(find.text(text))).style.fontSize;
Widget _harness(TargetPlatform platform) {
return MaterialApp(
theme: monoTheme(dark: false).copyWith(platform: platform),
home: Scaffold(
body: SettingsGroup(
children: [
SettingNavigationTile(
key: const ValueKey('navigation'),
icon: Icons.article,
title: 'View Logs',
subtitle: 'View application logs',
onTap: () {},
),
FocusableListTile(
key: const ValueKey('reference'),
leading: const Icon(Icons.cleaning_services),
title: const Text('Clear Cache'),
subtitle: const Text('Clear cached data'),
trailing: const Icon(Icons.chevron_right),
onTap: () {},
),
FocusableSwitchListTile(
key: const ValueKey('switch'),
secondary: const Icon(Icons.toggle_on),
title: const Text('Enable Thing'),
subtitle: const Text('Toggles the thing'),
value: true,
onChanged: (_) {},
),
SegmentedSetting<String>(
icon: Icons.view_list,
title: 'View Mode',
segments: const [
ButtonSegment(value: 'grid', label: Text('Grid')),
ButtonSegment(value: 'list', label: Text('List')),
],
selected: 'grid',
onChanged: (_) {},
),
// Non-interactive info rows are plain ListTiles; the group hands them
// the same geometry as their interactive siblings.
const ListTile(key: ValueKey('plain'), title: Text('Account'), subtitle: Text('signed in')),
],
),
),
);
}