// 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:flutter_plugin_tools/src/analyze_command.dart'; import 'package:flutter_plugin_tools/src/common.dart'; import 'package:test/test.dart'; import 'mocks.dart'; import 'util.dart'; void main() { late RecordingProcessRunner processRunner; late CommandRunner runner; setUp(() { initializeFakePackages(); processRunner = RecordingProcessRunner(); final AnalyzeCommand analyzeCommand = AnalyzeCommand(mockPackagesDir, processRunner: processRunner); runner = CommandRunner('analyze_command', 'Test for analyze_command'); runner.addCommand(analyzeCommand); }); tearDown(() { mockPackagesDir.deleteSync(recursive: true); }); test('analyzes all packages', () async { final Directory plugin1Dir = createFakePlugin('a'); final Directory plugin2Dir = createFakePlugin('b'); final MockProcess mockProcess = MockProcess(); mockProcess.exitCodeCompleter.complete(0); processRunner.processToReturn = mockProcess; await runner.run(['analyze']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall( 'flutter', const ['packages', 'get'], plugin1Dir.path), ProcessCall( 'flutter', const ['packages', 'get'], plugin2Dir.path), ProcessCall('dart', const ['analyze', '--fatal-infos'], plugin1Dir.path), ProcessCall('dart', const ['analyze', '--fatal-infos'], plugin2Dir.path), ])); }); test('skips flutter pub get for examples', () async { final Directory plugin1Dir = createFakePlugin('a', withSingleExample: true); final MockProcess mockProcess = MockProcess(); mockProcess.exitCodeCompleter.complete(0); processRunner.processToReturn = mockProcess; await runner.run(['analyze']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall( 'flutter', const ['packages', 'get'], plugin1Dir.path), ProcessCall('dart', const ['analyze', '--fatal-infos'], plugin1Dir.path), ])); }); test('don\'t elide a non-contained example package', () async { final Directory plugin1Dir = createFakePlugin('a'); final Directory plugin2Dir = createFakePlugin('example'); final MockProcess mockProcess = MockProcess(); mockProcess.exitCodeCompleter.complete(0); processRunner.processToReturn = mockProcess; await runner.run(['analyze']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall( 'flutter', const ['packages', 'get'], plugin1Dir.path), ProcessCall( 'flutter', const ['packages', 'get'], plugin2Dir.path), ProcessCall('dart', const ['analyze', '--fatal-infos'], plugin1Dir.path), ProcessCall('dart', const ['analyze', '--fatal-infos'], plugin2Dir.path), ])); }); test('uses a separate analysis sdk', () async { final Directory pluginDir = createFakePlugin('a'); final MockProcess mockProcess = MockProcess(); mockProcess.exitCodeCompleter.complete(0); processRunner.processToReturn = mockProcess; await runner.run(['analyze', '--analysis-sdk', 'foo/bar/baz']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall( 'flutter', const ['packages', 'get'], pluginDir.path, ), ProcessCall( 'foo/bar/baz/bin/dart', const ['analyze', '--fatal-infos'], pluginDir.path, ), ]), ); }); group('verifies analysis settings', () { test('fails analysis_options.yaml', () async { createFakePlugin('foo', withExtraFiles: >[ ['analysis_options.yaml'] ]); await expectLater(() => runner.run(['analyze']), throwsA(const TypeMatcher())); }); test('fails .analysis_options', () async { createFakePlugin('foo', withExtraFiles: >[ ['.analysis_options'] ]); await expectLater(() => runner.run(['analyze']), throwsA(const TypeMatcher())); }); test('takes an allow list', () async { final Directory pluginDir = createFakePlugin('foo', withExtraFiles: >[ ['analysis_options.yaml'] ]); final MockProcess mockProcess = MockProcess(); mockProcess.exitCodeCompleter.complete(0); processRunner.processToReturn = mockProcess; await runner.run(['analyze', '--custom-analysis', 'foo']); expect( processRunner.recordedCalls, orderedEquals([ ProcessCall( 'flutter', const ['packages', 'get'], pluginDir.path), ProcessCall('dart', const ['analyze', '--fatal-infos'], pluginDir.path), ])); }); // See: https://github.com/flutter/flutter/issues/78994 test('takes an empty allow list', () async { createFakePlugin('foo', withExtraFiles: >[ ['analysis_options.yaml'] ]); final MockProcess mockProcess = MockProcess(); mockProcess.exitCodeCompleter.complete(0); processRunner.processToReturn = mockProcess; await expectLater( () => runner.run(['analyze', '--custom-analysis', '']), throwsA(const TypeMatcher())); }); }); }