|
|
@@ -0,0 +1,176 @@
|
|
|
+"""Unit tests for Variable class."""
|
|
|
+
|
|
|
+import pytest
|
|
|
+
|
|
|
+from cli.core.template.variable import Variable
|
|
|
+
|
|
|
+# Test constants
|
|
|
+TEST_PORT = 8080
|
|
|
+TEST_COUNT = 42
|
|
|
+TEST_RATE = 3.14
|
|
|
+
|
|
|
+
|
|
|
+class TestVariableInitialization:
|
|
|
+ """Tests for Variable initialization."""
|
|
|
+
|
|
|
+ def test_create_simple_variable(self):
|
|
|
+ """Test creating a simple string variable."""
|
|
|
+ var = Variable({"name": "test_var", "type": "str"})
|
|
|
+ assert var.name == "test_var"
|
|
|
+ assert var.type == "str"
|
|
|
+ assert var.value is None
|
|
|
+
|
|
|
+ def test_create_variable_with_default(self):
|
|
|
+ """Test creating a variable with default value."""
|
|
|
+ var = Variable({"name": "port", "type": "int", "default": TEST_PORT})
|
|
|
+ assert var.name == "port"
|
|
|
+ assert var.value == TEST_PORT
|
|
|
+
|
|
|
+ def test_create_bool_variable_without_default(self):
|
|
|
+ """Test that bool variables default to False."""
|
|
|
+ var = Variable({"name": "enabled", "type": "bool"})
|
|
|
+ assert var.value is False
|
|
|
+
|
|
|
+ def test_create_variable_with_description(self):
|
|
|
+ """Test creating a variable with description."""
|
|
|
+ var = Variable({"name": "test", "type": "str", "description": "Test variable"})
|
|
|
+ assert var.description == "Test variable"
|
|
|
+
|
|
|
+ def test_missing_name_raises_error(self):
|
|
|
+ """Test that missing name key raises ValueError."""
|
|
|
+ with pytest.raises(ValueError, match="must contain 'name' key"):
|
|
|
+ Variable({"type": "str"})
|
|
|
+
|
|
|
+ def test_invalid_data_type_raises_error(self):
|
|
|
+ """Test that non-dict data raises ValueError."""
|
|
|
+ with pytest.raises(ValueError, match="must be a dictionary"):
|
|
|
+ Variable("not a dict")
|
|
|
+
|
|
|
+
|
|
|
+class TestVariableTypes:
|
|
|
+ """Tests for variable type handling."""
|
|
|
+
|
|
|
+ def test_string_type(self):
|
|
|
+ """Test string variable type."""
|
|
|
+ var = Variable({"name": "test", "type": "str", "default": "hello"})
|
|
|
+ assert var.value == "hello"
|
|
|
+
|
|
|
+ def test_int_type(self):
|
|
|
+ """Test integer variable type."""
|
|
|
+ var = Variable({"name": "count", "type": "int", "default": TEST_COUNT})
|
|
|
+ assert var.value == TEST_COUNT
|
|
|
+
|
|
|
+ def test_bool_type_true(self):
|
|
|
+ """Test boolean variable with true value."""
|
|
|
+ var = Variable({"name": "enabled", "type": "bool", "default": True})
|
|
|
+ assert var.value is True
|
|
|
+
|
|
|
+ def test_bool_type_false(self):
|
|
|
+ """Test boolean variable with false value."""
|
|
|
+ var = Variable({"name": "disabled", "type": "bool", "default": False})
|
|
|
+ assert var.value is False
|
|
|
+
|
|
|
+ def test_float_type(self):
|
|
|
+ """Test float variable type."""
|
|
|
+ var = Variable({"name": "rate", "type": "float", "default": TEST_RATE})
|
|
|
+ assert var.value == TEST_RATE
|
|
|
+
|
|
|
+
|
|
|
+class TestVariableProperties:
|
|
|
+ """Tests for variable properties."""
|
|
|
+
|
|
|
+ def test_sensitive_flag(self):
|
|
|
+ """Test sensitive flag for passwords."""
|
|
|
+ var = Variable({"name": "password", "type": "str", "sensitive": True})
|
|
|
+ assert var.sensitive is True
|
|
|
+
|
|
|
+ def test_autogenerated_flag(self):
|
|
|
+ """Test autogenerated flag."""
|
|
|
+ var = Variable({"name": "secret", "type": "str", "autogenerated": True})
|
|
|
+ assert var.autogenerated is True
|
|
|
+
|
|
|
+ def test_required_flag(self):
|
|
|
+ """Test required flag."""
|
|
|
+ var = Variable({"name": "hostname", "type": "str", "required": True})
|
|
|
+ assert var.required is True
|
|
|
+
|
|
|
+ def test_options_list(self):
|
|
|
+ """Test enum variable with options."""
|
|
|
+ var = Variable({"name": "mode", "type": "enum", "options": ["dev", "prod"]})
|
|
|
+ assert var.options == ["dev", "prod"]
|
|
|
+
|
|
|
+ def test_extra_help_text(self):
|
|
|
+ """Test extra help text."""
|
|
|
+ var = Variable({"name": "test", "type": "str", "extra": "Additional info"})
|
|
|
+ assert var.extra == "Additional info"
|
|
|
+
|
|
|
+
|
|
|
+class TestVariableNeeds:
|
|
|
+ """Tests for variable dependency constraints."""
|
|
|
+
|
|
|
+ def test_needs_single_string(self):
|
|
|
+ """Test needs constraint as single string."""
|
|
|
+ var = Variable({"name": "test", "type": "str", "needs": "other_var=value"})
|
|
|
+ assert var.needs == ["other_var=value"]
|
|
|
+
|
|
|
+ def test_needs_semicolon_separated(self):
|
|
|
+ """Test needs constraint with semicolon-separated conditions."""
|
|
|
+ var = Variable({"name": "test", "type": "str", "needs": "var1=value1;var2=value2"})
|
|
|
+ assert var.needs == ["var1=value1", "var2=value2"]
|
|
|
+
|
|
|
+ def test_needs_list(self):
|
|
|
+ """Test needs constraint as list."""
|
|
|
+ var = Variable({"name": "test", "type": "str", "needs": ["var1=value1", "var2=value2"]})
|
|
|
+ assert var.needs == ["var1=value1", "var2=value2"]
|
|
|
+
|
|
|
+ def test_needs_empty(self):
|
|
|
+ """Test variable without needs constraint."""
|
|
|
+ var = Variable({"name": "test", "type": "str"})
|
|
|
+ assert var.needs == []
|
|
|
+
|
|
|
+
|
|
|
+class TestVariableConversion:
|
|
|
+ """Tests for variable value conversion."""
|
|
|
+
|
|
|
+ def test_convert_string_to_int(self):
|
|
|
+ """Test converting string to integer."""
|
|
|
+ var = Variable({"name": "count", "type": "int"})
|
|
|
+ result = var.convert("42")
|
|
|
+ assert result == TEST_COUNT
|
|
|
+ assert isinstance(result, int)
|
|
|
+
|
|
|
+ def test_convert_string_to_bool_true(self):
|
|
|
+ """Test converting string to boolean true."""
|
|
|
+ var = Variable({"name": "enabled", "type": "bool"})
|
|
|
+ assert var.convert("true") is True
|
|
|
+ assert var.convert("1") is True
|
|
|
+ assert var.convert("yes") is True
|
|
|
+
|
|
|
+ def test_convert_string_to_bool_false(self):
|
|
|
+ """Test converting string to boolean false."""
|
|
|
+ var = Variable({"name": "disabled", "type": "bool"})
|
|
|
+ assert var.convert("false") is False
|
|
|
+ assert var.convert("0") is False
|
|
|
+ assert var.convert("no") is False
|
|
|
+
|
|
|
+ def test_convert_string_to_float(self):
|
|
|
+ """Test converting string to float."""
|
|
|
+ var = Variable({"name": "rate", "type": "float"})
|
|
|
+ result = var.convert("3.14")
|
|
|
+ assert result == TEST_RATE
|
|
|
+ assert isinstance(result, float)
|
|
|
+
|
|
|
+
|
|
|
+@pytest.mark.parametrize(
|
|
|
+ "var_type,default_value,expected",
|
|
|
+ [
|
|
|
+ ("str", "hello", "hello"),
|
|
|
+ ("int", TEST_COUNT, TEST_COUNT),
|
|
|
+ ("bool", True, True),
|
|
|
+ ("float", TEST_RATE, TEST_RATE),
|
|
|
+ ],
|
|
|
+)
|
|
|
+def test_variable_types_parametrized(var_type, default_value, expected):
|
|
|
+ """Test various variable types with parametrized inputs."""
|
|
|
+ var = Variable({"name": "test", "type": var_type, "default": default_value})
|
|
|
+ assert var.value == expected
|