Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[e2e] add support to report extra information #2873

Merged
merged 11 commits into from
Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
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/e2e/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.6.1

* Added `data` in the reported json.

## 0.6.0

* **Breaking change** `E2EPlugin` exports a `Future` for `testResults`.
Expand Down
19 changes: 13 additions & 6 deletions packages/e2e/lib/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ class Response {

final bool _allTestsPassed;

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

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

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

/// Whether the test ran successfully or not.
bool get allTestsPassed => _allTestsPassed;
Expand All @@ -33,16 +37,19 @@ class Response {
String toJson() => json.encode(<String, dynamic>{
'result': allTestsPassed.toString(),
'failureDetails': _failureDetailsAsString(),
if (data != null) 'data': data
});

/// Deserializes the result from JSON.
static Response fromJson(String source) {
Map<String, dynamic> responseJson = json.decode(source);
if (responseJson['result'] == 'true') {
return Response.allTestsPassed();
final Map<String, dynamic> responseJson = json.decode(source);
if (responseJson['result'] as String == 'true') {
return Response.allTestsPassed(data: responseJson['data']);
} else {
return Response.someTestsFailed(
_failureDetailsFromJson(responseJson['failureDetails']));
_failureDetailsFromJson(responseJson['failureDetails']),
data: responseJson['data'],
);
}
}

Expand Down
60 changes: 37 additions & 23 deletions packages/e2e/lib/e2e.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,33 +78,47 @@ class E2EWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding {

static Map<String, String> _results = <String, String>{};

/// The extra data for the reported result.
///
/// The values in `reportData` must be json-serializable objects or `null`.
/// If it's `null`, no extra data is attached to the result.
///
/// The default value is `null`.
Map<String, dynamic> reportData;

/// the callback function to response the driver side input.
@visibleForTesting
Future<Map<String, dynamic>> callback(Map<String, String> params) async {
final String command = params['command'];
Map<String, String> response;
switch (command) {
case 'request_data':
final bool allTestsPassed = await _allTestsPassed.future;
response = <String, String>{
'message': allTestsPassed
? Response.allTestsPassed(data: reportData).toJson()
: Response.someTestsFailed(
_failureMethodsDetails,
data: reportData,
).toJson(),
};
break;
case 'get_health':
response = <String, String>{'status': 'ok'};
break;
default:
throw UnimplementedError('$command is not implemented');
}
return <String, dynamic>{
'isError': false,
'response': response,
};
}

// Emulates the Flutter driver extension, returning 'pass' or 'fail'.
@override
void initServiceExtensions() {
super.initServiceExtensions();
Future<Map<String, dynamic>> callback(Map<String, String> params) async {
final String command = params['command'];
Map<String, String> response;
switch (command) {
case 'request_data':
final bool allTestsPassed = await _allTestsPassed.future;
response = <String, String>{
'message': allTestsPassed
? Response.allTestsPassed().toJson()
: Response.someTestsFailed(_failureMethodsDetails).toJson(),
};
break;
case 'get_health':
response = <String, String>{'status': 'ok'};
break;
default:
throw UnimplementedError('$command is not implemented');
}
return <String, dynamic>{
'isError': false,
'response': response,
};
}

if (kIsWeb) {
registerWebServiceExtension(callback);
Expand Down
4 changes: 2 additions & 2 deletions packages/e2e/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name: e2e
description: Runs tests that use the flutter_test API as integration tests.
version: 0.6.0
version: 0.6.1
homepage: https://github.com/flutter/plugins/tree/master/packages/e2e

environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.2.2 <3.0.0"
flutter: ">=1.12.13+hotfix.5 <2.0.0"

dependencies:
Expand Down
41 changes: 41 additions & 0 deletions packages/e2e/test/binding_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:flutter/material.dart';

import 'package:e2e/e2e.dart';
import 'package:e2e/common.dart';
import 'package:flutter_test/flutter_test.dart';

void main() async {
Future<Map<String, dynamic>> request;

group('Test E2E binding', () {
final WidgetsBinding binding = E2EWidgetsFlutterBinding.ensureInitialized();
assert(binding is E2EWidgetsFlutterBinding);
final E2EWidgetsFlutterBinding e2ebinding =
binding as E2EWidgetsFlutterBinding;

setUp(() {
request = e2ebinding.callback(<String, String>{
'command': 'request_data',
});
});

testWidgets('Run E2E app', (WidgetTester tester) async {
runApp(MaterialApp(
home: Text('Test'),
));
expect(tester.binding, e2ebinding);
e2ebinding.reportData = <String, dynamic>{'answer': 42};
});
});

tearDownAll(() async {
// This part is outside the group so that `request` has been compeleted as
// part of the `tearDownAll` registerred in the group during
// `E2EWidgetsFlutterBinding` initialization.
final Map<String, dynamic> response =
(await request)['response'] as Map<String, dynamic>;
final String message = response['message'] as String;
Response result = Response.fromJson(message);
assert(result.data['answer'] == 42);
});
}
47 changes: 47 additions & 0 deletions packages/e2e/test/response_serialization_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:flutter_test/flutter_test.dart';

import 'package:e2e/common.dart';

void main() {
test('Serialize and deserialize Failure', () {
Failure fail = Failure('what a name', 'no detail');
Failure restored = Failure.fromJsonString(fail.toString());
expect(restored.methodName, fail.methodName);
expect(restored.details, fail.details);
});

test('Serialize and deserialize Response', () {
Response response, restored;
String jsonString;

response = Response.allTestsPassed();
jsonString = response.toJson();
expect(jsonString, '{"result":"true","failureDetails":[]}');
restored = Response.fromJson(jsonString);
expect(restored.allTestsPassed, response.allTestsPassed);
expect(restored.data, null);
expect(restored.formattedFailureDetails, '');

final Failure fail = Failure('what a name', 'no detail');
final Failure fail2 = Failure('what a name2', 'no detail2');
response = Response.someTestsFailed([fail, fail2]);
jsonString = response.toJson();
restored = Response.fromJson(jsonString);
expect(restored.allTestsPassed, response.allTestsPassed);
expect(restored.data, null);
expect(restored.formattedFailureDetails, response.formattedFailureDetails);

Map<String, dynamic> data = <String, dynamic>{'aaa': 'bbb'};
response = Response.allTestsPassed(data: data);
jsonString = response.toJson();
restored = Response.fromJson(jsonString);
expect(restored.data.keys, ['aaa']);
expect(restored.data.values, ['bbb']);

response = Response.someTestsFailed([fail, fail2], data: data);
jsonString = response.toJson();
restored = Response.fromJson(jsonString);
expect(restored.data.keys, ['aaa']);
expect(restored.data.values, ['bbb']);
});
}