// 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.

// @dart=2.9

import 'dart:async';
import 'dart:convert';
import 'dart:io' as io;

import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:flutter_plugin_tools/src/common.dart';
import 'package:flutter_plugin_tools/src/publish_plugin_command.dart';
import 'package:git/git.dart';
import 'package:matcher/matcher.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';

import 'mocks.dart';
import 'util.dart';

void main() {
  const String testPluginName = 'foo';
  final List<String> printedMessages = <String>[];

  Directory parentDir;
  Directory pluginDir;
  GitDir gitDir;
  TestProcessRunner processRunner;
  CommandRunner<void> commandRunner;
  MockStdin mockStdin;
  // This test uses a local file system instead of an in memory one throughout
  // so that git actually works. In setup we initialize a mono repo of plugins
  // with one package and commit everything to Git.
  const FileSystem fileSystem = LocalFileSystem();

  void _createMockCredentialFile() {
    final String credentialPath = PublishPluginCommand.getCredentialPath();
    fileSystem.file(credentialPath)
      ..createSync(recursive: true)
      ..writeAsStringSync('some credential');
  }

  setUp(() async {
    parentDir = fileSystem.systemTempDirectory
        .createTempSync('publish_plugin_command_test-');
    initializeFakePackages(parentDir: parentDir);
    pluginDir = createFakePlugin(testPluginName,
        withSingleExample: false, packagesDirectory: parentDir);
    assert(pluginDir != null && pluginDir.existsSync());
    createFakePubspec(pluginDir, includeVersion: true);
    io.Process.runSync('git', <String>['init'],
        workingDirectory: parentDir.path);
    gitDir = await GitDir.fromExisting(parentDir.path);
    await gitDir.runCommand(<String>['add', '-A']);
    await gitDir.runCommand(<String>['commit', '-m', 'Initial commit']);
    processRunner = TestProcessRunner();
    mockStdin = MockStdin();
    commandRunner = CommandRunner<void>('tester', '')
      ..addCommand(PublishPluginCommand(parentDir, fileSystem,
          processRunner: processRunner,
          print: (Object message) => printedMessages.add(message.toString()),
          stdinput: mockStdin,
          gitDir: await GitDir.fromExisting(parentDir.path)));
  });

  tearDown(() {
    parentDir.deleteSync(recursive: true);
    printedMessages.clear();
  });

  group('Initial validation', () {
    test('requires a package flag', () async {
      await expectLater(() => commandRunner.run(<String>['publish-plugin']),
          throwsA(const TypeMatcher<ToolExit>()));
      expect(
          printedMessages.last, contains('Must specify a package to publish.'));
    });

    test('requires an existing flag', () async {
      await expectLater(
          () => commandRunner.run(<String>[
                'publish-plugin',
                '--package',
                'iamerror',
                '--no-push-tags'
              ]),
          throwsA(const TypeMatcher<ToolExit>()));

      expect(printedMessages.last, contains('iamerror does not exist'));
    });

    test('refuses to proceed with dirty files', () async {
      pluginDir.childFile('tmp').createSync();

      await expectLater(
          () => commandRunner.run(<String>[
                'publish-plugin',
                '--package',
                testPluginName,
                '--no-push-tags'
              ]),
          throwsA(const TypeMatcher<ToolExit>()));

      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'There are files in the package directory that haven\'t been saved in git. Refusing to publish these files:\n\n?? foo/tmp\n\nIf the directory should be clean, you can run `git clean -xdf && git reset --hard HEAD` to wipe all local changes.',
            'Failed, see above for details.',
          ]));
    });

    test('fails immediately if the remote doesn\'t exist', () async {
      await expectLater(
          () => commandRunner
              .run(<String>['publish-plugin', '--package', testPluginName]),
          throwsA(const TypeMatcher<ToolExit>()));
      expect(processRunner.results.last.stderr, contains('No such remote'));
    });

    test("doesn't validate the remote if it's not pushing tags", () async {
      // Immediately return 0 when running `pub publish`.
      processRunner.mockPublishCompleteCode = 0;

      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release'
      ]);

      expect(printedMessages.last, 'Done!');
    });

    test('can publish non-flutter package', () async {
      createFakePubspec(pluginDir, includeVersion: true, isFlutter: false);
      io.Process.runSync('git', <String>['init'],
          workingDirectory: parentDir.path);
      gitDir = await GitDir.fromExisting(parentDir.path);
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Initial commit']);
      // Immediately return 0 when running `pub publish`.
      processRunner.mockPublishCompleteCode = 0;
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release'
      ]);
      expect(printedMessages.last, 'Done!');
    });
  });

  group('Publishes package', () {
    test('while showing all output from pub publish to the user', () async {
      final Future<void> publishCommand = commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release'
      ]);

      processRunner.mockPublishStdout = 'Foo';
      processRunner.mockPublishStderr = 'Bar';
      processRunner.mockPublishCompleteCode = 0;

      await publishCommand;

      expect(printedMessages, contains('Foo'));
      expect(printedMessages, contains('Bar'));
    });

    test('forwards input from the user to `pub publish`', () async {
      final Future<void> publishCommand = commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release'
      ]);
      mockStdin.mockUserInputs.add(utf8.encode('user input'));
      processRunner.mockPublishCompleteCode = 0;

      await publishCommand;

      expect(processRunner.mockPublishProcess.stdinMock.lines,
          contains('user input'));
    });

    test('forwards --pub-publish-flags to pub publish', () async {
      processRunner.mockPublishCompleteCode = 0;
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release',
        '--pub-publish-flags',
        '--dry-run,--server=foo'
      ]);

      expect(processRunner.mockPublishArgs.length, 4);
      expect(processRunner.mockPublishArgs[0], 'pub');
      expect(processRunner.mockPublishArgs[1], 'publish');
      expect(processRunner.mockPublishArgs[2], '--dry-run');
      expect(processRunner.mockPublishArgs[3], '--server=foo');
    });

    test(
        '--skip-confirmation flag automatically adds --force to --pub-publish-flags',
        () async {
      processRunner.mockPublishCompleteCode = 0;
      _createMockCredentialFile();
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
        '--no-tag-release',
        '--skip-confirmation',
        '--pub-publish-flags',
        '--server=foo'
      ]);

      expect(processRunner.mockPublishArgs.length, 4);
      expect(processRunner.mockPublishArgs[0], 'pub');
      expect(processRunner.mockPublishArgs[1], 'publish');
      expect(processRunner.mockPublishArgs[2], '--server=foo');
      expect(processRunner.mockPublishArgs[3], '--force');
    });

    test('throws if pub publish fails', () async {
      processRunner.mockPublishCompleteCode = 128;
      await expectLater(
          () => commandRunner.run(<String>[
                'publish-plugin',
                '--package',
                testPluginName,
                '--no-push-tags',
                '--no-tag-release',
              ]),
          throwsA(const TypeMatcher<ToolExit>()));

      expect(printedMessages, contains('Publish foo failed.'));
    });

    test('publish, dry run', () async {
      // Immediately return 1 when running `pub publish`. If dry-run does not work, test should throw.
      processRunner.mockPublishCompleteCode = 1;
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--dry-run',
        '--no-push-tags',
        '--no-tag-release',
      ]);

      expect(processRunner.pushTagsArgs, isEmpty);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            '===============  DRY RUN ===============',
            'Running `pub publish ` in ${pluginDir.path}...\n',
            'Done!'
          ]));
    });
  });

  group('Tags release', () {
    test('with the version and name from the pubspec.yaml', () async {
      processRunner.mockPublishCompleteCode = 0;
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-push-tags',
      ]);

      final String tag =
          (await gitDir.runCommand(<String>['show-ref', 'fake_package-v0.0.1']))
              .stdout as String;
      expect(tag, isNotEmpty);
    });

    test('only if publishing succeeded', () async {
      processRunner.mockPublishCompleteCode = 128;
      await expectLater(
          () => commandRunner.run(<String>[
                'publish-plugin',
                '--package',
                testPluginName,
                '--no-push-tags',
              ]),
          throwsA(const TypeMatcher<ToolExit>()));

      expect(printedMessages, contains('Publish foo failed.'));
      final String tag = (await gitDir.runCommand(
              <String>['show-ref', 'fake_package-v0.0.1'],
              throwOnError: false))
          .stdout as String;
      expect(tag, isEmpty);
    });
  });

  group('Pushes tags', () {
    setUp(() async {
      await gitDir.runCommand(
          <String>['remote', 'add', 'upstream', 'http://localhost:8000']);
    });

    test('requires user confirmation', () async {
      processRunner.mockPublishCompleteCode = 0;
      mockStdin.readLineOutput = 'help';
      await expectLater(
          () => commandRunner.run(<String>[
                'publish-plugin',
                '--package',
                testPluginName,
              ]),
          throwsA(const TypeMatcher<ToolExit>()));

      expect(printedMessages, contains('Tag push canceled.'));
    });

    test('to upstream by default', () async {
      await gitDir.runCommand(<String>['tag', 'garbage']);
      processRunner.mockPublishCompleteCode = 0;
      mockStdin.readLineOutput = 'y';
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
      ]);

      expect(processRunner.pushTagsArgs.isNotEmpty, isTrue);
      expect(processRunner.pushTagsArgs[1], 'upstream');
      expect(processRunner.pushTagsArgs[2], 'fake_package-v0.0.1');
      expect(printedMessages.last, 'Done!');
    });

    test('does not ask for user input if the --skip-confirmation flag is on',
        () async {
      await gitDir.runCommand(<String>['tag', 'garbage']);
      processRunner.mockPublishCompleteCode = 0;
      _createMockCredentialFile();
      await commandRunner.run(<String>[
        'publish-plugin',
        '--skip-confirmation',
        '--package',
        testPluginName,
      ]);

      expect(processRunner.pushTagsArgs.isNotEmpty, isTrue);
      expect(processRunner.pushTagsArgs[1], 'upstream');
      expect(processRunner.pushTagsArgs[2], 'fake_package-v0.0.1');
      expect(printedMessages.last, 'Done!');
    });

    test('to upstream by default, dry run', () async {
      await gitDir.runCommand(<String>['tag', 'garbage']);
      // Immediately return 1 when running `pub publish`. If dry-run does not work, test should throw.
      processRunner.mockPublishCompleteCode = 1;
      mockStdin.readLineOutput = 'y';
      await commandRunner.run(
          <String>['publish-plugin', '--package', testPluginName, '--dry-run']);

      expect(processRunner.pushTagsArgs, isEmpty);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            '===============  DRY RUN ===============',
            'Running `pub publish ` in ${pluginDir.path}...\n',
            'Tagging release fake_package-v0.0.1...',
            'Pushing tag to upstream...',
            'Done!'
          ]));
    });

    test('to different remotes based on a flag', () async {
      await gitDir.runCommand(
          <String>['remote', 'add', 'origin', 'http://localhost:8001']);
      processRunner.mockPublishCompleteCode = 0;
      mockStdin.readLineOutput = 'y';
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--remote',
        'origin',
      ]);

      expect(processRunner.pushTagsArgs.isNotEmpty, isTrue);
      expect(processRunner.pushTagsArgs[1], 'origin');
      expect(processRunner.pushTagsArgs[2], 'fake_package-v0.0.1');
      expect(printedMessages.last, 'Done!');
    });

    test('only if tagging and pushing to remotes are both enabled', () async {
      processRunner.mockPublishCompleteCode = 0;
      await commandRunner.run(<String>[
        'publish-plugin',
        '--package',
        testPluginName,
        '--no-tag-release',
      ]);

      expect(processRunner.pushTagsArgs.isEmpty, isTrue);
      expect(printedMessages.last, 'Done!');
    });
  });

  group('Auto release (all-changed flag)', () {
    setUp(() async {
      io.Process.runSync('git', <String>['init'],
          workingDirectory: parentDir.path);
      gitDir = await GitDir.fromExisting(parentDir.path);
      await gitDir.runCommand(
          <String>['remote', 'add', 'upstream', 'http://localhost:8000']);
    });

    test('can release newly created plugins', () async {
      // Non-federated
      final Directory pluginDir1 = createFakePlugin('plugin1',
          withSingleExample: true, packagesDirectory: parentDir);
      // federated
      final Directory pluginDir2 = createFakePlugin('plugin2',
          withSingleExample: true,
          parentDirectoryName: 'plugin2',
          packagesDirectory: parentDir);
      createFakePubspec(pluginDir1,
          name: 'plugin1',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      createFakePubspec(pluginDir2,
          name: 'plugin2',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
      // Immediately return 0 when running `pub publish`.
      processRunner.mockPublishCompleteCode = 0;
      mockStdin.readLineOutput = 'y';
      await commandRunner
          .run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'Checking local repo...',
            'Local repo is ready!',
            'Getting existing tags...',
            'Running `pub publish ` in ${pluginDir1.path}...\n',
            'Running `pub publish ` in ${pluginDir2.path}...\n',
            'Packages released: plugin1, plugin2',
            'Done!'
          ]));
      expect(processRunner.pushTagsArgs, isNotEmpty);
      expect(processRunner.pushTagsArgs[0], 'push');
      expect(processRunner.pushTagsArgs[1], 'upstream');
      expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.1');
      expect(processRunner.pushTagsArgs[3], 'push');
      expect(processRunner.pushTagsArgs[4], 'upstream');
      expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.1');
    });

    test('can release newly created plugins, while there are existing plugins',
        () async {
      // Prepare an exiting plugin and tag it
      final Directory pluginDir0 = createFakePlugin('plugin0',
          withSingleExample: true, packagesDirectory: parentDir);
      createFakePubspec(pluginDir0,
          name: 'plugin0',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
      // Immediately return 0 when running `pub publish`.
      processRunner.mockPublishCompleteCode = 0;
      mockStdin.readLineOutput = 'y';
      await commandRunner
          .run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
      processRunner.pushTagsArgs.clear();

      // Non-federated
      final Directory pluginDir1 = createFakePlugin('plugin1',
          withSingleExample: true, packagesDirectory: parentDir);
      // federated
      final Directory pluginDir2 = createFakePlugin('plugin2',
          withSingleExample: true,
          parentDirectoryName: 'plugin2',
          packagesDirectory: parentDir);
      createFakePubspec(pluginDir1,
          name: 'plugin1',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      createFakePubspec(pluginDir2,
          name: 'plugin2',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
      // Immediately return 0 when running `pub publish`.
      await commandRunner
          .run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'Checking local repo...',
            'Local repo is ready!',
            'Getting existing tags...',
            'Running `pub publish ` in ${pluginDir1.path}...\n',
            'Running `pub publish ` in ${pluginDir2.path}...\n',
            'Packages released: plugin1, plugin2',
            'Done!'
          ]));
      expect(processRunner.pushTagsArgs, isNotEmpty);
      expect(processRunner.pushTagsArgs[0], 'push');
      expect(processRunner.pushTagsArgs[1], 'upstream');
      expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.1');
      expect(processRunner.pushTagsArgs[3], 'push');
      expect(processRunner.pushTagsArgs[4], 'upstream');
      expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.1');
    });

    test('can release newly created plugins, dry run', () async {
      // Non-federated
      final Directory pluginDir1 = createFakePlugin('plugin1',
          withSingleExample: true, packagesDirectory: parentDir);
      // federated
      final Directory pluginDir2 = createFakePlugin('plugin2',
          withSingleExample: true,
          parentDirectoryName: 'plugin2',
          packagesDirectory: parentDir);
      createFakePubspec(pluginDir1,
          name: 'plugin1',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      createFakePubspec(pluginDir2,
          name: 'plugin2',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
      // Immediately return 1 when running `pub publish`. If dry-run does not work, test should throw.
      processRunner.mockPublishCompleteCode = 1;
      mockStdin.readLineOutput = 'y';
      await commandRunner.run(<String>[
        'publish-plugin',
        '--all-changed',
        '--base-sha=HEAD~',
        '--dry-run'
      ]);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'Checking local repo...',
            'Local repo is ready!',
            '===============  DRY RUN ===============',
            'Getting existing tags...',
            'Running `pub publish ` in ${pluginDir1.path}...\n',
            'Tagging release plugin1-v0.0.1...',
            'Pushing tag to upstream...',
            'Running `pub publish ` in ${pluginDir2.path}...\n',
            'Tagging release plugin2-v0.0.1...',
            'Pushing tag to upstream...',
            'Packages released: plugin1, plugin2',
            'Done!'
          ]));
      expect(processRunner.pushTagsArgs, isEmpty);
    });

    test('version change triggers releases.', () async {
      // Non-federated
      final Directory pluginDir1 = createFakePlugin('plugin1',
          withSingleExample: true, packagesDirectory: parentDir);
      // federated
      final Directory pluginDir2 = createFakePlugin('plugin2',
          withSingleExample: true,
          parentDirectoryName: 'plugin2',
          packagesDirectory: parentDir);
      createFakePubspec(pluginDir1,
          name: 'plugin1',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      createFakePubspec(pluginDir2,
          name: 'plugin2',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
      // Immediately return 0 when running `pub publish`.
      processRunner.mockPublishCompleteCode = 0;
      mockStdin.readLineOutput = 'y';
      await commandRunner
          .run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'Checking local repo...',
            'Local repo is ready!',
            'Getting existing tags...',
            'Running `pub publish ` in ${pluginDir1.path}...\n',
            'Running `pub publish ` in ${pluginDir2.path}...\n',
            'Packages released: plugin1, plugin2',
            'Done!'
          ]));
      expect(processRunner.pushTagsArgs, isNotEmpty);
      expect(processRunner.pushTagsArgs[0], 'push');
      expect(processRunner.pushTagsArgs[1], 'upstream');
      expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.1');
      expect(processRunner.pushTagsArgs[3], 'push');
      expect(processRunner.pushTagsArgs[4], 'upstream');
      expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.1');

      processRunner.pushTagsArgs.clear();
      printedMessages.clear();

      final List<String> plugin1Pubspec =
          pluginDir1.childFile('pubspec.yaml').readAsLinesSync();
      plugin1Pubspec[plugin1Pubspec.indexWhere(
          (String element) => element.contains('version:'))] = 'version: 0.0.2';
      pluginDir1
          .childFile('pubspec.yaml')
          .writeAsStringSync(plugin1Pubspec.join('\n'));
      final List<String> plugin2Pubspec =
          pluginDir2.childFile('pubspec.yaml').readAsLinesSync();
      plugin2Pubspec[plugin2Pubspec.indexWhere(
          (String element) => element.contains('version:'))] = 'version: 0.0.2';
      pluginDir2
          .childFile('pubspec.yaml')
          .writeAsStringSync(plugin2Pubspec.join('\n'));
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir
          .runCommand(<String>['commit', '-m', 'Update versions to 0.0.2']);

      await commandRunner
          .run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'Checking local repo...',
            'Local repo is ready!',
            'Getting existing tags...',
            'Running `pub publish ` in ${pluginDir1.path}...\n',
            'Running `pub publish ` in ${pluginDir2.path}...\n',
            'Packages released: plugin1, plugin2',
            'Done!'
          ]));

      expect(processRunner.pushTagsArgs, isNotEmpty);
      expect(processRunner.pushTagsArgs[0], 'push');
      expect(processRunner.pushTagsArgs[1], 'upstream');
      expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.2');
      expect(processRunner.pushTagsArgs[3], 'push');
      expect(processRunner.pushTagsArgs[4], 'upstream');
      expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.2');
    });

    test(
        'delete package will not trigger publish but exit the command successfully.',
        () async {
      // Non-federated
      final Directory pluginDir1 = createFakePlugin('plugin1',
          withSingleExample: true, packagesDirectory: parentDir);
      // federated
      final Directory pluginDir2 = createFakePlugin('plugin2',
          withSingleExample: true,
          parentDirectoryName: 'plugin2',
          packagesDirectory: parentDir);
      createFakePubspec(pluginDir1,
          name: 'plugin1',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      createFakePubspec(pluginDir2,
          name: 'plugin2',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
      // Immediately return 0 when running `pub publish`.
      processRunner.mockPublishCompleteCode = 0;
      mockStdin.readLineOutput = 'y';
      await commandRunner
          .run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'Checking local repo...',
            'Local repo is ready!',
            'Getting existing tags...',
            'Running `pub publish ` in ${pluginDir1.path}...\n',
            'Running `pub publish ` in ${pluginDir2.path}...\n',
            'Packages released: plugin1, plugin2',
            'Done!'
          ]));
      expect(processRunner.pushTagsArgs, isNotEmpty);
      expect(processRunner.pushTagsArgs[0], 'push');
      expect(processRunner.pushTagsArgs[1], 'upstream');
      expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.1');
      expect(processRunner.pushTagsArgs[3], 'push');
      expect(processRunner.pushTagsArgs[4], 'upstream');
      expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.1');

      processRunner.pushTagsArgs.clear();
      printedMessages.clear();

      final List<String> plugin1Pubspec =
          pluginDir1.childFile('pubspec.yaml').readAsLinesSync();
      plugin1Pubspec[plugin1Pubspec.indexWhere(
          (String element) => element.contains('version:'))] = 'version: 0.0.2';
      pluginDir1
          .childFile('pubspec.yaml')
          .writeAsStringSync(plugin1Pubspec.join('\n'));

      pluginDir2.deleteSync(recursive: true);

      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>[
        'commit',
        '-m',
        'Update plugin1 versions to 0.0.2, delete plugin2'
      ]);

      await commandRunner
          .run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'Checking local repo...',
            'Local repo is ready!',
            'Getting existing tags...',
            'Running `pub publish ` in ${pluginDir1.path}...\n',
            'The file at The pubspec file at ${pluginDir2.childFile('pubspec.yaml').path} does not exist. Publishing will not happen for plugin2.\nSafe to ignore if the package is deleted in this commit.\n',
            'Packages released: plugin1',
            'Done!'
          ]));

      expect(processRunner.pushTagsArgs, isNotEmpty);
      expect(processRunner.pushTagsArgs.length, 3);
      expect(processRunner.pushTagsArgs[0], 'push');
      expect(processRunner.pushTagsArgs[1], 'upstream');
      expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.2');
    });

    test(
        'versions revert do not trigger releases. Also prints out warning message.',
        () async {
      // Non-federated
      final Directory pluginDir1 = createFakePlugin('plugin1',
          withSingleExample: true, packagesDirectory: parentDir);
      // federated
      final Directory pluginDir2 = createFakePlugin('plugin2',
          withSingleExample: true,
          parentDirectoryName: 'plugin2',
          packagesDirectory: parentDir);
      createFakePubspec(pluginDir1,
          name: 'plugin1',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.2');
      createFakePubspec(pluginDir2,
          name: 'plugin2',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.2');
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
      // Immediately return 0 when running `pub publish`.
      processRunner.mockPublishCompleteCode = 0;
      mockStdin.readLineOutput = 'y';
      await commandRunner
          .run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'Checking local repo...',
            'Local repo is ready!',
            'Getting existing tags...',
            'Running `pub publish ` in ${pluginDir1.path}...\n',
            'Running `pub publish ` in ${pluginDir2.path}...\n',
            'Packages released: plugin1, plugin2',
            'Done!'
          ]));
      expect(processRunner.pushTagsArgs, isNotEmpty);
      expect(processRunner.pushTagsArgs[0], 'push');
      expect(processRunner.pushTagsArgs[1], 'upstream');
      expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.2');
      expect(processRunner.pushTagsArgs[3], 'push');
      expect(processRunner.pushTagsArgs[4], 'upstream');
      expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.2');

      processRunner.pushTagsArgs.clear();
      printedMessages.clear();

      final List<String> plugin1Pubspec =
          pluginDir1.childFile('pubspec.yaml').readAsLinesSync();
      plugin1Pubspec[plugin1Pubspec.indexWhere(
          (String element) => element.contains('version:'))] = 'version: 0.0.1';
      pluginDir1
          .childFile('pubspec.yaml')
          .writeAsStringSync(plugin1Pubspec.join('\n'));
      final List<String> plugin2Pubspec =
          pluginDir2.childFile('pubspec.yaml').readAsLinesSync();
      plugin2Pubspec[plugin2Pubspec.indexWhere(
          (String element) => element.contains('version:'))] = 'version: 0.0.1';
      pluginDir2
          .childFile('pubspec.yaml')
          .writeAsStringSync(plugin2Pubspec.join('\n'));
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir
          .runCommand(<String>['commit', '-m', 'Update versions to 0.0.1']);

      await commandRunner
          .run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'Checking local repo...',
            'Local repo is ready!',
            'Getting existing tags...',
            'The new version (0.0.1) is lower than the current version (0.0.2) for plugin1.\nThis git commit is a revert, no release is tagged.',
            'The new version (0.0.1) is lower than the current version (0.0.2) for plugin2.\nThis git commit is a revert, no release is tagged.',
            'Done!'
          ]));

      expect(processRunner.pushTagsArgs, isEmpty);
    });

    test('No version change does not release any plugins', () async {
      // Non-federated
      final Directory pluginDir1 = createFakePlugin('plugin1',
          withSingleExample: true, packagesDirectory: parentDir);
      // federated
      final Directory pluginDir2 = createFakePlugin('plugin2',
          withSingleExample: true,
          parentDirectoryName: 'plugin2',
          packagesDirectory: parentDir);
      createFakePubspec(pluginDir1,
          name: 'plugin1',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');
      createFakePubspec(pluginDir2,
          name: 'plugin2',
          includeVersion: true,
          isFlutter: false,
          version: '0.0.1');

      io.Process.runSync('git', <String>['init'],
          workingDirectory: parentDir.path);
      gitDir = await GitDir.fromExisting(parentDir.path);
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);

      pluginDir1.childFile('plugin1.dart').createSync();
      pluginDir2.childFile('plugin2.dart').createSync();
      await gitDir.runCommand(<String>['add', '-A']);
      await gitDir.runCommand(<String>['commit', '-m', 'Add dart files']);

      // Immediately return 0 when running `pub publish`.
      processRunner.mockPublishCompleteCode = 0;
      mockStdin.readLineOutput = 'y';
      await commandRunner
          .run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
      expect(
          printedMessages,
          containsAllInOrder(<String>[
            'Checking local repo...',
            'Local repo is ready!',
            'No version updates in this commit.',
            'Done!'
          ]));
      expect(processRunner.pushTagsArgs, isEmpty);
    });
  });
}

