// 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 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:flutter_plugin_tools/src/lint_podspecs_command.dart';
import 'package:mockito/mockito.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:test/test.dart';

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

void main() {
  group('$LintPodspecsCommand', () {
    CommandRunner<void> runner;
    MockPlatform mockPlatform;
    final RecordingProcessRunner processRunner = RecordingProcessRunner();
    List<String> printedMessages;

    setUp(() {
      initializeFakePackages();

      printedMessages = <String>[];
      mockPlatform = MockPlatform();
      when(mockPlatform.isMacOS).thenReturn(true);
      final LintPodspecsCommand command = LintPodspecsCommand(
        mockPackagesDir,
        mockFileSystem,
        processRunner: processRunner,
        platform: mockPlatform,
        print: (Object message) => printedMessages.add(message.toString()),
      );

      runner =
          CommandRunner<void>('podspec_test', 'Test for $LintPodspecsCommand');
      runner.addCommand(command);
      final MockProcess mockLintProcess = MockProcess();
      mockLintProcess.exitCodeCompleter.complete(0);
      processRunner.processToReturn = mockLintProcess;
      processRunner.recordedCalls.clear();
    });

    tearDown(() {
      cleanupPackages();
    });

    test('only runs on macOS', () async {
      createFakePlugin('plugin1', withExtraFiles: <List<String>>[
        <String>['plugin1.podspec'],
      ]);

      when(mockPlatform.isMacOS).thenReturn(false);
      await runner.run(<String>['podspecs']);

      expect(
        processRunner.recordedCalls,
        equals(<ProcessCall>[]),
      );
    });

    test('runs pod lib lint on a podspec', () async {
      final Directory plugin1Dir =
          createFakePlugin('plugin1', withExtraFiles: <List<String>>[
        <String>['ios', 'plugin1.podspec'],
        <String>['bogus.dart'], // Ignore non-podspecs.
      ]);

      processRunner.resultStdout = 'Foo';
      processRunner.resultStderr = 'Bar';

      await runner.run(<String>['podspecs']);

      expect(
        processRunner.recordedCalls,
        orderedEquals(<ProcessCall>[
          ProcessCall('which', const <String>['pod'], mockPackagesDir.path),
          ProcessCall(
              'pod',
              <String>[
                'lib',
                'lint',
                p.join(plugin1Dir.path, 'ios', 'plugin1.podspec'),
                '--configuration=Debug',
                '--skip-tests',
                '--use-libraries'
              ],
              mockPackagesDir.path),
          ProcessCall(
              'pod',
              <String>[
                'lib',
                'lint',
                p.join(plugin1Dir.path, 'ios', 'plugin1.podspec'),
                '--configuration=Debug',
                '--skip-tests',
              ],
              mockPackagesDir.path),
        ]),
      );

      expect(printedMessages, contains('Linting plugin1.podspec'));
      expect(printedMessages, contains('Foo'));
      expect(printedMessages, contains('Bar'));
    });

    test('skips podspecs with known issues', () async {
      createFakePlugin('plugin1', withExtraFiles: <List<String>>[
        <String>['plugin1.podspec']
      ]);
      createFakePlugin('plugin2', withExtraFiles: <List<String>>[
        <String>['plugin2.podspec']
      ]);

      await runner
          .run(<String>['podspecs', '--skip=plugin1', '--skip=plugin2']);

      expect(
        processRunner.recordedCalls,
        orderedEquals(<ProcessCall>[
          ProcessCall('which', const <String>['pod'], mockPackagesDir.path),
        ]),
      );
    });

    test('allow warnings for podspecs with known warnings', () async {
      final Directory plugin1Dir =
          createFakePlugin('plugin1', withExtraFiles: <List<String>>[
        <String>['plugin1.podspec'],
      ]);

      await runner.run(<String>['podspecs', '--ignore-warnings=plugin1']);

      expect(
        processRunner.recordedCalls,
        orderedEquals(<ProcessCall>[
          ProcessCall('which', const <String>['pod'], mockPackagesDir.path),
          ProcessCall(
              'pod',
              <String>[
                'lib',
                'lint',
                p.join(plugin1Dir.path, 'plugin1.podspec'),
                '--configuration=Debug',
                '--skip-tests',
                '--allow-warnings',
                '--use-libraries'
              ],
              mockPackagesDir.path),
          ProcessCall(
              'pod',
              <String>[
                'lib',
                'lint',
                p.join(plugin1Dir.path, 'plugin1.podspec'),
                '--configuration=Debug',
                '--skip-tests',
                '--allow-warnings',
              ],
              mockPackagesDir.path),
        ]),
      );

      expect(printedMessages, contains('Linting plugin1.podspec'));
    });
  });
}

class MockPlatform extends Mock implements Platform {}
