window.dart 14.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
// Copyright 2018 The Chromium 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 'dart:typed_data' show ByteData;
import 'dart:ui' hide window;

import 'package:meta/meta.dart';

/// [Window] that wraps another [Window] and allows faking of some properties
/// for testing purposes.
///
/// Tests for certain widgets, e.g., [MaterialApp], might require faking certain
14 15 16 17
/// properties of a [Window]. [TestWindow] facilitates the faking of these
/// properties by overriding the properties of a real [Window] with desired fake
/// values. The binding used within tests, [TestWidgetsFlutterBinding], contains
/// a [TestWindow] that is used by all tests.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
///
/// ## Sample Code
///
/// A test can utilize a [TestWindow] in the following way:
///
/// ```dart
/// testWidgets('your test name here', (WidgetTester tester) async {
///   // Retrieve the TestWidgetsFlutterBinding.
///   final TestWidgetsFlutterBinding testBinding = tester.binding;
///
///   // Fake the desired properties of the TestWindow. All code running
///   // within this test will perceive the following fake text scale
///   // factor as the real text scale factor of the window.
///   testBinding.window.textScaleFactorFakeValue = 2.5;
///
///   // Test code that depends on text scale factor here.
/// });
/// ```
///
/// The [TestWidgetsFlutterBinding] is recreated for each test and
/// therefore any fake values defined in one test will not persist
/// to the next.
///
/// If a test needs to override a real [Window] property and then later
/// return to using the real [Window] property, [TestWindow] provides
/// methods to clear each individual test value, e.g., [clearLocaleTestValue()].
///
45 46
/// To clear all fake test values in a [TestWindow], consider using
/// [clearAllTestValues()].
47
class TestWindow implements Window {
48 49
  /// Constructs a [TestWindow] that defers all behavior to the given [Window]
  /// unless explicitly overridden for test purposes.
50 51 52 53 54 55 56 57 58 59
  TestWindow({
    @required Window window,
  }) : _window = window;

  /// The [Window] that is wrapped by this [TestWindow].
  final Window _window;

  @override
  double get devicePixelRatio => _devicePixelRatio ?? _window.devicePixelRatio;
  double _devicePixelRatio;
60 61
  /// Hides the real device pixel ratio and reports the given [devicePixelRatio]
  /// instead.
62 63
  set devicePixelRatioTestValue(double devicePixelRatio) {
    _devicePixelRatio = devicePixelRatio;
64
    onMetricsChanged();
65
  }
66 67
  /// Deletes any existing test device pixel ratio and returns to using the real
  /// device pixel ratio.
68 69
  void clearDevicePixelRatioTestValue() {
    _devicePixelRatio = null;
70
    onMetricsChanged();
71 72 73 74 75
  }

