Re-upload: CI infrastructure issue resolved, all tests verified passing
This commit is contained in:
0
envschema_repo/tests/integration/__init__.py
Normal file
0
envschema_repo/tests/integration/__init__.py
Normal file
120
envschema_repo/tests/integration/test_cli.py
Normal file
120
envschema_repo/tests/integration/test_cli.py
Normal file
@@ -0,0 +1,120 @@
|
||||
"""Integration tests for CLI commands."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from envschema.cli import cli
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def temp_schema_file():
|
||||
"""Create a temporary schema file."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
|
||||
json.dump({
|
||||
"version": "1.0",
|
||||
"envVars": [
|
||||
{"name": "DATABASE_URL", "type": "str", "required": True},
|
||||
{"name": "DEBUG_MODE", "type": "bool", "required": False, "default": "false"},
|
||||
{"name": "PORT", "type": "int", "required": False, "default": "8080"},
|
||||
]
|
||||
}, f)
|
||||
temp_path = f.name
|
||||
yield temp_path
|
||||
os.unlink(temp_path)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def temp_env_file():
|
||||
"""Create a temporary .env file."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".env", delete=False) as f:
|
||||
f.write("DATABASE_URL=postgres://localhost/mydb\n")
|
||||
f.write("DEBUG_MODE=true\n")
|
||||
temp_path = f.name
|
||||
yield temp_path
|
||||
os.unlink(temp_path)
|
||||
|
||||
|
||||
class TestValidateCommand:
|
||||
"""Tests for the validate command."""
|
||||
|
||||
def test_validate_missing_schema(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["validate", "/nonexistent/schema.json"])
|
||||
assert result.exit_code == 2
|
||||
assert "Error" in result.output
|
||||
|
||||
def test_validate_valid_env(self, temp_schema_file, temp_env_file):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["validate", temp_schema_file, "--file", temp_env_file, "--no-env"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
def test_validate_missing_required(self, temp_schema_file):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["validate", temp_schema_file, "--no-env"])
|
||||
assert result.exit_code == 1
|
||||
assert "DATABASE_URL" in result.output
|
||||
|
||||
def test_validate_with_json_output(self, temp_schema_file, temp_env_file):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["validate", temp_schema_file, "--file", temp_env_file, "--no-env", "--format", "json"])
|
||||
assert result.exit_code == 0
|
||||
data = json.loads(result.output)
|
||||
assert data["is_valid"] is True
|
||||
|
||||
def test_validate_ci_mode(self, temp_schema_file, temp_env_file):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["validate", temp_schema_file, "--file", temp_env_file, "--no-env", "--ci"])
|
||||
assert result.exit_code == 0
|
||||
assert "✓" not in result.output
|
||||
|
||||
|
||||
class TestGenerateCommand:
|
||||
"""Tests for the generate command."""
|
||||
|
||||
def test_generate_basic(self, temp_schema_file):
|
||||
runner = CliRunner()
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(cli, ["generate", temp_schema_file])
|
||||
assert result.exit_code == 0
|
||||
assert ".env.example" in result.output
|
||||
|
||||
def test_generate_to_custom_path(self, temp_schema_file, tmp_path):
|
||||
runner = CliRunner()
|
||||
output_path = tmp_path / "custom.env.example"
|
||||
result = runner.invoke(cli, ["generate", temp_schema_file, "--output", str(output_path)])
|
||||
assert result.exit_code == 0
|
||||
assert output_path.read_text()
|
||||
|
||||
def test_generate_no_comments(self, temp_schema_file, tmp_path):
|
||||
runner = CliRunner()
|
||||
output_path = tmp_path / "no_comments.env"
|
||||
result = runner.invoke(cli, ["generate", temp_schema_file, "--output", str(output_path), "--no-comments"])
|
||||
assert result.exit_code == 0
|
||||
content = output_path.read_text()
|
||||
assert "description" not in content.lower() or "#" not in content
|
||||
|
||||
|
||||
class TestCheckCommand:
|
||||
"""Tests for the check command."""
|
||||
|
||||
def test_check_valid_schema(self, temp_schema_file):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["check", temp_schema_file])
|
||||
assert result.exit_code == 0
|
||||
assert "valid" in result.output.lower()
|
||||
|
||||
def test_check_invalid_schema(self):
|
||||
runner = CliRunner()
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
|
||||
f.write('{"version": "1.0", "envVars": [{"name": "VAR", "type": "invalid_type"}]}')
|
||||
temp_path = f.name
|
||||
try:
|
||||
result = runner.invoke(cli, ["check", temp_path])
|
||||
assert result.exit_code == 2
|
||||
finally:
|
||||
os.unlink(temp_path)
|
||||
183
envschema_repo/tests/integration/test_full_flow.py
Normal file
183
envschema_repo/tests/integration/test_full_flow.py
Normal file
@@ -0,0 +1,183 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user