blob: 4f873127672d695a1af6171b41999e8895833c24 [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.
// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])
library;
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
class _FilterTest extends StatelessWidget {
const _FilterTest(Widget child, {this.brightness = Brightness.light}) : _child = child;
final Brightness brightness;
final Widget _child;
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.sizeOf(context);
final double tileHeight = size.height / 4;
final double tileWidth = size.width / 8;
return CupertinoApp(
home: Stack(
fit: StackFit.expand,
children: <Widget>[
// 512 color tiles
// 4 alpha levels (0.416, 0.25, 0.5, 0.75)
for (int a = 0; a < 4; a++)
for (int h = 0; h < 8; h++) // 8 hues
for (int s = 0; s < 4; s++) // 4 saturation levels
for (int b = 0; b < 4; b++) // 4 brightness levels
Positioned(
left: h * tileWidth + b * tileWidth / 4,
top: a * tileHeight + s * tileHeight / 4,
height: tileHeight,
width: tileWidth,
child: ColoredBox(
color: HSVColor.fromAHSV(
0.5 + a / 8,
h * 45,
0.5 + s / 8,
0.5 + b / 8,
).toColor(),
),
),
Padding(
padding: const EdgeInsets.all(32),
child: CupertinoTheme(
data: CupertinoThemeData(brightness: brightness),
child: _child,
),
),
],
),
);
}
}
void main() {
void disableVibranceForTest() {
CupertinoPopupSurface.debugIsVibrancePainted = false;
addTearDown(() {
CupertinoPopupSurface.debugIsVibrancePainted = true;
});
}
// Golden displays the color filter effect of the CupertinoPopupSurface
// when the ambient brightness is light.
testWidgets(
'Brightness.light color filter',
(WidgetTester tester) async {
await tester.pumpWidget(
const _FilterTest(
CupertinoPopupSurface(blurSigma: 0, isSurfacePainted: false, child: SizedBox()),
),
);
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.color-filter.light.png'),
);
},
skip: kIsWasm, // https://github.com/flutter/flutter/issues/152026
);
// Golden displays the color filter effect of the CupertinoPopupSurface
// when the ambient brightness is dark.
testWidgets(
'Brightness.dark color filter',
(WidgetTester tester) async {
await tester.pumpWidget(
const _FilterTest(
CupertinoPopupSurface(blurSigma: 0, isSurfacePainted: false, child: SizedBox()),
brightness: Brightness.dark,
),
);
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.color-filter.dark.png'),
);
},
skip: kIsWasm, // https://github.com/flutter/flutter/issues/152026
);
// Golden displays color tiles without CupertinoPopupSurface being
// displayed.
testWidgets('Setting debugIsVibrancePainted to false removes the color filter', (
WidgetTester tester,
) async {
disableVibranceForTest();
await tester.pumpWidget(
const _FilterTest(
CupertinoPopupSurface(blurSigma: 0, isSurfacePainted: false, child: SizedBox()),
),
);
// The BackdropFilter widget should not be mounted when blurSigma is 0 and
// CupertinoPopupSurface.debugIsVibrancePainted is false.
expect(
find.descendant(
of: find.byType(CupertinoPopupSurface),
matching: find.byType(BackdropFilter),
),
findsNothing,
);
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.color-filter.removed.png'),
);
});
// Golden displays the surface color of the CupertinoPopupSurface
// in light mode.
testWidgets('Brightness.light surface color', (WidgetTester tester) async {
disableVibranceForTest();
await tester.pumpWidget(
const _FilterTest(CupertinoPopupSurface(blurSigma: 0, child: SizedBox())),
);
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.surface-color.light.png'),
);
});
// Golden displays the surface color of the CupertinoPopupSurface
// in dark mode.
testWidgets('Brightness.dark surface color', (WidgetTester tester) async {
disableVibranceForTest();
await tester.pumpWidget(
const _FilterTest(
CupertinoPopupSurface(blurSigma: 0, child: SizedBox()),
brightness: Brightness.dark,
),
);
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.surface-color.dark.png'),
);
});
// Golden displays a CupertinoPopupSurface with the color removed. The result
// should only display color tiles.
testWidgets('Setting isSurfacePainted to false removes the surface color', (
WidgetTester tester,
) async {
disableVibranceForTest();
await tester.pumpWidget(
const _FilterTest(
CupertinoPopupSurface(blurSigma: 0, isSurfacePainted: false, child: SizedBox()),
brightness: Brightness.dark,
),
);
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.surface-color.removed.png'),
);
});
// Goldens display a CupertinoPopupSurface with no vibrance or surface
// color, with blur sigmas of 5 and 30 (default).
testWidgets(
'Positive blurSigma applies blur',
(WidgetTester tester) async {
disableVibranceForTest();
await tester.pumpWidget(
const _FilterTest(
CupertinoPopupSurface(isSurfacePainted: false, blurSigma: 5, child: SizedBox()),
),
);
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.blur.5.png'),
);
await tester.pumpWidget(
const _FilterTest(CupertinoPopupSurface(isSurfacePainted: false, child: SizedBox())),
);
await expectLater(
find.byType(CupertinoApp),
// 30 is the default blur sigma
matchesGoldenFile('cupertinoPopupSurface.blur.30.png'),
);
},
skip: kIsWasm, // https://github.com/flutter/flutter/issues/152026
);
// Golden displays a CupertinoPopupSurface with a blur sigma of 0. Because
// the blur sigma is 0 and vibrance and surface are not painted, no popup
// surface is displayed.
testWidgets('Setting blurSigma to zero removes blur', (WidgetTester tester) async {
disableVibranceForTest();
await tester.pumpWidget(
const _FilterTest(
CupertinoPopupSurface(isSurfacePainted: false, blurSigma: 0, child: SizedBox()),
),
);
// The BackdropFilter widget should not be mounted when blurSigma is 0 and
// CupertinoPopupSurface.isVibrancePainted is false.
expect(
find.descendant(
of: find.byType(CupertinoPopupSurface),
matching: find.byType(BackdropFilter),
),
findsNothing,
);
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.blur.0.png'),
);
await tester.pumpWidget(
const _FilterTest(
CupertinoPopupSurface(isSurfacePainted: false, blurSigma: 0, child: SizedBox()),
),
);
});
testWidgets('Setting a blurSigma to a negative number throws', (WidgetTester tester) async {
try {
disableVibranceForTest();
await tester.pumpWidget(
_FilterTest(
CupertinoPopupSurface(isSurfacePainted: false, blurSigma: -1, child: const SizedBox()),
),
);
fail('CupertinoPopupSurface did not throw when provided a negative blur sigma.');
} on AssertionError catch (error) {
expect(
error.toString(),
contains('CupertinoPopupSurface requires a non-negative blur sigma.'),
);
}
});
// Regression test for https://github.com/flutter/flutter/issues/154887.
testWidgets(
"Applying a FadeTransition to the CupertinoPopupSurface doesn't cause transparency",
(WidgetTester tester) async {
final controller = AnimationController(
duration: const Duration(milliseconds: 100),
vsync: const TestVSync(),
);
addTearDown(controller.dispose);
controller.forward();
await tester.pumpWidget(
_FilterTest(
FadeTransition(
opacity: controller,
child: const CupertinoPopupSurface(child: SizedBox()),
),
),
);
await tester.pump(const Duration(milliseconds: 50));
// Golden should display a CupertinoPopupSurface with no transparency
// directly underneath the surface. A small amount of transparency should be
// present on the upper-left corner of the screen.
//
// If transparency (gray and white grid) is present underneath the surface,
// the blendmode is being incorrectly applied.
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.blendmode-fix.0.png'),
);
await tester.pumpAndSettle();
},
variant: TargetPlatformVariant.only(TargetPlatform.iOS),
);
// Golden displays a CupertinoPopupSurface with all enabled features.
//
// CupertinoPopupSurface uses ImageFilter.compose, which applies an inner
// filter first, followed by an outer filter (e.g. result =
// outer(inner(source))).
//
// For CupertinoPopupSurface, this means that the pixels underlying the
// surface are first saturated with a ColorFilter, and the resulting saturated
// pixels are blurred with an ImageFilter.blur. This test verifies that this
// order does not change.
testWidgets('Saturation is applied before blur', (WidgetTester tester) async {
await tester.pumpWidget(const _FilterTest(CupertinoPopupSurface(child: SizedBox())));
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.composition.png'),
);
disableVibranceForTest();
await tester.pumpWidget(
const _FilterTest(
Stack(
fit: StackFit.expand,
children: <Widget>[
CupertinoPopupSurface(isSurfacePainted: false, blurSigma: 0, child: SizedBox()),
CupertinoPopupSurface(child: SizedBox()),
],
),
),
);
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoPopupSurface.composition.png'),
);
});
}