// Copyright (c) 2016, 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 'package:test/test.dart';

import '../descriptor.dart' as d;
import '../test_pub.dart';

const _validMain = 'main() {}';

main() {
  _testExecutablesOutput(output, {bool dev: true}) => () async {
        await pubGet();
        await runPub(
            args: ['deps', '--executables']
              ..addAll(dev ? ['--dev'] : ['--no-dev']),
            output: output);
      };

  _testAllDepsOutput(output) => _testExecutablesOutput(output);
  _testNonDevDepsOutput(output) => _testExecutablesOutput(output, dev: false);

  group("lists nothing when no executables found", () {
    setUp(() async {
      await d.dir(appPath, [d.appPubspec()]).create();
    });

    test("all dependencies", _testAllDepsOutput('\n'));
    test("non-dev dependencies", _testNonDevDepsOutput('\n'));
  });

  group("skips non-Dart executables", () {
    setUp(() async {
      await d.dir(appPath, [
        d.appPubspec(),
        d.dir('bin', [d.file('foo.py'), d.file('bar.sh')])
      ]).create();
    });

    test("all dependencies", _testAllDepsOutput('\n'));
    test("non-dev dependencies", _testNonDevDepsOutput('\n'));
  });

  group("skips Dart executables which are not parsable", () {
    setUp(() async {
      await d.dir(appPath, [
        d.appPubspec(),
        d.dir('bin', [d.file('foo.dart', 'main() {')])
      ]).create();
    });

    test("all dependencies", _testAllDepsOutput('\n'));
    test("non-dev dependencies", _testNonDevDepsOutput('\n'));
  });

  group("skips Dart executables without entrypoints", () {
    setUp(() async {
      await d.dir(appPath, [
        d.appPubspec(),
        d.dir(
            'bin', [d.file('foo.dart'), d.file('bar.dart', 'main(x, y, z) {}')])
      ]).create();
    });

    test("all dependencies", _testAllDepsOutput('\n'));
    test("non-dev dependencies", _testNonDevDepsOutput('\n'));
  });

  group("lists valid Dart executables with entrypoints", () {
    setUp(() async {
      await d.dir(appPath, [
        d.appPubspec(),
        d.dir('bin',
            [d.file('foo.dart', _validMain), d.file('bar.dart', _validMain)])
      ]).create();
    });

    test("all dependencies", _testAllDepsOutput('myapp: bar, foo'));
    test("non-dev dependencies", _testNonDevDepsOutput('myapp: bar, foo'));
  });

  group("skips executables in sub directories", () {
    setUp(() async {
      await d.dir(appPath, [
        d.appPubspec(),
        d.dir('bin', [
          d.file('foo.dart', _validMain),
          d.dir('sub', [d.file('bar.dart', _validMain)])
        ])
      ]).create();
    });

    test("all dependencies", _testAllDepsOutput('myapp:foo'));
    test("non-dev dependencies", _testNonDevDepsOutput('myapp:foo'));
  });

  group("lists executables from a dependency", () {
    setUp(() async {
      await d.dir('foo', [
        d.libPubspec('foo', '1.0.0'),
        d.dir('bin', [d.file('bar.dart', _validMain)])
      ]).create();

      await d.dir(appPath, [
        d.appPubspec({
          'foo': {'path': '../foo'}
        })
      ]).create();
    });

    test("all dependencies", _testAllDepsOutput('foo:bar'));
    test("non-dev dependencies", _testNonDevDepsOutput('foo:bar'));
  });

  group("lists executables only from immediate dependencies", () {
    setUp(() async {
      await d.dir(appPath, [
        d.appPubspec({
          'foo': {'path': '../foo'}
        })
      ]).create();

      await d.dir('foo', [
        d.libPubspec('foo', '1.0.0', deps: {
          'baz': {'path': '../baz'}
        }),
        d.dir('bin', [d.file('bar.dart', _validMain)])
      ]).create();

      await d.dir('baz', [
        d.libPubspec('baz', '1.0.0'),
        d.dir('bin', [d.file('qux.dart', _validMain)])
      ]).create();
    });

    test("all dependencies", _testAllDepsOutput('foo:bar'));
    test("non-dev dependencies", _testNonDevDepsOutput('foo:bar'));
  });

  group("applies formatting before printing executables", () {
    setUp(() async {
      await d.dir(appPath, [
        d.appPubspec({
          'foo': {'path': '../foo'},
          'bar': {'path': '../bar'}
        }),
        d.dir('bin', [d.file('myapp.dart', _validMain)])
      ]).create();

      await d.dir('foo', [
        d.libPubspec('foo', '1.0.0'),
        d.dir('bin',
            [d.file('baz.dart', _validMain), d.file('foo.dart', _validMain)])
      ]).create();

      await d.dir('bar', [
        d.libPubspec('bar', '1.0.0'),
        d.dir('bin', [d.file('qux.dart', _validMain)])
      ]).create();
    });

    test("all dependencies", _testAllDepsOutput('''
        myapp
        bar:qux
        foo: foo, baz'''));
    test("non-dev dependencies", _testNonDevDepsOutput('''
        myapp
        bar:qux
        foo: foo, baz'''));
  });

  group("dev dependencies", () {
    setUp(() async {
      await d.dir('foo', [
        d.libPubspec('foo', '1.0.0'),
        d.dir('bin', [d.file('bar.dart', _validMain)])
      ]).create();

      await d.dir(appPath, [
        d.pubspec({
          'name': 'myapp',
          'dev_dependencies': {
            'foo': {'path': '../foo'}
          }
        })
      ]).create();
    });

    test("are listed if --dev flag is set", _testAllDepsOutput('foo:bar'));
    test("are skipped if --no-dev flag is set", _testNonDevDepsOutput('\n'));
  });

  group("overriden dependencies executables", () {
    setUp(() async {
      await d.dir('foo-1.0', [
        d.libPubspec('foo', '1.0.0'),
        d.dir('bin', [d.file('bar.dart', _validMain)])
      ]).create();

      await d.dir('foo-2.0', [
        d.libPubspec('foo', '2.0.0'),
        d.dir('bin',
            [d.file('bar.dart', _validMain), d.file('baz.dart', _validMain)])
      ]).create();

      await d.dir(appPath, [
        d.pubspec({
          'name': 'myapp',
          'dependencies': {
            'foo': {'path': '../foo-1.0'}
          },
          'dependency_overrides': {
            'foo': {'path': '../foo-2.0'}
          }
        })
      ]).create();
    });

    test(
        'are listed if --dev flag is set', _testAllDepsOutput('foo: bar, baz'));
    test('are listed if --no-dev flag is set',
        _testNonDevDepsOutput('foo: bar, baz'));
  });
}
