Files
sceptre/tests/test_cli.py
Sean Rankine b0d2ba4504 Fix unittests
2017-09-27 13:23:06 -04:00

700 lines
28 KiB
Python

import logging
import yaml
import datetime
import os
import errno
from click.testing import CliRunner
from mock import Mock, patch, sentinel
import pytest
import sceptre.cli
from sceptre.cli import cli
from sceptre.exceptions import SceptreException
from sceptre.stack_status import StackStatus
from sceptre.stack_status import StackChangeSetStatus
class TestCli(object):
def setup_method(self, test_method):
self.runner = CliRunner()
@patch("sys.exit")
def test_catch_excecptions(self, mock_exit):
@sceptre.cli.catch_exceptions
def raises_exception():
raise SceptreException
raises_exception()
mock_exit.assert_called_once_with(1)
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_validate_template(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["validate-template", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].validate_template\
.assert_called_with()
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_generate_template(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
result = self.runner.invoke(cli, ["generate-template", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
assert result.output == "{0}\n".format(
mock_get_env.return_value.stacks["vpc"].template.body
)
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_lock_stack(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["lock-stack", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].lock\
.assert_called_with()
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_unlock_stack(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["unlock-stack", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].unlock\
.assert_called_with()
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_describe_env_resources(self, mock_get_env, mock_getcwd):
mock_get_env.return_value.describe_resources.return_value = {
"stack-name-1": {
"StackResources": [
{
"LogicalResourceId": "logical-resource-id",
"PhysicalResourceId": "physical-resource-id"
}
]
},
"stack-name-2": {
"StackResources": [
{
"LogicalResourceId": "logical-resource-id",
"PhysicalResourceId": "physical-resource-id"
}
]
}
}
mock_getcwd.return_value = sentinel.cwd
result = self.runner.invoke(cli, ["describe-env-resources", "dev"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.describe_resources\
.assert_called_with()
# Assert that there is output
assert result.output
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_describe_stack_resources(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
mock_get_env.return_value.stacks["vpc"].describe_resources\
.return_value = {
"StackResources": [
{
"LogicalResourceId": "logical-resource-id",
"PhysicalResourceId": "physical-resource-id"
}
]
}
result = self.runner.invoke(
cli, ["describe-stack-resources", "dev", "vpc"]
)
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].describe_resources\
.assert_called_with()
# Assert that there is output.
assert result.output
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_create_stack(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["create-stack", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].create\
.assert_called_with()
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_delete_stack(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["delete-stack", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].delete\
.assert_called_with()
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_update_stack(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["update-stack", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].update\
.assert_called_with()
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_launch_stack(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["launch-stack", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].launch\
.assert_called_with()
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_launch_env(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["launch-env", "dev"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.launch.assert_called_with()
@patch("sceptre.cli.get_env")
def test_launch_env_returns_zero_correctly(self, mock_get_env):
mock_get_env.return_value.launch.return_value = dict(
(sentinel.stack_name, StackStatus.COMPLETE) for _ in range(5)
)
result = self.runner.invoke(cli, ["launch-env", "environment"])
assert result.exit_code == 0
@patch("sceptre.cli.get_env")
def test_launch_env_returns_non_zero_correctly(self, mock_get_env):
mock_get_env.return_value.launch.return_value = dict(
(sentinel.stack_name, StackStatus.FAILED) for _ in range(5)
)
result = self.runner.invoke(cli, ["launch-env", "environment"])
assert result.exit_code == 1
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_delete_env(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
mock_get_env.return_value.delete.return_value = \
sentinel.response
self.runner.invoke(cli, ["delete-env", "dev"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.delete.assert_called_with()
@patch("sceptre.cli.get_env")
def test_delete_env_returns_zero_correctly(self, mock_get_env):
mock_get_env.return_value.delete.return_value = dict(
(sentinel.stack_name, StackStatus.COMPLETE) for _ in range(5)
)
result = self.runner.invoke(cli, ["delete-env", "environment"])
assert result.exit_code == 0
@patch("sceptre.cli.get_env")
def test_delete_env_returns_non_zero_correctly(self, mock_get_env):
mock_get_env.return_value.delete.return_value = dict(
(sentinel.stack_name, StackStatus.FAILED) for _ in range(5)
)
result = self.runner.invoke(cli, ["delete-env", "environment"])
assert result.exit_code == 1
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_continue_update_rollback(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["continue-update-rollback", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].\
continue_update_rollback.assert_called_with()
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_create_change_set(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(
cli, ["create-change-set", "dev", "vpc", "cs1"]
)
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].create_change_set\
.assert_called_with("cs1")
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_delete_change_set(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(
cli, ["delete-change-set", "dev", "vpc", "cs1"]
)
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].delete_change_set\
.assert_called_with("cs1")
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_describe_change_set(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
mock_get_env.return_value.stacks["vpc"].describe_change_set\
.return_value = {
"ChangeSetName": "change-set-1",
"Changes": [
{
"ResourceChange": {
"ResourceType": "AWS::EC2::InternetGateway",
"Replacement": "True",
"PhysicalResourceId": "igw-04a59561",
"Details": [],
"Action": "Remove",
"Scope": [],
"LogicalResourceId": "InternetGateway"
}
}
],
"CreationTime": "2017-01-20 14:10:25.239000+00:00",
"ExecutionStatus": "AVAILABLE",
"StackName": "example-dev-vpc",
"Status": "CREATE_COMPLETE"
}
result = self.runner.invoke(
cli, ["describe-change-set", "dev", "vpc", "cs1"]
)
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].describe_change_set\
.assert_called_with("cs1")
assert yaml.safe_load(result.output) == {
"ChangeSetName": "change-set-1",
"Changes": [
{
"ResourceChange": {
"ResourceType": "AWS::EC2::InternetGateway",
"Replacement": "True",
"PhysicalResourceId": "igw-04a59561",
"Action": "Remove",
"LogicalResourceId": "InternetGateway",
"Scope": []
}
}
],
"CreationTime": "2017-01-20 14:10:25.239000+00:00",
"ExecutionStatus": "AVAILABLE",
"StackName": "example-dev-vpc",
"Status": "CREATE_COMPLETE"
}
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_describe_change_set_with_verbose_flag(
self, mock_get_env, mock_getcwd
):
mock_getcwd.return_value = sentinel.cwd
mock_get_env.return_value.stacks["vpc"].describe_change_set\
.return_value = {
"Changes": [
{
"ResourceChange": {
"ResourceType": "AWS::EC2::InternetGateway",
"PhysicalResourceId": "igw-04a59561",
"Details": [],
"Action": "Remove",
"Scope": [],
"LogicalResourceId": "InternetGateway"
}
}
]
}
result = self.runner.invoke(
cli, ["describe-change-set", "--verbose", "dev", "vpc", "cs1"]
)
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].describe_change_set\
.assert_called_with("cs1")
assert yaml.safe_load(result.output) == {
"Changes": [
{
"ResourceChange": {
"ResourceType": "AWS::EC2::InternetGateway",
"PhysicalResourceId": "igw-04a59561",
"Details": [],
"Action": "Remove",
"Scope": [],
"LogicalResourceId": "InternetGateway"
}
}
]
}
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_execute_change_set(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["execute-change-set", "dev", "vpc", "cs1"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].execute_change_set\
.assert_called_with("cs1")
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_list_change_sets(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["list-change-sets", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].list_change_sets\
.assert_called_with()
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.uuid1")
@patch("sceptre.cli.get_env")
def test_update_with_change_set_with_input_yes(
self, mock_get_env, mock_uuid1, mock_getcwd
):
mock_getcwd.return_value = sentinel.cwd
mock_get_env.return_value.stacks["vpc"].wait_for_cs_completion\
.return_value = StackChangeSetStatus.READY
mock_get_env.return_value.stacks["vpc"].describe_change_set\
.return_value = "description"
mock_uuid1().hex = "1"
self.runner.invoke(
cli, ["update-stack-cs", "dev", "vpc", "--verbose"], input="y"
)
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].create_change_set\
.assert_called_with("change-set-1")
mock_get_env.return_value.stacks["vpc"].wait_for_cs_completion\
.assert_called_with("change-set-1")
mock_get_env.return_value.stacks["vpc"].execute_change_set\
.assert_called_with("change-set-1")
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli._simplify_change_set_description")
@patch("sceptre.cli.uuid1")
@patch("sceptre.cli.get_env")
def test_update_with_change_set_without_verbose_flag(
self, mock_get_environment, mock_uuid1,
mock_simplify_change_set_description, mock_getcwd
):
mock_getcwd.return_value = sentinel.cwd
mock_get_environment.return_value.stacks["vpc"].wait_for_cs_completion\
.return_value = StackChangeSetStatus.READY
mock_get_environment.return_value.stacks["vpc"].describe_change_set\
.return_value = "description"
mock_simplify_change_set_description.return_value = \
"simplified_description"
mock_uuid1().hex = "1"
response = self.runner.invoke(
cli, ["update-stack-cs", "dev", "vpc"], input="y"
)
assert "simplified_description" in response.output
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.uuid1")
@patch("sceptre.cli.get_env")
def test_update_with_change_set_with_input_no(
self, mock_get_env, mock_uuid1, mock_getcwd
):
mock_getcwd.return_value = sentinel.cwd
mock_get_env.return_value.stacks["vpc"].wait_for_cs_completion\
.return_value = StackChangeSetStatus.READY
mock_get_env.return_value.stacks["vpc"].describe_change_set\
.return_value = "description"
mock_uuid1().hex = "1"
self.runner.invoke(
cli, ["update-stack-cs", "dev", "vpc", "--verbose"], input="n"
)
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].create_change_set\
.assert_called_with("change-set-1")
mock_get_env.return_value.stacks["vpc"].wait_for_cs_completion\
.assert_called_with("change-set-1")
mock_get_env.return_value.stacks["vpc"].delete_change_set\
.assert_called_with("change-set-1")
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.uuid1")
@patch("sceptre.cli.get_env")
def test_update_with_change_set_with_status_defunct(
self, mock_get_env, mock_uuid1, mock_getcwd
):
mock_getcwd.return_value = sentinel.cwd
mock_get_env.return_value.stacks["vpc"].wait_for_cs_completion\
.return_value = StackChangeSetStatus.DEFUNCT
mock_get_env.return_value.stacks["vpc"].describe_change_set\
.return_value = "description"
mock_uuid1().hex = "1"
result = self.runner.invoke(
cli, ["update-stack-cs", "dev", "vpc", "--verbose"]
)
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].create_change_set\
.assert_called_with("change-set-1")
mock_get_env.return_value.stacks["vpc"].wait_for_cs_completion\
.assert_called_with("change-set-1")
assert result.exit_code == 1
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_describe_stack_outputs(self, mock_get_env, mock_getcwd):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, ["describe-stack-outputs", "dev", "vpc"])
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value.stacks["vpc"].describe_outputs\
.assert_called_with()
@patch("sceptre.cli.get_env")
def test_describe_stack_outputs_handles_envvar_flag(
self, mock_get_env
):
mock_get_env.return_value.stacks["vpc"].describe_outputs\
.return_value = [
{
"OutputKey": "key",
"OutputValue": "value"
}
]
result = self.runner.invoke(
cli, ["describe-stack-outputs", "--export=envvar", "dev", "vpc"]
)
assert result.output == "export SCEPTRE_key=value\n"
@patch("sceptre.cli.get_env")
def test_describe_env(self, mock_get_env):
mock_Environment = Mock()
mock_Environment.describe.return_value = {"stack": "status"}
mock_get_env.return_value = mock_Environment
result = self.runner.invoke(cli, ["describe-env", "dev"])
assert result.output == "stack: status\n\n"
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.get_env")
def test_set_stack_policy_with_file_flag(
self, mock_get_env, mock_getcwd
):
mock_getcwd.return_value = sentinel.cwd
self.runner.invoke(cli, [
"set-stack-policy", "dev", "vpc",
"--policy-file=tests/fixtures/stack_policies/lock.json"
])
mock_Environment = Mock()
mock_get_env.assert_called_with(sentinel.cwd, "dev", {})
mock_get_env.return_value = mock_Environment
@patch("sceptre.cli.get_env")
def test_get_stack_policy_with_existing_policy(self, mock_get_env):
mock_get_env.return_value.stacks["vpc"].get_policy\
.return_value = {
"StackPolicyBody": "policy"
}
result = self.runner.invoke(cli, ["get-stack-policy", "dev", "vpc"])
assert result.output == "policy\n"
@patch("sceptre.cli.get_env")
def test_get_stack_policy_without_existing_policy(
self, mock_get_env
):
mock_get_env.return_value.stacks["vpc"].get_policy\
.return_value = {}
result = self.runner.invoke(cli, ["get-stack-policy", "dev", "vpc"])
assert result.output == "{}\n"
@patch("sceptre.cli.os.getcwd")
@patch("sceptre.cli.Environment")
def test_get_env(self, mock_Environment, mock_getcwd):
mock_Environment.return_value = sentinel.environment
mock_getcwd.return_value = sentinel.cwd
response = sceptre.cli.get_env(
sentinel.cwd, sentinel.environment_path, sentinel.options
)
mock_Environment.assert_called_once_with(
sceptre_dir=sentinel.cwd,
environment_path=sentinel.environment_path,
options=sentinel.options
)
assert response == sentinel.environment
def test_init_project_non_existant(self):
with self.runner.isolated_filesystem():
sceptre_dir = os.path.abspath('./example')
config_dir = os.path.join(sceptre_dir, "config")
template_dir = os.path.join(sceptre_dir, "templates")
region = "test-region"
os.environ["AWS_DEFAULT_REGION"] = region
defaults = {
"project_code": "example",
"region": region
}
result = self.runner.invoke(cli, ["init", "project", "example"])
assert not result.exception
assert os.path.isdir(config_dir)
assert os.path.isdir(template_dir)
with open(os.path.join(config_dir, "config.yaml")) as config_file:
config = yaml.load(config_file)
assert config == defaults
def test_init_project_already_exist(self):
with self.runner.isolated_filesystem():
sceptre_dir = os.path.abspath('./example')
config_dir = os.path.join(sceptre_dir, "config")
template_dir = os.path.join(sceptre_dir, "templates")
existing_config = {"Test": "Test"}
os.mkdir(sceptre_dir)
os.mkdir(config_dir)
os.mkdir(template_dir)
config_filepath = os.path.join(config_dir, "config.yaml")
with open(config_filepath, 'w') as config_file:
yaml.dump(existing_config, config_file)
result = self.runner.invoke(cli, ["init", "project", "example"])
assert result.exit_code == 1
assert result.output == 'Folder \"example\" already exists.\n'
assert os.path.isdir(config_dir)
assert os.path.isdir(template_dir)
with open(os.path.join(config_dir, "config.yaml")) as config_file:
config = yaml.load(config_file)
assert existing_config == config
@pytest.mark.parametrize("environment,config_structure,stdin,result", [
(
"A",
{"": {}},
'y\nA\nA\n', {"project_code": "A", "region": "A"}
),
(
"A",
{"": {"project_code": "top", "region": "top"}},
'y\n\n\n', {}
),
(
"A",
{"": {"project_code": "top", "region": "top"}},
'y\nA\nA\n', {"project_code": "A", "region": "A"}
),
(
"A/A",
{
"": {"project_code": "top", "region": "top"},
"A": {"project_code": "A", "region": "A"},
},
'y\nA/A\nA/A\n', {"project_code": "A/A", "region": "A/A"}
),
(
"A/A",
{
"": {"project_code": "top", "region": "top"},
"A": {"project_code": "A", "region": "A"},
},
'y\nA\nA\n', {}
)
])
def test_init_environment(
self, environment, config_structure, stdin, result
):
with self.runner.isolated_filesystem():
sceptre_dir = os.path.abspath('./example')
config_dir = os.path.join(sceptre_dir, "config")
os.makedirs(config_dir)
env_dir = os.path.join(sceptre_dir, "config", environment)
for env_path, config in config_structure.items():
path = os.path.join(config_dir, env_path)
try:
os.makedirs(path)
except OSError as e:
if e.errno == errno.EEXIST and os.path.isdir(path):
pass
else:
raise
filepath = os.path.join(path, "config.yaml")
with open(filepath, 'w') as config_file:
yaml.safe_dump(
config, stream=config_file, default_flow_style=False
)
os.chdir(sceptre_dir)
cmd_result = self.runner.invoke(
cli, ["init", "env", environment],
input=stdin
)
if result:
with open(os.path.join(env_dir, "config.yaml")) as config_file:
config = yaml.load(config_file)
assert config == result
else:
assert cmd_result.output.endswith(
"No config.yaml file needed - covered by parent config.\n"
)
def test_setup_logging_with_debug(self):
logger = sceptre.cli.setup_logging(True, False)
assert logger.getEffectiveLevel() == logging.DEBUG
assert logging.getLogger("botocore").getEffectiveLevel() == \
logging.INFO
# Silence logging for the rest of the tests
logger.setLevel(logging.CRITICAL)
def test_setup_logging_without_debug(self):
logger = sceptre.cli.setup_logging(False, False)
assert logger.getEffectiveLevel() == logging.INFO
assert logging.getLogger("botocore").getEffectiveLevel() == \
logging.CRITICAL
# Silence logging for the rest of the tests
logger.setLevel(logging.CRITICAL)
@patch("sceptre.cli.click.echo")
def test_write_with_yaml_format(self, mock_echo):
sceptre.cli.write({"key": "value"}, "yaml")
mock_echo.assert_called_once_with("key: value\n")
@patch("sceptre.cli.click.echo")
def test_write_with_json_format(self, mock_echo):
sceptre.cli.write({"key": "value"}, "json")
mock_echo.assert_called_once_with('{"key": "value"}')
@patch("sceptre.cli.click.echo")
def test_write_status_with_colour(self, mock_echo):
sceptre.cli.write("stack: CREATE_COMPLETE", no_colour=False)
mock_echo.assert_called_once_with(
"stack: \x1b[32mCREATE_COMPLETE\x1b[0m"
)
@patch("sceptre.cli.click.echo")
def test_write_status_without_colour(self, mock_echo):
sceptre.cli.write("stack: CREATE_COMPLETE", no_colour=True)
mock_echo.assert_called_once_with("stack: CREATE_COMPLETE")
@patch("sceptre.cli.StackStatusColourer.colour")
@patch("sceptre.cli.Formatter.format")
def test_ColouredFormatter_format_with_string(
self, mock_format, mock_colour
):
mock_format.return_value = sentinel.response
mock_colour.return_value = sentinel.coloured_response
coloured_formatter = sceptre.cli.ColouredFormatter()
response = coloured_formatter.format("string")
mock_format.assert_called_once_with("string")
mock_colour.assert_called_once_with(sentinel.response)
assert response == sentinel.coloured_response
def test_CustomJsonEncoder_with_non_json_serialisable_object(self):
encoder = sceptre.cli.CustomJsonEncoder()
response = encoder.encode(datetime.datetime(2016, 5, 3))
assert response == '"2016-05-03 00:00:00"'