Skip to content

Commit 3ebdd83

Browse files
authored
Merge pull request #58 from eBay/feature/expose-device-size-api
Feature/expose device size api
2 parents 7ed7efd + b2b44c2 commit 3ebdd83

File tree

7 files changed

+144
-58
lines changed

7 files changed

+144
-58
lines changed

packages/golden_toolkit/CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,26 @@ Future releases will likely consolidate these APIs.
2929

3030
Thanks to @christian-muertz for this enhancement.
3131

32+
### Added additional utility functions for preparing for goldens
33+
34+
Extracted out some public extension methods that were previously private implementation details of ```multiScreenGolden``` & ```screenMatchesGolden```
35+
36+
Added the following extensions. These can be used with any vanilla golden assertions and do not require ```multiScreenGolden```, ```screenMatchesGolden```, or ```GoldenBuilder```.
37+
38+
```dart
39+
// configures the simulated device to mirror the supplied device configuration (dimensions, pixel density, safe area, etc)
40+
tester.binding.applyDeviceOverrides(device);
41+
42+
// resets any configuration applied by applyDeviceOverrides
43+
tester.binding.resetDeviceOverrides();
44+
45+
// runs a block of code with the simulated device settings and automatically clears upon completion
46+
tester.binding.runWithDeviceOverrides(device, body: (){});
47+
48+
// convenience helper for configurating the safe area... the built-in paddingTestValue is difficult to work with
49+
tester.binding.window.safeAreaTestValue = EdgeInsets.all(8);
50+
```
51+
3252
### Misc Changes
3353

3454
A few API / parameters were marked as deprecated and will be removed in future releases.

packages/golden_toolkit/lib/golden_toolkit.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ export 'src/font_loader.dart' show loadAppFonts;
1313
export 'src/golden_builder.dart';
1414
export 'src/multi_screen_golden.dart';
1515
export 'src/testing_tools.dart' hide compareWithGolden;
16+
export 'src/widget_tester_extensions.dart';

packages/golden_toolkit/lib/src/multi_screen_golden.dart

Lines changed: 6 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@
88
99
//ignore_for_file: deprecated_member_use_from_same_package
1010

11-
import 'dart:ui';
12-
1311
import 'package:flutter/material.dart';
1412
import 'package:flutter_test/flutter_test.dart';
1513

1614
import 'configuration.dart';
1715
import 'device.dart';
1816
import 'testing_tools.dart';
17+
import 'widget_tester_extensions.dart';
1918

