# coding=utf-8
"""
Tasks for running various tests for Rookeries

:copyright: Copyright 2013-2017, Dorian Pula
    <dorian.pula@amber-penguin-software.ca>
:license: AGPL v3+
"""

import invoke as inv


@inv.task
def style(ctx):
    """
    Test the coding style using Flake8 and eslint

    :param ctx: Context of the invoke task.
    """
    flake_command = ' '.join((
        'flake8',
        '--exclude=docs,node_modules',
        '--max-line-length=80',
        '--max-complexity=10',
    ))
    ctx.run(flake_command, echo=True, pty=True)
    ctx.run('npm run lint', echo=True, pty=True)
    ctx.run('cargo fmt --all -- --write-mode diff', echo=True, pty=True)


def _prepare_py_test_command(test_path, verbosity=0, **extra_test_params):
    verbose_flag = ''
    if verbosity > 0:
        verbose_flag = '-{}'.format('v' * verbosity)

    if verbosity >= 3:
        verbose_flag = f'{verbose_flag} -r a'

    additional_test_params = ' '.join(
        ['--{}={}'.format(key.replace('_', '-'), value)
         for (key, value) in extra_test_params.items()])

    pytest_command = ' '.join((
        'py.test',
        test_path,
        '--capture=no',
        verbose_flag,
        additional_test_params,
    ))

    return pytest_command


@inv.task
def server(
        ctx,
        server_host='localhost:5000',
        verbosity=0,
        test_tag='',
        unskip_xfail=False,
        stop_on_first_failure=False,
        randomize=False):
    """
    Test the API using unit and integration tests.

    :param ctx: Context of the invoke task.
    :param server_host: The host and port of the server to test.
    :param verbosity: The amount of logging from the test.  Default is 0 and
        is the lowest.  3 is the highest.
    :param test_tag: Optional tag (pytest mark) to run individually decorated
        tests in suite.
    :param randomize: Flag whether or not to randomize test order.
    """

    test_command = _prepare_py_test_command(
        'tests',
        verbosity=verbosity,
        server_host=server_host,
    )

    if unskip_xfail:
        test_command = f'{test_command} --runxfail'

    if stop_on_first_failure:
        test_command = f'{test_command} --maxfail 1'

    if test_tag:
        test_command = f'{test_command} -m {test_tag}'

    if randomize:
        test_command = f'{test_command} --random'
    ctx.run(test_command, echo=True, pty=True)
    ctx.run('cargo test', echo=True, pty=True)


@inv.task
def js(ctx):
    """
    Test the UI using unit and integration tests.

    :param ctx: Context of the invoke task.
    """
    ctx.run('npm run test', echo=True, pty=True)
