1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | /// @docImport 'package:integration_test/integration_test.dart'; |
6 | library; |
7 | |
8 | import 'dart:convert'; |
9 | import 'dart:io'; |
10 | |
11 | import 'package:flutter_test/flutter_test.dart'; |
12 | import 'package:path/path.dart' as path; |
13 | |
14 | final String bat = Platform.isWindows ? '.bat' : '' ; |
15 | final String _flutterBin = path.join(Directory.current.parent.parent.path, 'bin' , 'flutter $bat' ); |
16 | const String _integrationResultsPrefix = 'IntegrationTestWidgetsFlutterBinding test results:' ; |
17 | const String _failureExcerpt = r'Expected: <false>\n Actual: <true>' ; |
18 | |
19 | Future<void> main() async { |
20 | group('Integration binding result' , () { |
21 | test('when multiple tests pass' , () async { |
22 | final Map<String, dynamic>? results = await _runTest( |
23 | path.join('test' , 'data' , 'pass_test_script.dart' ), |
24 | ); |
25 | |
26 | expect( |
27 | results, |
28 | equals(<String, dynamic>{'passing test 1' : 'success' , 'passing test 2' : 'success' }), |
29 | ); |
30 | }); |
31 | |
32 | test('when multiple tests fail' , () async { |
33 | final Map<String, dynamic>? results = await _runTest( |
34 | path.join('test' , 'data' , 'fail_test_script.dart' ), |
35 | ); |
36 | |
37 | expect(results, hasLength(2)); |
38 | expect(results, containsPair('failing test 1' , contains(_failureExcerpt))); |
39 | expect(results, containsPair('failing test 2' , contains(_failureExcerpt))); |
40 | }); |
41 | |
42 | test('when one test passes, then another fails' , () async { |
43 | final Map<String, dynamic>? results = await _runTest( |
44 | path.join('test' , 'data' , 'pass_then_fail_test_script.dart' ), |
45 | ); |
46 | |
47 | expect(results, hasLength(2)); |
48 | expect(results, containsPair('passing test' , equals('success' ))); |
49 | expect(results, containsPair('failing test' , contains(_failureExcerpt))); |
50 | }); |
51 | |
52 | test('when one test fails, then another passes' , () async { |
53 | final Map<String, dynamic>? results = await _runTest( |
54 | path.join('test' , 'data' , 'fail_then_pass_test_script.dart' ), |
55 | ); |
56 | |
57 | expect(results, hasLength(2)); |
58 | expect(results, containsPair('failing test' , contains(_failureExcerpt))); |
59 | expect(results, containsPair('passing test' , equals('success' ))); |
60 | }); |
61 | }); |
62 | } |
63 | |
64 | /// Runs a test script and returns the [IntegrationTestWidgetsFlutterBinding.results]. |
65 | /// |
66 | /// [scriptPath] is relative to the package root. |
67 | Future<Map<String, dynamic>?> _runTest(String scriptPath) async { |
68 | final Process process = await Process.start(_flutterBin, <String>[ |
69 | 'test' , |
70 | '--machine' , |
71 | scriptPath, |
72 | ]); |
73 | |
74 | /// In the test [tearDownAll] block, the test results are encoded into JSON and |
75 | /// are printed with the [_integrationResultsPrefix] prefix. |
76 | /// |
77 | /// See the following for the test event spec which we parse the printed lines |
78 | /// out of: https://github.com/dart-lang/test/blob/master/pkgs/test/doc/json_reporter.md |
79 | final String testResults = (await process.stdout |
80 | .transform(utf8.decoder) |
81 | .expand((String text) => text.split('\n' )) |
82 | .map<dynamic>((String line) { |
83 | try { |
84 | return jsonDecode(line); |
85 | } on FormatException { |
86 | // Only interested in test events which are JSON. |
87 | } |
88 | }) |
89 | .expand<Map<String, dynamic>>((dynamic json) { |
90 | if (json is List<dynamic>) { |
91 | return json.cast(); |
92 | } |
93 | return <Map<String, dynamic>>[if (json != null) json as Map<String, dynamic>]; |
94 | }) |
95 | .where((Map<String, dynamic> testEvent) => testEvent['type' ] == 'print' ) |
96 | .map((Map<String, dynamic> printEvent) => printEvent['message' ] as String) |
97 | .firstWhere( |
98 | (String message) => message.startsWith(_integrationResultsPrefix), |
99 | )).replaceAll(_integrationResultsPrefix, '' ); |
100 | |
101 | return jsonDecode(testResults) as Map<String, dynamic>?; |
102 | } |
103 | |