Add a isSystemTextScaler
matcher (#160120)
This is for https://github.com/flutter/flutter/pull/159999. That PR breaks registered tests so a new matcher is added for soft transition & making it slightly easier to write tests that verify nothing is shadowing the system text scaler in the widget tree. If this approach sounds plausible & gets merged, I'm going to: 1. remake the breaking change announcement 2. update the migration guide with the new matcher, 3. migrate the registered tests and mark #159999 as ready for review. ## Pre-launch Checklist - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ ] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
696251d25a
commit
ac7118832d
@ -246,6 +246,22 @@ Matcher isSameColorAs(Color color, {double threshold = colorEpsilon}) {
|
|||||||
return _ColorMatcher(color, threshold);
|
return _ColorMatcher(color, threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Asserts that the object is a [TextScaler] that reflects the user's font
|
||||||
|
/// scale preferences from the platform's accessibility settings.
|
||||||
|
///
|
||||||
|
/// This matcher is useful for verifying the text scaling within a widget subtree
|
||||||
|
/// respects the user accessibility preferences, and not accidentally being
|
||||||
|
/// shadowed by a [MediaQuery] with a different type of [TextScaler].
|
||||||
|
///
|
||||||
|
/// In widget tests, the value of the system font scale preference can be
|
||||||
|
/// changed via [TestPlatformDispatcher.textScaleFactorTestValue].
|
||||||
|
///
|
||||||
|
/// If `withScaleFactor` is specified and non-null, this matcher also asserts
|
||||||
|
/// that the [TextScaler]'s' `textScaleFactor` equals `withScaleFactor`.
|
||||||
|
Matcher isSystemTextScaler({double? withScaleFactor}) {
|
||||||
|
return _IsSystemTextScaler(withScaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
/// Asserts that an object's toString() is a plausible one-line description.
|
/// Asserts that an object's toString() is a plausible one-line description.
|
||||||
///
|
///
|
||||||
/// Specifically, this matcher checks that the string does not contains newline
|
/// Specifically, this matcher checks that the string does not contains newline
|
||||||
@ -1205,6 +1221,58 @@ class _IsNotInCard extends Matcher {
|
|||||||
Description describe(Description description) => description.add('not in card');
|
Description describe(Description description) => description.add('not in card');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _IsSystemTextScaler extends Matcher {
|
||||||
|
const _IsSystemTextScaler(this.expectedUserTextScaleFactor);
|
||||||
|
|
||||||
|
final double? expectedUserTextScaleFactor;
|
||||||
|
|
||||||
|
// TODO(LongCatIsLooong): update the runtime type after introducing _SystemTextScaler.
|
||||||
|
static final Type _expectedRuntimeType = (const TextScaler.linear(2)).runtimeType;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
|
||||||
|
if (item is! TextScaler) {
|
||||||
|
return failWithDescription(matchState, '${item.runtimeType} is not a TextScaler');
|
||||||
|
}
|
||||||
|
if (!identical(item.runtimeType, _expectedRuntimeType)) {
|
||||||
|
return failWithDescription(matchState, '${item.runtimeType} is not a system TextScaler');
|
||||||
|
}
|
||||||
|
final double actualTextScaleFactor = item.textScaleFactor;
|
||||||
|
if (expectedUserTextScaleFactor != null &&
|
||||||
|
expectedUserTextScaleFactor != actualTextScaleFactor) {
|
||||||
|
return failWithDescription(
|
||||||
|
matchState,
|
||||||
|
'expecting a scale factor of $expectedUserTextScaleFactor, but got $actualTextScaleFactor',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Description describe(Description description) {
|
||||||
|
final String scaleFactorExpectation =
|
||||||
|
expectedUserTextScaleFactor == null ? '' : '(${expectedUserTextScaleFactor}x)';
|
||||||
|
return description.add(
|
||||||
|
'A TextScaler that reflects the font scale settings in the system user preference ($_expectedRuntimeType$scaleFactorExpectation)',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool failWithDescription(Map<dynamic, dynamic> matchState, String description) {
|
||||||
|
matchState['failure'] = description;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Description describeMismatch(
|
||||||
|
dynamic item,
|
||||||
|
Description mismatchDescription,
|
||||||
|
Map<dynamic, dynamic> matchState,
|
||||||
|
bool verbose,
|
||||||
|
) {
|
||||||
|
return mismatchDescription.add(matchState['failure'] as String);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _HasOneLineDescription extends Matcher {
|
class _HasOneLineDescription extends Matcher {
|
||||||
const _HasOneLineDescription();
|
const _HasOneLineDescription();
|
||||||
|
|
||||||
|
@ -320,6 +320,9 @@ class TestPlatformDispatcher implements PlatformDispatcher {
|
|||||||
onTextScaleFactorChanged?.call();
|
onTextScaleFactorChanged?.call();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double scaleFontSize(double unscaledFontSize) => textScaleFactor * unscaledFontSize;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Brightness get platformBrightness =>
|
Brightness get platformBrightness =>
|
||||||
_platformBrightnessTestValue ?? _platformDispatcher.platformBrightness;
|
_platformBrightnessTestValue ?? _platformDispatcher.platformBrightness;
|
||||||
|
@ -393,6 +393,17 @@ void main() {
|
|||||||
expect(const Color(0x00000000), isSameColorAs(const Color(0x00000002), threshold: 0.008));
|
expect(const Color(0x00000000), isSameColorAs(const Color(0x00000002), threshold: 0.008));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('isSystemTextScaler', (WidgetTester tester) async {
|
||||||
|
addTearDown(tester.platformDispatcher.clearAllTestValues);
|
||||||
|
tester.platformDispatcher.textScaleFactorTestValue = 123;
|
||||||
|
|
||||||
|
final MediaQueryData mediaQueryData = MediaQueryData.fromView(tester.view);
|
||||||
|
final TextScaler systemScaler = mediaQueryData.textScaler;
|
||||||
|
expect(systemScaler, isSystemTextScaler());
|
||||||
|
expect(systemScaler, isSystemTextScaler(withScaleFactor: 123));
|
||||||
|
expect(systemScaler, isNot(isSystemTextScaler(withScaleFactor: 2)));
|
||||||
|
});
|
||||||
|
|
||||||
group('coversSameAreaAs', () {
|
group('coversSameAreaAs', () {
|
||||||
test('empty Paths', () {
|
test('empty Paths', () {
|
||||||
expect(
|
expect(
|
||||||
|
@ -181,6 +181,20 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('TestPlatformDispatcher has a working scaleFontSize implementation', (
|
||||||
|
WidgetTester tester,
|
||||||
|
) async {
|
||||||
|
expect(
|
||||||
|
TestPlatformDispatcher(
|
||||||
|
platformDispatcher: _FakePlatformDispatcher(
|
||||||
|
displays: <Display>[_FakeDisplay(id: 2)],
|
||||||
|
views: <FlutterView>[_FakeFlutterView(display: _FakeDisplay(id: 1))],
|
||||||
|
),
|
||||||
|
).scaleFontSize(2.0),
|
||||||
|
2.0,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// TODO(pdblasi-google): Removed this group of tests when the Display API is stable and supported on all platforms.
|
// 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', () {
|
group('TestPlatformDispatcher with unsupported Display API', () {
|
||||||
testWidgets('can initialize with empty displays', (WidgetTester tester) async {
|
testWidgets('can initialize with empty displays', (WidgetTester tester) async {
|
||||||
@ -314,4 +328,7 @@ class _FakePlatformDispatcher extends Fake implements PlatformDispatcher {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
ViewFocusChangeCallback? onViewFocusChange;
|
ViewFocusChangeCallback? onViewFocusChange;
|
||||||
|
|
||||||
|
@override
|
||||||
|
double get textScaleFactor => 1.0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user