  @override
  Size get physicalSize => _physicalSizeTestValue ?? _window.physicalSize;
  Size _physicalSizeTestValue;
76 77
  /// Hides the real physical size and reports the given [physicalSizeTestValue]
  /// instead.
78 79
  set physicalSizeTestValue (Size physicalSizeTestValue) {
    _physicalSizeTestValue = physicalSizeTestValue;
80
    onMetricsChanged();
81
  }
82 83
  /// Deletes any existing test physical size and returns to using the real
  /// physical size.
84 85
  void clearPhysicalSizeTestValue() {
    _physicalSizeTestValue = null;
86
    onMetricsChanged();
87 88
  }

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
  @override
  double get physicalDepth => _physicalDepthTestValue ?? _window.physicalDepth;
  double _physicalDepthTestValue;
  /// Hides the real physical depth and reports the given
  /// [physicalDepthTestValue] instead.
  set physicalDepthTestValue (double physicalDepthTestValue) {
    _physicalDepthTestValue = physicalDepthTestValue;
    onMetricsChanged();
  }
  /// Deletes any existing test physical depth and returns to using the real
  /// physical depth.
  void clearPhysicalDepthTestValue() {
    _physicalDepthTestValue = null;
    onMetricsChanged();
  }

105 106 107
  @override
  WindowPadding get viewInsets => _viewInsetsTestValue ??  _window.viewInsets;
  WindowPadding _viewInsetsTestValue;
108 109
  /// Hides the real view insets and reports the given [viewInsetsTestValue]
  /// instead.
110 111
  set viewInsetsTestValue(WindowPadding viewInsetsTestValue) {
    _viewInsetsTestValue = viewInsetsTestValue;
112
    onMetricsChanged();
113
  }
114 115
  /// Deletes any existing test view insets and returns to using the real view
  /// insets.
116 117
  void clearViewInsetsTestValue() {
    _viewInsetsTestValue = null;
118
    onMetricsChanged();
119 120
  }

121
  @override
122 123
  WindowPadding get viewPadding => _viewPaddingTestValue ?? _window.padding;
  WindowPadding _viewPaddingTestValue;
124 125
  /// Hides the real view padding and reports the given [paddingTestValue]
  /// instead.
126 127 128 129
  set viewPaddingTestValue(WindowPadding viewPaddingTestValue) {
    _viewPaddingTestValue = viewPaddingTestValue;
    onMetricsChanged();
  }
130 131
  /// Deletes any existing test view padding and returns to using the real
  /// viewPadding.
132 133 134 135 136
  void clearViewPaddingTestValue() {
    _viewPaddingTestValue = null;
    onMetricsChanged();
  }

137 138 139 140 141 142
  @override
  WindowPadding get padding => _paddingTestValue ?? _window.padding;
  WindowPadding _paddingTestValue;
  /// Hides the real padding and reports the given [paddingTestValue] instead.
  set paddingTestValue(WindowPadding paddingTestValue) {
    _paddingTestValue = paddingTestValue;
143
    onMetricsChanged();
144 145 146 147
  }
  /// Deletes any existing test padding and returns to using the real padding.
  void clearPaddingTestValue() {
    _paddingTestValue = null;
148
    onMetricsChanged();
149 150
  }

151 152 153 154 155 156 157 158 159 160 161 162 163 164
  @override
  WindowPadding get systemGestureInsets => _systemGestureInsetsTestValue ?? _window.systemGestureInsets;
  WindowPadding _systemGestureInsetsTestValue;
  /// Hides the real system gesture insets and reports the given [systemGestureInsetsTestValue] instead.
  set systemGestureInsetsTestValue(WindowPadding systemGestureInsetsTestValue) {
    _systemGestureInsetsTestValue = systemGestureInsetsTestValue;
    onMetricsChanged();
  }
  /// Deletes any existing test system gesture insets and returns to using the real system gesture insets.
  void clearSystemGestureInsetsTestValue() {
    _systemGestureInsetsTestValue = null;
    onMetricsChanged();
  }

165 166 167 168 169 170 171 172 173 174 175 176 177
  @override
  VoidCallback get onMetricsChanged => _window.onMetricsChanged;
  @override
  set onMetricsChanged(VoidCallback callback) {
    _window.onMetricsChanged = callback;
  }

  @override
  Locale get locale => _localeTestValue ?? _window.locale;
  Locale _localeTestValue;
  /// Hides the real locale and reports the given [localeTestValue] instead.
  set localeTestValue(Locale localeTestValue) {
    _localeTestValue = localeTestValue;
178
    onLocaleChanged();
179 180 181 182
  }
  /// Deletes any existing test locale and returns to using the real locale.
  void clearLocaleTestValue() {
    _localeTestValue = null;
183
    onLocaleChanged();
184 185 186 187 188 189 190 191
  }

  @override
  List<Locale> get locales => _localesTestValue ?? _window.locales;
  List<Locale> _localesTestValue;
  /// Hides the real locales and reports the given [localesTestValue] instead.
  set localesTestValue(List<Locale> localesTestValue) {
    _localesTestValue = localesTestValue;
192
    onLocaleChanged();
193 194 195 196
  }
  /// Deletes any existing test locales and returns to using the real locales.
  void clearLocalesTestValue() {
    _localesTestValue = null;
197
    onLocaleChanged();
198 199 200 201 202 203 204 205 206
  }

