mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-11 18:40:57 -07:00
132 lines
5.7 KiB
Python
132 lines
5.7 KiB
Python
import unittest
|
|
import copy
|
|
from utils.validator import validate_triage_result
|
|
|
|
VALID_TRIAGE_PAYLOAD = {
|
|
"triage_metadata": {
|
|
"quality": "OK",
|
|
"effort_estimate": "SMALL",
|
|
"reasoning": "Clear bug report with reproduction steps."
|
|
},
|
|
"workable_spec": {
|
|
"issue_id": "google-gemini/gemini-cli#245",
|
|
"summary": {
|
|
"problem": "Uncaught TypeError when running gemini triage with empty config.",
|
|
"root_cause": "Config loader assumes .gemini/settings.json always exists.",
|
|
"context": "Occurs during fresh installs before settings are initialized."
|
|
},
|
|
"implementation_plan": {
|
|
"files_to_modify": ["src/config.ts", "src/cli.ts"],
|
|
"steps": [
|
|
"Add filesystem check for settings.json in config loader.",
|
|
"Return default configuration if file is missing."
|
|
]
|
|
},
|
|
"testing_strategy": {
|
|
"test_file": "tests/config.test.ts",
|
|
"expected_behavior": "CLI boots with default settings when settings.json is missing.",
|
|
"verification_steps": [
|
|
"Add unit test mocking missing settings.json.",
|
|
"Assert default config object is returned."
|
|
],
|
|
"framework": "Vitest"
|
|
}
|
|
}
|
|
}
|
|
|
|
class TestValidator(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
self.payload = copy.deepcopy(VALID_TRIAGE_PAYLOAD)
|
|
|
|
def test_valid_triage(self):
|
|
"""valid triage result matching complete schema should pass"""
|
|
validate_triage_result(self.payload)
|
|
|
|
def test_needs_info_comment_fallback(self):
|
|
"""
|
|
NEEDS_INFO quality with missing/empty comment injects a non-empty
|
|
default fallback comment string instead of raising a validation failure.
|
|
"""
|
|
for empty_val in [None, "", " "]:
|
|
with self.subTest(empty_val=empty_val):
|
|
payload = {
|
|
"triage_metadata": {
|
|
"quality": "NEEDS_INFO",
|
|
"reasoning": "Issue missing logs."
|
|
}
|
|
}
|
|
if empty_val is not None:
|
|
payload["triage_metadata"]["comment"] = empty_val
|
|
validate_triage_result(payload)
|
|
comment = payload["triage_metadata"].get("comment")
|
|
self.assertIsInstance(comment, str)
|
|
self.assertTrue(len(comment.strip()) > 0)
|
|
|
|
def test_missing_triage_metadata(self):
|
|
"""payload missing triage_metadata should fail"""
|
|
del self.payload["triage_metadata"]
|
|
with self.assertRaises(ValueError):
|
|
validate_triage_result(self.payload)
|
|
|
|
def test_invalid_quality(self):
|
|
"""triage_metadata with unexpected quality status should fail"""
|
|
self.payload["triage_metadata"]["quality"] = "DANGER"
|
|
with self.assertRaises(ValueError) as ctx:
|
|
validate_triage_result(self.payload)
|
|
self.assertIn("Invalid or missing 'quality'", str(ctx.exception))
|
|
|
|
def test_invalid_effort(self):
|
|
"""triage_metadata with unexpected effort estimate should fail"""
|
|
self.payload["triage_metadata"]["effort_estimate"] = "HUGE"
|
|
with self.assertRaises(ValueError) as ctx:
|
|
validate_triage_result(self.payload)
|
|
self.assertIn("Invalid or missing 'effort_estimate'", str(ctx.exception))
|
|
|
|
def test_invalid_issue_id_format(self):
|
|
"""workable_spec with malformed issue_id format should fail"""
|
|
self.payload["workable_spec"]["issue_id"] = "123_invalid"
|
|
with self.assertRaises(ValueError) as ctx:
|
|
validate_triage_result(self.payload)
|
|
self.assertIn("issue_id", str(ctx.exception))
|
|
|
|
def test_summary_not_object(self):
|
|
"""workable_spec with summary as string instead of object should fail"""
|
|
self.payload["workable_spec"]["summary"] = "Raw string summary"
|
|
with self.assertRaises(ValueError) as ctx:
|
|
validate_triage_result(self.payload)
|
|
self.assertIn("summary", str(ctx.exception))
|
|
|
|
def test_summary_missing_keys(self):
|
|
"""workable_spec summary missing required keys should fail"""
|
|
for missing_key in ["problem", "root_cause", "context"]:
|
|
with self.subTest(missing_key=missing_key):
|
|
payload = copy.deepcopy(self.payload)
|
|
del payload["workable_spec"]["summary"][missing_key]
|
|
with self.assertRaises(ValueError) as ctx:
|
|
validate_triage_result(payload)
|
|
self.assertIn(missing_key, str(ctx.exception))
|
|
|
|
def test_implementation_plan_missing_keys(self):
|
|
"""workable_spec implementation_plan missing required keys or invalid types should fail"""
|
|
for missing_key in ["files_to_modify", "steps"]:
|
|
with self.subTest(missing_key=missing_key):
|
|
payload = copy.deepcopy(self.payload)
|
|
del payload["workable_spec"]["implementation_plan"][missing_key]
|
|
with self.assertRaises(ValueError) as ctx:
|
|
validate_triage_result(payload)
|
|
self.assertIn(missing_key, str(ctx.exception))
|
|
|
|
def test_testing_strategy_missing_keys(self):
|
|
"""workable_spec testing_strategy missing required keys should fail"""
|
|
for missing_key in ["test_file", "expected_behavior", "verification_steps", "framework"]:
|
|
with self.subTest(missing_key=missing_key):
|
|
payload = copy.deepcopy(self.payload)
|
|
del payload["workable_spec"]["testing_strategy"][missing_key]
|
|
with self.assertRaises(ValueError) as ctx:
|
|
validate_triage_result(payload)
|
|
self.assertIn(missing_key, str(ctx.exception))
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|