"""Test suite for prance.cli ."""

__author__ = 'Jens Finkhaeuser'
__copyright__ = 'Copyright (c) 2016-2021 Jens Finkhaeuser'
__license__ = 'MIT'
__all__ = ()

import pytest

from . import none_of

@pytest.fixture
def runner():
  from click.testing import CliRunner
  return CliRunner()


@pytest.mark.skipif(none_of('click'), reason = 'Click does not exist')
def test_validate_defaults(runner):
  from prance import cli

  # Good example
  result = runner.invoke(cli.validate, ['tests/specs/petstore.yaml'])
  assert result.exit_code == 0
  expected = """Processing "tests/specs/petstore.yaml"...
 -> Resolving external references.
Validates OK as Swagger/OpenAPI 2.0!
"""
  assert result.output == expected

  # Bad example
  result = runner.invoke(cli.validate, ['tests/specs/definitions.yaml'])
  assert result.exit_code == 1
  assert 'ValidationError' in result.output


@pytest.mark.skipif(none_of('click'), reason = 'Click does not exist')
def test_validate_multiple(runner):
  from prance import cli

  result = runner.invoke(cli.validate,
      ['tests/specs/petstore.yaml', 'tests/specs/petstore.yaml'])
  assert result.exit_code == 0
  expected = """Processing "tests/specs/petstore.yaml"...
 -> Resolving external references.
Validates OK as Swagger/OpenAPI 2.0!
Processing "tests/specs/petstore.yaml"...
 -> Resolving external references.
Validates OK as Swagger/OpenAPI 2.0!
"""
  assert result.output == expected


@pytest.mark.skipif(none_of('click'), reason = 'Click does not exist')
def test_validate_no_resolve(runner):
  from prance import cli

  # Good example
  result = runner.invoke(cli.validate, ['--no-resolve', 'tests/specs/petstore.yaml'])
  assert result.exit_code == 0
  expected = """Processing "tests/specs/petstore.yaml"...
 -> Not resolving external references.
Validates OK as Swagger/OpenAPI 2.0!
"""
  assert result.output == expected


@pytest.mark.skipif(none_of('click'), reason = 'Click does not exist')
def test_validate_output_too_many_inputs(runner):
  from prance import cli

  result = runner.invoke(cli.validate,
      ['-o', 'foo', 'tests/specs/petstore.yaml', 'tests/specs/petstore.yaml'])
  assert result.exit_code == 2
  assert 'If --output-file is given,' in result.output


@pytest.mark.skipif(none_of('click'), reason = 'Click does not exist')
def test_validate_output(runner):
  from prance import cli

  import os, os.path
  curdir = os.getcwd()

  outnames = ['foo.json', 'foo.yaml']
  for outname in outnames:
    with runner.isolated_filesystem():
      result = runner.invoke(cli.validate,
          ['-o', outname, os.path.join(curdir, 'tests/specs/petstore.yaml')])
      assert result.exit_code == 0

      # There also must be a 'foo' file now.
      files = [f for f in os.listdir('.') if os.path.isfile(f)]
      assert outname in files

      # Ensure a UTF-8 file encoding.
      from prance.util import fs
      assert 'utf-8' in fs.detect_encoding(outname, default_to_utf8 = False,
                                           read_all = True)

      # Now do a full encoding detection, too

      # The 'foo' file must be a valid swagger spec.
      result = runner.invoke(cli.validate, [outname])
      assert result.exit_code == 0


@pytest.mark.skipif(none_of('click'), reason = 'Click does not exist')
def test_compile_defaults(runner):
  from prance import cli

  # Good example
  result = runner.invoke(cli.compile, ['tests/specs/petstore.yaml'])
  assert result.exit_code == 0
  expected = """Processing "tests/specs/petstore.yaml"...
 -> Resolving external references.
Validates OK as Swagger/OpenAPI 2.0!
"""
  assert result.output.startswith(expected)

  # Bad example
  result = runner.invoke(cli.validate, ['tests/specs/definitions.yaml'])
  assert result.exit_code == 1
  assert 'ValidationError' in result.output


@pytest.mark.skipif(none_of('click'), reason = 'Click does not exist')
def test_compile_output(runner):
  from prance import cli

  import os, os.path
  curdir = os.getcwd()

  outnames = ['foo.json', 'foo.yaml']
  for outname in outnames:
    with runner.isolated_filesystem():
      result = runner.invoke(cli.compile,
          [os.path.join(curdir, 'tests/specs/petstore.yaml'), outname])
      assert result.exit_code == 0

      # There also must be a 'foo' file now.
      files = [f for f in os.listdir('.') if os.path.isfile(f)]
      assert outname in files

      # Ensure a UTF-8 file encoding.
      from prance.util import fs
      assert 'utf-8' in fs.detect_encoding(outname, default_to_utf8 = False,
                                           read_all = True)

      # Now do a full encoding detection, too

      # The 'foo' file must be a valid swagger spec.
      result = runner.invoke(cli.validate, [outname])
      assert result.exit_code == 0


@pytest.mark.skipif(none_of('click'), reason = 'Click does not exist')
@pytest.mark.requires_network()
def test_convert_defaults(runner):
  from prance import cli

  # Good example
  result = runner.invoke(cli.convert, ['tests/specs/petstore.yaml'])
  assert result.exit_code == 0
  assert 'openapi' in result.output
  assert '3.' in result.output

  # Bad example
  result = runner.invoke(cli.validate, ['tests/specs/definitions.yaml'])
  assert result.exit_code == 1
  assert 'ValidationError' in result.output


@pytest.mark.skipif(none_of('click'), reason = 'Click does not exist')
@pytest.mark.requires_network()
def test_convert_output(runner):
  from prance import cli

  import os, os.path
  curdir = os.getcwd()

  outnames = ['foo.json', 'foo.yaml']
  for outname in outnames:
    with runner.isolated_filesystem():
      result = runner.invoke(cli.convert,
          [os.path.join(curdir, 'tests/specs/petstore.yaml'), outname])
      assert result.exit_code == 0

      # There also must be a 'foo' file now.
      files = [f for f in os.listdir('.') if os.path.isfile(f)]
      assert outname in files

      # Ensure a UTF-8 file encoding.
      from prance.util import fs
      assert 'utf-8' in fs.detect_encoding(outname, default_to_utf8 = False,
                                           read_all = True)

      # Now do a full encoding detection, too
      contents = fs.read_file(outname)
      assert 'openapi' in contents
      assert '3.' in contents
