// Copyright 2014 The Flutter 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 'package:dds/src/dap/protocol_generated.dart'; import 'package:file/file.dart'; import 'package:flutter_tools/src/cache.dart'; import '../../src/common.dart'; import '../test_data/tests_project.dart'; import '../test_utils.dart'; import 'test_client.dart'; import 'test_support.dart'; void main() { late Directory tempDir; late DapTestSession dap; setUpAll(() { Cache.flutterRoot = getFlutterRoot(); }); setUp(() async { tempDir = createResolvedTempDirectorySync('flutter_test_adapter_test.'); dap = await DapTestSession.setUp(additionalArgs: <String>['--test']); }); tearDown(() async { await dap.tearDown(); tryToDelete(tempDir); }); test('can run in debug mode', () async { final DapTestClient client = dap.client; final TestsProject project = TestsProject(); await project.setUpIn(tempDir); // Collect output and test events while running the script. final TestEvents outputEvents = await client.collectTestOutput( launch: () => client.launch( program: project.testFilePath, cwd: project.dir.path, ), ); // Check the printed output shows that the run finished, and it's exit // code (which is 1 due to the failing test). final String output = outputEvents.output.map((OutputEventBody e) => e.output).join(); expectLines( output, <Object>[ startsWith('Connecting to VM Service at'), ..._testsProjectExpectedOutput ], allowExtras: true, // Allow for printed call stack etc. ); _expectStandardTestsProjectResults(outputEvents); }); test('can run in noDebug mode', () async { final DapTestClient client = dap.client; final TestsProject project = TestsProject(); await project.setUpIn(tempDir); // Collect output and test events while running the script. final TestEvents outputEvents = await client.collectTestOutput( launch: () => client.launch( program: project.testFilePath, noDebug: true, cwd: project.dir.path, ), ); // Check the printed output shows that the run finished, and it's exit // code (which is 1 due to the failing test). final String output = outputEvents.output.map((OutputEventBody e) => e.output).join(); expectLines( output, _testsProjectExpectedOutput, allowExtras: true, // Allow for printed call stack etc. ); _expectStandardTestsProjectResults(outputEvents); }); test('can run a single test', () async { final DapTestClient client = dap.client; final TestsProject project = TestsProject(); await project.setUpIn(tempDir); // Collect output and test events while running the script. final TestEvents outputEvents = await client.collectTestOutput( launch: () => client.launch( program: project.testFilePath, noDebug: true, cwd: project.dir.path, // It's up to the calling IDE to pass the correct args for 'dart test' // if it wants to run a subset of tests. args: <String>[ '--plain-name', 'can pass', ], ), ); final List<Object> testsNames = outputEvents.testNotifications .where((Map<String, Object?> e) => e['type'] == 'testStart') .map((Map<String, Object?> e) => (e['test']! as Map<String, Object?>)['name']!) .toList(); expect(testsNames, contains('Flutter tests can pass')); expect(testsNames, isNot(contains('Flutter tests can fail'))); }); } /// Matchers for the expected console output of [TestsProject]. final List<Object> _testsProjectExpectedOutput = <Object>[ // First test '✓ Flutter tests can pass', // Second test '══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════', 'The following TestFailure was thrown running a test:', 'Expected: false', ' Actual: <true>', '', 'The test description was: can fail', '', '✖ Flutter tests can fail', // Exit '', 'Exited (1).', ]; /// A helper that verifies a full set of expected test results for the /// [TestsProject] script. void _expectStandardTestsProjectResults(TestEvents events) { // Check we received all expected test events passed through from // package:test. final List<Object> eventNames = events.testNotifications.map((Map<String, Object?> e) => e['type']!).toList(); // start/done should always be first/last. expect(eventNames.first, equals('start')); expect(eventNames.last, equals('done')); // allSuites should have occurred after start. expect( eventNames, containsAllInOrder(<String>['start', 'allSuites']), ); // Expect two tests, with the failing one emitting an error. expect( eventNames, containsAllInOrder(<String>[ 'testStart', 'testDone', 'testStart', 'error', 'testDone', ]), ); }