// Copyright 2013 The Flutter Authors // 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:flutter_plugin_tools/src/common/core.dart'; import 'package:flutter_plugin_tools/src/custom_test_command.dart'; import 'package:git/git.dart'; import 'package:test/test.dart'; import 'mocks.dart'; import 'util.dart'; void main() { late MockPlatform mockPlatform; late Directory packagesDir; late RecordingProcessRunner processRunner; late CommandRunner runner; group('posix', () { setUp(() { mockPlatform = MockPlatform(); final GitDir gitDir; (:packagesDir, :processRunner, gitProcessRunner: _, :gitDir) = configureBaseCommandMocks(platform: mockPlatform); final analyzeCommand = CustomTestCommand( packagesDir, processRunner: processRunner, platform: mockPlatform, gitDir: gitDir, ); runner = CommandRunner( 'custom_test_command', 'Test for custom_test_command', ); runner.addCommand(analyzeCommand); }); test('runs both new and legacy when both are present', () async { final RepositoryPackage package = createFakePackage( 'a_package', packagesDir, extraFiles: ['tool/run_tests.dart', 'run_tests.sh'], ); final List output = await runCapturingPrint(runner, [ 'custom-test', ]); expect( processRunner.recordedCalls, containsAll([ ProcessCall( package.directory.childFile('run_tests.sh').path, const [], package.path, ), ProcessCall('dart', const [ 'run', 'tool/run_tests.dart', ], package.path), ]), ); expect( output, containsAllInOrder([contains('Ran for 1 package(s)')]), ); }); test('runs when only new is present', () async { final RepositoryPackage package = createFakePackage( 'a_package', packagesDir, extraFiles: ['tool/run_tests.dart'], ); final List output = await runCapturingPrint(runner, [ 'custom-test', ]); expect( processRunner.recordedCalls, containsAll([ ProcessCall('dart', const [ 'run', 'tool/run_tests.dart', ], package.path), ]), ); expect( output, containsAllInOrder([contains('Ran for 1 package(s)')]), ); }); test('runs pub get before running Dart test script', () async { final RepositoryPackage package = createFakePackage( 'a_package', packagesDir, extraFiles: ['tool/run_tests.dart'], ); await runCapturingPrint(runner, ['custom-test']); expect( processRunner.recordedCalls, containsAll([ ProcessCall('dart', const ['pub', 'get'], package.path), ProcessCall('dart', const [ 'run', 'tool/run_tests.dart', ], package.path), ]), ); }); test('runs when only legacy is present', () async { final RepositoryPackage package = createFakePackage( 'a_package', packagesDir, extraFiles: ['run_tests.sh'], ); final List output = await runCapturingPrint(runner, [ 'custom-test', ]); expect( processRunner.recordedCalls, containsAll([ ProcessCall( package.directory.childFile('run_tests.sh').path, const [], package.path, ), ]), ); expect( output, containsAllInOrder([contains('Ran for 1 package(s)')]), ); }); test('skips when neither is present', () async { createFakePackage('a_package', packagesDir); final List output = await runCapturingPrint(runner, [ 'custom-test', ]); expect(processRunner.recordedCalls, isEmpty); expect( output, containsAllInOrder([contains('Skipped 1 package(s)')]), ); }); test('fails if new fails', () async { createFakePackage( 'a_package', packagesDir, extraFiles: ['tool/run_tests.dart', 'run_tests.sh'], ); processRunner.mockProcessesForExecutable['dart'] = [ FakeProcessInfo(MockProcess(), ['pub', 'get']), FakeProcessInfo(MockProcess(exitCode: 1), ['test']), ]; Error? commandError; final List output = await runCapturingPrint( runner, ['custom-test'], errorHandler: (Error e) { commandError = e; }, ); expect(commandError, isA()); expect( output, containsAllInOrder([ contains('The following packages had errors:'), contains('a_package'), ]), ); }); test('fails if pub get fails', () async { createFakePackage( 'a_package', packagesDir, extraFiles: ['tool/run_tests.dart', 'run_tests.sh'], ); processRunner.mockProcessesForExecutable['dart'] = [ FakeProcessInfo(MockProcess(exitCode: 1), ['pub', 'get']), ]; Error? commandError; final List output = await runCapturingPrint( runner, ['custom-test'], errorHandler: (Error e) { commandError = e; }, ); expect(commandError, isA()); expect( output, containsAllInOrder([ contains('The following packages had errors:'), contains( 'a_package:\n' ' Unable to get script dependencies', ), ]), ); }); test('fails if legacy fails', () async { final RepositoryPackage package = createFakePackage( 'a_package', packagesDir, extraFiles: ['tool/run_tests.dart', 'run_tests.sh'], ); processRunner.mockProcessesForExecutable[package.directory .childFile('run_tests.sh') .path] = [ FakeProcessInfo(MockProcess(exitCode: 1)), ]; Error? commandError; final List output = await runCapturingPrint( runner, ['custom-test'], errorHandler: (Error e) { commandError = e; }, ); expect(commandError, isA()); expect( output, containsAllInOrder([ contains('The following packages had errors:'), contains('a_package'), ]), ); }); }); group('Windows', () { setUp(() { mockPlatform = MockPlatform(isWindows: true); final GitDir gitDir; (:packagesDir, :processRunner, gitProcessRunner: _, :gitDir) = configureBaseCommandMocks(platform: mockPlatform); final analyzeCommand = CustomTestCommand( packagesDir, processRunner: processRunner, platform: mockPlatform, gitDir: gitDir, ); runner = CommandRunner( 'custom_test_command', 'Test for custom_test_command', ); runner.addCommand(analyzeCommand); }); test('runs new and skips old when both are present', () async { final RepositoryPackage package = createFakePackage( 'a_package', packagesDir, extraFiles: ['tool/run_tests.dart', 'run_tests.sh'], ); final List output = await runCapturingPrint(runner, [ 'custom-test', ]); expect( processRunner.recordedCalls, containsAll([ ProcessCall('dart', const [ 'run', 'tool/run_tests.dart', ], package.path), ]), ); expect( output, containsAllInOrder([contains('Ran for 1 package(s)')]), ); }); test('runs when only new is present', () async { final RepositoryPackage package = createFakePackage( 'a_package', packagesDir, extraFiles: ['tool/run_tests.dart'], ); final List output = await runCapturingPrint(runner, [ 'custom-test', ]); expect( processRunner.recordedCalls, containsAll([ ProcessCall('dart', const [ 'run', 'tool/run_tests.dart', ], package.path), ]), ); expect( output, containsAllInOrder([contains('Ran for 1 package(s)')]), ); }); test('skips package when only legacy is present', () async { createFakePackage( 'a_package', packagesDir, extraFiles: ['run_tests.sh'], ); final List output = await runCapturingPrint(runner, [ 'custom-test', ]); expect(processRunner.recordedCalls, isEmpty); expect( output, containsAllInOrder([ contains('run_tests.sh is not supported on Windows'), contains('Skipped 1 package(s)'), ]), ); }); test('fails if new fails', () async { createFakePackage( 'a_package', packagesDir, extraFiles: ['tool/run_tests.dart', 'run_tests.sh'], ); processRunner.mockProcessesForExecutable['dart'] = [ FakeProcessInfo(MockProcess(), ['pub', 'get']), FakeProcessInfo(MockProcess(exitCode: 1), ['test']), ]; Error? commandError; final List output = await runCapturingPrint( runner, ['custom-test'], errorHandler: (Error e) { commandError = e; }, ); expect(commandError, isA()); expect( output, containsAllInOrder([ contains('The following packages had errors:'), contains('a_package'), ]), ); }); }); }