2019
Future<void> _twoPumps(Device device, WidgetTester tester) async {
2120
await tester.pump();
@@ -66,10 +65,12 @@ Future<void> multiScreenGolden(
6665
assert(devices?.isNotEmpty ?? false);
6766
final deviceSetupPump = deviceSetup ?? _twoPumps;
6867
for (final device in devices) {
69-
await tester._applyDeviceOverrides(
68+
await tester.binding.runWithDeviceOverrides(
7069
device,
71-
overriddenHeight: overrideGoldenHeight,
72-
operation: () async {
70+
body: () async {
71+
if (overrideGoldenHeight != null) {
72+
await tester.binding.setSurfaceSize(Size(device.size.width, overrideGoldenHeight));
73+
}
7374
await deviceSetupPump(device, tester);
7475
await compareWithGolden(
7576
tester,
@@ -86,53 +87,3 @@ Future<void> multiScreenGolden(
8687
);
8788
}
8889
}
89-
90-
extension on WidgetTester {
91-
Future<void> _applyDeviceOverrides(
92-
Device device, {
93-
double overriddenHeight,
94-
Future<void> Function() operation,
95-
}) async {
96-
await binding.setSurfaceSize(Size(device.size.width, overriddenHeight ?? device.size.height));
97-
binding.window.physicalSizeTestValue = device.size;
98-
binding.window.devicePixelRatioTestValue = device.devicePixelRatio;
99-
binding.window.textScaleFactorTestValue = device.textScale;
100-
binding.window.paddingTestValue = _FakeWindowPadding(
101-
bottom: device.safeArea.bottom,
102-
left: device.safeArea.left,
103-
right: device.safeArea.right,
104-
top: device.safeArea.top,
105-
);
106-
binding.window.platformBrightnessTestValue = device.brightness;
107-
108-
await operation();
109-
110-
binding.window.clearDevicePixelRatioTestValue();
111-
binding.window.clearPlatformBrightnessTestValue();
112-
binding.window.clearPaddingTestValue();
113-
binding.window.clearTextScaleFactorTestValue();
114-
binding.window.clearPhysicalSizeTestValue();
115-
await binding.setSurfaceSize(null);
116-
}
117-
}
118-
119-
class _FakeWindowPadding implements WindowPadding {
120-
const _FakeWindowPadding({
121-
this.bottom = 0,
122-
this.left = 0,
123-
this.right = 0,
124-
this.top = 0,
125-
});
126-
127-
@override
128-
final double bottom;
129-
130-
@override
131-
final double left;
132-
133-
@override
134-
final double right;
135-
136-
@override
137-
final double top;
138-
}

packages/golden_toolkit/lib/src/testing_tools.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,23 +192,21 @@ Future<void> compareWithGolden(
192192
fail(
193193
'Golden tests MUST be run within a testGoldens method, not just a testWidgets method. This is so we can be confident that running "flutter test --name=GOLDEN" will run all golden tests.');
194194
}
195-
196195
final shouldSkipGoldenGeneration = skip ?? GoldenToolkit.configuration.skipGoldenAssertion();
197196

198197
final pumpAfterPrime = customPump ?? _onlyPumpAndSettle;
199198
/* if no finder is specified, use the first widget. Note, there is no guarantee this evaluates top-down, but in theory if all widgets are in the same
200199
RepaintBoundary, it should not matter */
201200
final actualFinder = finder ?? find.byWidgetPredicate((w) => true).first;
202201
final fileName = fileNameFactory(name, device);
202+
final originalWindowSize = tester.binding.window.physicalSize;
203203

204204
// This is a minor optimization and works around an issue with the current hacky implementation of invoking the golden assertion method.
205205
if (!shouldSkipGoldenGeneration) {
206206
await _primeImages(fileName, actualFinder);
207207
}
208208
await pumpAfterPrime(tester);
209209

210-
final originalWindowSize = tester.binding.window.physicalSize;
211-
212210
if (autoHeight == true) {
213211
// Find the first scrollable element which can be scrolled vertical.
214212
// ListView, SingleChildScrollView, CustomScrollView? are implemented using a Scrollable widget.
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import 'dart:ui';
2+
3+
import 'package:flutter/widgets.dart';
4+
import 'package:flutter_test/flutter_test.dart';
5+
6+
import 'device.dart';
7+
8+
/// Convenience extensions for more easily configuring WidgetTester for pre-set configurations
9+
extension WidgetTesterExtensions on TestWidgetsFlutterBinding {
10+
/// Configure the Test device for the duration of the supplied operation and revert
11+
///
12+
/// [device] the desired configuration to apply
13+
///
14+
/// [body] the closure you wish to be executed with the device configuration applied
15+
///
16+
Future<void> runWithDeviceOverrides(
17+
Device device, {
18+
Future<void> Function() body,
19+
}) async {
20+
await applyDeviceOverrides(device);
21+
try {
22+
await body();
23+
} finally {
24+
await resetDeviceOverrides();
25+
}
26+
}
27+
28+
/// Configure the Test device to match the configuration of the supplied device
29+
///
30+
/// Note: these settings will persist across multiple tests in the same file. It is recommended
31+
/// that you reset upon completion.
32+
///
33+
/// [device] the desired configuration to apply
34+
///
35+
Future<void> applyDeviceOverrides(Device device) async {
36+
await setSurfaceSize(Size(device.size.width, device.size.height));
37+
this.window.physicalSizeTestValue = device.size;
38+
this.window.devicePixelRatioTestValue = device.devicePixelRatio;
39+
this.window.textScaleFactorTestValue = device.textScale;
40+
this.window.safeAreaTestValue = device.safeArea;
41+
this.window.platformBrightnessTestValue = device.brightness;
42+
}
43+
44+
/// Resets any configuration that may be been specified by applyDeviceOverrides
45+
///
46+
/// Only needs to be called if you are concerned about the result of applyDeviceOverrides bleeding over across tests.
47+
Future<void> resetDeviceOverrides() async {
48+
// there is an untested assumption that clearing these specific values is cheaper than
49+
// calling binding.window.clearAllTestValues().
50+
this.window.clearDevicePixelRatioTestValue();
51+
this.window.clearPlatformBrightnessTestValue();
52+
this.window.clearPaddingTestValue();
53+
this.window.clearTextScaleFactorTestValue();
54+
this.window.clearPhysicalSizeTestValue();
55+
await setSurfaceSize(null);
56+
}
57+
}
58+
59+
/// Convenience extensions for configuring elements of the TestWindow
60+
extension TestWindowExtensions on TestWindow {
61+
/// convenience wrapper for configuring the paddingTestValue
62+
///
63+
/// paddingTestValue requires you creating your own class that implements WindowPadding
64+
///
65+
/// [safeArea] specifies the safe area insets for all 4 edges that you wish to simulate
66+
///
67+
set safeAreaTestValue(EdgeInsets safeArea) {
68+
paddingTestValue = _FakeWindowPadding(
69+
bottom: safeArea.bottom,
70+
left: safeArea.left,
71+
right: safeArea.right,
72+
top: safeArea.top,
73+
);
74+
}
75+
}
76+
77+
class _FakeWindowPadding implements WindowPadding {
78+
const _FakeWindowPadding({
79+
this.bottom = 0,
80+
this.left = 0,
81+
this.right = 0,
82+
this.top = 0,
83+
});
84+
85+
@override
86+
final double bottom;
87+
88+
@override
89+
final double left;
90+
91+
@override
92+
final double right;
93+
94+
@override
95+
final double top;
96+
}
338 Bytes
Loading

packages/golden_toolkit/test/multi_screen_golden_test.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,26 @@ Future<void> main() async {
162162
],
163163
);
164164
});
165+
166+
testGoldens('Should set to exact height if override height is specified', (tester) async {
167+
await tester.pumpWidget(Center(
168+
// We center here so the Container is not forced to go full height
169+
child: Container(color: Colors.red, height: 50),
170+
));
171+
172+
await multiScreenGolden(
173+
tester,
174+
'override_height',
175+
overrideGoldenHeight: 300,
176+
devices: [
177+
const Device(
178+
name: 'anything',
179+
size: Size(100, 200),
180+
brightness: Brightness.light,
181+
)
182+
],
183+
);
184+
});
165185
});
166186
});
167187
}

0 commit comments

Comments
 (0)