// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:io'; import 'package:cli_util/cli_logging.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; import '../utils.dart'; void main() { group('fix', defineFix, timeout: longTimeout); } /// Enable to run from local source (useful in development). const runFromSource = false; void defineFix() { TestProject p; ProcessResult result; final bullet = Logger.standard().ansi.bullet; setUp(() => p = null); tearDown(() => p?.dispose()); void assertResult({int exitCode = 0}) { String message; if (result.exitCode != exitCode) { if (result.stderr.isNotEmpty) { message = 'Error code was ${result.exitCode} and stderr was not empty'; } else { message = 'Error code was ${result.exitCode}'; } } else if (result.stderr.isNotEmpty) { message = 'stderr was not empty'; } else { return; } fail(''' $message stdout: ${result.stdout} stderr: ${result.stderr} '''); } ProcessResult runFix(List args, {String workingDir}) { if (runFromSource) { var binary = path.join(Directory.current.path, 'bin', 'dartdev.dart'); return p.runSync([binary, 'fix', ...?args], workingDir: workingDir); } return p.runSync(['fix', ...args], workingDir: workingDir); } test('help', () { p = project(mainSrc: 'int get foo => 1;\n'); var result = runFix([p.dirPath, '--help']); expect(result.exitCode, 0); expect(result.stderr, isEmpty); expect( result.stdout, contains('Apply automated fixes to Dart source code.')); }); test('none', () { p = project(mainSrc: 'int get foo => 1;\n'); var result = runFix([p.dirPath]); expect(result.exitCode, 0); expect(result.stderr, isEmpty); expect( result.stdout, contains('Apply automated fixes to Dart source code.')); }); test('--apply (none)', () { p = project(mainSrc: 'int get foo => 1;\n'); var result = runFix(['--apply', p.dirPath]); expect(result.exitCode, 0); expect(result.stderr, isEmpty); expect(result.stdout, contains('Nothing to fix!')); }); test('--apply (no args)', () { p = project( mainSrc: ''' var x = ""; ''', analysisOptions: ''' linter: rules: - prefer_single_quotes ''', ); var result = runFix(['--apply'], workingDir: p.dirPath); expect(result.exitCode, 0); expect(result.stderr, isEmpty); expect( result.stdout, stringContainsInOrder([ 'Applying fixes...', 'lib${Platform.pathSeparator}main.dart', ' prefer_single_quotes $bullet 1 fix', ])); }); test('--dry-run', () { p = project( mainSrc: ''' class A { String a() => ""; } class B extends A { String a() => ""; } ''', analysisOptions: ''' linter: rules: - annotate_overrides - prefer_single_quotes ''', ); var result = runFix(['--dry-run', '.'], workingDir: p.dirPath); expect(result.exitCode, 0); expect(result.stderr, isEmpty); expect( result.stdout, stringContainsInOrder([ '3 proposed fixes in 1 file.', 'lib${Platform.pathSeparator}main.dart', ' annotate_overrides $bullet 1 fix', ' prefer_single_quotes $bullet 2 fixes', ])); }); test('--apply (.)', () { p = project( mainSrc: ''' var x = ""; ''', analysisOptions: ''' linter: rules: - prefer_single_quotes ''', ); var result = runFix(['--apply', '.'], workingDir: p.dirPath); expect(result.exitCode, 0); expect(result.stderr, isEmpty); expect( result.stdout, stringContainsInOrder([ 'Applying fixes...', 'lib${Platform.pathSeparator}main.dart', ' prefer_single_quotes $bullet 1 fix', '1 fix made in 1 file.', ])); }); test('--apply (excludes)', () { p = project( mainSrc: ''' var x = ""; ''', analysisOptions: ''' analyzer: exclude: - lib/** linter: rules: - prefer_single_quotes ''', ); var result = runFix(['--apply', '.'], workingDir: p.dirPath); expect(result.exitCode, 0); expect(result.stderr, isEmpty); expect(result.stdout, contains('Nothing to fix!')); }); test('--apply (ignores)', () { p = project( mainSrc: ''' // ignore: prefer_single_quotes var x = ""; ''', analysisOptions: ''' linter: rules: - prefer_single_quotes ''', ); var result = runFix(['--apply', '.'], workingDir: p.dirPath); expect(result.exitCode, 0); expect(result.stderr, isEmpty); expect(result.stdout, contains('Nothing to fix!')); }); group('compare-to-golden', () { test('applied fixes do not match expected', () { p = project( mainSrc: ''' class A { String a() => ""; } class B extends A { String a() => ""; } ''', analysisOptions: ''' linter: rules: - annotate_overrides - prefer_single_quotes ''', ); p.file('lib/main.dart.expect', ''' class A { String a() => ''; } class B extends A { String a() => ''; } '''); result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath); assertResult(exitCode: 1); }); test('applied fixes match expected', () { p = project( mainSrc: ''' class A { String a() => ""; } class B extends A { String a() => ""; } ''', analysisOptions: ''' linter: rules: - annotate_overrides - prefer_single_quotes ''', ); p.file('lib/main.dart.expect', ''' class A { String a() => ''; } class B extends A { @override String a() => ''; } '''); result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath); assertResult(); }); test('missing expect', () { p = project( mainSrc: ''' class A { String a() => ""; } class B extends A { String a() => ""; } ''', analysisOptions: ''' linter: rules: - annotate_overrides - prefer_single_quotes ''', ); result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath); assertResult(exitCode: 1); }); test('missing original', () { p = project(mainSrc: ''' class C {} '''); p.file('lib/main.dart.expect', ''' class C {} '''); p.file('lib/secondary.dart.expect', ''' class A {} '''); result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath); assertResult(exitCode: 1); }); test('no fixes to apply does not match expected', () { p = project( mainSrc: ''' class A { String a() => ""; } ''', analysisOptions: ''' linter: rules: - annotate_overrides ''', ); p.file('lib/main.dart.expect', ''' class A { String a() => ''; } '''); result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath); assertResult(exitCode: 1); }); }); }