Harden M8 preflight foundation
This commit is contained in:
+131
-1
@@ -2,7 +2,8 @@
|
||||
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch, MagicMock
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import call, patch, MagicMock
|
||||
from io import StringIO
|
||||
|
||||
import pytest
|
||||
@@ -441,3 +442,132 @@ class TestDocsCommand:
|
||||
assert result == 1 # Returns 1 when no README
|
||||
captured = capsys.readouterr()
|
||||
assert 'No documentation' in captured.out or '--edit' in captured.out
|
||||
|
||||
|
||||
class TestRegistryPublishDryRun:
|
||||
@pytest.fixture
|
||||
def tool_dir(self, tmp_path):
|
||||
directory = tmp_path / "dry-run-tool"
|
||||
directory.mkdir()
|
||||
(directory / "config.yaml").write_text(
|
||||
"name: dry-run-tool\n"
|
||||
"version: 1.0.0\n"
|
||||
"description: Test dry-run behavior\n"
|
||||
"output: constant\n"
|
||||
)
|
||||
return directory
|
||||
|
||||
@staticmethod
|
||||
def args(tool_dir):
|
||||
return SimpleNamespace(
|
||||
path=str(tool_dir), dry_run=True, force=False, owner=""
|
||||
)
|
||||
|
||||
def test_without_token_stops_after_local_preflight(
|
||||
self, tool_dir, monkeypatch, capsys
|
||||
):
|
||||
from cmdforge.cli.registry_commands import _cmd_registry_publish
|
||||
|
||||
get_client = MagicMock()
|
||||
monkeypatch.setattr(
|
||||
"cmdforge.cli.registry_commands.load_config",
|
||||
lambda: SimpleNamespace(registry=SimpleNamespace(token="")),
|
||||
)
|
||||
monkeypatch.setattr("cmdforge.registry_client.get_client", get_client)
|
||||
|
||||
assert _cmd_registry_publish(self.args(tool_dir)) == 0
|
||||
get_client.assert_not_called()
|
||||
assert "local preflight only" in capsys.readouterr().out
|
||||
|
||||
def test_renders_structured_registry_evidence(
|
||||
self, tool_dir, monkeypatch, capsys
|
||||
):
|
||||
from cmdforge.cli.registry_commands import _cmd_registry_publish
|
||||
|
||||
client = MagicMock()
|
||||
client.publish_tool.return_value = {
|
||||
"preflight": {
|
||||
"errors": [],
|
||||
"warnings": ["remote warning"],
|
||||
"suggestions": ["remote hint"],
|
||||
},
|
||||
"suggestions": {
|
||||
"similar_tools": [{
|
||||
"name": "official/similar",
|
||||
"similarity": 0.8,
|
||||
}],
|
||||
"scrutiny": {
|
||||
"findings": [{"result": "warning", "message": "review me"}]
|
||||
},
|
||||
},
|
||||
}
|
||||
monkeypatch.setattr(
|
||||
"cmdforge.cli.registry_commands.load_config",
|
||||
lambda: SimpleNamespace(registry=SimpleNamespace(token="token")),
|
||||
)
|
||||
monkeypatch.setattr("cmdforge.registry_client.get_client", lambda: client)
|
||||
|
||||
assert _cmd_registry_publish(self.args(tool_dir)) == 0
|
||||
output = capsys.readouterr().out
|
||||
assert "remote warning" in output
|
||||
assert "official/similar" in output
|
||||
assert "review me" in output
|
||||
client.publish_tool.assert_called_once()
|
||||
|
||||
def test_registry_rejection_returns_failure(
|
||||
self, tool_dir, monkeypatch, capsys
|
||||
):
|
||||
from cmdforge.cli.registry_commands import _cmd_registry_publish
|
||||
from cmdforge.registry_client import RegistryError
|
||||
|
||||
client = MagicMock()
|
||||
client.publish_tool.side_effect = RegistryError(
|
||||
"SCRUTINY_FAILED", "Tool rejected"
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"cmdforge.cli.registry_commands.load_config",
|
||||
lambda: SimpleNamespace(registry=SimpleNamespace(token="token")),
|
||||
)
|
||||
monkeypatch.setattr("cmdforge.registry_client.get_client", lambda: client)
|
||||
|
||||
assert _cmd_registry_publish(self.args(tool_dir)) == 1
|
||||
assert "Tool rejected" in capsys.readouterr().err
|
||||
|
||||
def test_non_mapping_config_returns_failure(self, tool_dir, capsys):
|
||||
from cmdforge.cli.registry_commands import _cmd_registry_publish
|
||||
|
||||
(tool_dir / "config.yaml").write_text("- not\n- a\n- tool\n")
|
||||
|
||||
assert _cmd_registry_publish(self.args(tool_dir)) == 1
|
||||
assert "YAML mapping" in capsys.readouterr().err
|
||||
|
||||
|
||||
def test_inspect_with_registry_uses_similarity_results(monkeypatch, capsys):
|
||||
from cmdforge.cli import cmd_inspect
|
||||
from cmdforge.registry_client import PaginatedResponse
|
||||
|
||||
tool = Tool(name="summary", output="constant")
|
||||
client = MagicMock()
|
||||
client.search_tools.return_value = PaginatedResponse(data=[{
|
||||
"owner": "official",
|
||||
"name": "summarize",
|
||||
"description": "Summarize text",
|
||||
}])
|
||||
monkeypatch.setattr("cmdforge.tool.load_tool", lambda name: tool)
|
||||
monkeypatch.setattr("cmdforge.registry_client.get_client", lambda: client)
|
||||
|
||||
assert cmd_inspect(SimpleNamespace(name="summary", registry=True)) == 0
|
||||
assert "official/summarize" in capsys.readouterr().out
|
||||
|
||||
|
||||
def test_switch_to_existing_tool_closes_creation_page_first():
|
||||
pytest.importorskip("PySide6")
|
||||
from cmdforge.gui.pages.tool_builder_page import _switch_to_existing_tool
|
||||
|
||||
main_window = MagicMock()
|
||||
_switch_to_existing_tool(main_window, "existing")
|
||||
|
||||
assert main_window.method_calls == [
|
||||
call.close_tool_builder(),
|
||||
call.open_tool_builder("existing"),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user