class TestProcessRunner extends ProcessRunner {
  final List<io.ProcessResult> results = <io.ProcessResult>[];
  // Most recent returned publish process.
  MockProcess mockPublishProcess;
  final List<String> mockPublishArgs = <String>[];
  final MockProcessResult mockPushTagsResult = MockProcessResult();
  final List<String> pushTagsArgs = <String>[];

  String mockPublishStdout;
  String mockPublishStderr;
  int mockPublishCompleteCode;

  @override
  Future<io.ProcessResult> run(
    String executable,
    List<String> args, {
    Directory workingDir,
    bool exitOnError = false,
    bool logOnError = false,
    Encoding stdoutEncoding = io.systemEncoding,
    Encoding stderrEncoding = io.systemEncoding,
  }) async {
    // Don't ever really push tags.
    if (executable == 'git' && args.isNotEmpty && args[0] == 'push') {
      pushTagsArgs.addAll(args);
      return mockPushTagsResult;
    }

    final io.ProcessResult result = io.Process.runSync(executable, args,
        workingDirectory: workingDir?.path);
    results.add(result);
    if (result.exitCode != 0) {
      throw ToolExit(result.exitCode);
    }
    return result;
  }

  @override
  Future<io.Process> start(String executable, List<String> args,
      {Directory workingDirectory}) async {
    /// Never actually publish anything. Start is always and only used for this
    /// since it returns something we can route stdin through.
    assert(executable == 'flutter' &&
        args.isNotEmpty &&
        args[0] == 'pub' &&
        args[1] == 'publish');
    mockPublishArgs.addAll(args);
    mockPublishProcess = MockProcess();
    if (mockPublishStdout != null) {
      mockPublishProcess.stdoutController.add(utf8.encode(mockPublishStdout));
    }
    if (mockPublishStderr != null) {
      mockPublishProcess.stderrController.add(utf8.encode(mockPublishStderr));
    }
    if (mockPublishCompleteCode != null) {
      mockPublishProcess.exitCodeCompleter.complete(mockPublishCompleteCode);
    }

    return mockPublishProcess;
  }
}

