Unverified Commit 3ece9c63 authored by Dan Field's avatar Dan Field Committed by GitHub

Flutter_driver nnbd (#74856)

parent 650b2406
......@@ -669,7 +669,7 @@ Future<void> _runFrameworkTests() async {
await _runFlutterTest(path.join(flutterRoot, 'examples', 'hello_world'), options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'examples', 'layers'), options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'dev', 'benchmarks', 'test_apps', 'stocks'));
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'), tests: <String>[path.join('test', 'src', 'real_tests')]);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'), tests: <String>[path.join('test', 'src', 'real_tests')], options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'integration_test'));
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_goldens'), options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'), options: soundNullSafetyOptions);
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// Provides API to test Flutter applications that run on real
/// devices and emulators.
///
......
......@@ -14,10 +14,10 @@ class DriverError extends Error {
final String message;
/// The error object that was caught and wrapped by this error object, if any.
final dynamic originalError;
final Object? originalError;
/// The stack trace that was caught and wrapped by this error object, if any.
final dynamic originalStackTrace;
final Object? originalStackTrace;
@override
String toString() {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// Convenience methods for Flutter application driving on Fuchsia. Can
/// be run on either a host machine (making a remote connection to a Fuchsia
/// device), or on the target Fuchsia machine.
......@@ -40,13 +38,13 @@ class _DummySshCommandRunner implements SshCommandRunner {
}
@override
String get sshConfigPath => null;
String get sshConfigPath => '';
@override
String get address => InternetAddress.loopbackIPv4.address;
@override
String get interface => null;
String get interface => '';
@override
Future<List<String>> run(String command) async {
......@@ -72,8 +70,8 @@ class _DummySshCommandRunner implements SshCommandRunner {
Future<PortForwarder> _dummyPortForwardingFunction(
String address,
int remotePort, [
String interface = '',
String configFile,
String? interface,
String? configFile,
]) async {
return _DummyPortForwarder(remotePort, remotePort);
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:io' show Platform;
import 'package:file/file.dart';
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// Returns the [p]-th percentile element from the [doubles].
/// `List<doubles>` will be sorted.
double findPercentile(List<double> doubles, double p) {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'percentile_utils.dart';
import 'timeline.dart';
......@@ -63,7 +61,7 @@ class ProfilingSummarizer {
assert(kProfilingEvents.contains(event.name));
final ProfileType type = _getProfileType(event.name);
eventsByType[type] ??= <TimelineEvent>[];
eventsByType[type].add(event);
eventsByType[type]!.add(event);
}
return ProfilingSummarizer._(eventsByType);
}
......@@ -96,7 +94,7 @@ class ProfilingSummarizer {
/// Returns true if there are events in the timeline corresponding to [profileType].
bool hasProfilingInfo(ProfileType profileType) {
if (eventByType.containsKey(profileType)) {
return eventByType[profileType].isNotEmpty;
return eventByType[profileType]!.isNotEmpty;
} else {
return false;
}
......@@ -104,7 +102,7 @@ class ProfilingSummarizer {
/// Computes the average of the `profileType` over the recorded events.
double computeAverage(ProfileType profileType) {
final List<TimelineEvent> events = eventByType[profileType];
final List<TimelineEvent> events = eventByType[profileType]!;
assert(events.isNotEmpty);
final double total = events
.map((TimelineEvent e) => _getProfileValue(profileType, e))
......@@ -114,7 +112,7 @@ class ProfilingSummarizer {
/// The [percentile]-th percentile `profileType` over the recorded events.
double computePercentile(ProfileType profileType, double percentile) {
final List<TimelineEvent> events = eventByType[profileType];
final List<TimelineEvent> events = eventByType[profileType]!;
assert(events.isNotEmpty);
final List<double> doubles = events
.map((TimelineEvent e) => _getProfileValue(profileType, e))
......@@ -122,7 +120,7 @@ class ProfilingSummarizer {
return findPercentile(doubles, percentile);
}
static ProfileType _getProfileType(String eventName) {
static ProfileType _getProfileType(String? eventName) {
switch (eventName) {
case _kCpuProfile:
return ProfileType.CPU;
......@@ -147,13 +145,11 @@ class ProfilingSummarizer {
_getArgValue('owned_shared_memory_usage', e);
return dirtyMem + ownedSharedMem;
}
throw Exception('Invalid $profileType.');
}
double _getArgValue(String argKey, TimelineEvent e) {
assert(e.arguments.containsKey(argKey));
final dynamic argVal = e.arguments[argKey];
assert(e.arguments!.containsKey(argKey));
final dynamic argVal = e.arguments![argKey];
assert(argVal is String);
return double.parse(argVal as String);
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'percentile_utils.dart';
import 'timeline.dart';
......@@ -68,8 +66,8 @@ class SceneDisplayLagSummarizer {
double _getVsyncTransitionsMissed(TimelineEvent e) {
assert(e.name == kSceneDisplayLagEvent);
assert(e.arguments.containsKey(_kVsyncTransitionsMissed));
final dynamic transitionsMissed = e.arguments[_kVsyncTransitionsMissed];
assert(e.arguments!.containsKey(_kVsyncTransitionsMissed));
final dynamic transitionsMissed = e.arguments![_kVsyncTransitionsMissed];
assert(transitionsMissed is String);
return double.parse(transitionsMissed as String);
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// Timeline data recorded by the Flutter runtime.
class Timeline {
/// Creates a timeline given JSON-encoded timeline data.
......@@ -25,27 +23,29 @@ class Timeline {
///
/// This is parsed from "traceEvents" data within [json] and sorted by
/// timestamp. Anything without a valid timestamp is put in the beginning.
final List<TimelineEvent> events;
///
/// This will be null if there are are no "traceEvents" in the [json].
final List<TimelineEvent>? events;
}
/// A single timeline event.
class TimelineEvent {
/// Creates a timeline event given JSON-encoded event data.
TimelineEvent(this.json)
: name = json['name'] as String,
category = json['cat'] as String,
phase = json['ph'] as String,
processId = json['pid'] as int,
threadId = json['tid'] as int,
: name = json['name'] as String?,
category = json['cat'] as String?,
phase = json['ph'] as String?,
processId = json['pid'] as int?,
threadId = json['tid'] as int?,
duration = json['dur'] != null
? Duration(microseconds: json['dur'] as int)
: null,
threadDuration = json['tdur'] != null
? Duration(microseconds: json['tdur'] as int)
: null,
timestampMicros = json['ts'] as int,
threadTimestampMicros = json['tts'] as int,
arguments = json['args'] as Map<String, dynamic>;
timestampMicros = json['ts'] as int?,
threadTimestampMicros = json['tts'] as int?,
arguments = json['args'] as Map<String, dynamic>?;
/// The original event JSON.
final Map<String, dynamic> json;
......@@ -53,28 +53,28 @@ class TimelineEvent {
/// The name of the event.
///
/// Corresponds to the "name" field in the JSON event.
final String name;
final String? name;
/// Event category. Events with different names may share the same category.
///
/// Corresponds to the "cat" field in the JSON event.
final String category;
final String? category;
/// For a given long lasting event, denotes the phase of the event, such as
/// "B" for "event began", and "E" for "event ended".
///
/// Corresponds to the "ph" field in the JSON event.
final String phase;
final String? phase;
/// ID of process that emitted the event.
///
/// Corresponds to the "pid" field in the JSON event.
final int processId;
final int? processId;
/// ID of thread that issues the event.
///
/// Corresponds to the "tid" field in the JSON event.
final int threadId;
final int? threadId;
/// The duration of the event.
///
......@@ -82,7 +82,7 @@ class TimelineEvent {
/// pair of begin/end events.
///
/// Corresponds to the "dur" field in the JSON event.
final Duration duration;
final Duration? duration;
/// The thread duration of the event.
///
......@@ -90,32 +90,31 @@ class TimelineEvent {
/// pair of begin/end events.
///
/// Corresponds to the "tdur" field in the JSON event.
final Duration threadDuration;
final Duration? threadDuration;
/// Time passed since tracing was enabled, in microseconds.
///
/// Corresponds to the "ts" field in the JSON event.
final int timestampMicros;
final int? timestampMicros;
/// Thread clock time, in microseconds.
///
/// Corresponds to the "tts" field in the JSON event.
final int threadTimestampMicros;
final int? threadTimestampMicros;
/// Arbitrary data attached to the event.
///
/// Corresponds to the "args" field in the JSON event.
final Map<String, dynamic> arguments;
final Map<String, dynamic>? arguments;
}
List<TimelineEvent> _parseEvents(Map<String, dynamic> json) {
final List<dynamic> jsonEvents = json['traceEvents'] as List<dynamic>;
List<TimelineEvent>? _parseEvents(Map<String, dynamic> json) {
final List<dynamic>? jsonEvents = json['traceEvents'] as List<dynamic>?;
if (jsonEvents == null) {
return null;
}
// TODO(vegorov): use instance method version of castFrom when it is available.
final List<TimelineEvent> timelineEvents =
Iterable.castFrom<dynamic, Map<String, dynamic>>(jsonEvents)
.map<TimelineEvent>(
......@@ -123,8 +122,8 @@ List<TimelineEvent> _parseEvents(Map<String, dynamic> json) {
.toList();
timelineEvents.sort((TimelineEvent e1, TimelineEvent e2) {
final int ts1 = e1.timestampMicros;
final int ts2 = e2.timestampMicros;
final int? ts1 = e1.timestampMicros;
final int? ts2 = e2.timestampMicros;
if (ts1 == null) {
if (ts2 == null) {
return 0;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:convert' show json, JsonEncoder;
import 'dart:math' as math;
......@@ -197,7 +195,7 @@ class TimelineSummary {
/// * [Timeline.fromJson], which explains detail about the timeline data.
Future<void> writeTimelineToFile(
String traceName, {
String destinationDirectory,
String? destinationDirectory,
bool pretty = false,
}) async {
destinationDirectory ??= testOutputsDirectory;
......@@ -209,7 +207,7 @@ class TimelineSummary {
/// Writes [summaryJson] to a file.
Future<void> writeSummaryToFile(
String traceName, {
String destinationDirectory,
String? destinationDirectory,
bool pretty = false,
}) async {
destinationDirectory ??= testOutputsDirectory;
......@@ -225,13 +223,13 @@ class TimelineSummary {
}
List<TimelineEvent> _extractNamedEvents(String name) {
return _timeline.events
return _timeline.events!
.where((TimelineEvent event) => event.name == name)
.toList();
}
List<TimelineEvent> _extractEventsWithNames(Set<String> names) {
return _timeline.events
return _timeline.events!
.where((TimelineEvent event) => names.contains(event.name))
.toList();
}
......@@ -244,7 +242,7 @@ class TimelineSummary {
final List<TimelineEvent> events = _extractNamedEvents(name);
// Timeline does not guarantee that the first event is the "begin" event.
TimelineEvent begin;
TimelineEvent? begin;
for (final TimelineEvent event in events) {
if (event.phase == 'B') {
begin = event;
......@@ -273,7 +271,7 @@ class TimelineSummary {
return _extractDurations(
name,
(TimelineEvent beginEvent, TimelineEvent endEvent) {
return Duration(microseconds: endEvent.timestampMicros - beginEvent.timestampMicros);
return Duration(microseconds: endEvent.timestampMicros! - beginEvent.timestampMicros!);
},
);
}
......@@ -282,7 +280,7 @@ class TimelineSummary {
final List<Duration> result = _extractDurations(
name,
(TimelineEvent beginEvent, TimelineEvent endEvent) {
return Duration(microseconds: beginEvent.timestampMicros);
return Duration(microseconds: beginEvent.timestampMicros!);
},
);
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:convert';
import 'dart:io';
......@@ -53,7 +51,7 @@ class WebFlutterDriver extends FlutterDriver {
/// DRIVER_SESSION_CAPABILITIES and ANDROID_CHROME_ON_EMULATOR for
/// configurations.
static Future<FlutterDriver> connectWeb(
{String hostUrl, Duration timeout}) async {
{String? hostUrl, Duration? timeout}) async {
hostUrl ??= Platform.environment['VM_SERVICE_URL'];
final Map<String, dynamic> settings = <String, dynamic>{
'support-timeline-action': Platform.environment['SUPPORT_TIMELINE_ACTION'] == 'true',
......@@ -64,7 +62,7 @@ class WebFlutterDriver extends FlutterDriver {
'session-capabilities': Platform.environment['DRIVER_SESSION_CAPABILITIES'],
};
final FlutterWebConnection connection = await FlutterWebConnection.connect
(hostUrl, settings, timeout: timeout);
(hostUrl!, settings, timeout: timeout);
return WebFlutterDriver.connectedTo(connection);
}
......@@ -90,7 +88,7 @@ class WebFlutterDriver extends FlutterDriver {
final Map<String, String> serialized = command.serialize();
try {
final dynamic data = await _connection.sendCommand("window.\$flutterDriver('${jsonEncode(serialized)}')", command.timeout);
response = data != null ? json.decode(data as String) as Map<String, dynamic> : <String, dynamic>{};
response = data != null ? (json.decode(data as String) as Map<String, dynamic>?)! : <String, dynamic>{};
} catch (error, stackTrace) {
throw DriverError("Failed to respond to $command due to remote error\n : \$flutterDriver('${jsonEncode(serialized)}')",
error,
......@@ -132,7 +130,7 @@ class WebFlutterDriver extends FlutterDriver {
final List<Map<String, dynamic>> events = <Map<String, dynamic>>[];
for (final async_io.LogEntry entry in await _connection.logs.toList()) {
if (_startTime.isBefore(entry.timestamp)) {
final Map<String, dynamic> data = jsonDecode(entry.message)['message'] as Map<String, dynamic>;
final Map<String, dynamic> data = jsonDecode(entry.message!)['message'] as Map<String, dynamic>;
if (data['method'] == 'Tracing.dataCollected') {
// 'ts' data collected from Chrome is in double format, conversion needed
try {
......@@ -142,7 +140,7 @@ class WebFlutterDriver extends FlutterDriver {
// data is corrupted, skip
continue;
}
events.add(data['params'] as Map<String, dynamic>);
events.add(data['params']! as Map<String, dynamic>);
}
}
}
......@@ -203,7 +201,7 @@ class FlutterWebConnection {
static Future<FlutterWebConnection> connect(
String url,
Map<String, dynamic> settings,
{Duration timeout}) async {
{Duration? timeout}) async {
final String sessionId = settings['session-id'].toString();
final Uri sessionUri = Uri.parse(settings['session-uri'].toString());
final async_io.WebDriver driver = async_io.WebDriver(
......@@ -226,7 +224,7 @@ class FlutterWebConnection {
}
/// Sends command via WebDriver to Flutter web application.
Future<dynamic> sendCommand(String script, Duration duration) async {
Future<dynamic> sendCommand(String script, Duration? duration) async {
dynamic result;
try {
await _driver.execute(script, <void>[]);
......@@ -265,7 +263,7 @@ class FlutterWebConnection {
}
/// Waits until extension is installed.
Future<void> waitUntilExtensionInstalled(async_io.WebDriver driver, Duration timeout) async {
Future<void> waitUntilExtensionInstalled(async_io.WebDriver driver, Duration? timeout) async {
await waitFor<void>(() =>
driver.execute(r'return typeof(window.$flutterDriver)', <String>[]),
matcher: 'function',
......
......@@ -8,16 +8,16 @@ environment:
dependencies:
file: 6.0.0-nullsafety.4
meta: 1.3.0-nullsafety.6
path: 1.8.0-nullsafety.3
vm_service: 6.0.1-nullsafety.0
webdriver: 3.0.0-nullsafety.1
flutter:
sdk: flutter
flutter_test:
sdk: flutter
fuchsia_remote_debug_protocol:
sdk: flutter
path: 1.8.0-nullsafety.3
meta: 1.3.0-nullsafety.6
vm_service: 6.0.1-nullsafety.0
webdriver: 3.0.0-nullsafety.1
archive: 3.0.0-nullsafety.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
async: 2.5.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
......@@ -27,7 +27,6 @@ dependencies:
clock: 1.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
collection: 1.15.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
crypto: 3.0.0-nullsafety.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
fake_async: 1.2.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
matcher: 0.12.10-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
platform: 3.0.0-nullsafety.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
process: 4.0.0-nullsafety.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
......@@ -42,7 +41,7 @@ dependencies:
vector_math: 2.1.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
dev_dependencies:
quiver: 2.1.5
fake_async: 1.2.0-nullsafety.3
test: 1.16.0-nullsafety.16
_fe_analyzer_shared: 14.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
......@@ -77,4 +76,4 @@ dev_dependencies:
webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
# PUBSPEC CHECKSUM: 91b1
# PUBSPEC CHECKSUM: 62c3
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:io';
import 'package:flutter_driver/src/common/error.dart';
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_driver/driver_extension.dart';
import 'package:flutter_driver/flutter_driver.dart';
import 'package:flutter_driver/src/common/find.dart';
......
......@@ -2,15 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_driver/src/extension/_extension_io.dart';
import '../../common.dart';
void main() {
group('test io_extension',() {
Future<Map<String, dynamic>> Function(Map<String, String>) call;
late Future<Map<String, dynamic>> Function(Map<String, String>) call;
setUp(() {
call = (Map<String, String> args) async {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_driver/flutter_driver.dart';
import '../../common.dart';
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:convert' show json;
import 'package:file/file.dart';
......@@ -409,7 +407,7 @@ void main() {
group('writeTimelineToFile', () {
Directory tempDir;
late Directory tempDir;
setUp(() {
useMemoryFileSystemForTesting();
......@@ -480,7 +478,7 @@ void main() {
final Timeline timeline = Timeline.fromJson(<String, dynamic>{
'traceEvents': traceEvents,
});
return SceneDisplayLagSummarizer(timeline.events);
return SceneDisplayLagSummarizer(timeline.events!);
}
test('average_vsyncs_missed', () async {
......@@ -531,7 +529,7 @@ void main() {
final Timeline timeline = Timeline.fromJson(<String, dynamic>{
'traceEvents': traceEvents,
});
return ProfilingSummarizer.fromEvents(timeline.events);
return ProfilingSummarizer.fromEvents(timeline.events!);
}
test('has_both_cpu_and_memory_usage', () async {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_driver/src/driver/timeline.dart';
import '../../common.dart';
......@@ -34,7 +32,7 @@ void main() {
expect(timeline.events, hasLength(2));
final TimelineEvent e1 = timeline.events[1];
final TimelineEvent e1 = timeline.events![1];
expect(e1.name, 'test event');
expect(e1.category, 'test category');
expect(e1.phase, 'B');
......@@ -46,7 +44,7 @@ void main() {
expect(e1.threadTimestampMicros, 567);
expect(e1.arguments, <String, dynamic>{'arg1': true});
final TimelineEvent e2 = timeline.events[0];
final TimelineEvent e2 = timeline.events![0];
expect(e2.name, isNull);
expect(e2.category, isNull);
expect(e2.phase, isNull);
......@@ -74,10 +72,10 @@ void main() {
});
expect(timeline.events, hasLength(2));
expect(timeline.events[0].timestampMicros, equals(456));
expect(timeline.events[1].timestampMicros, equals(457));
expect(timeline.events[0].name, equals('test event 2'));
expect(timeline.events[1].name, equals('test event 1'));
expect(timeline.events![0].timestampMicros, equals(456));
expect(timeline.events![1].timestampMicros, equals(457));
expect(timeline.events![0].name, equals('test event 2'));
expect(timeline.events![1].name, equals('test event 1'));
});
test('sorts JSON nulls first', () {
......@@ -103,14 +101,14 @@ void main() {
});
expect(timeline.events, hasLength(4));
expect(timeline.events[0].timestampMicros, isNull);
expect(timeline.events[1].timestampMicros, isNull);
expect(timeline.events[2].timestampMicros, equals(456));
expect(timeline.events[3].timestampMicros, equals(457));
expect(timeline.events[0].name, equals('test event 0'));
expect(timeline.events[1].name, equals('test event 3'));
expect(timeline.events[2].name, equals('test event 2'));
expect(timeline.events[3].name, equals('test event 1'));
expect(timeline.events![0].timestampMicros, isNull);
expect(timeline.events![1].timestampMicros, isNull);
expect(timeline.events![2].timestampMicros, equals(456));
expect(timeline.events![3].timestampMicros, equals(457));
expect(timeline.events![0].name, equals('test event 0'));
expect(timeline.events![1].name, equals('test event 3'));
expect(timeline.events![2].name, equals('test event 2'));
expect(timeline.events![3].name, equals('test event 1'));
});
});
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_driver/src/common/wait.dart';
import '../../common.dart';
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_driver/driver_extension.dart';
void main() {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import '../test/common.dart';
void main() {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_driver/driver_extension.dart';
void main() {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import '../test/common.dart';
void main() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment