1// Copyright 2018 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5import 'dart:ui' as ui show window; 6import 'dart:ui' show Size, Locale, WindowPadding, AccessibilityFeatures, Brightness; 7 8import 'package:flutter/widgets.dart' show WidgetsBinding; 9import 'package:flutter_test/flutter_test.dart'; 10import 'package:meta/meta.dart'; 11 12void main() { 13 test('TestWindow can handle new methods without breaking', () { 14 final dynamic testWindow = TestWindow(window: ui.window); 15 expect(testWindow.someNewProperty, null); 16 }); 17 18 testWidgets('TestWindow can fake device pixel ratio', (WidgetTester tester) async { 19 verifyThatTestWindowCanFakeProperty<double>( 20 tester: tester, 21 realValue: ui.window.devicePixelRatio, 22 fakeValue: 2.5, 23 propertyRetriever: () { 24 return WidgetsBinding.instance.window.devicePixelRatio; 25 }, 26 propertyFaker: (TestWidgetsFlutterBinding binding, double fakeValue) { 27 binding.window.devicePixelRatioTestValue = fakeValue; 28 }, 29 ); 30 }); 31 32 testWidgets('TestWindow can fake physical size', (WidgetTester tester) async { 33 verifyThatTestWindowCanFakeProperty<Size>( 34 tester: tester, 35 realValue: ui.window.physicalSize, 36 fakeValue: const Size(50, 50), 37 propertyRetriever: () { 38 return WidgetsBinding.instance.window.physicalSize; 39 }, 40 propertyFaker: (TestWidgetsFlutterBinding binding, Size fakeValue) { 41 binding.window.physicalSizeTestValue = fakeValue; 42 }, 43 ); 44 }); 45 46 testWidgets('TestWindow can fake physical depth', (WidgetTester tester) async { 47 verifyThatTestWindowCanFakeProperty<double>( 48 tester: tester, 49 realValue: ui.window.physicalDepth, 50 fakeValue: 120.0, 51 propertyRetriever: () { 52 return WidgetsBinding.instance.window.physicalDepth; 53 }, 54 propertyFaker: (TestWidgetsFlutterBinding binding, double fakeValue) { 55 binding.window.physicalDepthTestValue = fakeValue; 56 }, 57 ); 58 }); 59 60 testWidgets('TestWindow can fake view insets', (WidgetTester tester) async { 61 verifyThatTestWindowCanFakeProperty<WindowPadding>( 62 tester: tester, 63 realValue: ui.window.viewInsets, 64 fakeValue: const FakeWindowPadding(), 65 propertyRetriever: () { 66 return WidgetsBinding.instance.window.viewInsets; 67 }, 68 propertyFaker: (TestWidgetsFlutterBinding binding, WindowPadding fakeValue) { 69 binding.window.viewInsetsTestValue = fakeValue; 70 }, 71 ); 72 }); 73 74 testWidgets('TestWindow can fake padding', (WidgetTester tester) async { 75 verifyThatTestWindowCanFakeProperty<WindowPadding>( 76 tester: tester, 77 realValue: ui.window.padding, 78 fakeValue: const FakeWindowPadding(), 79 propertyRetriever: () { 80 return WidgetsBinding.instance.window.padding; 81 }, 82 propertyFaker: (TestWidgetsFlutterBinding binding, WindowPadding fakeValue) { 83 binding.window.paddingTestValue = fakeValue; 84 }, 85 ); 86 }); 87 88 testWidgets('TestWindow can fake locale', (WidgetTester tester) async { 89 verifyThatTestWindowCanFakeProperty<Locale>( 90 tester: tester, 91 realValue: ui.window.locale, 92 fakeValue: const Locale('fake_language_code'), 93 propertyRetriever: () { 94 return WidgetsBinding.instance.window.locale; 95 }, 96 propertyFaker: (TestWidgetsFlutterBinding binding, Locale fakeValue) { 97 binding.window.localeTestValue = fakeValue; 98 }, 99 ); 100 }); 101 102 testWidgets('TestWindow can fake locales', (WidgetTester tester) async { 103 verifyThatTestWindowCanFakeProperty<List<Locale>>( 104 tester: tester, 105 realValue: ui.window.locales, 106 fakeValue: <Locale>[const Locale('fake_language_code')], 107 propertyRetriever: () { 108 return WidgetsBinding.instance.window.locales; 109 }, 110 propertyFaker: (TestWidgetsFlutterBinding binding, List<Locale> fakeValue) { 111 binding.window.localesTestValue = fakeValue; 112 }, 113 ); 114 }); 115 116 testWidgets('TestWindow can fake text scale factor', (WidgetTester tester) async { 117 verifyThatTestWindowCanFakeProperty<double>( 118 tester: tester, 119 realValue: ui.window.textScaleFactor, 120 fakeValue: 2.5, 121 propertyRetriever: () { 122 return WidgetsBinding.instance.window.textScaleFactor; 123 }, 124 propertyFaker: (TestWidgetsFlutterBinding binding, double fakeValue) { 125 binding.window.textScaleFactorTestValue = fakeValue; 126 }, 127 ); 128 }); 129 130 testWidgets('TestWindow can fake clock format', (WidgetTester tester) async { 131 verifyThatTestWindowCanFakeProperty<bool>( 132 tester: tester, 133 realValue: ui.window.alwaysUse24HourFormat, 134 fakeValue: !ui.window.alwaysUse24HourFormat, 135 propertyRetriever: () { 136 return WidgetsBinding.instance.window.alwaysUse24HourFormat; 137 }, 138 propertyFaker: (TestWidgetsFlutterBinding binding, bool fakeValue) { 139 binding.window.alwaysUse24HourFormatTestValue = fakeValue; 140 }, 141 ); 142 }); 143 144 testWidgets('TestWindow can fake default route name', (WidgetTester tester) async { 145 verifyThatTestWindowCanFakeProperty<String>( 146 tester: tester, 147 realValue: ui.window.defaultRouteName, 148 fakeValue: 'fake_route', 149 propertyRetriever: () { 150 return WidgetsBinding.instance.window.defaultRouteName; 151 }, 152 propertyFaker: (TestWidgetsFlutterBinding binding, String fakeValue) { 153 binding.window.defaultRouteNameTestValue = fakeValue; 154 }, 155 ); 156 }); 157 158 testWidgets('TestWindow can fake accessibility features', (WidgetTester tester) async { 159 verifyThatTestWindowCanFakeProperty<AccessibilityFeatures>( 160 tester: tester, 161 realValue: ui.window.accessibilityFeatures, 162 fakeValue: const FakeAccessibilityFeatures(), 163 propertyRetriever: () { 164 return WidgetsBinding.instance.window.accessibilityFeatures; 165 }, 166 propertyFaker: (TestWidgetsFlutterBinding binding, AccessibilityFeatures fakeValue) { 167 binding.window.accessibilityFeaturesTestValue = fakeValue; 168 }, 169 ); 170 }); 171 172 testWidgets('TestWindow can fake platform brightness', (WidgetTester tester) async { 173 verifyThatTestWindowCanFakeProperty<Brightness>( 174 tester: tester, 175 realValue: Brightness.light, 176 fakeValue: Brightness.dark, 177 propertyRetriever: () { 178 return WidgetsBinding.instance.window.platformBrightness; 179 }, 180 propertyFaker: (TestWidgetsFlutterBinding binding, Brightness fakeValue) { 181 binding.window.platformBrightnessTestValue = fakeValue; 182 }, 183 ); 184 }); 185 186 testWidgets('TestWindow can clear out fake properties all at once', (WidgetTester tester) async { 187 final double originalDevicePixelRatio = ui.window.devicePixelRatio; 188 final double originalTextScaleFactor = ui.window.textScaleFactor; 189 final TestWindow testWindow = retrieveTestBinding(tester).window; 190 191 // Set fake values for window properties. 192 testWindow.devicePixelRatioTestValue = 2.5; 193 testWindow.textScaleFactorTestValue = 3.0; 194 195 // Erase fake window property values. 196 testWindow.clearAllTestValues(); 197 198 // Verify that the window once again reports real property values. 199 expect(WidgetsBinding.instance.window.devicePixelRatio, originalDevicePixelRatio); 200 expect(WidgetsBinding.instance.window.textScaleFactor, originalTextScaleFactor); 201 }); 202} 203 204void verifyThatTestWindowCanFakeProperty<WindowPropertyType>({ 205 @required WidgetTester tester, 206 @required WindowPropertyType realValue, 207 @required WindowPropertyType fakeValue, 208 @required WindowPropertyType Function() propertyRetriever, 209 @required Function(TestWidgetsFlutterBinding, WindowPropertyType fakeValue) propertyFaker, 210}) { 211 WindowPropertyType propertyBeforeFaking; 212 WindowPropertyType propertyAfterFaking; 213 214 propertyBeforeFaking = propertyRetriever(); 215 216 propertyFaker(retrieveTestBinding(tester), fakeValue); 217 218 propertyAfterFaking = propertyRetriever(); 219 220 expect(propertyBeforeFaking, realValue); 221 expect(propertyAfterFaking, fakeValue); 222} 223 224TestWidgetsFlutterBinding retrieveTestBinding(WidgetTester tester) { 225 final WidgetsBinding binding = tester.binding; 226 assert(binding is TestWidgetsFlutterBinding); 227 final TestWidgetsFlutterBinding testBinding = binding; 228 return testBinding; 229} 230 231class FakeWindowPadding implements WindowPadding { 232 const FakeWindowPadding({ 233 this.left = 0.0, 234 this.top = 0.0, 235 this.right = 0.0, 236 this.bottom = 0.0, 237 }); 238 239 @override 240 final double left; 241 242 @override 243 final double top; 244 245 @override 246 final double right; 247 248 @override 249 final double bottom; 250} 251 252class FakeAccessibilityFeatures implements AccessibilityFeatures { 253 const FakeAccessibilityFeatures({ 254 this.accessibleNavigation = false, 255 this.invertColors = false, 256 this.disableAnimations = false, 257 this.boldText = false, 258 this.reduceMotion = false, 259 }); 260 261 @override 262 final bool accessibleNavigation; 263 264 @override 265 final bool invertColors; 266 267 @override 268 final bool disableAnimations; 269 270 @override 271 final bool boldText; 272 273 @override 274 final bool reduceMotion; 275} 276