  @override
  VoidCallback get onLocaleChanged => _window.onLocaleChanged;
  @override
  set onLocaleChanged(VoidCallback callback) {
    _window.onLocaleChanged = callback;
  }

207 208 209 210 211 212 213 214
  @override
  String get initialLifecycleState => _initialLifecycleStateTestValue;
  String _initialLifecycleStateTestValue;
  /// Sets a faked initialLifecycleState for testing.
  set initialLifecycleStateTestValue(String state) {
    _initialLifecycleStateTestValue = state;
  }

215 216 217
  @override
  double get textScaleFactor => _textScaleFactorTestValue ?? _window.textScaleFactor;
  double _textScaleFactorTestValue;
218 219
  /// Hides the real text scale factor and reports the given
  /// [textScaleFactorTestValue] instead.
220 221
  set textScaleFactorTestValue(double textScaleFactorTestValue) {
    _textScaleFactorTestValue = textScaleFactorTestValue;
222
    onTextScaleFactorChanged();
223
  }
224 225
  /// Deletes any existing test text scale factor and returns to using the real
  /// text scale factor.
226 227
  void clearTextScaleFactorTestValue() {
    _textScaleFactorTestValue = null;
228
    onTextScaleFactorChanged();
229 230
  }

231 232 233 234 235 236 237
  @override
  Brightness get platformBrightness => _platformBrightnessTestValue ?? _window.platformBrightness;
  Brightness _platformBrightnessTestValue;
  @override
  VoidCallback get onPlatformBrightnessChanged => _window.onPlatformBrightnessChanged;
  @override
  set onPlatformBrightnessChanged(VoidCallback callback) {
238
    _window.onPlatformBrightnessChanged = callback;
239
  }
240 241
  /// Hides the real text scale factor and reports the given
  /// [platformBrightnessTestValue] instead.
242 243
  set platformBrightnessTestValue(Brightness platformBrightnessTestValue) {
    _platformBrightnessTestValue = platformBrightnessTestValue;
244
    onPlatformBrightnessChanged();
245
  }
246 247
  /// Deletes any existing test platform brightness and returns to using the
  /// real platform brightness.
248 249
  void clearPlatformBrightnessTestValue() {
    _platformBrightnessTestValue = null;
250
    onPlatformBrightnessChanged();
251 252
  }

253 254 255
  @override
  bool get alwaysUse24HourFormat => _alwaysUse24HourFormatTestValue ?? _window.alwaysUse24HourFormat;
  bool _alwaysUse24HourFormatTestValue;
256 257
  /// Hides the real clock format and reports the given
  /// [alwaysUse24HourFormatTestValue] instead.
258 259 260
  set alwaysUse24HourFormatTestValue(bool alwaysUse24HourFormatTestValue) {
    _alwaysUse24HourFormatTestValue = alwaysUse24HourFormatTestValue;
  }
261 262
  /// Deletes any existing test clock format and returns to using the real clock
  /// format.
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
  void clearAlwaysUse24HourTestValue() {
    _alwaysUse24HourFormatTestValue = null;
  }

  @override
  VoidCallback get onTextScaleFactorChanged => _window.onTextScaleFactorChanged;
  @override
  set onTextScaleFactorChanged(VoidCallback callback) {
    _window.onTextScaleFactorChanged = callback;
  }

  @override
  FrameCallback get onBeginFrame => _window.onBeginFrame;
  @override
  set onBeginFrame(FrameCallback callback) {
    _window.onBeginFrame = callback;
  }

  @override
  VoidCallback get onDrawFrame => _window.onDrawFrame;
  @override
  set onDrawFrame(VoidCallback callback) {
    _window.onDrawFrame = callback;
  }

288
  @override
289
  Stream<FrameTiming> get frameTimings => _window.frameTimings;
290

291 292 293 294 295 296 297 298 299 300
  @override
  PointerDataPacketCallback get onPointerDataPacket => _window.onPointerDataPacket;
  @override
  set onPointerDataPacket(PointerDataPacketCallback callback) {
    _window.onPointerDataPacket = callback;
  }

  @override
  String get defaultRouteName => _defaultRouteNameTestValue ?? _window.defaultRouteName;
  String _defaultRouteNameTestValue;
301 302
  /// Hides the real default route name and reports the given
  /// [defaultRouteNameTestValue] instead.
303 304 305
  set defaultRouteNameTestValue(String defaultRouteNameTestValue) {
    _defaultRouteNameTestValue = defaultRouteNameTestValue;
  }
306 307
  /// Deletes any existing test default route name and returns to using the real
  /// default route name.
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
  void clearDefaultRouteNameTestValue() {
    _defaultRouteNameTestValue = null;
  }

  @override
  void scheduleFrame() {
    _window.scheduleFrame();
  }

  @override
  void render(Scene scene) {
    _window.render(scene);
  }

