Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/integration_test/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include: ../../analysis_options.yaml
analyzer:
enable-experiment:
- non-nullable
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ void main() {
find.byWidgetPredicate(
(Widget widget) =>
widget is Text &&
widget.data.startsWith('Platform: ${Platform.operatingSystem}'),
widget.data != null &&
widget.data!.startsWith('Platform: ${Platform.operatingSystem}'),
),
findsOneWidget,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ void main() {
find.byWidgetPredicate(
(Widget widget) =>
widget is Text &&
widget.data
widget.data != null &&
widget.data!
.startsWith('Platform: ${html.window.navigator.platform}\n'),
),
findsOneWidget,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ void main() {
find.byWidgetPredicate(
(Widget widget) =>
widget is Text &&
widget.data.startsWith('Platform: ${Platform.operatingSystem}'),
widget.data != null &&
widget.data!.startsWith('Platform: ${Platform.operatingSystem}'),
),
findsOneWidget,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import 'package:integration_test_example/main.dart' as app;

void main() {
final IntegrationTestWidgetsFlutterBinding binding =
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
IntegrationTestWidgetsFlutterBinding.ensureInitialized()
as IntegrationTestWidgetsFlutterBinding;

testWidgets('verify text', (WidgetTester tester) async {
// Build our app and trigger a frame.
Expand All @@ -31,7 +32,8 @@ void main() {
find.byWidgetPredicate(
(Widget widget) =>
widget is Text &&
widget.data
widget.data != null &&
widget.data!
.startsWith('Platform: ${html.window.navigator.platform}\n'),
),
findsOneWidget,
Expand Down
2 changes: 1 addition & 1 deletion packages/integration_test/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Demonstrates how to use the integration_test plugin.
publish_to: 'none'

environment:
sdk: ">=2.1.0 <3.0.0"
sdk: '>=2.10.0-56.0.dev <3.0.0'
flutter: ">=1.6.7 <2.0.0"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also update flutter version?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the Dart constraint will take care of that, but we could.


dependencies:
Expand Down
4 changes: 3 additions & 1 deletion packages/integration_test/example/test_driver/failure.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ void main() {
await expectLater(
find.byWidgetPredicate(
(Widget widget) =>
widget is Text && widget.data.startsWith('This should fail'),
widget is Text &&
widget.data != null &&
widget.data!.startsWith('This should fail'),
),
findsOneWidget,
);
Expand Down
2 changes: 1 addition & 1 deletion packages/integration_test/lib/_callback_io.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class IOCallbackManager implements CallbackManager {
@override
Future<Map<String, dynamic>> callback(
Map<String, String> params, IntegrationTestResults testRunner) async {
final String command = params['command'];
final String command = params['command'] as String;
Map<String, String> response;
switch (command) {
case 'request_data':
Expand Down
5 changes: 2 additions & 3 deletions packages/integration_test/lib/_callback_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,13 @@ class WebCallbackManager implements CallbackManager {
@override
Future<Map<String, dynamic>> callback(
Map<String, String> params, IntegrationTestResults testRunner) async {
final String command = params['command'];
final String command = params['command'] as String;
Map<String, String> response;
switch (command) {
case 'request_data':
return params['message'] == null
? _requestData(testRunner)
: _requestDataWithMessage(params['message'], testRunner);
break;
Comment thread
CareF marked this conversation as resolved.
: _requestDataWithMessage(params['message'] as String, testRunner);
case 'get_health':
response = <String, String>{'status': 'ok'};
break;
Expand Down
38 changes: 19 additions & 19 deletions packages/integration_test/lib/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@ class Response {
final bool _allTestsPassed;

/// The extra information to be added along side the test result.
Map<String, dynamic> data;
Map<String, dynamic>? data;

/// Constructor to use for positive response.
Response.allTestsPassed({this.data})
: this._allTestsPassed = true,
this._failureDetails = null;
: _allTestsPassed = true,
_failureDetails = <Failure>[];

/// Constructor for failure response.
Response.someTestsFailed(this._failureDetails, {this.data})
: this._allTestsPassed = false;
: _allTestsPassed = false;

/// Constructor for failure response.
Response.toolException({String ex})
: this._allTestsPassed = false,
this._failureDetails = [Failure('ToolException', ex)];
Response.toolException({String? ex})
: _allTestsPassed = false,
_failureDetails = <Failure>[Failure('ToolException', ex)];

/// Constructor for web driver commands response.
Response.webDriverCommand({this.data})
: this._allTestsPassed = false,
this._failureDetails = null;
: _allTestsPassed = false,
_failureDetails = <Failure>[];

/// Whether the test ran successfully or not.
bool get allTestsPassed => _allTestsPassed;
Expand Down Expand Up @@ -86,8 +86,8 @@ class Response {

/// Create a list of Strings from [_failureDetails].
List<String> _failureDetailsAsString() {
final List<String> list = List<String>();
if (_failureDetails == null || _failureDetails.isEmpty) {
final List<String> list = <String>[];
if (_failureDetails.isEmpty) {
return list;
}

Expand All @@ -100,7 +100,7 @@ class Response {

/// Creates a [Failure] list using a json response.
static List<Failure> _failureDetailsFromJson(List<dynamic> list) {
final List<Failure> failureList = List<Failure>();
final List<Failure> failureList = <Failure>[];
list.forEach((s) {
final String failure = s as String;
failureList.add(Failure.fromJsonString(failure));
Expand All @@ -115,14 +115,14 @@ class Failure {
final String methodName;

/// The details of the failure such as stack trace.
final String details;
final String? details;

/// Constructor requiring all fields during initialization.
Failure(this.methodName, this.details);

/// Serializes the object to JSON.
String toJson() {
return json.encode(<String, String>{
return json.encode(<String, String?>{
'methodName': methodName,
'details': details,
});
Expand Down Expand Up @@ -244,13 +244,13 @@ class WebDriverCommand {

/// Constructor for [WebDriverCommandType.noop] command.
WebDriverCommand.noop()
: this.type = WebDriverCommandType.noop,
this.values = Map();
: type = WebDriverCommandType.noop,
values = Map();

/// Constructor for [WebDriverCommandType.noop] screenshot.
WebDriverCommand.screenshot(String screenshot_name)
: this.type = WebDriverCommandType.screenshot,
this.values = {'screenshot_name': screenshot_name};
: type = WebDriverCommandType.screenshot,
values = {'screenshot_name': screenshot_name};

/// Util method for converting [WebDriverCommandType] to a map entry.
///
Expand Down Expand Up @@ -294,7 +294,7 @@ abstract class IntegrationTestResults {
List<Failure> get failureMethodsDetails;

/// The extra data for the reported result.
Map<String, dynamic> get reportData;
Map<String, dynamic>? get reportData;

/// Whether all the test methods completed succesfully.
Completer<bool> get allTestsPassed;
Expand Down
58 changes: 30 additions & 28 deletions packages/integration_test/lib/integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ class IntegrationTestWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding
@override
bool get registerTestTextInput => false;

Size _surfaceSize;
Size? _surfaceSize;

/// Artificially changes the surface size to `size` on the Widget binding,
/// then flushes microtasks.
///
/// Set to null to use the default surface size.
@override
Future<void> setSurfaceSize(Size size) {
Future<void> setSurfaceSize(Size? size) {
return TestAsyncUtils.guard<void>(() async {
assert(inTest);
if (_surfaceSize == size) {
Expand Down Expand Up @@ -123,7 +123,7 @@ class IntegrationTestWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding
IntegrationTestWidgetsFlutterBinding();
}
assert(WidgetsBinding.instance is IntegrationTestWidgetsFlutterBinding);
return WidgetsBinding.instance;
return WidgetsBinding.instance!;
}

static const MethodChannel _channel =
Expand All @@ -145,9 +145,9 @@ class IntegrationTestWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding
///
/// The default value is `null`.
@override
Map<String, dynamic> get reportData => _reportData;
Map<String, dynamic> _reportData;
set reportData(Map<String, dynamic> data) => this._reportData = data;
Map<String, dynamic>? get reportData => _reportData;
Map<String, dynamic>? _reportData;
set reportData(Map<String, dynamic>? data) => this._reportData = data;

/// Manages callbacks received from driver side and commands send to driver
/// side.
Expand Down Expand Up @@ -184,7 +184,7 @@ class IntegrationTestWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding
Future<void> testBody(),
VoidCallback invariantTester, {
String description = '',
Duration timeout,
Duration? timeout,
}) async {
await super.runTest(
testBody,
Expand All @@ -195,28 +195,29 @@ class IntegrationTestWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding
results[description] ??= _success;
}

vm.VmService _vmService;
vm.VmService? _cachedVmService;
Future<vm.VmService> get _vmService async {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change related to nnbd?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be split out into a separate patch. It came up because with nnbd I had to think more carefully about whether this property was nullable or not, and when it'd be set, and came to realize it was getting set by a method when another method might want to use it too.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, let's keep it here. I think it's enough as long as we add it to the change log/pr description (if something goes wrong it will be easier to see 😅 )

if (_cachedVmService == null) {
final developer.ServiceProtocolInfo info =
await developer.Service.getInfo();
assert(info.serverUri != null);
_cachedVmService = await vm_io.vmServiceConnectUri(
'ws://localhost:${info.serverUri!.port}${info.serverUri!.path}ws',
);
}
return _cachedVmService!;
}

/// Initialize the [vm.VmService] settings for the timeline.
@visibleForTesting
Future<void> enableTimeline({
List<String> streams = const <String>['all'],
@visibleForTesting vm.VmService vmService,
@visibleForTesting vm.VmService? vmService,
}) async {
assert(streams != null);
assert(streams != null); // ignore: unnecessary_null_comparison

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line seems no longer necessary when we have null-safety.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still useful when not in sound null safety e.g. importing a non nnbd package

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: does it make sense to merge to asserts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nturgut I'm not sure I'm understanding what merge asserts would be in this context...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's very nit :)

assert(streams !=null && streams. isNotEmpty, 'Non empty stream is required')

assert(streams.isNotEmpty);
if (vmService != null) {
_vmService = vmService;
}
if (_vmService == null) {
final developer.ServiceProtocolInfo info =
await developer.Service.getInfo();
assert(info.serverUri != null);
_vmService = await vm_io.vmServiceConnectUri(
'ws://localhost:${info.serverUri.port}${info.serverUri.path}ws',
);
}
await _vmService.setVMTimelineFlags(streams);
vmService ??= await _vmService;

@CareF CareF Oct 15, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be if (vmService != null) _cachedVmService = vmService, so that traceTimeline will use the provided vmService. And to make it logically more consistent I would change the next line back to await _vmService.setVMTimelineFlags(streams);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made the private member a future. I'm also not clear on this, I assumed the param was only for testing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this parameter is intended to replace the standard vmService for testing purposes. If I understand it correctly, your version traceTimeline will still call the _cachedVmService obtained by vm_io.vmServiceConnectUri, but what it should call is the vmService provided here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. We should add it as a param there then or move it to the ctor/ensureInitialized It's pretty strange to have a method alter a private member for tests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've cleaned this up a bit, let me know what you think.

await vmService.setVMTimelineFlags(streams);
}

/// Runs [action] and returns a [vm.Timeline] trace for it.
Expand All @@ -238,16 +239,17 @@ class IntegrationTestWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding
bool retainPriorEvents = false,
}) async {
await enableTimeline(streams: streams);
final vm.VmService vmService = await _vmService;
if (retainPriorEvents) {
await action();
return await _vmService.getVMTimeline();
return await vmService.getVMTimeline();
}

await _vmService.clearVMTimeline();
final vm.Timestamp startTime = await _vmService.getVMTimelineMicros();
await vmService.clearVMTimeline();
final vm.Timestamp startTime = await vmService.getVMTimelineMicros();
await action();
final vm.Timestamp endTime = await _vmService.getVMTimelineMicros();
return await _vmService.getVMTimeline(
final vm.Timestamp endTime = await vmService.getVMTimelineMicros();
return await vmService.getVMTimeline(
timeOriginMicros: startTime.timestamp,
timeExtentMicros: endTime.timestamp,
);
Expand Down Expand Up @@ -280,6 +282,6 @@ class IntegrationTestWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding
retainPriorEvents: retainPriorEvents,
);
reportData ??= <String, dynamic>{};
reportData[reportKey] = timeline.toJson();
reportData![reportKey] = timeline.toJson();
}
}
8 changes: 4 additions & 4 deletions packages/integration_test/lib/integration_test_driver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ typedef ResponseDataCallback = FutureOr<void> Function(Map<String, dynamic>);
Future<void> writeResponseData(
Map<String, dynamic> data, {
String testOutputFilename = 'integration_response_data',
String destinationDirectory,
String? destinationDirectory,
}) async {
assert(testOutputFilename != null);
assert(testOutputFilename != null); // ignore: unnecessary_null_comparison

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line seems no longer necessary when we have null-safety.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above - these are still helpful when working in mixed/unsound mode.

destinationDirectory ??= testOutputsDirectory;
await fs.directory(destinationDirectory).create(recursive: true);
final File file = fs.file(path.join(
Expand Down Expand Up @@ -65,7 +65,7 @@ Future<void> writeResponseData(
/// ```
Future<void> integrationDriver({
Duration timeout = const Duration(minutes: 1),
ResponseDataCallback responseDataCallback = writeResponseData,
ResponseDataCallback? responseDataCallback = writeResponseData,
}) async {
final FlutterDriver driver = await FlutterDriver.connect();
final String jsonResult = await driver.requestData(null, timeout: timeout);
Expand All @@ -75,7 +75,7 @@ Future<void> integrationDriver({
if (response.allTestsPassed) {
print('All tests passed.');
if (responseDataCallback != null) {
await responseDataCallback(response.data);
await responseDataCallback(response.data!);
}
exit(0);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'package:flutter_driver/flutter_driver.dart';
/// Example Integration Test which can also run WebDriver command depending on
/// the requests coming from the test methods.
Future<void> integrationDriver(
{FlutterDriver driver, Function onScreenshot}) async {
{FlutterDriver? driver, required Function onScreenshot}) async {
if (driver == null) {
driver = await FlutterDriver.connect();
}
Expand All @@ -23,13 +23,13 @@ Future<void> integrationDriver(
// Until `integration_test` returns a [WebDriverCommandType.noop], keep
// executing WebDriver commands.
while (response.data != null &&
response.data['web_driver_command'] != null &&
response.data['web_driver_command'] != '${WebDriverCommandType.noop}') {
final String webDriverCommand = response.data['web_driver_command'];
response.data!['web_driver_command'] != null &&
response.data!['web_driver_command'] != '${WebDriverCommandType.noop}') {
final String webDriverCommand = response.data!['web_driver_command'];
if (webDriverCommand == '${WebDriverCommandType.screenshot}') {
// Use `driver.screenshot()` method to get a screenshot of the web page.
final List<int> screenshotImage = await driver.screenshot();
final String screenshotName = response.data['screenshot_name'];
final String screenshotName = response.data!['screenshot_name'];

final bool screenshotSuccess =
await onScreenshot(screenshotName, screenshotImage);
Expand All @@ -55,8 +55,8 @@ Future<void> integrationDriver(

// If No-op command is sent, ask for the result of all tests.
if (response.data != null &&
response.data['web_driver_command'] != null &&
response.data['web_driver_command'] == '${WebDriverCommandType.noop}') {
response.data!['web_driver_command'] != null &&
response.data!['web_driver_command'] == '${WebDriverCommandType.noop}') {
jsonResponse = await driver.requestData(null);

response = Response.fromJson(jsonResponse);
Expand Down
Loading