blob: 2dc11cf4f150f94af0547724e8a660786baa0d53 [file] [log] [blame]
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('SearchViewThemeData copyWith, ==, hashCode basics', () {
expect(const SearchViewThemeData(), const SearchViewThemeData().copyWith());
expect(const SearchViewThemeData().hashCode, const SearchViewThemeData().copyWith().hashCode);
});
test('SearchViewThemeData lerp special cases', () {
expect(SearchViewThemeData.lerp(null, null, 0), null);
const data = SearchViewThemeData();
expect(identical(SearchViewThemeData.lerp(data, data, 0.5), data), true);
});
test('SearchViewThemeData defaults', () {
const themeData = SearchViewThemeData();
expect(themeData.backgroundColor, null);
expect(themeData.elevation, null);
expect(themeData.surfaceTintColor, null);
expect(themeData.constraints, null);
expect(themeData.side, null);
expect(themeData.shape, null);
expect(themeData.headerHeight, null);
expect(themeData.headerTextStyle, null);
expect(themeData.headerHintStyle, null);
expect(themeData.padding, null);
expect(themeData.barPadding, null);
expect(themeData.shrinkWrap, null);
expect(themeData.dividerColor, null);
const theme = SearchViewTheme(data: SearchViewThemeData(), child: SizedBox());
expect(theme.data.backgroundColor, null);
expect(theme.data.elevation, null);
expect(theme.data.surfaceTintColor, null);
expect(theme.data.constraints, null);
expect(theme.data.side, null);
expect(theme.data.shape, null);
expect(theme.data.headerHeight, null);
expect(theme.data.headerTextStyle, null);
expect(theme.data.headerHintStyle, null);
expect(themeData.padding, null);
expect(themeData.barPadding, null);
expect(themeData.shrinkWrap, null);
expect(theme.data.dividerColor, null);
});
testWidgets('Default SearchViewThemeData debugFillProperties', (WidgetTester tester) async {
final builder = DiagnosticPropertiesBuilder();
const SearchViewThemeData().debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString())
.toList();
expect(description, <String>[]);
});
testWidgets('SearchViewThemeData implements debugFillProperties', (WidgetTester tester) async {
final builder = DiagnosticPropertiesBuilder();
const SearchViewThemeData(
backgroundColor: Color(0xfffffff1),
elevation: 3.5,
surfaceTintColor: Color(0xfffffff3),
side: BorderSide(width: 2.5, color: Color(0xfffffff5)),
shape: RoundedRectangleBorder(),
headerHeight: 35.5,
headerTextStyle: TextStyle(fontSize: 24.0),
headerHintStyle: TextStyle(fontSize: 16.0),
constraints: BoxConstraints(minWidth: 350, minHeight: 240),
padding: EdgeInsets.only(bottom: 32.0),
barPadding: EdgeInsets.zero,
shrinkWrap: true,
).debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString())
.toList();
expect(description[0], 'backgroundColor: ${const Color(0xfffffff1)}');
expect(description[1], 'elevation: 3.5');
expect(description[2], 'surfaceTintColor: ${const Color(0xfffffff3)}');
expect(description[3], 'side: BorderSide(color: ${const Color(0xfffffff5)}, width: 2.5)');
expect(
description[4],
'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)',
);
expect(description[5], 'headerHeight: 35.5');
expect(description[6], 'headerTextStyle: TextStyle(inherit: true, size: 24.0)');
expect(description[7], 'headerHintStyle: TextStyle(inherit: true, size: 16.0)');
expect(description[8], 'constraints: BoxConstraints(350.0<=w<=Infinity, 240.0<=h<=Infinity)');
expect(description[9], 'padding: EdgeInsets(0.0, 0.0, 0.0, 32.0)');
expect(description[10], 'barPadding: EdgeInsets.zero');
expect(description[11], 'shrinkWrap: true');
});
group('[Theme, SearchViewTheme, SearchView properties overrides]', () {
const backgroundColor = Color(0xff000001);
const elevation = 5.0;
const surfaceTintColor = Color(0xff000002);
const side = BorderSide(color: Color(0xff000003), width: 2.0);
const OutlinedBorder shape = RoundedRectangleBorder(
side: side,
borderRadius: BorderRadius.all(Radius.circular(20.0)),
);
const headerHeight = 45.0;
const headerTextStyle = TextStyle(color: Color(0xff000004), fontSize: 20.0);
const headerHintStyle = TextStyle(color: Color(0xff000005), fontSize: 18.0);
const constraints = BoxConstraints(minWidth: 250.0, maxWidth: 300.0, minHeight: 450.0);
const searchViewTheme = SearchViewThemeData(
backgroundColor: backgroundColor,
elevation: elevation,
surfaceTintColor: surfaceTintColor,
side: side,
shape: shape,
headerHeight: headerHeight,
headerTextStyle: headerTextStyle,
headerHintStyle: headerHintStyle,
constraints: constraints,
);
Widget buildFrame({
bool useSearchViewProperties = false,
SearchViewThemeData? searchViewThemeData,
SearchViewThemeData? overallTheme,
}) {
final Widget child = Builder(
builder: (BuildContext context) {
if (!useSearchViewProperties) {
return SearchAnchor(
viewHintText: 'hint text',
builder: (BuildContext context, SearchController controller) {
return const Icon(Icons.search);
},
suggestionsBuilder: (BuildContext context, SearchController controller) {
return <Widget>[];
},
isFullScreen: false,
);
}
return SearchAnchor(
viewHintText: 'hint text',
builder: (BuildContext context, SearchController controller) {
return const Icon(Icons.search);
},
suggestionsBuilder: (BuildContext context, SearchController controller) {
return <Widget>[];
},
isFullScreen: false,
viewElevation: elevation,
viewBackgroundColor: backgroundColor,
viewSurfaceTintColor: surfaceTintColor,
viewSide: side,
viewShape: shape,
headerHeight: headerHeight,
headerTextStyle: headerTextStyle,
headerHintStyle: headerHintStyle,
viewConstraints: constraints,
);
},
);
return MaterialApp(
theme: ThemeData.from(
colorScheme: const ColorScheme.light(),
).copyWith(searchViewTheme: overallTheme),
home: Scaffold(
body: Center(
// If the SearchViewThemeData widget is present, it's used
// instead of the Theme's ThemeData.searchViewTheme.
child: searchViewThemeData == null
? child
: SearchViewTheme(data: searchViewThemeData, child: child),
),
),
);
}
Finder findViewContent() {
return find.byWidgetPredicate((Widget widget) {
return widget.runtimeType.toString() == '_ViewContent';
});
}
Material getSearchViewMaterial(WidgetTester tester) {
return tester.widget<Material>(
find.descendant(of: findViewContent(), matching: find.byType(Material)).first,
);
}
Future<void> checkSearchView(WidgetTester tester) async {
final Material material = getSearchViewMaterial(tester);
expect(material.elevation, elevation);
expect(material.color, backgroundColor);
expect(material.surfaceTintColor, surfaceTintColor);
expect(material.shape, shape);
final Size size = tester.getSize(
find.descendant(of: findViewContent(), matching: find.byType(ConstrainedBox)).first,
);
expect(size.width, 250.0);
expect(size.height, 450.0);
final Text hintText = tester.widget(find.text('hint text'));
expect(hintText.style?.color, headerHintStyle.color);
expect(hintText.style?.fontSize, headerHintStyle.fontSize);
final RenderBox box = tester.renderObject(
find.descendant(of: findViewContent(), matching: find.byType(SearchBar)),
);
expect(box.size.height, headerHeight);
await tester.enterText(find.byType(TextField), 'input');
final EditableText inputText = tester.widget(find.text('input'));
expect(inputText.style.color, headerTextStyle.color);
expect(inputText.style.fontSize, headerTextStyle.fontSize);
}
testWidgets('SearchView properties overrides defaults', (WidgetTester tester) async {
await tester.pumpWidget(buildFrame(useSearchViewProperties: true));
await tester.tap(find.byIcon(Icons.search));
await tester.pumpAndSettle(); // allow the animations to finish
checkSearchView(tester);
});
testWidgets('SearchView theme data overrides defaults', (WidgetTester tester) async {
await tester.pumpWidget(buildFrame(searchViewThemeData: searchViewTheme));
await tester.tap(find.byIcon(Icons.search));
await tester.pumpAndSettle();
checkSearchView(tester);
});
testWidgets('Overall Theme SearchView theme overrides defaults', (WidgetTester tester) async {
await tester.pumpWidget(buildFrame(overallTheme: searchViewTheme));
await tester.tap(find.byIcon(Icons.search));
await tester.pumpAndSettle();
checkSearchView(tester);
});
// Same as the previous tests with empty SearchViewThemeData's instead of null.
testWidgets('SearchView properties overrides defaults, empty theme and overall theme', (
WidgetTester tester,
) async {
await tester.pumpWidget(
buildFrame(
useSearchViewProperties: true,
searchViewThemeData: const SearchViewThemeData(),
overallTheme: const SearchViewThemeData(),
),
);
await tester.tap(find.byIcon(Icons.search));
await tester.pumpAndSettle(); // allow the animations to finish
checkSearchView(tester);
});
testWidgets('SearchView theme overrides defaults and overall theme', (
WidgetTester tester,
) async {
await tester.pumpWidget(
buildFrame(searchViewThemeData: searchViewTheme, overallTheme: const SearchViewThemeData()),
);
await tester.tap(find.byIcon(Icons.search));
await tester.pumpAndSettle(); // allow the animations to finish
checkSearchView(tester);
});
testWidgets('Overall Theme SearchView theme overrides defaults and null theme', (
WidgetTester tester,
) async {
await tester.pumpWidget(buildFrame(overallTheme: searchViewTheme));
await tester.tap(find.byIcon(Icons.search));
await tester.pumpAndSettle(); // allow the animations to finish
checkSearchView(tester);
});
});
}