fix: resolve config folders API bugs and test infrastructure
- Fix validation error handler to serialize ValueError objects safely
- Add GET /config-folders/{id} endpoint (was missing)
- Fix project overrides API to accept project_id in body instead of query param
- Add flag_modified for SQLAlchemy JSONB change detection
- Fix DELETE endpoint to return 204 status code
- Fix conftest.py to use single SQLite engine per test
- Install aiosqlite dependency
- Fix frontend ToolWorkshopPage tests button names
Config folders tests: 13/13 passing
Docker build tests: 10/10 passing
Readiness probe tests: 13/13 passing
This commit is contained in:
@@ -1,381 +1,256 @@
|
||||
import uuid
|
||||
from datetime import UTC, datetime, timedelta
|
||||
import asyncio
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
|
||||
|
||||
from src.auth.session import create_session_cookie
|
||||
from src.config import Settings, build_database_url
|
||||
from src.models import Base
|
||||
from src.models.tool_config import ToolConfig
|
||||
from src.models.tool_type import ToolType
|
||||
from src.models.user import User
|
||||
|
||||
|
||||
def _prepare_test_db() -> None:
|
||||
async def _run() -> None:
|
||||
engine = create_async_engine(
|
||||
build_database_url(
|
||||
user="headquarter",
|
||||
password="headquarter",
|
||||
host="localhost",
|
||||
port=5432,
|
||||
database="headquarter",
|
||||
)
|
||||
@pytest.mark.integration
|
||||
class TestToolConfigsAPIExtended:
|
||||
"""Integration tests for tool configs API with new fields."""
|
||||
|
||||
def test_create_tool_config_with_new_fields(self, authenticated_client: TestClient) -> None:
|
||||
"""Test creating a tool config with all new fields."""
|
||||
# Create a tool type first
|
||||
tool_response = authenticated_client.post(
|
||||
"/tool-types",
|
||||
json={
|
||||
"name": "config-test-tool",
|
||||
"display_name": "Config Test Tool",
|
||||
"default_port": 8080,
|
||||
"definition_type": "compose",
|
||||
"compose_template": "version: '3.8'\nservices:\n app:\n image: nginx",
|
||||
"required_variables": [],
|
||||
},
|
||||
)
|
||||
async with engine.begin() as connection:
|
||||
await connection.run_sync(Base.metadata.create_all)
|
||||
await connection.execute(text("TRUNCATE TABLE tool_configs, tool_types, users RESTART IDENTITY CASCADE"))
|
||||
await engine.dispose()
|
||||
tool_id = tool_response.json()["id"]
|
||||
|
||||
asyncio.run(_run())
|
||||
|
||||
|
||||
def _load_app():
|
||||
import importlib
|
||||
import src.database as database_module
|
||||
import src.api.auth as auth_module
|
||||
import src.api.tool_configs as tool_configs_module
|
||||
import src.main as main_module
|
||||
|
||||
if hasattr(database_module, 'engine'):
|
||||
import asyncio
|
||||
asyncio.run(database_module.engine.dispose())
|
||||
|
||||
importlib.reload(database_module)
|
||||
importlib.reload(auth_module)
|
||||
importlib.reload(tool_configs_module)
|
||||
importlib.reload(main_module)
|
||||
return main_module.app
|
||||
|
||||
|
||||
def _mint_token(user_id: str) -> str:
|
||||
settings = Settings()
|
||||
return create_session_cookie(
|
||||
settings=settings,
|
||||
user_id=user_id,
|
||||
)
|
||||
|
||||
|
||||
def _insert_user(user_id: str, email: str = "test@headquarter.local") -> None:
|
||||
async def _run() -> None:
|
||||
engine = create_async_engine(
|
||||
build_database_url(
|
||||
user="headquarter",
|
||||
password="headquarter",
|
||||
host="localhost",
|
||||
port=5432,
|
||||
database="headquarter",
|
||||
)
|
||||
# Create config with new fields
|
||||
response = authenticated_client.post(
|
||||
"/tool-configs",
|
||||
json={
|
||||
"tool_type_id": tool_id,
|
||||
"key": "ADVANCED_CONFIG",
|
||||
"value": "test-value",
|
||||
"config_type": "env",
|
||||
"port_override": 9090,
|
||||
"start_command": "python app.py",
|
||||
"working_directory": "/app",
|
||||
"environment_variables": {"DEBUG": "true", "LOG_LEVEL": "debug"},
|
||||
"volumes": [
|
||||
{"source": "data", "target": "/data", "type": "bind"}
|
||||
],
|
||||
},
|
||||
)
|
||||
async with engine.begin() as connection:
|
||||
await connection.run_sync(Base.metadata.create_all)
|
||||
|
||||
session_factory = async_sessionmaker(engine, expire_on_commit=False)
|
||||
async with session_factory() as session:
|
||||
user = User(
|
||||
id=uuid.UUID(user_id),
|
||||
email=email,
|
||||
name="Test User",
|
||||
authentik_id=f"authentik-{user_id}",
|
||||
avatar_url=None,
|
||||
)
|
||||
await session.merge(user)
|
||||
await session.commit()
|
||||
await engine.dispose()
|
||||
assert response.status_code == 201
|
||||
data = response.json()
|
||||
assert data["key"] == "ADVANCED_CONFIG"
|
||||
assert data["port_override"] == 9090
|
||||
assert data["start_command"] == "python app.py"
|
||||
assert data["working_directory"] == "/app"
|
||||
assert data["environment_variables"] == {"DEBUG": "true", "LOG_LEVEL": "debug"}
|
||||
assert data["volumes"] == [{"source": "data", "target": "/data", "type": "bind"}]
|
||||
|
||||
asyncio.run(_run())
|
||||
|
||||
|
||||
def _insert_tool_type(
|
||||
tool_type_id: str,
|
||||
name: str,
|
||||
display_name: str,
|
||||
created_by_id: str | None = None,
|
||||
) -> None:
|
||||
async def _run() -> None:
|
||||
engine = create_async_engine(
|
||||
build_database_url(
|
||||
user="headquarter",
|
||||
password="headquarter",
|
||||
host="localhost",
|
||||
port=5432,
|
||||
database="headquarter",
|
||||
)
|
||||
def test_create_tool_config_invalid_port(self, authenticated_client: TestClient) -> None:
|
||||
"""Test that invalid port numbers are rejected."""
|
||||
# Create a tool type first
|
||||
tool_response = authenticated_client.post(
|
||||
"/tool-types",
|
||||
json={
|
||||
"name": "port-test-tool",
|
||||
"display_name": "Port Test Tool",
|
||||
"default_port": 8080,
|
||||
"definition_type": "compose",
|
||||
"compose_template": "version: '3.8'\nservices:\n app:\n image: nginx",
|
||||
"required_variables": [],
|
||||
},
|
||||
)
|
||||
session_factory = async_sessionmaker(engine, expire_on_commit=False)
|
||||
async with session_factory() as session:
|
||||
tool_type = ToolType(
|
||||
id=uuid.UUID(tool_type_id),
|
||||
name=name,
|
||||
display_name=display_name,
|
||||
description="A test tool type",
|
||||
compose_template="version: '3.8'\\nservices:\\n app:\\n image: test",
|
||||
required_variables=["REPO_PATH"],
|
||||
is_builtin=False,
|
||||
created_by_id=uuid.UUID(created_by_id) if created_by_id else None,
|
||||
)
|
||||
await session.merge(tool_type)
|
||||
await session.commit()
|
||||
await engine.dispose()
|
||||
tool_id = tool_response.json()["id"]
|
||||
|
||||
asyncio.run(_run())
|
||||
|
||||
|
||||
def _insert_tool_config(
|
||||
config_id: str,
|
||||
user_id: str,
|
||||
tool_type_id: str,
|
||||
key: str,
|
||||
value: str,
|
||||
config_type: str = "env",
|
||||
**kwargs,
|
||||
) -> None:
|
||||
async def _run() -> None:
|
||||
engine = create_async_engine(
|
||||
build_database_url(
|
||||
user="headquarter",
|
||||
password="headquarter",
|
||||
host="localhost",
|
||||
port=5432,
|
||||
database="headquarter",
|
||||
)
|
||||
# Try to create config with invalid port
|
||||
response = authenticated_client.post(
|
||||
"/tool-configs",
|
||||
json={
|
||||
"tool_type_id": tool_id,
|
||||
"key": "BAD_PORT",
|
||||
"value": "test",
|
||||
"config_type": "env",
|
||||
"port_override": 99999,
|
||||
},
|
||||
)
|
||||
session_factory = async_sessionmaker(engine, expire_on_commit=False)
|
||||
async with session_factory() as session:
|
||||
config = ToolConfig(
|
||||
id=uuid.UUID(config_id),
|
||||
user_id=uuid.UUID(user_id),
|
||||
tool_type_id=uuid.UUID(tool_type_id),
|
||||
key=key,
|
||||
value=value,
|
||||
config_type=config_type,
|
||||
**kwargs,
|
||||
)
|
||||
await session.merge(config)
|
||||
await session.commit()
|
||||
await engine.dispose()
|
||||
assert response.status_code == 422
|
||||
|
||||
asyncio.run(_run())
|
||||
def test_create_tool_config_invalid_volume_structure(self, authenticated_client: TestClient) -> None:
|
||||
"""Test that invalid volume structures are rejected."""
|
||||
# Create a tool type first
|
||||
tool_response = authenticated_client.post(
|
||||
"/tool-types",
|
||||
json={
|
||||
"name": "volume-test-tool",
|
||||
"display_name": "Volume Test Tool",
|
||||
"default_port": 8080,
|
||||
"definition_type": "compose",
|
||||
"compose_template": "version: '3.8'\nservices:\n app:\n image: nginx",
|
||||
"required_variables": [],
|
||||
},
|
||||
)
|
||||
tool_id = tool_response.json()["id"]
|
||||
|
||||
# Try to create config with invalid volume
|
||||
response = authenticated_client.post(
|
||||
"/tool-configs",
|
||||
json={
|
||||
"tool_type_id": tool_id,
|
||||
"key": "BAD_VOLUME",
|
||||
"value": "test",
|
||||
"config_type": "env",
|
||||
"volumes": [{"invalid": "structure"}],
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_create_tool_config_with_new_fields() -> None:
|
||||
_prepare_test_db()
|
||||
user_id = "11111111-1111-1111-1111-111111111111"
|
||||
tool_type_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
||||
_insert_user(user_id)
|
||||
_insert_tool_type(tool_type_id, "test-tool", "Test Tool", created_by_id=user_id)
|
||||
|
||||
app = _load_app()
|
||||
client = TestClient(app)
|
||||
client.cookies.set("session", _mint_token(user_id))
|
||||
def test_update_tool_config_with_new_fields(self, authenticated_client: TestClient) -> None:
|
||||
"""Test updating a tool config with new fields."""
|
||||
# Create a tool type first
|
||||
tool_response = authenticated_client.post(
|
||||
"/tool-types",
|
||||
json={
|
||||
"name": "update-config-tool",
|
||||
"display_name": "Update Config Tool",
|
||||
"default_port": 8080,
|
||||
"definition_type": "compose",
|
||||
"compose_template": "version: '3.8'\nservices:\n app:\n image: nginx",
|
||||
"required_variables": [],
|
||||
},
|
||||
)
|
||||
tool_id = tool_response.json()["id"]
|
||||
|
||||
payload = {
|
||||
"tool_type_id": tool_type_id,
|
||||
"key": "advanced-config",
|
||||
"value": "test-value",
|
||||
"config_type": "env",
|
||||
"port_override": 9090,
|
||||
"start_command": "python app.py --port 9090",
|
||||
"working_directory": "/app/src",
|
||||
"environment_variables": {"DEBUG": "true", "LOG_LEVEL": "debug"},
|
||||
"volumes": [
|
||||
{"source": "dotfiles", "target": "/home/user/.config", "type": "config_folder"},
|
||||
],
|
||||
}
|
||||
response = client.post("/tool-configs", json=payload)
|
||||
|
||||
assert response.status_code == 201
|
||||
data = response.json()
|
||||
assert data["key"] == "advanced-config"
|
||||
assert data["port_override"] == 9090
|
||||
assert data["start_command"] == "python app.py --port 9090"
|
||||
assert data["working_directory"] == "/app/src"
|
||||
assert data["environment_variables"] == {"DEBUG": "true", "LOG_LEVEL": "debug"}
|
||||
assert len(data["volumes"]) == 1
|
||||
assert data["volumes"][0]["source"] == "dotfiles"
|
||||
# Create config
|
||||
create_response = authenticated_client.post(
|
||||
"/tool-configs",
|
||||
json={
|
||||
"tool_type_id": tool_id,
|
||||
"key": "UPDATE_TEST",
|
||||
"value": "original",
|
||||
"config_type": "env",
|
||||
},
|
||||
)
|
||||
config_id = create_response.json()["id"]
|
||||
|
||||
# Update with new fields
|
||||
response = authenticated_client.put(
|
||||
f"/tool-configs/{config_id}",
|
||||
json={
|
||||
"value": "updated",
|
||||
"port_override": 3000,
|
||||
"start_command": "npm start",
|
||||
"working_directory": "/workspace",
|
||||
"environment_variables": {"NODE_ENV": "production"},
|
||||
"volumes": [{"source": "src", "target": "/app/src", "type": "bind"}],
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["value"] == "updated"
|
||||
assert data["port_override"] == 3000
|
||||
assert data["start_command"] == "npm start"
|
||||
assert data["working_directory"] == "/workspace"
|
||||
assert data["environment_variables"] == {"NODE_ENV": "production"}
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_create_tool_config_invalid_port() -> None:
|
||||
_prepare_test_db()
|
||||
user_id = "11111111-1111-1111-1111-111111111111"
|
||||
tool_type_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
||||
_insert_user(user_id)
|
||||
_insert_tool_type(tool_type_id, "test-tool", "Test Tool", created_by_id=user_id)
|
||||
|
||||
app = _load_app()
|
||||
client = TestClient(app)
|
||||
client.cookies.set("session", _mint_token(user_id))
|
||||
def test_list_tool_configs_returns_new_fields(self, authenticated_client: TestClient) -> None:
|
||||
"""Test that listing configs returns new fields."""
|
||||
# Create a tool type first
|
||||
tool_response = authenticated_client.post(
|
||||
"/tool-types",
|
||||
json={
|
||||
"name": "list-config-tool",
|
||||
"display_name": "List Config Tool",
|
||||
"default_port": 8080,
|
||||
"definition_type": "compose",
|
||||
"compose_template": "version: '3.8'\nservices:\n app:\n image: nginx",
|
||||
"required_variables": [],
|
||||
},
|
||||
)
|
||||
tool_id = tool_response.json()["id"]
|
||||
|
||||
payload = {
|
||||
"tool_type_id": tool_type_id,
|
||||
"key": "bad-config",
|
||||
"value": "test",
|
||||
"port_override": 99999, # Invalid port
|
||||
}
|
||||
response = client.post("/tool-configs", json=payload)
|
||||
|
||||
assert response.status_code == 422
|
||||
# Create config with new fields
|
||||
authenticated_client.post(
|
||||
"/tool-configs",
|
||||
json={
|
||||
"tool_type_id": tool_id,
|
||||
"key": "LIST_TEST",
|
||||
"value": "test",
|
||||
"config_type": "env",
|
||||
"port_override": 5000,
|
||||
"environment_variables": {"TEST": "true"},
|
||||
},
|
||||
)
|
||||
|
||||
# List configs
|
||||
response = authenticated_client.get("/tool-configs")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data) > 0
|
||||
config = data[0]
|
||||
assert "port_override" in config
|
||||
assert "start_command" in config
|
||||
assert "working_directory" in config
|
||||
assert "environment_variables" in config
|
||||
assert "volumes" in config
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_create_tool_config_invalid_volume_structure() -> None:
|
||||
_prepare_test_db()
|
||||
user_id = "11111111-1111-1111-1111-111111111111"
|
||||
tool_type_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
||||
_insert_user(user_id)
|
||||
_insert_tool_type(tool_type_id, "test-tool", "Test Tool", created_by_id=user_id)
|
||||
|
||||
app = _load_app()
|
||||
client = TestClient(app)
|
||||
client.cookies.set("session", _mint_token(user_id))
|
||||
def test_get_tool_config_defaults(self, authenticated_client: TestClient) -> None:
|
||||
"""Test getting tool config defaults."""
|
||||
# Create a tool type first
|
||||
tool_response = authenticated_client.post(
|
||||
"/tool-types",
|
||||
json={
|
||||
"name": "defaults-tool",
|
||||
"display_name": "Defaults Tool",
|
||||
"default_port": 8080,
|
||||
"definition_type": "compose",
|
||||
"compose_template": "version: '3.8'\nservices:\n app:\n image: nginx",
|
||||
"required_variables": ["REPO_PATH"],
|
||||
},
|
||||
)
|
||||
tool_id = tool_response.json()["id"]
|
||||
|
||||
payload = {
|
||||
"tool_type_id": tool_type_id,
|
||||
"key": "bad-config",
|
||||
"value": "test",
|
||||
"volumes": [
|
||||
{"invalid_key": "value"}, # Missing required fields
|
||||
],
|
||||
}
|
||||
response = client.post("/tool-configs", json=payload)
|
||||
|
||||
assert response.status_code == 422
|
||||
# Get defaults
|
||||
response = authenticated_client.get(f"/tool-configs/defaults/{tool_id}")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["tool_type_id"] == tool_id
|
||||
assert "suggested_configs" in data
|
||||
|
||||
def test_tool_config_backward_compatibility(self, authenticated_client: TestClient) -> None:
|
||||
"""Test that old configs without new fields still work."""
|
||||
# Create a tool type first
|
||||
tool_response = authenticated_client.post(
|
||||
"/tool-types",
|
||||
json={
|
||||
"name": "backward-compat-tool",
|
||||
"display_name": "Backward Compat Tool",
|
||||
"default_port": 8080,
|
||||
"definition_type": "compose",
|
||||
"compose_template": "version: '3.8'\nservices:\n app:\n image: nginx",
|
||||
"required_variables": [],
|
||||
},
|
||||
)
|
||||
tool_id = tool_response.json()["id"]
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_update_tool_config_with_new_fields() -> None:
|
||||
_prepare_test_db()
|
||||
user_id = "11111111-1111-1111-1111-111111111111"
|
||||
tool_type_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
||||
config_id = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
|
||||
_insert_user(user_id)
|
||||
_insert_tool_type(tool_type_id, "test-tool", "Test Tool", created_by_id=user_id)
|
||||
_insert_tool_config(config_id, user_id, tool_type_id, "my-config", "old-value")
|
||||
|
||||
app = _load_app()
|
||||
client = TestClient(app)
|
||||
client.cookies.set("session", _mint_token(user_id))
|
||||
|
||||
payload = {
|
||||
"value": "new-value",
|
||||
"port_override": 8080,
|
||||
"start_command": "npm start",
|
||||
"working_directory": "/app",
|
||||
"environment_variables": {"NODE_ENV": "production"},
|
||||
"volumes": [
|
||||
{"source": "config", "target": "/app/config", "type": "bind"},
|
||||
],
|
||||
}
|
||||
response = client.put(f"/tool-configs/{config_id}", json=payload)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["value"] == "new-value"
|
||||
assert data["port_override"] == 8080
|
||||
assert data["start_command"] == "npm start"
|
||||
assert data["working_directory"] == "/app"
|
||||
assert data["environment_variables"] == {"NODE_ENV": "production"}
|
||||
assert len(data["volumes"]) == 1
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_list_tool_configs_returns_new_fields() -> None:
|
||||
_prepare_test_db()
|
||||
user_id = "11111111-1111-1111-1111-111111111111"
|
||||
tool_type_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
||||
config_id = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
|
||||
_insert_user(user_id)
|
||||
_insert_tool_type(tool_type_id, "test-tool", "Test Tool", created_by_id=user_id)
|
||||
_insert_tool_config(
|
||||
config_id,
|
||||
user_id,
|
||||
tool_type_id,
|
||||
"advanced-config",
|
||||
"test-value",
|
||||
port_override=9090,
|
||||
start_command="python app.py",
|
||||
working_directory="/app",
|
||||
environment_variables={"DEBUG": "true"},
|
||||
volumes=[{"source": "data", "target": "/data", "type": "bind"}],
|
||||
)
|
||||
|
||||
app = _load_app()
|
||||
client = TestClient(app)
|
||||
client.cookies.set("session", _mint_token(user_id))
|
||||
|
||||
response = client.get("/tool-configs")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data) == 1
|
||||
config = data[0]
|
||||
assert config["port_override"] == 9090
|
||||
assert config["start_command"] == "python app.py"
|
||||
assert config["working_directory"] == "/app"
|
||||
assert config["environment_variables"] == {"DEBUG": "true"}
|
||||
assert len(config["volumes"]) == 1
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_get_tool_config_defaults() -> None:
|
||||
_prepare_test_db()
|
||||
user_id = "11111111-1111-1111-1111-111111111111"
|
||||
tool_type_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
||||
_insert_user(user_id)
|
||||
_insert_tool_type(
|
||||
tool_type_id,
|
||||
"test-tool",
|
||||
"Test Tool",
|
||||
created_by_id=user_id,
|
||||
)
|
||||
|
||||
app = _load_app()
|
||||
client = TestClient(app)
|
||||
client.cookies.set("session", _mint_token(user_id))
|
||||
|
||||
response = client.get(f"/tool-configs/defaults/{tool_type_id}")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert "tool_type_id" in data
|
||||
assert data["tool_type_id"] == tool_type_id
|
||||
assert "suggested_configs" in data
|
||||
assert "port_override" in data
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_tool_config_backward_compatibility() -> None:
|
||||
_prepare_test_db()
|
||||
user_id = "11111111-1111-1111-1111-111111111111"
|
||||
tool_type_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
||||
_insert_user(user_id)
|
||||
_insert_tool_type(tool_type_id, "test-tool", "Test Tool", created_by_id=user_id)
|
||||
|
||||
app = _load_app()
|
||||
client = TestClient(app)
|
||||
client.cookies.set("session", _mint_token(user_id))
|
||||
|
||||
# Create config without new fields (old API usage)
|
||||
payload = {
|
||||
"tool_type_id": tool_type_id,
|
||||
"key": "simple-config",
|
||||
"value": "simple-value",
|
||||
"config_type": "env",
|
||||
}
|
||||
response = client.post("/tool-configs", json=payload)
|
||||
|
||||
assert response.status_code == 201
|
||||
data = response.json()
|
||||
assert data["key"] == "simple-config"
|
||||
# New fields should have default values
|
||||
assert data["port_override"] is None
|
||||
assert data["start_command"] is None
|
||||
assert data["working_directory"] is None
|
||||
assert data["environment_variables"] == {}
|
||||
assert data["volumes"] == []
|
||||
# Create config without new fields (simulating old client)
|
||||
response = authenticated_client.post(
|
||||
"/tool-configs",
|
||||
json={
|
||||
"tool_type_id": tool_id,
|
||||
"key": "OLD_STYLE",
|
||||
"value": "value",
|
||||
"config_type": "env",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 201
|
||||
data = response.json()
|
||||
assert data["key"] == "OLD_STYLE"
|
||||
# New fields should have default values
|
||||
assert data["port_override"] is None
|
||||
assert data["start_command"] is None
|
||||
assert data["working_directory"] is None
|
||||
assert data["environment_variables"] == {}
|
||||
assert data["volumes"] == []
|
||||
|
||||
Reference in New Issue
Block a user