  @override
  bool get semanticsEnabled => _semanticsEnabledTestValue ?? _window.semanticsEnabled;
  bool _semanticsEnabledTestValue;
325 326
  /// Hides the real semantics enabled and reports the given
  /// [semanticsEnabledTestValue] instead.
327 328
  set semanticsEnabledTestValue(bool semanticsEnabledTestValue) {
    _semanticsEnabledTestValue = semanticsEnabledTestValue;
329
    onSemanticsEnabledChanged();
330
  }
331 332
  /// Deletes any existing test semantics enabled and returns to using the real
  /// semantics enabled.
333 334
  void clearSemanticsEnabledTestValue() {
    _semanticsEnabledTestValue = null;
335
    onSemanticsEnabledChanged();
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
  }

  @override
  VoidCallback get onSemanticsEnabledChanged => _window.onSemanticsEnabledChanged;
  @override
  set onSemanticsEnabledChanged(VoidCallback callback) {
    _window.onSemanticsEnabledChanged = callback;
  }

  @override
  SemanticsActionCallback get onSemanticsAction => _window.onSemanticsAction;
  @override
  set onSemanticsAction(SemanticsActionCallback callback) {
    _window.onSemanticsAction = callback;
  }

  @override
  AccessibilityFeatures get accessibilityFeatures => _accessibilityFeaturesTestValue ?? _window.accessibilityFeatures;
  AccessibilityFeatures _accessibilityFeaturesTestValue;
355 356
  /// Hides the real accessibility features and reports the given
  /// [accessibilityFeaturesTestValue] instead.
357 358
  set accessibilityFeaturesTestValue(AccessibilityFeatures accessibilityFeaturesTestValue) {
    _accessibilityFeaturesTestValue = accessibilityFeaturesTestValue;
359
    onAccessibilityFeaturesChanged();
360
  }
361 362
  /// Deletes any existing test accessibility features and returns to using the
  /// real accessibility features.
363 364
  void clearAccessibilityFeaturesTestValue() {
    _accessibilityFeaturesTestValue = null;
365
    onAccessibilityFeaturesChanged();
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
  }

  @override
  VoidCallback get onAccessibilityFeaturesChanged => _window.onAccessibilityFeaturesChanged;
  @override
  set onAccessibilityFeaturesChanged(VoidCallback callback) {
    _window.onAccessibilityFeaturesChanged = callback;
  }

  @override
  void updateSemantics(SemanticsUpdate update) {
    _window.updateSemantics(update);
  }

  @override
  void setIsolateDebugName(String name) {
    _window.setIsolateDebugName(name);
  }

  @override
386 387 388 389 390
  void sendPlatformMessage(
    String name,
    ByteData data,
    PlatformMessageResponseCallback callback,
  ) {
391 392 393 394 395 396 397 398 399 400 401
    _window.sendPlatformMessage(name, data, callback);
  }

  @override
  PlatformMessageCallback get onPlatformMessage => _window.onPlatformMessage;
  @override
  set onPlatformMessage(PlatformMessageCallback callback) {
    _window.onPlatformMessage = callback;
  }

  /// Delete any test value properties that have been set on this [TestWindow]
402 403
  /// and return to reporting the real [Window] values for all [Window]
  /// properties.
404
  ///
405 406
  /// If desired, clearing of properties can be done on an individual basis,
  /// e.g., [clearLocaleTestValue()].
407 408 409 410 411
  void clearAllTestValues() {
    clearAccessibilityFeaturesTestValue();
    clearAlwaysUse24HourTestValue();
    clearDefaultRouteNameTestValue();
    clearDevicePixelRatioTestValue();
412
    clearPlatformBrightnessTestValue();
413 414 415 416
    clearLocaleTestValue();
    clearLocalesTestValue();
    clearPaddingTestValue();
    clearPhysicalSizeTestValue();
417
    clearPhysicalDepthTestValue();
418 419 420 421
    clearSemanticsEnabledTestValue();
    clearTextScaleFactorTestValue();
    clearViewInsetsTestValue();
  }
422 423

  /// This gives us some grace time when the dart:ui side adds something to
424 425
  /// Window, and makes things easier when we do rolls to give us time to catch
  /// up.
426 427 428 429
  @override
  dynamic noSuchMethod(Invocation invocation) {
    return null;
  }
430
}