184 lines
6.7 KiB
Python
184 lines
6.7 KiB
Python
"""End-to-end integration tests for the full validation flow."""
|
|
|
|
import json
|
|
import os
|
|
import tempfile
|
|
|
|
import pytest
|
|
from click.testing import CliRunner
|
|
|
|
from envschema.cli import cli
|
|
from envschema.core import validate_environment
|
|
from envschema.generator import generate_env_example
|
|
|
|
|
|
class TestFullValidationFlow:
|
|
"""Integration tests for complete validation workflows."""
|
|
|
|
def test_json_schema_with_valid_env(self):
|
|
"""Test validating a valid .env against a JSON schema."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
schema_path = os.path.join(tmpdir, "schema.json")
|
|
env_path = os.path.join(tmpdir, ".env")
|
|
|
|
schema_data = {
|
|
"version": "1.0",
|
|
"envVars": [
|
|
{"name": "DATABASE_URL", "type": "str", "required": True},
|
|
{"name": "DEBUG", "type": "bool", "required": False, "default": "false"},
|
|
{"name": "PORT", "type": "int", "required": False, "default": "8080"},
|
|
{"name": "ALLOWED_HOSTS", "type": "list", "required": False},
|
|
]
|
|
}
|
|
|
|
with open(schema_path, "w") as f:
|
|
json.dump(schema_data, f)
|
|
|
|
with open(env_path, "w") as f:
|
|
f.write("DATABASE_URL=postgres://localhost/mydb\n")
|
|
f.write("DEBUG=true\n")
|
|
f.write("PORT=3000\n")
|
|
f.write("ALLOWED_HOSTS=localhost,127.0.0.1\n")
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["validate", schema_path, "--file", env_path, "--no-env"])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
def test_json_schema_with_invalid_types(self):
|
|
"""Test that type mismatches are caught."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
schema_path = os.path.join(tmpdir, "schema.json")
|
|
env_path = os.path.join(tmpdir, ".env")
|
|
|
|
schema_data = {
|
|
"version": "1.0",
|
|
"envVars": [
|
|
{"name": "PORT", "type": "int", "required": True},
|
|
]
|
|
}
|
|
|
|
with open(schema_path, "w") as f:
|
|
json.dump(schema_data, f)
|
|
|
|
with open(env_path, "w") as f:
|
|
f.write("PORT=not_a_number\n")
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["validate", schema_path, "--file", env_path, "--no-env"])
|
|
|
|
assert result.exit_code == 1
|
|
assert "PORT" in result.output
|
|
|
|
def test_missing_required_variables(self):
|
|
"""Test that missing required variables are reported."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
schema_path = os.path.join(tmpdir, "schema.json")
|
|
env_path = os.path.join(tmpdir, ".env")
|
|
|
|
schema_data = {
|
|
"version": "1.0",
|
|
"envVars": [
|
|
{"name": "REQUIRED_VAR1", "type": "str", "required": True},
|
|
{"name": "REQUIRED_VAR2", "type": "str", "required": True},
|
|
{"name": "OPTIONAL_VAR", "type": "str", "required": False},
|
|
]
|
|
}
|
|
|
|
with open(schema_path, "w") as f:
|
|
json.dump(schema_data, f)
|
|
|
|
with open(env_path, "w") as f:
|
|
f.write("REQUIRED_VAR1=value1\n")
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["validate", schema_path, "--file", env_path, "--no-env"])
|
|
|
|
assert result.exit_code == 1
|
|
assert "REQUIRED_VAR2" in result.output
|
|
|
|
def test_generate_and_validate_flow(self):
|
|
"""Test generating .env.example and then validating it."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
schema_path = os.path.join(tmpdir, "schema.json")
|
|
example_path = os.path.join(tmpdir, ".env.example")
|
|
|
|
schema_data = {
|
|
"version": "1.0",
|
|
"envVars": [
|
|
{"name": "DATABASE_URL", "type": "str", "required": True, "description": "Database connection string"},
|
|
{"name": "DEBUG", "type": "bool", "required": False, "default": "false", "description": "Enable debug mode"},
|
|
{"name": "PORT", "type": "int", "required": False, "default": "8080", "description": "Server port"},
|
|
]
|
|
}
|
|
|
|
with open(schema_path, "w") as f:
|
|
json.dump(schema_data, f)
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["generate", schema_path, "--output", example_path])
|
|
assert result.exit_code == 0
|
|
|
|
with open(example_path, "r") as f:
|
|
content = f.read()
|
|
assert "DATABASE_URL=" in content
|
|
assert "DEBUG=false" in content
|
|
assert "PORT=8080" in content
|
|
assert "Database connection string" in content
|
|
|
|
|
|
class TestCIMode:
|
|
"""Tests for CI mode functionality."""
|
|
|
|
def test_ci_mode_clean_output(self):
|
|
"""Test that CI mode produces cleaner output."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
schema_path = os.path.join(tmpdir, "schema.json")
|
|
env_path = os.path.join(tmpdir, ".env")
|
|
|
|
schema_data = {
|
|
"version": "1.0",
|
|
"envVars": [
|
|
{"name": "DATABASE_URL", "type": "str", "required": True},
|
|
]
|
|
}
|
|
|
|
with open(schema_path, "w") as f:
|
|
json.dump(schema_data, f)
|
|
|
|
with open(env_path, "w") as f:
|
|
f.write("DATABASE_URL=postgres://localhost/mydb\n")
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["validate", schema_path, "--file", env_path, "--no-env", "--ci"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "✓" not in result.output
|
|
assert "✗" not in result.output
|
|
|
|
def test_ci_mode_json_output(self):
|
|
"""Test CI mode with JSON output."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
schema_path = os.path.join(tmpdir, "schema.json")
|
|
env_path = os.path.join(tmpdir, ".env")
|
|
|
|
schema_data = {
|
|
"version": "1.0",
|
|
"envVars": [
|
|
{"name": "DATABASE_URL", "type": "str", "required": True},
|
|
]
|
|
}
|
|
|
|
with open(schema_path, "w") as f:
|
|
json.dump(schema_data, f)
|
|
|
|
with open(env_path, "w") as f:
|
|
f.write("DATABASE_URL=postgres://localhost/mydb\n")
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["validate", schema_path, "--file", env_path, "--no-env", "--ci", "--format", "json"])
|
|
|
|
assert result.exit_code == 0
|
|
data = json.loads(result.output)
|
|
assert data["is_valid"] is True
|