Files
noo/test/widgets/noo/noo_test_utils.dart
T
ayushya 72472c771a Make the custom accent-color picker actually retint the app
NooColors (the color source for nearly the whole redesigned UI) only
had two states: the fixed violet palette, or a Material You dynamic
scheme when "Match wallpaper" was on. The 5-swatch custom accent
picker still wrote to SettingsController.seedColor, but nothing read
it back into NooColors - it only reached the underlying Material
ColorScheme, which the Noo-styled UI doesn't use, so every custom
swatch looked identically purple.

Add NooColors.fromSeed, which retints just the accent/accentText/
accentSoft roles from a chosen seed color via ColorScheme.fromSeed
(bg/surface/fg etc. stay the fixed warm-neutral palette, unlike
dynamic color which reshapes everything to match the wallpaper), and
wire it into AppTheme.light/dark. Add a "Default" (Noo violet) swatch
to the picker, and move SettingsController's initial seed color to
that same violet so a fresh install - or any device without dynamic
color - keeps today's look instead of picking up the leftover
Nextcloud-blue default from before seed colors did anything visible.
2026-09-28 13:11:11 -04:00

75 lines
2.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:noo/theme/app_theme.dart';
import 'package:noo/theme/design_tokens.dart';
/// Shared setup for the design-system component tests. Google Fonts can't
/// fetch in the sandbox, so runtime fetching is off (see standards.md
/// "Testing"); the resulting missing-font load errors are async and don't
/// affect layout assertions.
void setUpNooTests() {
setUpAll(() => GoogleFonts.config.allowRuntimeFetching = false);
}
/// Themes built through the real [AppTheme] (non-dynamic), so the
/// [NooColors] extension is registered exactly as in the app. Built lazily
/// inside test bodies - AppTheme touches Google Fonts, which needs the test
/// binding to exist first. Seeded with [AppTheme.defaultAccent] (not just
/// any color) so component tests exercise the exact fixed [NooColors.light]/
/// `.dark` palette their color assertions are written against, rather than
/// a [NooColors.fromSeed] retint - see its doc comment.
ThemeData nooTheme(Brightness brightness) => brightness == Brightness.light
? AppTheme.light(AppTheme.defaultAccent, useDynamicColor: false)
: AppTheme.dark(AppTheme.defaultAccent, useDynamicColor: false);
Future<void> pumpNoo(
WidgetTester tester,
Widget child, {
ThemeData? theme,
Size surfaceSize = const Size(800, 900),
}) async {
await tester.binding.setSurfaceSize(surfaceSize);
addTearDown(() => tester.binding.setSurfaceSize(null));
await tester.pumpWidget(
MaterialApp(
theme: theme ?? nooTheme(Brightness.light),
home: Scaffold(
body: Center(
child: Padding(padding: const EdgeInsets.all(16), child: child),
),
),
),
);
}
/// Runs [body] once per theme, each as its own named test.
void testNooWidgets(
String description,
Future<void> Function(WidgetTester tester, ThemeData theme, NooColors colors)
body,
) {
for (final brightness in Brightness.values) {
testWidgets('$description (${brightness.name})', (tester) async {
final theme = nooTheme(brightness);
await body(tester, theme, theme.extension<NooColors>()!);
});
}
}
/// The nearest colored [BoxDecoration] painted around [finder] (Container
/// and AnimatedContainer both build a [DecoratedBox]).
BoxDecoration decorationOf(WidgetTester tester, Finder finder) {
final boxes = find.ancestor(
of: finder,
matching: find.byWidgetPredicate(
(w) =>
w is DecoratedBox &&
w.decoration is BoxDecoration &&
(w.decoration as BoxDecoration).color != null,
),
matchRoot: true,
);
return tester.widget<DecoratedBox>(boxes.first).decoration as BoxDecoration;
}