2
2
// Use of this source code is governed by a BSD-style license that can be
3
3
// found in the LICENSE file.
4
4
5
- import 'dart:async' ;
6
-
7
- import 'package:collection/collection.dart' ;
8
5
import 'package:devtools_app/devtools_app.dart' ;
9
- import 'package:devtools_app/src/service/service_extension_widgets.dart' ;
10
- import 'package:devtools_app/src/service/service_extensions.dart' as extensions;
11
- import 'package:devtools_app_shared/service.dart' ;
12
6
import 'package:devtools_app_shared/ui.dart' ;
13
7
import 'package:devtools_app_shared/utils.dart' ;
14
- import 'package:devtools_shared/devtools_shared.dart' ;
15
8
import 'package:devtools_test/helpers.dart' ;
16
9
import 'package:devtools_test/integration_test.dart' ;
17
- import 'package:flutter/widgets.dart' ;
18
10
import 'package:flutter_test/flutter_test.dart' ;
19
11
import 'package:integration_test/integration_test.dart' ;
20
- import 'package:vm_service/vm_service.dart' ;
21
12
22
13
// To run:
23
14
// dart run integration_test/run_tests.dart --target=integration_test/test/live_connection/service_connection_test.dart
@@ -54,7 +45,7 @@ void main() {
54
45
// Use a range instead of an exact number because service extension
55
46
// calls are not consistent. This will still catch any spurious calls
56
47
// that are unintentionally added at start up.
57
- const Range (40 , 70 ).contains (vmServiceCallCount),
48
+ const Range (35 , 70 ).contains (vmServiceCallCount),
58
49
isTrue,
59
50
reason: 'Unexpected number of vm service calls upon connection: '
60
51
'$vmServiceCallCount . If this is expected, please update this test '
@@ -69,10 +60,12 @@ void main() {
69
60
// Filter out unawaited streamListen calls.
70
61
.where ((call) => call != 'streamListen' )
71
62
.toList ()
72
- .sublist (0 , 6 ),
63
+ .sublist (0 , 8 ),
73
64
equals ([
74
65
'getSupportedProtocols' ,
75
66
'getVersion' ,
67
+ 'setFlag' ,
68
+ 'requirePermissionToResume' ,
76
69
'getFlagList' ,
77
70
'getDartDevelopmentServiceVersion' ,
78
71
'getDartDevelopmentServiceVersion' ,
@@ -110,339 +103,4 @@ void main() {
110
103
111
104
await disconnectFromTestApp (tester);
112
105
});
113
-
114
- testWidgets ('can call services and service extensions' , (tester) async {
115
- await pumpAndConnectDevTools (tester, testApp);
116
- await tester.pump (longDuration);
117
-
118
- // TODO(kenz): re-work this integration test so that we do not have to be
119
- // on the inspector screen for this to pass.
120
- await switchToScreen (
121
- tester,
122
- tabIcon: ScreenMetaData .inspector.icon! ,
123
- screenId: ScreenMetaData .inspector.id,
124
- );
125
- await tester.pump (longDuration);
126
-
127
- // Ensure all futures are completed before running checks.
128
- await serviceConnection.serviceManager.service! .allFuturesCompleted;
129
-
130
- logStatus ('verify Flutter framework service extensions' );
131
- await _verifyBooleanExtension (tester);
132
- await _verifyNumericExtension (tester);
133
- await _verifyStringExtension (tester);
134
-
135
- logStatus ('verify Flutter engine service extensions' );
136
- expect (
137
- await serviceConnection.queryDisplayRefreshRate,
138
- equals (60 ),
139
- );
140
-
141
- logStatus ('verify services that are registered to exactly one client' );
142
- await _verifyHotReloadAndHotRestart ();
143
- await expectLater (
144
- serviceConnection.serviceManager.callService ('fakeMethod' ),
145
- throwsException,
146
- );
147
-
148
- await disconnectFromTestApp (tester);
149
- });
150
-
151
- testWidgets ('loads initial extension states from device' , (tester) async {
152
- await pumpAndConnectDevTools (tester, testApp);
153
- await tester.pump (longDuration);
154
-
155
- // Ensure all futures are completed before running checks.
156
- final service = serviceConnection.serviceManager.service! ;
157
- await service.allFuturesCompleted;
158
-
159
- final serviceExtensionsToEnable = [
160
- (extensions.debugPaint.extension , true ),
161
- (extensions.slowAnimations.extension , 5.0 ),
162
- (extensions.togglePlatformMode.extension , 'iOS' ),
163
- ];
164
-
165
- logStatus ('enabling service extensions on the test device' );
166
- // Enable a service extension of each type (boolean, numeric, string).
167
- for (final ext in serviceExtensionsToEnable) {
168
- await serviceConnection.serviceManager.serviceExtensionManager
169
- .setServiceExtensionState (
170
- ext.$1,
171
- enabled: true ,
172
- value: ext.$2,
173
- );
174
- }
175
-
176
- logStatus ('disconnecting from the test device' );
177
- await disconnectFromTestApp (tester);
178
-
179
- for (final ext in serviceExtensionsToEnable) {
180
- expect (
181
- serviceConnection.serviceManager.serviceExtensionManager
182
- .isServiceExtensionAvailable (ext.$1),
183
- isFalse,
184
- );
185
- }
186
-
187
- logStatus ('reconnecting to the test device' );
188
- await connectToTestApp (tester, testApp);
189
-
190
- logStatus ('verify extension states have been restored from the device' );
191
- for (final ext in serviceExtensionsToEnable) {
192
- expect (
193
- serviceConnection.serviceManager.serviceExtensionManager
194
- .isServiceExtensionAvailable (ext.$1),
195
- isTrue,
196
- );
197
- await _verifyExtensionStateInServiceManager (
198
- ext.$1,
199
- enabled: true ,
200
- value: ext.$2,
201
- );
202
- }
203
-
204
- await disconnectFromTestApp (tester);
205
- });
206
- }
207
-
208
- Future <void > _verifyBooleanExtension (WidgetTester tester) async {
209
- final extensionName = extensions.debugPaint.extension ;
210
- const evalExpression = 'debugPaintSizeEnabled' ;
211
- final library = EvalOnDartLibrary (
212
- 'package:flutter/src/rendering/debug.dart' ,
213
- serviceConnection.serviceManager.service! ,
214
- serviceManager: serviceConnection.serviceManager,
215
- );
216
- await _verifyExtension (
217
- tester,
218
- extensionName: extensionName,
219
- evalExpression: evalExpression,
220
- library: library,
221
- initialValue: false ,
222
- newValue: true ,
223
- );
224
- }
225
-
226
- Future <void > _verifyNumericExtension (WidgetTester tester) async {
227
- final extensionName = extensions.slowAnimations.extension ;
228
- const evalExpression = 'timeDilation' ;
229
- final library = EvalOnDartLibrary (
230
- 'package:flutter/src/scheduler/binding.dart' ,
231
- serviceConnection.serviceManager.service! ,
232
- serviceManager: serviceConnection.serviceManager,
233
- );
234
- await _verifyExtension (
235
- tester,
236
- extensionName: extensionName,
237
- evalExpression: evalExpression,
238
- library: library,
239
- initialValue: 1.0 ,
240
- newValue: 5.0 ,
241
- initialValueOnDevice: '1.0' ,
242
- newValueOnDevice: '5.0' ,
243
- );
244
- }
245
-
246
- Future <void > _verifyStringExtension (WidgetTester tester) async {
247
- final extensionName = extensions.togglePlatformMode.extension ;
248
- await _serviceExtensionAvailable (extensionName);
249
- const evalExpression = 'defaultTargetPlatform.toString()' ;
250
- final library = EvalOnDartLibrary (
251
- 'package:flutter/src/foundation/platform.dart' ,
252
- serviceConnection.serviceManager.service! ,
253
- serviceManager: serviceConnection.serviceManager,
254
- );
255
- await _verifyExtension (
256
- tester,
257
- extensionName: extensionName,
258
- evalExpression: evalExpression,
259
- library: library,
260
- initialValue: 'android' ,
261
- newValue: 'iOS' ,
262
- initialValueOnDevice: 'TargetPlatform.android' ,
263
- newValueOnDevice: 'TargetPlatform.iOS' ,
264
- initialValueInServiceManager: (true , 'android' ),
265
- // TODO(https://github.com/flutter/devtools/issues/2780): change this
266
- // extension from the DevTools UI when it has a button in the inspector.
267
- toggleExtensionFromUi: false ,
268
- );
269
- }
270
-
271
- Future <void > _verifyHotReloadAndHotRestart () async {
272
- const evalExpression = 'topLevelFieldForTest' ;
273
- final library = EvalOnDartLibrary (
274
- 'package:flutter_app/main.dart' ,
275
- serviceConnection.serviceManager.service! ,
276
- serviceManager: serviceConnection.serviceManager,
277
- );
278
-
279
- // Verify the initial value of [topLevelFieldForTest].
280
- var value = await library.eval (evalExpression, isAlive: null );
281
- expect (value.runtimeType, InstanceRef );
282
- expect (value! .valueAsString, 'false' );
283
-
284
- // Change the value of [topLevelFieldForTest].
285
- await library.eval ('$evalExpression = true' , isAlive: null );
286
-
287
- // Verify the value of [topLevelFieldForTest] is now changed.
288
- value = await library.eval (evalExpression, isAlive: null );
289
- expect (value.runtimeType, InstanceRef );
290
- expect (value! .valueAsString, 'true' );
291
-
292
- await serviceConnection.serviceManager.performHotReload ();
293
-
294
- // Verify the value of [topLevelFieldForTest] is still changed after hot
295
- // reload.
296
- value = await library.eval (evalExpression, isAlive: null );
297
- expect (value.runtimeType, InstanceRef );
298
- expect (value! .valueAsString, 'true' );
299
-
300
- await serviceConnection.serviceManager.performHotRestart ();
301
-
302
- // Verify the value of [topLevelFieldForTest] is back to its original value
303
- // after hot restart.
304
- value = await library.eval (evalExpression, isAlive: null );
305
- expect (value.runtimeType, InstanceRef );
306
- expect (value! .valueAsString, 'false' );
307
- }
308
-
309
- Future <void > _verifyExtension (
310
- WidgetTester tester, {
311
- required String extensionName,
312
- required String evalExpression,
313
- required EvalOnDartLibrary library,
314
- required Object initialValue,
315
- required Object newValue,
316
- (bool , Object ? )? initialValueInServiceManager,
317
- String ? initialValueOnDevice,
318
- String ? newValueOnDevice,
319
- bool toggleExtensionFromUi = true ,
320
- }) async {
321
- await _serviceExtensionAvailable (extensionName);
322
-
323
- await _verifyExtensionStateOnTestDevice (
324
- evalExpression: evalExpression,
325
- expectedResult: initialValueOnDevice ?? initialValue.toString (),
326
- library: library,
327
- );
328
- await _verifyExtensionStateInServiceManager (
329
- extensionName,
330
- enabled: initialValueInServiceManager? .$1 ?? false ,
331
- value: initialValueInServiceManager? .$2,
332
- );
333
-
334
- // Enable the service extension state from the service manager.
335
- await serviceConnection.serviceManager.serviceExtensionManager
336
- .setServiceExtensionState (
337
- extensionName,
338
- enabled: true ,
339
- value: newValue,
340
- );
341
-
342
- await _verifyExtensionStateOnTestDevice (
343
- evalExpression: evalExpression,
344
- expectedResult: newValueOnDevice ?? newValue.toString (),
345
- library: library,
346
- );
347
- await _verifyExtensionStateInServiceManager (
348
- extensionName,
349
- enabled: true ,
350
- value: newValue,
351
- );
352
-
353
- if (toggleExtensionFromUi) {
354
- // Disable the service extension state from the UI.
355
- await _changeServiceExtensionFromButton (
356
- extensionName,
357
- evalExpression: evalExpression,
358
- library: library,
359
- expectedResultOnDevice: initialValueOnDevice ?? initialValue.toString (),
360
- expectedResultInServiceManager: (false , initialValue),
361
- tester: tester,
362
- );
363
- }
364
- }
365
-
366
- Future <void > _changeServiceExtensionFromButton (
367
- String extensionName, {
368
- required String evalExpression,
369
- required EvalOnDartLibrary library,
370
- required String ? expectedResultOnDevice,
371
- required (bool , Object ? ) expectedResultInServiceManager,
372
- required WidgetTester tester,
373
- }) async {
374
- final serviceExtensionButtons = tester
375
- .widgetList <ServiceExtensionButton >(find.byType (ServiceExtensionButton ));
376
- final button = serviceExtensionButtons.firstWhereOrNull (
377
- (b) => b.extensionState.description.extension == extensionName,
378
- );
379
- expect (button, isNotNull);
380
- await tester.tap (find.byWidget (button as Widget ));
381
- await tester.pumpAndSettle (shortPumpDuration);
382
-
383
- await _verifyExtensionStateOnTestDevice (
384
- evalExpression: evalExpression,
385
- expectedResult: expectedResultOnDevice,
386
- library: library,
387
- );
388
- await _verifyExtensionStateInServiceManager (
389
- extensionName,
390
- enabled: expectedResultInServiceManager.$1,
391
- value: expectedResultInServiceManager.$2,
392
- );
393
- }
394
-
395
- /// Returns a future that completes when the service extension is available.
396
- Future <void > _serviceExtensionAvailable (String extensionName) async {
397
- final listenable = serviceConnection.serviceManager.serviceExtensionManager
398
- .hasServiceExtension (extensionName);
399
-
400
- final completer = Completer <void >();
401
- void listener () {
402
- if (listenable.value) {
403
- completer.safeComplete ();
404
- }
405
- }
406
-
407
- listener ();
408
- listenable.addListener (listener);
409
- await completer.future;
410
- listenable.removeListener (listener);
411
- }
412
-
413
- Future <void > _verifyExtensionStateOnTestDevice ({
414
- required String evalExpression,
415
- required String ? expectedResult,
416
- required EvalOnDartLibrary library,
417
- }) async {
418
- final result = await library.eval (evalExpression, isAlive: null );
419
- if (result is InstanceRef ) {
420
- expect (result.valueAsString, equals (expectedResult));
421
- }
422
- }
423
-
424
- Future <void > _verifyExtensionStateInServiceManager (
425
- String extensionName, {
426
- required bool enabled,
427
- required Object ? value,
428
- }) async {
429
- final stateListenable = serviceConnection
430
- .serviceManager.serviceExtensionManager
431
- .getServiceExtensionState (extensionName);
432
-
433
- // Wait for the service extension state to match the expected value.
434
- final Completer <ServiceExtensionState > stateCompleter = Completer ();
435
- void stateListener () {
436
- if (stateListenable.value.value == value) {
437
- stateCompleter.complete (stateListenable.value);
438
- }
439
- }
440
-
441
- stateListenable.addListener (stateListener);
442
- stateListener ();
443
-
444
- final ServiceExtensionState state = await stateCompleter.future;
445
- stateListenable.removeListener (stateListener);
446
- expect (state.enabled, equals (enabled));
447
- expect (state.value, equals (value));
448
106
}
0 commit comments