class MockStdin extends Mock implements io.Stdin {
  List<List<int>> mockUserInputs = <List<int>>[];
  StreamController<List<int>> _controller;
  String readLineOutput;

  @override
  Stream<S> transform<S>(StreamTransformer<List<int>, S> streamTransformer) {
    // In the test context, only one `PublishPluginCommand` object is created for a single test case.
    // However, sometimes, we need to run multiple commands in a single test case.
    // In such situation, this `MockStdin`'s StreamController might be listened to more than once, which is not allowed.
    //
    // Create a new controller every time so this Stdin could be listened to multiple times.
    _controller = StreamController<List<int>>();
    mockUserInputs.forEach(_addUserInputsToSteam);
    return _controller.stream.transform(streamTransformer);
  }

  @override
  StreamSubscription<List<int>> listen(void onData(List<int> event),
      {Function onError, void onDone(), bool cancelOnError}) {
    return _controller.stream.listen(onData,
        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
  }

  @override
  String readLineSync(
          {Encoding encoding = io.systemEncoding,
          bool retainNewlines = false}) =>
      readLineOutput;

  void _addUserInputsToSteam(List<int> input) => _controller.add(input);
}

class MockProcessResult extends Mock implements io.ProcessResult {
  MockProcessResult({int exitCode = 0}) : _exitCode = exitCode;

  final int _exitCode;

  @override
  int get exitCode => _exitCode;
}
