// Copyright 2013 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:args/command_runner.dart'; import 'package:file/file.dart'; import 'package:file/memory.dart'; import 'package:flutter_plugin_tools/src/common/core.dart'; import 'package:flutter_plugin_tools/src/common/plugin_utils.dart'; import 'package:flutter_plugin_tools/src/dart_test_command.dart'; import 'package:platform/platform.dart'; import 'package:test/test.dart'; import 'mocks.dart'; import 'util.dart'; void main() { group('TestCommand', () { late FileSystem fileSystem; late Platform mockPlatform; late Directory packagesDir; late CommandRunner runner; late RecordingProcessRunner processRunner; setUp(() { fileSystem = MemoryFileSystem(); mockPlatform = MockPlatform(); packagesDir = createPackagesDirectory(fileSystem: fileSystem); processRunner = RecordingProcessRunner(); final DartTestCommand command = DartTestCommand( packagesDir, processRunner: processRunner, platform: mockPlatform, ); runner = CommandRunner('test_test', 'Test for $DartTestCommand'); runner.addCommand(command); }); test('legacy "test" name still works', () async { final RepositoryPackage plugin = createFakePlugin('a_plugin', packagesDir, extraFiles: ['test/a_test.dart']); await runCapturingPrint(runner, ['test']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall(getFlutterCommand(mockPlatform), const ['test', '--color'], plugin.path), ]), ); }); test('runs flutter test on each plugin', () async { final RepositoryPackage plugin1 = createFakePlugin('plugin1', packagesDir, extraFiles: ['test/empty_test.dart']); final RepositoryPackage plugin2 = createFakePlugin('plugin2', packagesDir, extraFiles: ['test/empty_test.dart']); await runCapturingPrint(runner, ['dart-test']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall(getFlutterCommand(mockPlatform), const ['test', '--color'], plugin1.path), ProcessCall(getFlutterCommand(mockPlatform), const ['test', '--color'], plugin2.path), ]), ); }); test('runs flutter test on Flutter package example tests', () async { final RepositoryPackage plugin = createFakePlugin('a_plugin', packagesDir, extraFiles: [ 'test/empty_test.dart', 'example/test/an_example_test.dart' ]); await runCapturingPrint(runner, ['dart-test']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall(getFlutterCommand(mockPlatform), const ['test', '--color'], plugin.path), ProcessCall(getFlutterCommand(mockPlatform), const ['test', '--color'], getExampleDir(plugin).path), ]), ); }); test('fails when Flutter tests fail', () async { createFakePlugin('plugin1', packagesDir, extraFiles: ['test/empty_test.dart']); createFakePlugin('plugin2', packagesDir, extraFiles: ['test/empty_test.dart']); processRunner .mockProcessesForExecutable[getFlutterCommand(mockPlatform)] = [ FakeProcessInfo( MockProcess(exitCode: 1), ['dart-test']), // plugin 1 test FakeProcessInfo(MockProcess(), ['dart-test']), // plugin 2 test ]; Error? commandError; final List output = await runCapturingPrint( runner, ['dart-test'], errorHandler: (Error e) { commandError = e; }); expect(commandError, isA()); expect( output, containsAllInOrder([ contains('The following packages had errors:'), contains(' plugin1'), ])); }); test('skips testing plugins without test directory', () async { createFakePlugin('plugin1', packagesDir); final RepositoryPackage plugin2 = createFakePlugin('plugin2', packagesDir, extraFiles: ['test/empty_test.dart']); await runCapturingPrint(runner, ['dart-test']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall(getFlutterCommand(mockPlatform), const ['test', '--color'], plugin2.path), ]), ); }); test('runs dart run test on non-Flutter packages', () async { final RepositoryPackage plugin = createFakePlugin('a', packagesDir, extraFiles: ['test/empty_test.dart']); final RepositoryPackage package = createFakePackage('b', packagesDir, extraFiles: ['test/empty_test.dart']); await runCapturingPrint( runner, ['dart-test', '--enable-experiment=exp1']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall( getFlutterCommand(mockPlatform), const ['test', '--color', '--enable-experiment=exp1'], plugin.path), ProcessCall('dart', const ['pub', 'get'], package.path), ProcessCall( 'dart', const ['run', '--enable-experiment=exp1', 'test'], package.path), ]), ); }); test('runs dart run test on non-Flutter package examples', () async { final RepositoryPackage package = createFakePackage( 'a_package', packagesDir, extraFiles: [ 'test/empty_test.dart', 'example/test/an_example_test.dart' ]); await runCapturingPrint(runner, ['dart-test']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall('dart', const ['pub', 'get'], package.path), ProcessCall('dart', const ['run', 'test'], package.path), ProcessCall('dart', const ['pub', 'get'], getExampleDir(package).path), ProcessCall('dart', const ['run', 'test'], getExampleDir(package).path), ]), ); }); test('fails when getting non-Flutter package dependencies fails', () async { createFakePackage('a_package', packagesDir, extraFiles: ['test/empty_test.dart']); processRunner.mockProcessesForExecutable['dart'] = [ FakeProcessInfo(MockProcess(exitCode: 1), ['pub', 'get']) ]; Error? commandError; final List output = await runCapturingPrint( runner, ['dart-test'], errorHandler: (Error e) { commandError = e; }); expect(commandError, isA()); expect( output, containsAllInOrder([ contains('Unable to fetch dependencies'), contains('The following packages had errors:'), contains(' a_package'), ])); }); test('fails when non-Flutter tests fail', () async { createFakePackage('a_package', packagesDir, extraFiles: ['test/empty_test.dart']); processRunner.mockProcessesForExecutable['dart'] = [ FakeProcessInfo(MockProcess(), ['pub', 'get']), FakeProcessInfo(MockProcess(exitCode: 1), ['run']), // run test ]; Error? commandError; final List output = await runCapturingPrint( runner, ['dart-test'], errorHandler: (Error e) { commandError = e; }); expect(commandError, isA()); expect( output, containsAllInOrder([ contains('The following packages had errors:'), contains(' a_package'), ])); }); test('runs on Chrome for web plugins', () async { final RepositoryPackage plugin = createFakePlugin( 'plugin', packagesDir, extraFiles: ['test/empty_test.dart'], platformSupport: { platformWeb: const PlatformDetails(PlatformSupport.inline), }, ); await runCapturingPrint(runner, ['dart-test']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall( getFlutterCommand(mockPlatform), const ['test', '--color', '--platform=chrome'], plugin.path), ]), ); }); test('Does not run on Chrome for web endorsements', () async { final RepositoryPackage plugin = createFakePlugin( 'plugin', packagesDir, extraFiles: ['test/empty_test.dart'], platformSupport: { platformWeb: const PlatformDetails(PlatformSupport.federated), }, ); await runCapturingPrint(runner, ['dart-test']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall(getFlutterCommand(mockPlatform), const ['test', '--color'], plugin.path), ]), ); }); test('enable-experiment flag', () async { final RepositoryPackage plugin = createFakePlugin('a', packagesDir, extraFiles: ['test/empty_test.dart']); final RepositoryPackage package = createFakePackage('b', packagesDir, extraFiles: ['test/empty_test.dart']); await runCapturingPrint( runner, ['dart-test', '--enable-experiment=exp1']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall( getFlutterCommand(mockPlatform), const ['test', '--color', '--enable-experiment=exp1'], plugin.path), ProcessCall('dart', const ['pub', 'get'], package.path), ProcessCall( 'dart', const ['run', '--enable-experiment=exp1', 'test'], package.path), ]), ); }); }); }