mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
bcede8dffb
As per the recent fix to the `always_specify_types` lint (https://github.com/dart-lang/linter/issues/199), literal maps and lists are now expected to be explicitly typed. Running that lint on the repo identifies quite a few spots to update. This focuses on `flutter_driver` and `flutter_sprites` (somewhat arbitrarily) but the changes are fairly representative. Note there are a number of places where I made a quick judgement on how specific to make the types. Feedback on those is welcome. (Especially as we move forward with more.)
305 lines
10 KiB
Dart
305 lines
10 KiB
Dart
// Copyright 2016 The Chromium 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:async';
|
|
|
|
import 'package:flutter_driver/src/driver.dart';
|
|
import 'package:flutter_driver/src/error.dart';
|
|
import 'package:flutter_driver/src/health.dart';
|
|
import 'package:flutter_driver/src/timeline.dart';
|
|
import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
|
|
import 'package:mockito/mockito.dart';
|
|
import 'package:test/test.dart';
|
|
import 'package:vm_service_client/vm_service_client.dart';
|
|
|
|
void main() {
|
|
group('FlutterDriver.connect', () {
|
|
List<LogRecord> log;
|
|
StreamSubscription<LogRecord> logSub;
|
|
MockVMServiceClient mockClient;
|
|
MockVM mockVM;
|
|
MockIsolate mockIsolate;
|
|
|
|
void expectLogContains(String message) {
|
|
expect(log.map((LogRecord r) => '$r'), anyElement(contains(message)));
|
|
}
|
|
|
|
setUp(() {
|
|
log = <LogRecord>[];
|
|
logSub = flutterDriverLog.listen(log.add);
|
|
mockClient = new MockVMServiceClient();
|
|
mockVM = new MockVM();
|
|
mockIsolate = new MockIsolate();
|
|
when(mockClient.getVM()).thenReturn(mockVM);
|
|
when(mockVM.isolates).thenReturn(<VMRunnableIsolate>[mockIsolate]);
|
|
when(mockIsolate.loadRunnable()).thenReturn(mockIsolate);
|
|
when(mockIsolate.invokeExtension(any, any))
|
|
.thenReturn(new Future<Map<String, dynamic>>.value(<String, String>{'status': 'ok'}));
|
|
vmServiceConnectFunction = (String url) {
|
|
return new Future<VMServiceClientConnection>.value(
|
|
new VMServiceClientConnection(mockClient, null)
|
|
);
|
|
};
|
|
});
|
|
|
|
tearDown(() async {
|
|
await logSub.cancel();
|
|
restoreVmServiceConnectFunction();
|
|
});
|
|
|
|
test('connects to isolate paused at start', () async {
|
|
when(mockIsolate.pauseEvent).thenReturn(new MockVMPauseStartEvent());
|
|
when(mockIsolate.resume()).thenReturn(new Future<Null>.value());
|
|
when(mockIsolate.onExtensionAdded).thenReturn(new Stream<String>.fromIterable(<String>['ext.flutter.driver']));
|
|
|
|
FlutterDriver driver = await FlutterDriver.connect();
|
|
expect(driver, isNotNull);
|
|
expectLogContains('Isolate is paused at start');
|
|
});
|
|
|
|
test('connects to isolate paused mid-flight', () async {
|
|
when(mockIsolate.pauseEvent).thenReturn(new MockVMPauseBreakpointEvent());
|
|
when(mockIsolate.resume()).thenReturn(new Future<Null>.value());
|
|
|
|
FlutterDriver driver = await FlutterDriver.connect();
|
|
expect(driver, isNotNull);
|
|
expectLogContains('Isolate is paused mid-flight');
|
|
});
|
|
|
|
// This test simulates a situation when we believe that the isolate is
|
|
// currently paused, but something else (e.g. a debugger) resumes it before
|
|
// we do. There's no need to fail as we should be able to drive the app
|
|
// just fine.
|
|
test('connects despite losing the race to resume isolate', () async {
|
|
when(mockIsolate.pauseEvent).thenReturn(new MockVMPauseBreakpointEvent());
|
|
when(mockIsolate.resume()).thenAnswer((_) {
|
|
// This needs to be wrapped in a closure to not be considered uncaught
|
|
// by package:test
|
|
return new Future<Null>.error(new rpc.RpcException(101, ''));
|
|
});
|
|
|
|
FlutterDriver driver = await FlutterDriver.connect();
|
|
expect(driver, isNotNull);
|
|
expectLogContains('Attempted to resume an already resumed isolate');
|
|
});
|
|
|
|
test('connects to unpaused isolate', () async {
|
|
when(mockIsolate.pauseEvent).thenReturn(new MockVMResumeEvent());
|
|
FlutterDriver driver = await FlutterDriver.connect();
|
|
expect(driver, isNotNull);
|
|
expectLogContains('Isolate is not paused. Assuming application is ready.');
|
|
});
|
|
});
|
|
|
|
group('FlutterDriver', () {
|
|
MockVMServiceClient mockClient;
|
|
MockPeer mockPeer;
|
|
MockIsolate mockIsolate;
|
|
FlutterDriver driver;
|
|
|
|
setUp(() {
|
|
mockClient = new MockVMServiceClient();
|
|
mockPeer = new MockPeer();
|
|
mockIsolate = new MockIsolate();
|
|
driver = new FlutterDriver.connectedTo(mockClient, mockPeer, mockIsolate);
|
|
});
|
|
|
|
test('checks the health of the driver extension', () async {
|
|
when(mockIsolate.invokeExtension(any, any)).thenReturn(new Future<Map<String, dynamic>>.value(<String, dynamic>{
|
|
'status': 'ok',
|
|
}));
|
|
Health result = await driver.checkHealth();
|
|
expect(result.status, HealthStatus.ok);
|
|
});
|
|
|
|
test('closes connection', () async {
|
|
when(mockClient.close()).thenReturn(new Future<Null>.value());
|
|
await driver.close();
|
|
});
|
|
|
|
group('ByValueKey', () {
|
|
test('restricts value types', () async {
|
|
expect(() => find.byValueKey(null),
|
|
throwsA(new isInstanceOf<DriverError>()));
|
|
});
|
|
|
|
test('finds by ValueKey', () async {
|
|
when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) {
|
|
expect(i.positionalArguments[1], <String, String>{
|
|
'command': 'tap',
|
|
'finderType': 'ByValueKey',
|
|
'keyValueString': 'foo',
|
|
'keyValueType': 'String'
|
|
});
|
|
return new Future<Null>.value();
|
|
});
|
|
await driver.tap(find.byValueKey('foo'));
|
|
});
|
|
});
|
|
|
|
group('tap', () {
|
|
test('requires a target reference', () async {
|
|
expect(driver.tap(null), throwsA(new isInstanceOf<DriverError>()));
|
|
});
|
|
|
|
test('sends the tap command', () async {
|
|
when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) {
|
|
expect(i.positionalArguments[1], <String, dynamic>{
|
|
'command': 'tap',
|
|
'finderType': 'ByText',
|
|
'text': 'foo',
|
|
});
|
|
return new Future<Map<String, dynamic>>.value();
|
|
});
|
|
await driver.tap(find.text('foo'));
|
|
});
|
|
});
|
|
|
|
group('getText', () {
|
|
test('requires a target reference', () async {
|
|
expect(driver.getText(null), throwsA(new isInstanceOf<DriverError>()));
|
|
});
|
|
|
|
test('sends the getText command', () async {
|
|
when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) {
|
|
expect(i.positionalArguments[1], <String, dynamic>{
|
|
'command': 'get_text',
|
|
'finderType': 'ByValueKey',
|
|
'keyValueString': '123',
|
|
'keyValueType': 'int'
|
|
});
|
|
return new Future<Map<String, dynamic>>.value(<String, String>{
|
|
'text': 'hello'
|
|
});
|
|
});
|
|
String result = await driver.getText(find.byValueKey(123));
|
|
expect(result, 'hello');
|
|
});
|
|
});
|
|
|
|
group('waitFor', () {
|
|
test('requires a target reference', () async {
|
|
expect(driver.waitFor(null), throwsA(new isInstanceOf<DriverError>()));
|
|
});
|
|
|
|
test('sends the waitFor command', () async {
|
|
when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) {
|
|
expect(i.positionalArguments[1], <String, dynamic>{
|
|
'command': 'waitFor',
|
|
'finderType': 'ByTooltipMessage',
|
|
'text': 'foo',
|
|
'timeout': '1000',
|
|
});
|
|
return new Future<Map<String, dynamic>>.value(<String, dynamic>{});
|
|
});
|
|
await driver.waitFor(find.byTooltip('foo'), timeout: new Duration(seconds: 1));
|
|
});
|
|
});
|
|
|
|
group('traceAction', () {
|
|
test('traces action', () async {
|
|
bool actionCalled = false;
|
|
bool startTracingCalled = false;
|
|
bool stopTracingCalled = false;
|
|
|
|
when(mockPeer.sendRequest('_setVMTimelineFlags', argThat(equals(<String, dynamic>{'recordedStreams': '[all]'}))))
|
|
.thenAnswer((_) async {
|
|
startTracingCalled = true;
|
|
return null;
|
|
});
|
|
|
|
when(mockPeer.sendRequest('_setVMTimelineFlags', argThat(equals(<String, dynamic>{'recordedStreams': '[]'}))))
|
|
.thenAnswer((_) async {
|
|
stopTracingCalled = true;
|
|
return null;
|
|
});
|
|
|
|
when(mockPeer.sendRequest('_getVMTimeline')).thenAnswer((_) async {
|
|
return <String, dynamic> {
|
|
'traceEvents': <dynamic>[
|
|
<String, String>{
|
|
'name': 'test event'
|
|
}
|
|
],
|
|
};
|
|
});
|
|
|
|
Timeline timeline = await driver.traceAction(() {
|
|
actionCalled = true;
|
|
});
|
|
|
|
expect(actionCalled, isTrue);
|
|
expect(startTracingCalled, isTrue);
|
|
expect(stopTracingCalled, isTrue);
|
|
expect(timeline.events.single.name, 'test event');
|
|
});
|
|
});
|
|
|
|
group('traceAction categories', () {
|
|
test('specify non-default categories', () async {
|
|
bool actionCalled = false;
|
|
bool startTracingCalled = false;
|
|
bool stopTracingCalled = false;
|
|
|
|
when(mockPeer.sendRequest('_setVMTimelineFlags', argThat(equals(<String, dynamic>{'recordedStreams': '[Dart, GC, Compiler]'}))))
|
|
.thenAnswer((_) async {
|
|
startTracingCalled = true;
|
|
return null;
|
|
});
|
|
|
|
when(mockPeer.sendRequest('_setVMTimelineFlags', argThat(equals(<String, dynamic>{'recordedStreams': '[]'}))))
|
|
.thenAnswer((_) async {
|
|
stopTracingCalled = true;
|
|
return null;
|
|
});
|
|
|
|
when(mockPeer.sendRequest('_getVMTimeline')).thenAnswer((_) async {
|
|
return <String, dynamic> {
|
|
'traceEvents': <dynamic>[
|
|
<String, String>{
|
|
'name': 'test event'
|
|
}
|
|
],
|
|
};
|
|
});
|
|
|
|
Timeline timeline = await driver.traceAction(() {
|
|
actionCalled = true;
|
|
},
|
|
categories: const <TracingCategory>[
|
|
TracingCategory.dart,
|
|
TracingCategory.gc,
|
|
TracingCategory.compiler
|
|
]);
|
|
|
|
expect(actionCalled, isTrue);
|
|
expect(startTracingCalled, isTrue);
|
|
expect(stopTracingCalled, isTrue);
|
|
expect(timeline.events.single.name, 'test event');
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
@proxy
|
|
class MockVMServiceClient extends Mock implements VMServiceClient { }
|
|
|
|
@proxy
|
|
class MockVM extends Mock implements VM { }
|
|
|
|
@proxy
|
|
class MockIsolate extends Mock implements VMRunnableIsolate { }
|
|
|
|
@proxy
|
|
class MockVMPauseStartEvent extends Mock implements VMPauseStartEvent { }
|
|
|
|
@proxy
|
|
class MockVMPauseBreakpointEvent extends Mock implements VMPauseBreakpointEvent { }
|
|
|
|
@proxy
|
|
class MockVMResumeEvent extends Mock implements VMResumeEvent { }
|
|
|
|
@proxy
|
|
class MockPeer extends Mock implements rpc.Peer { }
|