diff --git a/connect/cli/plugins/project/commands.py b/connect/cli/plugins/project/commands.py index 865c51a8..51050791 100644 --- a/connect/cli/plugins/project/commands.py +++ b/connect/cli/plugins/project/commands.py @@ -4,10 +4,13 @@ import click -from connect.cli.plugins.project.helpers import ( +from connect.cli.plugins.project.extension_helpers import ( + bootstrap_extension_project, +) +from connect.cli.plugins.project.report_helpers import ( add_report, - bootstrap_project, - validate_project, + bootstrap_report_project, + validate_report_project, ) @@ -16,6 +19,7 @@ def grp_project(): pass # pragma: no cover +# REPORTS @grp_project.group( name='report', short_help='Manage report projects.', @@ -36,7 +40,7 @@ def grp_project_report(): help='Directory where the new report project will be created.', ) def cmd_bootstrap_report_project(output_dir): - bootstrap_project(output_dir) + bootstrap_report_project(output_dir) @grp_project_report.command( @@ -50,7 +54,7 @@ def cmd_bootstrap_report_project(output_dir): help='Project directory.', ) def cmd_validate_project(project_dir): - validate_project(project_dir) + validate_report_project(project_dir) @grp_project_report.command( @@ -72,5 +76,29 @@ def cmd_add_report(project_dir, package_name): add_report(project_dir, package_name) +# EXTENSION AS A SERVICE +@grp_project.group( + name='extension', + short_help='Manage extension projects.', +) +def grp_project_extension(): + pass # pragma: no cover + + +@grp_project_extension.command( + name='bootstrap', + short_help='Bootstrap new extension project.', +) +@click.option( + '--output-dir', '-o', + default=os.getcwd(), + type=click.Path(exists=False, file_okay=False, dir_okay=True), + required=False, + help='Directory where the new extension project will be created.', +) +def cmd_bootstrap_extension_project(output_dir): + bootstrap_extension_project(output_dir) + + def get_group(): return grp_project diff --git a/connect/cli/plugins/project/constants.py b/connect/cli/plugins/project/constants.py index 4eb64556..e6241c4e 100644 --- a/connect/cli/plugins/project/constants.py +++ b/connect/cli/plugins/project/constants.py @@ -1,3 +1,4 @@ # Copyright © 2021 CloudBlue. All rights reserved. -PROJECT_BOILERPLATE_URL = 'https://github.com/cloudblue/connect-report-python-boilerplate.git' +PROJECT_REPORT_BOILERPLATE_URL = 'https://github.com/cloudblue/connect-report-python-boilerplate.git' +PROJECT_EXTENSION_BOILERPLATE_URL = 'https://github.com/cloudblue/connect-extension-python-boilerplate.git' diff --git a/connect/cli/plugins/project/extension_helpers.py b/connect/cli/plugins/project/extension_helpers.py new file mode 100644 index 00000000..55607de2 --- /dev/null +++ b/connect/cli/plugins/project/extension_helpers.py @@ -0,0 +1,43 @@ +import click +from click.exceptions import ClickException +from cookiecutter.exceptions import OutputDirExistsException +from cookiecutter.main import cookiecutter + +from connect.cli.plugins.project.constants import PROJECT_EXTENSION_BOILERPLATE_URL +from connect.cli.plugins.project import utils + + +def bootstrap_extension_project(data_dir: str): + click.secho('Bootstraping extension project...\n', fg='blue') + + utils._purge_cookiecutters_dir() + + index = 1 + answers = {} + function_list = [ + '_general_questions', + '_asset_process_capabilities', + '_asset_validation_capabilities', + '_tier_config_capabilities', + '_product_capabilities', + ] + for question_function in function_list: + partial = getattr(utils, question_function)(index, len(function_list)) + index += 1 + answers.update(partial) + + try: + project_dir = cookiecutter( + PROJECT_EXTENSION_BOILERPLATE_URL, + no_input=True, + extra_context=answers, + output_dir=data_dir, + ) + click.secho(f'\nExtension Project location: {project_dir}', fg='blue') + except OutputDirExistsException as error: + project_path = str(error).split('"')[1] + raise ClickException( + f'\nThe directory "{project_path}" already exists, ' + '\nif you would like to use that name, please delete ' + 'the directory or use another location.', + ) diff --git a/connect/cli/plugins/project/helpers.py b/connect/cli/plugins/project/report_helpers.py similarity index 94% rename from connect/cli/plugins/project/helpers.py rename to connect/cli/plugins/project/report_helpers.py index 7d5a13bc..00b8edd0 100644 --- a/connect/cli/plugins/project/helpers.py +++ b/connect/cli/plugins/project/report_helpers.py @@ -10,7 +10,7 @@ from collections import OrderedDict from cookiecutter.main import cookiecutter -from cookiecutter.config import DEFAULT_CONFIG, get_user_config +from cookiecutter.config import get_user_config from cookiecutter.exceptions import OutputDirExistsException from cookiecutter.generate import generate_context, generate_files from cookiecutter.prompt import prompt_for_config @@ -20,8 +20,9 @@ from click import ClickException from connect.cli.plugins.project.constants import ( - PROJECT_BOILERPLATE_URL, + PROJECT_REPORT_BOILERPLATE_URL, ) +from connect.cli.plugins.project.utils import _purge_cookiecutters_dir from connect.reports.validator import ( validate, validate_with_schema, @@ -29,13 +30,13 @@ from connect.reports.parser import parse -def bootstrap_project(data_dir: str): +def bootstrap_report_project(data_dir: str): click.secho('Bootstraping report project...\n', fg='blue') _purge_cookiecutters_dir() try: - project_dir = cookiecutter(PROJECT_BOILERPLATE_URL, output_dir=data_dir) + project_dir = cookiecutter(PROJECT_REPORT_BOILERPLATE_URL, output_dir=data_dir) click.secho(f'\nReport Project location: {project_dir}', fg='blue') except OutputDirExistsException as error: project_path = str(error).split('"')[1] @@ -46,7 +47,7 @@ def bootstrap_project(data_dir: str): ) -def validate_project(project_dir): +def validate_report_project(project_dir): click.secho(f'Validating project {project_dir}...\n', fg='blue') data = _file_descriptor_validations(project_dir) @@ -86,7 +87,7 @@ def add_report(project_dir, package_name): # Instead of using cookiecutter use the internals report_dir, report_slug = _custom_cookiecutter( - PROJECT_BOILERPLATE_URL, + PROJECT_REPORT_BOILERPLATE_URL, output_dir=add_report_tmpdir, ) @@ -228,10 +229,3 @@ def _entrypoint_validations(project_dir, entrypoint, report_spec): '\n>> def generate(client=None, input_data=None, progress_callback=None, ' 'renderer_type=None, extra_context_callback=None) <<', ) - - -def _purge_cookiecutters_dir(): - # Avoid asking rewrite clone boilerplate project - cookie_dir = DEFAULT_CONFIG['cookiecutters_dir'] - if os.path.isdir(cookie_dir): - rmtree(cookie_dir) diff --git a/connect/cli/plugins/project/utils.py b/connect/cli/plugins/project/utils.py new file mode 100644 index 00000000..ecb215fe --- /dev/null +++ b/connect/cli/plugins/project/utils.py @@ -0,0 +1,174 @@ +import os + +from click.exceptions import ClickException +from cookiecutter.config import DEFAULT_CONFIG +from cookiecutter.utils import rmtree +from interrogatio import dialogus +from interrogatio.validators.builtins import RequiredValidator + + +def _purge_cookiecutters_dir(): + # Avoid asking rewrite clone boilerplate project + cookie_dir = DEFAULT_CONFIG['cookiecutters_dir'] + if os.path.isdir(cookie_dir): + rmtree(cookie_dir) + + +def _general_questions(idx, total): + questions = [ + { + 'name': 'project_name', + 'type': 'input', + 'message': 'Extension project name: ', + 'default': 'My Awesome Project', + 'validators': (RequiredValidator(message='Please, provide a project name.'),), + }, + { + 'name': 'description', + 'type': 'input', + 'message': 'Extension project description: ', + 'default': 'Project description', + 'validators': (RequiredValidator(message='Please, provide a description.'),), + }, + { + 'name': 'package_name', + 'type': 'input', + 'message': 'Extension project package name: ', + 'default': 'connect_ext', + 'validators': (RequiredValidator(message='Please, provide a package name.'),), + }, + { + 'name': 'author', + 'type': 'input', + 'message': 'Extension project author: ', + 'default': 'Globex Corporation', + 'validators': (RequiredValidator(message='Please, provide an author name.'),), + }, + { + 'name': 'version', + 'type': 'input', + 'message': 'Extension project version: ', + 'default': '0.1.0', + 'validators': (RequiredValidator(message='Please, provide a version.'),), + }, + { + 'name': 'license', + 'type': 'selectone', + 'description': 'Extension project license: ', + 'values': [ + ('Apache Software License 2.0', 'Apache Software License 2.0'), + ('MIT', 'MIT'), + ('BSD', 'BSD'), + ], + }, + { + 'name': 'use_github_actions', + 'type': 'selectone', + 'description': 'Do you want to use Github actions? ', + 'values': [ + ('n', 'No'), + ('y', 'Yes'), + ], + }, + { + 'name': 'use_asyncio', + 'type': 'selectone', + 'description': 'Do you want to use asynchronous libraries? ', + 'values': [ + ('n', 'No'), + ('y', 'Yes'), + ], + }, + ] + answers = _show_dialog(questions, idx, total) + return answers + + +def _asset_process_capabilities(idx, total): + questions = [ + { + 'name': 'asset_processing', + 'type': 'selectmany', + 'description': 'Asset processing capabilities', + 'values': [ + ('subscription_process_capabilities_1of6', 'Purchase Request'), + ('subscription_process_capabilities_2of6', 'Change Request'), + ('subscription_process_capabilities_3of6', 'Suspend Request'), + ('subscription_process_capabilities_4of6', 'Resume Request'), + ('subscription_process_capabilities_5of6', 'Cancel Request'), + ('subscription_process_capabilities_6of6', 'Adjustment Request'), + ], + }, + ] + answers = _show_dialog(questions, idx, total) + return _gen_cookie_capabilities(answers['asset_processing']) + + +def _asset_validation_capabilities(idx, total): + questions = [ + { + 'name': 'asset_validation', + 'type': 'selectmany', + 'description': 'Asset validation capabilities', + 'values': [ + ('subscription_validation_capabilities_1of2', 'Purchase Request'), + ('subscription_validation_capabilities_2of2', 'Change Request'), + ], + }, + ] + answers = _show_dialog(questions, idx, total) + return _gen_cookie_capabilities(answers['asset_validation']) + + +def _tier_config_capabilities(idx, total): + questions = [ + { + 'name': 'tierconfig', + 'type': 'selectmany', + 'description': 'Tier configuration capabilities', + 'values': [ + ('tier_config_process_capabilities_1of2', 'Setup Request Processing'), + ('tier_config_process_capabilities_2of2', 'Change Request Processing'), + ('tier_config_validation_capabilities_1of2', 'Setup Request Validation'), + ('tier_config_validation_capabilities_1of2', 'Change Request Validation'), + ], + }, + ] + answers = _show_dialog(questions, idx, total) + return _gen_cookie_capabilities(answers['tierconfig']) + + +def _product_capabilities(idx, total): + questions = [ + { + 'name': 'product', + 'type': 'selectmany', + 'description': 'Product capabilities', + 'values': [ + ('product_capabilities_1of2', 'Product Action Execution'), + ('product_capabilities_2of2', 'Product Custom Event'), + ], + }, + ] + answers = _show_dialog(questions, idx, total) + return _gen_cookie_capabilities(answers['product']) + + +def _show_dialog(questions, idx, total): + answers = dialogus( + questions, + title=f'Extension Project Configuration ({idx}/{total})', + confirm='Next', + ) + if not answers: + raise ClickException('Aborted by user input') + return answers + + +def _gen_cookie_capabilities(answers): + cookicutter_answers = {} + if answers: + for capability in answers: + cookicutter_answers[capability] = 'y' + + return cookicutter_answers diff --git a/tests/conftest.py b/tests/conftest.py index c1f4134e..0b57aa64 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,11 +3,8 @@ from shutil import copy2 import pytest - import responses - from fs.tempfs import TempFS - from openpyxl import load_workbook from connect.cli.core.base import cli diff --git a/tests/data.py b/tests/data.py index 501ce107..ceed8c36 100644 --- a/tests/data.py +++ b/tests/data.py @@ -12,6 +12,6 @@ 'name': 'Account 1', 'api_key': 'ApiKey ZZZZ:SSSS', 'endpoint': 'https://localhost/public/v1', - } + }, ], -} \ No newline at end of file +} diff --git a/tests/plugins/project/test_commands.py b/tests/plugins/project/test_commands.py index 6faa3738..c190d854 100644 --- a/tests/plugins/project/test_commands.py +++ b/tests/plugins/project/test_commands.py @@ -5,9 +5,9 @@ import os -def test_bootstrap_command(fs, ccli, mocker, capsys): +def test_bootstrap_report_command(fs, ccli, mocker, capsys): mocked_bootstrap = mocker.patch( - 'connect.cli.plugins.project.commands.bootstrap_project', + 'connect.cli.plugins.project.commands.bootstrap_report_project', side_effect=print('project_dir'), ) os.mkdir(f'{fs.root_path}/projects') @@ -29,9 +29,9 @@ def test_bootstrap_command(fs, ccli, mocker, capsys): assert result.exit_code == 0 -def test_validate_command(fs, ccli, mocker, capsys): +def test_validate_report_command(fs, ccli, mocker, capsys): mocked_validate_project = mocker.patch( - 'connect.cli.plugins.project.commands.validate_project', + 'connect.cli.plugins.project.commands.validate_report_project', side_effect=print('Report Project connect/.data/logan has been successfully validated.'), ) os.mkdir(f'{fs.root_path}/project') @@ -77,3 +77,27 @@ def test_add_report_command(fs, ccli, mocker, capsys): mocked_add_report.assert_called_once_with(f'{fs.root_path}/project', 'reports') captured = capsys.readouterr() assert 'successfully added' == captured.out.strip() + + +def test_bootstrap_extension_command(fs, ccli, mocker, capsys): + mocked_bootstrap = mocker.patch( + 'connect.cli.plugins.project.commands.bootstrap_extension_project', + side_effect=print('project_dir'), + ) + os.mkdir(f'{fs.root_path}/projects') + runner = CliRunner() + result = runner.invoke( + ccli, + [ + 'project', + 'extension', + 'bootstrap', + '--output-dir', + f'{fs.root_path}/projects', + ], + ) + + mocked_bootstrap.assert_called_once_with(f'{fs.root_path}/projects') + captured = capsys.readouterr() + assert 'project_dir' in captured.out + assert result.exit_code == 0 diff --git a/tests/plugins/project/test_extension_helpers.py b/tests/plugins/project/test_extension_helpers.py new file mode 100644 index 00000000..ee711a08 --- /dev/null +++ b/tests/plugins/project/test_extension_helpers.py @@ -0,0 +1,97 @@ +# Copyright © 2021 CloudBlue. All rights reserved. + +import os + +import pytest +from click import ClickException +from cookiecutter.config import DEFAULT_CONFIG +from cookiecutter.exceptions import OutputDirExistsException + +from connect.cli.plugins.project.extension_helpers import bootstrap_extension_project +from connect.cli.plugins.project import utils + + +def _cookiecutter_result(local_path): + os.makedirs(f'{local_path}/project_dir/connect_ext') + open(f'{local_path}/project_dir/connect_ext/README.md', 'w').write('# Extension') + + +@pytest.mark.parametrize( + 'exists_cookiecutter_dir', + (True, False), +) +def test_bootstrap_extension_project(fs, mocker, capsys, exists_cookiecutter_dir): + mocked_cookiecutter = mocker.patch( + 'connect.cli.plugins.project.extension_helpers.cookiecutter', + return_value='project_dir', + ) + mocked_dialogus = mocker.patch( + 'connect.cli.plugins.project.utils.dialogus', + return_value={ + 'project_name': 'foo', + 'asset_processing': [], + 'asset_validation': [], + 'tierconfig': [], + 'product': [], + }, + ) + cookie_dir = f'{fs.root_path}/.cookiecutters' + if exists_cookiecutter_dir: + os.mkdir(cookie_dir) + DEFAULT_CONFIG['cookiecutters_dir'] = cookie_dir + + output_dir = f'{fs.root_path}/projects' + os.mkdir(output_dir) + bootstrap_extension_project(output_dir) + + captured = capsys.readouterr() + assert 'project_dir' in captured.out + assert mocked_cookiecutter.call_count == 1 + assert mocked_dialogus.call_count == 5 + + +def test_bootstrap_direxists_error(fs, mocker): + mocked_cookiecutter = mocker.patch( + 'connect.cli.plugins.project.extension_helpers.cookiecutter', + side_effect=OutputDirExistsException('dir "project_dir" exists'), + ) + mocked_dialogus = mocker.patch( + 'connect.cli.plugins.project.utils.dialogus', + return_value={ + 'project_name': 'foo', + 'asset_processing': [], + 'asset_validation': [], + 'tierconfig': [], + 'product': [], + }, + ) + cookie_dir = f'{fs.root_path}/.cookiecutters' + os.mkdir(cookie_dir) + DEFAULT_CONFIG['cookiecutters_dir'] = cookie_dir + + output_dir = f'{fs.root_path}/projects' + os.mkdir(output_dir) + + with pytest.raises(ClickException): + bootstrap_extension_project(output_dir) + assert mocked_cookiecutter.call_count == 1 + assert mocked_dialogus.call_count == 5 + + +def test_bootstrap_show_empty_dialog(mocker): + mocked_dialogus = mocker.patch( + 'connect.cli.plugins.project.utils.dialogus', + return_value={}, + ) + with pytest.raises(ClickException): + utils._show_dialog({}, 1, 5) + + assert mocked_dialogus.call_count == 1 + + +def test_bootstrap_generate_capabilities(): + answers = {'asset': ['one', 'two']} + cookiecutter_answers = utils._gen_cookie_capabilities(answers['asset']) + + assert cookiecutter_answers['one'] == 'y' + assert cookiecutter_answers['two'] == 'y' diff --git a/tests/plugins/project/test_helpers.py b/tests/plugins/project/test_report_helpers.py similarity index 81% rename from tests/plugins/project/test_helpers.py rename to tests/plugins/project/test_report_helpers.py index 9395e7bb..e411e520 100644 --- a/tests/plugins/project/test_helpers.py +++ b/tests/plugins/project/test_report_helpers.py @@ -9,13 +9,13 @@ from cookiecutter.config import DEFAULT_CONFIG from cookiecutter.exceptions import OutputDirExistsException -from connect.cli.plugins.project.helpers import ( +from connect.cli.plugins.project.report_helpers import ( _add_report_to_descriptor, _custom_cookiecutter, _entrypoint_validations, add_report, - bootstrap_project, - validate_project, + bootstrap_report_project, + validate_report_project, ) @@ -28,9 +28,9 @@ def _cookiecutter_result(local_path): 'exists_cookiecutter_dir', (True, False), ) -def test_bootstrap_project(fs, mocker, capsys, exists_cookiecutter_dir): +def test_bootstrap_report_project(fs, mocker, capsys, exists_cookiecutter_dir): mocker.patch( - 'connect.cli.plugins.project.helpers.cookiecutter', + 'connect.cli.plugins.project.report_helpers.cookiecutter', return_value='project_dir', ) cookie_dir = f'{fs.root_path}/.cookiecutters' @@ -40,7 +40,7 @@ def test_bootstrap_project(fs, mocker, capsys, exists_cookiecutter_dir): output_dir = f'{fs.root_path}/projects' os.mkdir(output_dir) - bootstrap_project(output_dir) + bootstrap_report_project(output_dir) captured = capsys.readouterr() assert 'project_dir' in captured.out @@ -48,7 +48,7 @@ def test_bootstrap_project(fs, mocker, capsys, exists_cookiecutter_dir): def test_bootstrap_direxists_error(fs, mocker): mocked_cookiecutter = mocker.patch( - 'connect.cli.plugins.project.helpers.cookiecutter', + 'connect.cli.plugins.project.report_helpers.cookiecutter', side_effect=OutputDirExistsException('dir "project_dir" exists'), ) cookie_dir = f'{fs.root_path}/.cookiecutters' @@ -59,39 +59,39 @@ def test_bootstrap_direxists_error(fs, mocker): os.mkdir(output_dir) with pytest.raises(ClickException): - bootstrap_project(output_dir) + bootstrap_report_project(output_dir) assert mocked_cookiecutter.call_count == 1 -def test_validate_project(capsys): +def test_validate_report_project(capsys): project_dir = './tests/fixtures/reports/basic_report' - validate_project(project_dir) + validate_report_project(project_dir) captured = capsys.readouterr() assert 'successfully' in captured.out -def test_validate_no_descriptor_file(fs): +def test_validate_report_no_descriptor_file(fs): with pytest.raises(ClickException) as error: - validate_project(fs.root_path) + validate_report_project(fs.root_path) assert 'the mandatory `reports.json` file descriptor is not present' in str(error.value) -def test_validate_wrong_descriptor_file(fs, mocked_reports): +def test_validate_report_wrong_descriptor_file(fs, mocked_reports): wrong_data = f'{mocked_reports} - extrachar' with open(f'{fs.root_path}/reports.json', 'w') as fp: fp.write(wrong_data) with pytest.raises(ClickException) as error: - validate_project(f'{fs.root_path}') + validate_report_project(f'{fs.root_path}') assert str(error.value) == 'The report project descriptor `reports.json` is not a valid json file.' -def test_validate_schema(fs, mocked_reports): +def test_validate_report_schema(fs, mocked_reports): wrong_data = mocked_reports # no valid value for 'reports' field wrong_data['reports'] = 'string' @@ -100,19 +100,19 @@ def test_validate_schema(fs, mocked_reports): json.dump(wrong_data, fp) with pytest.raises(ClickException) as error: - validate_project(f'{fs.root_path}') + validate_report_project(f'{fs.root_path}') assert 'Invalid `reports.json`: \'string\' is not of type' in str(error.value) -def test_validate_missing_files(fs, mocked_reports): +def test_validate_report_missing_files(fs, mocked_reports): with open(f'{fs.root_path}/reports.json', 'w') as fp: json.dump(mocked_reports, fp) # validate function will fail due to missing project files # like `readme.md` for instance, let's try it... with pytest.raises(ClickException) as error: - validate_project(f'{fs.root_path}') + validate_report_project(f'{fs.root_path}') assert 'repository property `readme_file` cannot be resolved to a file' in str(error.value) @@ -146,11 +146,11 @@ def test_add_report_no_package_dir(fs): def test_add_report_wrong_descriptor_project_file(fs, mocker, mocked_reports): desc_validations_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers._file_descriptor_validations', + 'connect.cli.plugins.project.report_helpers._file_descriptor_validations', return_value=mocked_reports, ) schema_validation_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers.validate_with_schema', + 'connect.cli.plugins.project.report_helpers.validate_with_schema', return_value=['error'], ) @@ -166,15 +166,15 @@ def test_add_report_wrong_descriptor_project_file(fs, mocker, mocked_reports): def test_add_report_existing_repo_dir(fs, mocker, mocked_reports): desc_validations_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers._file_descriptor_validations', + 'connect.cli.plugins.project.report_helpers._file_descriptor_validations', return_value=mocked_reports, ) schema_validation_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers.validate_with_schema', + 'connect.cli.plugins.project.report_helpers.validate_with_schema', return_value=[], ) cookie_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers._custom_cookiecutter', + 'connect.cli.plugins.project.report_helpers._custom_cookiecutter', side_effect=_cookiecutter_result(fs.root_path), return_value=(f'{fs.root_path}/project_dir', 'report_dir'), ) @@ -191,15 +191,15 @@ def test_add_report_existing_repo_dir(fs, mocker, mocked_reports): def test_add_report(fs, mocker, mocked_reports): desc_validations_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers._file_descriptor_validations', + 'connect.cli.plugins.project.report_helpers._file_descriptor_validations', return_value=mocked_reports, ) schema_validation_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers.validate_with_schema', + 'connect.cli.plugins.project.report_helpers.validate_with_schema', return_value=[], ) cookie_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers._custom_cookiecutter', + 'connect.cli.plugins.project.report_helpers._custom_cookiecutter', side_effect=_cookiecutter_result(fs.root_path), return_value=(f'{fs.root_path}/project_dir', 'report_dir'), ) @@ -208,7 +208,7 @@ def test_add_report(fs, mocker, mocked_reports): assert os.path.isfile(f'{cookie_mocked.return_value[0]}/reports/report_dir/README.md') cookie_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers._add_report_to_descriptor', + 'connect.cli.plugins.project.report_helpers._add_report_to_descriptor', ) cookie_dir = f'{fs.root_path}/.cookiecutters' @@ -263,26 +263,26 @@ def test_custom_cookiecutter(fs, mocker): } config_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers.get_user_config', + 'connect.cli.plugins.project.report_helpers.get_user_config', ) mocker.patch( - 'connect.cli.plugins.project.helpers.rmtree', + 'connect.cli.plugins.project.report_helpers.rmtree', ) repo_dir_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers.determine_repo_dir', + 'connect.cli.plugins.project.report_helpers.determine_repo_dir', ) generate_context_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers.generate_context', + 'connect.cli.plugins.project.report_helpers.generate_context', return_value={ 'cookiecutter': cookiecutter_json_content, }, ) prompt_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers.prompt_for_config', + 'connect.cli.plugins.project.report_helpers.prompt_for_config', return_value=report_context, ) generate_files_mocked = mocker.patch( - 'connect.cli.plugins.project.helpers.generate_files', + 'connect.cli.plugins.project.report_helpers.generate_files', return_value=f'{fs.root_path}/project_name', ) diff --git a/tests/plugins/report/test_helpers.py b/tests/plugins/report/test_helpers.py index c15eedce..84f594a2 100644 --- a/tests/plugins/report/test_helpers.py +++ b/tests/plugins/report/test_helpers.py @@ -1,7 +1,6 @@ import json import pytest - from click import ClickException from connect.cli.core.config import Config diff --git a/tests/plugins/report/test_wizard.py b/tests/plugins/report/test_wizard.py index 9643301b..68a0a279 100644 --- a/tests/plugins/report/test_wizard.py +++ b/tests/plugins/report/test_wizard.py @@ -1,17 +1,16 @@ import pytest - from interrogatio.core.exceptions import ValidationError from interrogatio.validators import DateTimeRangeValidator, DateTimeValidator, RequiredValidator from connect.cli.core.config import Config from connect.cli.plugins.report.wizard import ( - ObjectValidator, checkbox, date, date_range, hub_list, marketplace_list, object_param, + ObjectValidator, product_list, required_validator, single_line,