Adds TestDisplay
API for testing Display
features (#127525)
* Adds `TestDisplay` * Updates `TestPlatformDispatcher` to wrap all `Display`s and relate them to their appropriate `TestFlutterView` * Updates `TestFlutterView` to tie `devicePixelRatio` to its display as per the documentation on `Display` Closes #127225
This commit is contained in:
parent
51f7fdbc16
commit
07f7ffde50
@ -153,7 +153,7 @@ class TestPlatformDispatcher implements PlatformDispatcher {
|
||||
TestPlatformDispatcher({
|
||||
required PlatformDispatcher platformDispatcher,
|
||||
}) : _platformDispatcher = platformDispatcher {
|
||||
_updateViews();
|
||||
_updateViewsAndDisplays();
|
||||
_platformDispatcher.onMetricsChanged = _handleMetricsChanged;
|
||||
}
|
||||
|
||||
@ -168,6 +168,7 @@ class TestPlatformDispatcher implements PlatformDispatcher {
|
||||
}
|
||||
|
||||
final Map<Object, TestFlutterView> _testViews = <Object, TestFlutterView>{};
|
||||
final Map<Object, TestDisplay> _testDisplays = <Object, TestDisplay>{};
|
||||
|
||||
@override
|
||||
VoidCallback? get onMetricsChanged => _platformDispatcher.onMetricsChanged;
|
||||
@ -178,7 +179,7 @@ class TestPlatformDispatcher implements PlatformDispatcher {
|
||||
}
|
||||
|
||||
void _handleMetricsChanged() {
|
||||
_updateViews();
|
||||
_updateViewsAndDisplays();
|
||||
_onMetricsChanged?.call();
|
||||
}
|
||||
|
||||
@ -509,16 +510,50 @@ class TestPlatformDispatcher implements PlatformDispatcher {
|
||||
@override
|
||||
Iterable<TestFlutterView> get views => _testViews.values;
|
||||
|
||||
void _updateViews() {
|
||||
final List<Object> extraKeys = <Object>[..._testViews.keys];
|
||||
@override
|
||||
Iterable<TestDisplay> get displays => _testDisplays.values;
|
||||
|
||||
void _updateViewsAndDisplays() {
|
||||
final List<Object> extraDisplayKeys = <Object>[..._testDisplays.keys];
|
||||
for (final Display display in _platformDispatcher.displays) {
|
||||
extraDisplayKeys.remove(display.id);
|
||||
if (!_testDisplays.containsKey(display.id)) {
|
||||
_testDisplays[display.id] = TestDisplay(this, display);
|
||||
}
|
||||
}
|
||||
extraDisplayKeys.forEach(_testDisplays.remove);
|
||||
|
||||
final List<Object> extraViewKeys = <Object>[..._testViews.keys];
|
||||
for (final FlutterView view in _platformDispatcher.views) {
|
||||
extraKeys.remove(view.viewId);
|
||||
// TODO(pdblasi-google): Remove this try-catch once the Display API is stable and supported on all platforms
|
||||
late final TestDisplay display;
|
||||
try {
|
||||
final Display realDisplay = view.display;
|
||||
if (_testDisplays.containsKey(realDisplay.id)) {
|
||||
display = _testDisplays[view.display.id]!;
|
||||
} else {
|
||||
display = _UnsupportedDisplay(
|
||||
this,
|
||||
view,
|
||||
'PlatformDispatcher did not contain a Display with id ${realDisplay.id}, '
|
||||
'which was expected by FlutterView ($view)',
|
||||
);
|
||||
}
|
||||
} catch (error){
|
||||
display = _UnsupportedDisplay(this, view, error);
|
||||
}
|
||||
|
||||
extraViewKeys.remove(view.viewId);
|
||||
if (!_testViews.containsKey(view.viewId)) {
|
||||
_testViews[view.viewId] = TestFlutterView(view: view, platformDispatcher: this);
|
||||
_testViews[view.viewId] = TestFlutterView(
|
||||
view: view,
|
||||
platformDispatcher: this,
|
||||
display: display,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extraKeys.forEach(_testViews.remove);
|
||||
extraViewKeys.forEach(_testViews.remove);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -625,7 +660,11 @@ class TestFlutterView implements FlutterView {
|
||||
TestFlutterView({
|
||||
required FlutterView view,
|
||||
required TestPlatformDispatcher platformDispatcher,
|
||||
}) : _view = view, _platformDispatcher = platformDispatcher;
|
||||
required TestDisplay display,
|
||||
}) :
|
||||
_view = view,
|
||||
_platformDispatcher = platformDispatcher,
|
||||
_display = display;
|
||||
|
||||
/// The [FlutterView] backing this [TestFlutterView].
|
||||
final FlutterView _view;
|
||||
@ -634,6 +673,10 @@ class TestFlutterView implements FlutterView {
|
||||
TestPlatformDispatcher get platformDispatcher => _platformDispatcher;
|
||||
final TestPlatformDispatcher _platformDispatcher;
|
||||
|
||||
@override
|
||||
TestDisplay get display => _display;
|
||||
final TestDisplay _display;
|
||||
|
||||
@override
|
||||
Object get viewId => _view.viewId;
|
||||
|
||||
@ -646,20 +689,21 @@ class TestFlutterView implements FlutterView {
|
||||
/// See also:
|
||||
///
|
||||
/// * [FlutterView.devicePixelRatio] for the standard implementation
|
||||
/// * [TestDisplay.devicePixelRatio] which will stay in sync with this value
|
||||
/// * [resetDevicePixelRatio] to reset this value specifically
|
||||
/// * [reset] to reset all test values for this view
|
||||
@override
|
||||
double get devicePixelRatio => _devicePixelRatio ?? _view.devicePixelRatio;
|
||||
double? _devicePixelRatio;
|
||||
double get devicePixelRatio => _display._devicePixelRatio ?? _view.devicePixelRatio;
|
||||
set devicePixelRatio(double value) {
|
||||
_devicePixelRatio = value;
|
||||
platformDispatcher.onMetricsChanged?.call();
|
||||
_display.devicePixelRatio = value;
|
||||
}
|
||||
|
||||
/// Resets [devicePixelRatio] for this test view to the default value for this view.
|
||||
///
|
||||
/// This will also reset the [devicePixelRatio] for the [TestDisplay]
|
||||
/// that is related to this view.
|
||||
void resetDevicePixelRatio() {
|
||||
_devicePixelRatio = null;
|
||||
platformDispatcher.onMetricsChanged?.call();
|
||||
_display.resetDevicePixelRatio();
|
||||
}
|
||||
|
||||
/// The display features to use for this test.
|
||||
@ -947,6 +991,158 @@ class TestFlutterView implements FlutterView {
|
||||
}
|
||||
}
|
||||
|
||||
/// A version of [Display] that can be modified to allow for testing various
|
||||
/// use cases.
|
||||
///
|
||||
/// Updates to the [TestDisplay] will be surfaced through
|
||||
/// [PlatformDispatcher.onMetricsChanged].
|
||||
class TestDisplay implements Display {
|
||||
/// Creates a new [TestDisplay] backed by the given [Display].
|
||||
TestDisplay(TestPlatformDispatcher platformDispatcher, Display display)
|
||||
: _platformDispatcher = platformDispatcher, _display = display;
|
||||
|
||||
final Display _display;
|
||||
final TestPlatformDispatcher _platformDispatcher;
|
||||
|
||||
@override
|
||||
int get id => _display.id;
|
||||
|
||||
/// The device pixel ratio to use for this test.
|
||||
///
|
||||
/// Defaults to the value provided by [Display.devicePixelRatio]. This
|
||||
/// can only be set in a test environment to emulate different display
|
||||
/// configurations. A standard [Display] is not mutable from the framework.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Display.devicePixelRatio] for the standard implementation
|
||||
/// * [TestFlutterView.devicePixelRatio] which will stay in sync with this value
|
||||
/// * [resetDevicePixelRatio] to reset this value specifically
|
||||
/// * [reset] to reset all test values for this display
|
||||
@override
|
||||
double get devicePixelRatio => _devicePixelRatio ?? _display.devicePixelRatio;
|
||||
double? _devicePixelRatio;
|
||||
set devicePixelRatio(double value) {
|
||||
_devicePixelRatio = value;
|
||||
_platformDispatcher.onMetricsChanged?.call();
|
||||
}
|
||||
|
||||
/// Resets [devicePixelRatio] to the default value for this display.
|
||||
///
|
||||
/// This will also reset the [devicePixelRatio] for any [TestFlutterView]s
|
||||
/// that are related to this display.
|
||||
void resetDevicePixelRatio() {
|
||||
_devicePixelRatio = null;
|
||||
_platformDispatcher.onMetricsChanged?.call();
|
||||
}
|
||||
|
||||
/// The refresh rate to use for this test.
|
||||
///
|
||||
/// Defaults to the value provided by [Display.refreshRate]. This
|
||||
/// can only be set in a test environment to emulate different display
|
||||
/// configurations. A standard [Display] is not mutable from the framework.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Display.refreshRate] for the standard implementation
|
||||
/// * [resetRefreshRate] to reset this value specifically
|
||||
/// * [reset] to reset all test values for this display
|
||||
@override
|
||||
double get refreshRate => _refreshRate ?? _display.refreshRate;
|
||||
double? _refreshRate;
|
||||
set refreshRate(double value) {
|
||||
_refreshRate = value;
|
||||
_platformDispatcher.onMetricsChanged?.call();
|
||||
}
|
||||
|
||||
/// Resets [refreshRate] to the default value for this display.
|
||||
void resetRefreshRate() {
|
||||
_refreshRate = null;
|
||||
_platformDispatcher.onMetricsChanged?.call();
|
||||
}
|
||||
|
||||
/// The size of the [Display] to use for this test.
|
||||
///
|
||||
/// Defaults to the value provided by [Display.refreshRate]. This
|
||||
/// can only be set in a test environment to emulate different display
|
||||
/// configurations. A standard [Display] is not mutable from the framework.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Display.refreshRate] for the standard implementation
|
||||
/// * [resetRefreshRate] to reset this value specifically
|
||||
/// * [reset] to reset all test values for this display
|
||||
@override
|
||||
Size get size => _size ?? _display.size;
|
||||
Size? _size;
|
||||
set size(Size value) {
|
||||
_size = value;
|
||||
_platformDispatcher.onMetricsChanged?.call();
|
||||
}
|
||||
|
||||
/// Resets [size] to the default value for this display.
|
||||
void resetSize() {
|
||||
_size = null;
|
||||
_platformDispatcher.onMetricsChanged?.call();
|
||||
}
|
||||
|
||||
/// Resets all values on this [TestDisplay].
|
||||
///
|
||||
/// See also:
|
||||
/// * [resetDevicePixelRatio] to reset [devicePixelRatio] specifically
|
||||
/// * [resetRefreshRate] to reset [refreshRate] specifically
|
||||
/// * [resetSize] to reset [size] specifically
|
||||
void reset() {
|
||||
resetDevicePixelRatio();
|
||||
resetRefreshRate();
|
||||
resetSize();
|
||||
}
|
||||
|
||||
/// This gives us some grace time when the dart:ui side adds something to
|
||||
/// [Display], and makes things easier when we do rolls to give
|
||||
/// us time to catch up.
|
||||
@override
|
||||
dynamic noSuchMethod(Invocation invocation) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(pdblasi-google): Remove this once the Display API is stable and supported on all platforms
|
||||
class _UnsupportedDisplay implements TestDisplay {
|
||||
_UnsupportedDisplay(this._platformDispatcher, this._view, this.error);
|
||||
|
||||
final FlutterView _view;
|
||||
final Object? error;
|
||||
|
||||
@override
|
||||
final TestPlatformDispatcher _platformDispatcher;
|
||||
|
||||
@override
|
||||
double get devicePixelRatio => _devicePixelRatio ?? _view.devicePixelRatio;
|
||||
@override
|
||||
double? _devicePixelRatio;
|
||||
@override
|
||||
set devicePixelRatio(double value) {
|
||||
_devicePixelRatio = value;
|
||||
_platformDispatcher.onMetricsChanged?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
void resetDevicePixelRatio() {
|
||||
_devicePixelRatio = null;
|
||||
_platformDispatcher.onMetricsChanged?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
dynamic noSuchMethod(Invocation invocation) {
|
||||
throw UnsupportedError(
|
||||
'The Display API is unsupported in this context. '
|
||||
'As of the last metrics change on PlatformDispatcher, this was the error '
|
||||
'given when trying to prepare the display for testing: $error',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Deprecated. Will be removed in a future version of Flutter.
|
||||
///
|
||||
/// This class has been deprecated to prepare for Flutter's upcoming support
|
||||
|
192
packages/flutter_test/test/display_test.dart
Normal file
192
packages/flutter_test/test/display_test.dart
Normal file
@ -0,0 +1,192 @@
|
||||
// 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 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'utils/fake_and_mock_utils.dart';
|
||||
|
||||
void main() {
|
||||
group('TestDisplay', () {
|
||||
Display trueDisplay() => PlatformDispatcher.instance.displays.single;
|
||||
TestDisplay boundDisplay() => WidgetsBinding.instance.platformDispatcher.displays.single as TestDisplay;
|
||||
|
||||
tearDown(() {
|
||||
boundDisplay().reset();
|
||||
});
|
||||
|
||||
testWidgets('can handle new methods without breaking', (WidgetTester tester) async {
|
||||
final dynamic testDisplay = tester.view.display;
|
||||
//ignore: avoid_dynamic_calls
|
||||
expect(testDisplay.someNewProperty, null);
|
||||
});
|
||||
|
||||
testWidgets('can fake devicePixelRatio', (WidgetTester tester) async {
|
||||
verifyPropertyFaked<double>(
|
||||
tester: tester,
|
||||
realValue: trueDisplay().devicePixelRatio,
|
||||
fakeValue: trueDisplay().devicePixelRatio + 1,
|
||||
propertyRetriever: () => boundDisplay().devicePixelRatio,
|
||||
propertyFaker: (_, double fake) {
|
||||
boundDisplay().devicePixelRatio = fake;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('can reset devicePixelRatio', (WidgetTester tester) async {
|
||||
verifyPropertyReset<double>(
|
||||
tester: tester,
|
||||
fakeValue: trueDisplay().devicePixelRatio + 1,
|
||||
propertyRetriever: () => boundDisplay().devicePixelRatio,
|
||||
propertyResetter: () => boundDisplay().resetDevicePixelRatio(),
|
||||
propertyFaker: (double fake) {
|
||||
boundDisplay().devicePixelRatio = fake;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('resetting devicePixelRatio also resets view.devicePixelRatio', (WidgetTester tester) async {
|
||||
verifyPropertyReset(
|
||||
tester: tester,
|
||||
fakeValue: trueDisplay().devicePixelRatio + 1,
|
||||
propertyRetriever: () => tester.view.devicePixelRatio,
|
||||
propertyResetter: () => boundDisplay().resetDevicePixelRatio(),
|
||||
propertyFaker: (double dpr) => boundDisplay().devicePixelRatio = dpr,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('updating devicePixelRatio also updates view.devicePixelRatio', (WidgetTester tester) async {
|
||||
tester.view.display.devicePixelRatio = tester.view.devicePixelRatio + 1;
|
||||
|
||||
expect(tester.view.devicePixelRatio, tester.view.display.devicePixelRatio);
|
||||
});
|
||||
|
||||
testWidgets('can fake refreshRate', (WidgetTester tester) async {
|
||||
verifyPropertyFaked<double>(
|
||||
tester: tester,
|
||||
realValue: trueDisplay().refreshRate,
|
||||
fakeValue: trueDisplay().refreshRate + 1,
|
||||
propertyRetriever: () => boundDisplay().refreshRate,
|
||||
propertyFaker: (_, double fake) {
|
||||
boundDisplay().refreshRate = fake;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('can reset refreshRate', (WidgetTester tester) async {
|
||||
verifyPropertyReset<double>(
|
||||
tester: tester,
|
||||
fakeValue: trueDisplay().refreshRate + 1,
|
||||
propertyRetriever: () => boundDisplay().refreshRate,
|
||||
propertyResetter: () => boundDisplay().resetRefreshRate(),
|
||||
propertyFaker: (double fake) {
|
||||
boundDisplay().refreshRate = fake;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('can fake size', (WidgetTester tester) async {
|
||||
verifyPropertyFaked<Size>(
|
||||
tester: tester,
|
||||
realValue: trueDisplay().size,
|
||||
fakeValue: const Size(354, 856),
|
||||
propertyRetriever: () => boundDisplay().size,
|
||||
propertyFaker: (_, Size fake) {
|
||||
boundDisplay().size = fake;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('can reset size', (WidgetTester tester) async {
|
||||
verifyPropertyReset<Size>(
|
||||
tester: tester,
|
||||
fakeValue: const Size(465, 980),
|
||||
propertyRetriever: () => boundDisplay().size,
|
||||
propertyResetter: () => boundDisplay().resetSize(),
|
||||
propertyFaker: (Size fake) {
|
||||
boundDisplay().size = fake;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('can reset all values', (WidgetTester tester) async {
|
||||
final DisplaySnapshot initial = DisplaySnapshot(tester.view.display);
|
||||
|
||||
tester.view.display.devicePixelRatio = 7;
|
||||
tester.view.display.refreshRate = 40;
|
||||
tester.view.display.size = const Size(476, 823);
|
||||
|
||||
final DisplaySnapshot faked = DisplaySnapshot(tester.view.display);
|
||||
|
||||
tester.view.display.reset();
|
||||
|
||||
final DisplaySnapshot reset = DisplaySnapshot(tester.view.display);
|
||||
|
||||
expect(initial, isNot(matchesSnapshot(faked)));
|
||||
expect(initial, matchesSnapshot(reset));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class DisplaySnapshot {
|
||||
DisplaySnapshot(Display display) :
|
||||
devicePixelRatio = display.devicePixelRatio,
|
||||
refreshRate = display.refreshRate,
|
||||
id = display.id,
|
||||
size = display.size;
|
||||
|
||||
final double devicePixelRatio;
|
||||
final double refreshRate;
|
||||
final int id;
|
||||
final Size size;
|
||||
}
|
||||
|
||||
Matcher matchesSnapshot(DisplaySnapshot expected) => _DisplaySnapshotMatcher(expected);
|
||||
|
||||
class _DisplaySnapshotMatcher extends Matcher {
|
||||
_DisplaySnapshotMatcher(this.expected);
|
||||
|
||||
final DisplaySnapshot expected;
|
||||
|
||||
@override
|
||||
Description describe(Description description) {
|
||||
description.add('snapshot of a Display matches');
|
||||
return description;
|
||||
}
|
||||
|
||||
@override
|
||||
Description describeMismatch(dynamic item, Description mismatchDescription, Map<dynamic, dynamic> matchState, bool verbose) {
|
||||
assert(item is DisplaySnapshot, 'Can only match against snapshots of Display.');
|
||||
final DisplaySnapshot actual = item as DisplaySnapshot;
|
||||
|
||||
if (actual.devicePixelRatio != expected.devicePixelRatio) {
|
||||
mismatchDescription.add('actual.devicePixelRatio (${actual.devicePixelRatio}) did not match expected.devicePixelRatio (${expected.devicePixelRatio})');
|
||||
}
|
||||
if (actual.refreshRate != expected.refreshRate) {
|
||||
mismatchDescription.add('actual.refreshRate (${actual.refreshRate}) did not match expected.refreshRate (${expected.refreshRate})');
|
||||
}
|
||||
if (actual.size != expected.size) {
|
||||
mismatchDescription.add('actual.size (${actual.size}) did not match expected.size (${expected.size})');
|
||||
}
|
||||
if (actual.id != expected.id) {
|
||||
mismatchDescription.add('actual.id (${actual.id}) did not match expected.id (${expected.id})');
|
||||
}
|
||||
|
||||
return mismatchDescription;
|
||||
}
|
||||
|
||||
@override
|
||||
bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
|
||||
assert(item is DisplaySnapshot, 'Can only match against snapshots of Display.');
|
||||
final DisplaySnapshot actual = item as DisplaySnapshot;
|
||||
|
||||
return actual.devicePixelRatio == expected.devicePixelRatio &&
|
||||
actual.refreshRate == expected.refreshRate &&
|
||||
actual.size == expected.size &&
|
||||
actual.id == expected.id;
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:ui' show AccessibilityFeatures, Brightness, Locale, PlatformDispatcher;
|
||||
import 'dart:ui' show AccessibilityFeatures, Brightness, Display, FlutterView, Locale, PlatformDispatcher, VoidCallback;
|
||||
|
||||
import 'package:flutter/widgets.dart' show WidgetsBinding, WidgetsBindingObserver;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -152,6 +152,102 @@ void main() {
|
||||
expect(observer.locales, equals(expectedValue));
|
||||
retrieveTestBinding(tester).platformDispatcher.localesTestValue = defaultLocales;
|
||||
});
|
||||
|
||||
// TODO(pdblasi-google): Removed this group of tests when the Display API is stable and supported on all platforms.
|
||||
group('TestPlatformDispatcher with unsupported Display API', () {
|
||||
testWidgets('can initialize with empty displays', (WidgetTester tester) async {
|
||||
expect(() {
|
||||
TestPlatformDispatcher(
|
||||
platformDispatcher: _FakePlatformDispatcher(
|
||||
displays: <Display>[],
|
||||
views: <FlutterView>[
|
||||
_FakeFlutterView(),
|
||||
],
|
||||
)
|
||||
);
|
||||
}, isNot(throwsA(anything)));
|
||||
});
|
||||
|
||||
testWidgets('can initialize with mismatched displays', (WidgetTester tester) async {
|
||||
expect(() {
|
||||
TestPlatformDispatcher(
|
||||
platformDispatcher: _FakePlatformDispatcher(
|
||||
displays: <Display>[
|
||||
_FakeDisplay(id: 2),
|
||||
],
|
||||
views: <FlutterView>[
|
||||
_FakeFlutterView(display: _FakeDisplay(id: 1)),
|
||||
],
|
||||
)
|
||||
);
|
||||
}, isNot(throwsA(anything)));
|
||||
});
|
||||
|
||||
testWidgets('creates test views for all views', (WidgetTester tester) async {
|
||||
final PlatformDispatcher backingDispatcher = _FakePlatformDispatcher(
|
||||
displays: <Display>[],
|
||||
views: <FlutterView>[
|
||||
_FakeFlutterView(),
|
||||
],
|
||||
);
|
||||
final TestPlatformDispatcher testDispatcher = TestPlatformDispatcher(
|
||||
platformDispatcher: backingDispatcher,
|
||||
);
|
||||
|
||||
expect(testDispatcher.views.length, backingDispatcher.views.length);
|
||||
});
|
||||
|
||||
group('creates TestFlutterViews', () {
|
||||
testWidgets('that defaults to the correct devicePixelRatio', (WidgetTester tester) async {
|
||||
const double expectedDpr = 2.5;
|
||||
final TestPlatformDispatcher testDispatcher = TestPlatformDispatcher(
|
||||
platformDispatcher: _FakePlatformDispatcher(
|
||||
displays: <Display>[],
|
||||
views: <FlutterView>[
|
||||
_FakeFlutterView(devicePixelRatio: expectedDpr),
|
||||
],
|
||||
)
|
||||
);
|
||||
|
||||
expect(testDispatcher.views.single.devicePixelRatio, expectedDpr);
|
||||
});
|
||||
|
||||
testWidgets('with working devicePixelRatio setter', (WidgetTester tester) async {
|
||||
const double expectedDpr = 2.5;
|
||||
const double defaultDpr = 4;
|
||||
final TestPlatformDispatcher testDispatcher = TestPlatformDispatcher(
|
||||
platformDispatcher: _FakePlatformDispatcher(
|
||||
displays: <Display>[],
|
||||
views: <FlutterView>[
|
||||
_FakeFlutterView(devicePixelRatio: defaultDpr),
|
||||
],
|
||||
)
|
||||
);
|
||||
|
||||
testDispatcher.views.single.devicePixelRatio = expectedDpr;
|
||||
|
||||
expect(testDispatcher.views.single.devicePixelRatio, expectedDpr);
|
||||
});
|
||||
|
||||
testWidgets('with working resetDevicePixelRatio', (WidgetTester tester) async {
|
||||
const double changedDpr = 2.5;
|
||||
const double defaultDpr = 4;
|
||||
final TestPlatformDispatcher testDispatcher = TestPlatformDispatcher(
|
||||
platformDispatcher: _FakePlatformDispatcher(
|
||||
displays: <Display>[],
|
||||
views: <FlutterView>[
|
||||
_FakeFlutterView(devicePixelRatio: defaultDpr),
|
||||
],
|
||||
)
|
||||
);
|
||||
|
||||
testDispatcher.views.single.devicePixelRatio = changedDpr;
|
||||
testDispatcher.views.single.resetDevicePixelRatio();
|
||||
|
||||
expect(testDispatcher.views.single.devicePixelRatio, defaultDpr);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class TestObserver with WidgetsBindingObserver {
|
||||
@ -162,3 +258,45 @@ class TestObserver with WidgetsBindingObserver {
|
||||
this.locales = locales;
|
||||
}
|
||||
}
|
||||
|
||||
class _FakeDisplay extends Fake implements Display {
|
||||
_FakeDisplay({this.id = 0});
|
||||
|
||||
@override
|
||||
final int id;
|
||||
}
|
||||
|
||||
class _FakeFlutterView extends Fake implements FlutterView {
|
||||
_FakeFlutterView({
|
||||
this.devicePixelRatio = 1,
|
||||
Display? display,
|
||||
}) : _display = display;
|
||||
|
||||
@override
|
||||
final double devicePixelRatio;
|
||||
|
||||
// This emulates the PlatformDispatcher not having a display on the engine
|
||||
// side. We don't have access to the `_displayId` used in the engine to try
|
||||
// to find it and can't directly extend `FlutterView` to emulate it closer.
|
||||
@override
|
||||
Display get display {
|
||||
assert(_display != null);
|
||||
return _display!;
|
||||
}
|
||||
final Display? _display;
|
||||
|
||||
@override
|
||||
final Object viewId = 1;
|
||||
}
|
||||
|
||||
class _FakePlatformDispatcher extends Fake implements PlatformDispatcher {
|
||||
_FakePlatformDispatcher({required this.displays, required this.views});
|
||||
@override
|
||||
final Iterable<Display> displays;
|
||||
|
||||
@override
|
||||
final Iterable<FlutterView> views;
|
||||
|
||||
@override
|
||||
VoidCallback? onMetricsChanged;
|
||||
}
|
||||
|
@ -52,6 +52,12 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('updating devicePixelRatio also updates display.devicePixelRatio', (WidgetTester tester) async {
|
||||
tester.view.devicePixelRatio = tester.view.devicePixelRatio + 1;
|
||||
|
||||
expect(tester.view.display.devicePixelRatio, tester.view.devicePixelRatio);
|
||||
});
|
||||
|
||||
testWidgets('can fake displayFeatures', (WidgetTester tester) async {
|
||||
verifyPropertyFaked<List<DisplayFeature>>(
|
||||
tester: tester,
|
||||
@ -288,6 +294,7 @@ void main() {
|
||||
final TestFlutterView view = TestFlutterView(
|
||||
view: backingView,
|
||||
platformDispatcher: tester.binding.platformDispatcher,
|
||||
display: _FakeDisplay(),
|
||||
);
|
||||
|
||||
view.render(expectedScene);
|
||||
@ -302,6 +309,7 @@ void main() {
|
||||
final TestFlutterView view = TestFlutterView(
|
||||
view: backingView,
|
||||
platformDispatcher: tester.binding.platformDispatcher,
|
||||
display: _FakeDisplay(),
|
||||
);
|
||||
|
||||
view.updateSemantics(expectedUpdate);
|
||||
@ -312,7 +320,6 @@ void main() {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Matcher matchesSnapshot(FlutterViewSnapshot expected) => _FlutterViewSnapshotMatcher(expected);
|
||||
|
||||
class _FlutterViewSnapshotMatcher extends Matcher {
|
||||
@ -424,7 +431,7 @@ class FlutterViewSnapshot {
|
||||
final ViewPadding viewPadding;
|
||||
}
|
||||
|
||||
class _FakeFlutterView implements FlutterView {
|
||||
class _FakeFlutterView extends Fake implements FlutterView {
|
||||
SemanticsUpdate? lastSemanticsUpdate;
|
||||
Scene? lastRenderedScene;
|
||||
|
||||
@ -437,9 +444,6 @@ class _FakeFlutterView implements FlutterView {
|
||||
void render(Scene scene) {
|
||||
lastRenderedScene = scene;
|
||||
}
|
||||
|
||||
@override
|
||||
dynamic noSuchMethod(Invocation invocation) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class _FakeDisplay extends Fake implements TestDisplay { }
|
||||
|
Loading…
x
Reference in New Issue
Block a user