-
Notifications
You must be signed in to change notification settings - Fork 111
/
common.dart
162 lines (142 loc) · 5.16 KB
/
common.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// ignore_for_file: invalid_use_of_internal_member, implementation_imports
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:meta/meta.dart';
import 'package:patrol/src/binding.dart';
import 'package:patrol/src/custom_finders/patrol_tester.dart';
import 'package:patrol/src/native/contracts/contracts.pb.dart';
import 'package:patrol/src/native/contracts/contracts.pbgrpc.dart';
import 'package:patrol/src/native/native.dart';
import 'package:test_api/src/backend/group.dart';
import 'package:test_api/src/backend/invoker.dart';
import 'package:test_api/src/backend/test.dart';
import 'constants.dart' as constants;
/// Signature for callback to [patrolTest].
typedef PatrolTesterCallback = Future<void> Function(PatrolTester $);
/// Like [testWidgets], but with support for Patrol custom finders.
///
/// To customize the Patrol-specific configuration, set [config].
///
/// ### Using the default [WidgetTester]
///
/// If you need to do something using Flutter's [WidgetTester], you can access
/// it like this:
///
/// ```dart
/// patrolTest(
/// 'increase counter text',
/// ($) async {
/// await $.tester.tap(find.byIcon(Icons.add));
/// },
/// );
/// ```
///
/// [bindingType] specifies the binding to use. [bindingType] is ignored if
/// [nativeAutomation] is false.
@isTest
void patrolTest(
String description,
PatrolTesterCallback callback, {
bool? skip,
Timeout? timeout,
bool semanticsEnabled = true,
TestVariant<Object?> variant = const DefaultTestVariant(),
dynamic tags,
PatrolTesterConfig config = const PatrolTesterConfig(),
NativeAutomatorConfig nativeAutomatorConfig = const NativeAutomatorConfig(),
bool nativeAutomation = false,
BindingType bindingType = BindingType.patrol,
LiveTestWidgetsFlutterBindingFramePolicy framePolicy =
LiveTestWidgetsFlutterBindingFramePolicy.fadePointers,
}) {
NativeAutomator? nativeAutomator;
PatrolBinding? patrolBinding;
if (nativeAutomation) {
switch (bindingType) {
case BindingType.patrol:
nativeAutomator = NativeAutomator(config: nativeAutomatorConfig);
patrolBinding = PatrolBinding.ensureInitialized();
patrolBinding.framePolicy = framePolicy;
break;
case BindingType.integrationTest:
IntegrationTestWidgetsFlutterBinding.ensureInitialized().framePolicy =
framePolicy;
break;
case BindingType.none:
break;
}
}
testWidgets(
description,
skip: skip,
timeout: timeout,
semanticsEnabled: semanticsEnabled,
variant: variant,
tags: tags,
(widgetTester) async {
if (patrolBinding != null && !constants.hotRestartEnabled) {
// If Patrol's native automation feature is enabled, then this test will
// be executed only if the native side requested it to be executed.
// Otherwise, it returns early.
//
// The assumption here is that this test doesn't have any extra parent
// groups. Every Dart test suite has an implict, unnamed, top-level
// group. An additional group is present in the bundled_test.dart, and
// its name is equal to the path to the Dart test file in the
// integration_test directory.
//
// In other words, the developer cannot use `group()` in the tests.
//
// Example: if this function is called from the Dart test file named
// "example_test.dart", and that file is located in the
// "integration_test/examples" directory, we assume that the name of the
// immediate parent group is "examples.example_test".
final parentGroupName = Invoker.current!.liveTest.groups.last.name;
final requestedToExecute = await patrolBinding.patrolAppService
.waitForExecutionRequest(parentGroupName);
if (!requestedToExecute) {
return;
}
await nativeAutomator?.configure();
}
final patrolTester = PatrolTester(
tester: widgetTester,
nativeAutomator: nativeAutomator,
config: config,
);
await callback(patrolTester);
// ignore: prefer_const_declarations
final waitSeconds = const int.fromEnvironment('PATROL_WAIT');
final waitDuration = Duration(seconds: waitSeconds);
if (waitDuration > Duration.zero) {
final stopwatch = Stopwatch()..start();
await Future.doWhile(() async {
await widgetTester.pump();
if (stopwatch.elapsed > waitDuration) {
stopwatch.stop();
return false;
}
return true;
});
}
},
);
}
/// Creates a DartTestGroup by visiting the subgroups of [topLevelGroup].
@internal
DartTestGroup createDartTestGroup(
Group topLevelGroup, {
String prefix = '',
}) {
final groupName = topLevelGroup.name.replaceFirst(prefix, '').trim();
final group = DartTestGroup(name: groupName);
for (final entry in topLevelGroup.entries) {
if (entry is Group) {
group.groups.add(DartTestGroup(name: entry.name));
}
if (entry is Test && entry.name != 'patrol_test_explorer') {
throw StateError('Expected group, got test: ${entry.name}');
}
}
return group;
}