diff --git a/lib/build_verify.dart b/lib/build_verify.dart index 0a5c39f..c367622 100644 --- a/lib/build_verify.dart +++ b/lib/build_verify.dart @@ -20,6 +20,9 @@ const defaultCommand = [ /// with the full, platform-specific path to the corresponding executable in the /// currently executing SDK. /// +/// If [afterBuildCommand] is specified, it will be run after the build and +/// has the same behavior as [customCommand]. +/// /// If provided, [gitDiffPathArguments] are passed as `-- ` to `git diff`. /// This can be useful if you want to include certain files from the diff /// calculation. @@ -29,10 +32,12 @@ const defaultCommand = [ Future expectBuildClean({ String? packageRelativeDirectory, List customCommand = defaultCommand, + List? afterBuildCommand, List? gitDiffPathArguments, }) => expectBuildCleanImpl( Directory.current.resolveSymbolicLinksSync(), command: customCommand, + afterBuildCommand: afterBuildCommand, packageRelativeDirectory: packageRelativeDirectory, gitDiffPathArguments: gitDiffPathArguments, ); diff --git a/lib/src/impl.dart b/lib/src/impl.dart index 5d78588..e4a4f8d 100644 --- a/lib/src/impl.dart +++ b/lib/src/impl.dart @@ -13,6 +13,7 @@ const dartPlaceHolder = 'DART'; Future expectBuildCleanImpl( String workingDir, { List command = defaultCommand, + List? afterBuildCommand, String? packageRelativeDirectory, List? gitDiffPathArguments, }) async { @@ -54,7 +55,19 @@ Future expectBuildCleanImpl( expectResultOutputSucceeds(result); - // 3 - get a list of modified files after the build - should still be empty + // 3 - run after build command + if (afterBuildCommand != null && afterBuildCommand.isNotEmpty) { + var executable = afterBuildCommand.first; + if (executable == 'DART') { + executable = dartPath; + } + + final arguments = afterBuildCommand.skip(1).toList(); + + await _runProc(executable, arguments, workingDir); + } + + // 4 - get a list of modified files after the build - should still be empty expect( await _changedGeneratedFiles( workingDir, diff --git a/test/integration/simple_integration_test.dart b/test/integration/simple_integration_test.dart index 4f61a69..63bd523 100644 --- a/test/integration/simple_integration_test.dart +++ b/test/integration/simple_integration_test.dart @@ -61,4 +61,72 @@ void main() { ); }); }); + + group('afterBuildCommand without file changes', () { + test( + 'should succeed if afterBuildCommand does not produce git changes', + () async { + final afterBuildCommand = [dartPlaceHolder, 'pub', 'get']; + await expectBuildCleanImpl( + d.sandbox, + afterBuildCommand: afterBuildCommand, + ); + }, + ); + + test( + 'should fail if afterBuildCommand itself fails (e.g. command not exists)', + () async { + final failingAfterBuildCommand = ['this_command_does_not_exist']; + + await expectLater( + expectBuildCleanImpl( + d.sandbox, + afterBuildCommand: failingAfterBuildCommand, + ), + throwsA(isA()), + ); + }, + ); + }); + + group('afterBuildCommand when a file changes', () { + const pubspecLockFileName = 'pubspec.lock'; + + setUp(() async { + await gitDir.runCommand(['add', pubspecLockFileName]); + await gitDir.runCommand(['commit', '-am', 'commit pubspec']); + }); + + test('should fail if afterBuildCommand produces git changes', () async { + final afterBuildCommand = [ + 'sh', + '-c', + 'echo "new content just for this test" > $pubspecLockFileName', + ]; + + await expectLater( + expectBuildCleanImpl(d.sandbox, afterBuildCommand: afterBuildCommand), + throwsATestFailure, + ); + }); + + test( + 'should succeed if afterBuildCommand produces git changes which are then ' + 'ignored by gitDiffPathArguments', + () async { + final afterBuildCommand = [ + 'sh', + '-c', + 'echo "new content just for this test" > $pubspecLockFileName', + ]; + + await expectBuildCleanImpl( + d.sandbox, + afterBuildCommand: afterBuildCommand, + gitDiffPathArguments: [':!$pubspecLockFileName'], + ); + }, + ); + }); }