/ cli / tests / test_output.py
test_output.py
  1  # Copyright 2026 Alibaba Group Holding Ltd.
  2  #
  3  # Licensed under the Apache License, Version 2.0 (the "License");
  4  # you may not use this file except in compliance with the License.
  5  # You may obtain a copy of the License at
  6  #
  7  #     http://www.apache.org/licenses/LICENSE-2.0
  8  #
  9  # Unless required by applicable law or agreed to in writing, software
 10  # distributed under the License is distributed on an "AS IS" BASIS,
 11  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  # See the License for the specific language governing permissions and
 13  # limitations under the License.
 14  
 15  """Tests for opensandbox_cli.output — table, JSON, YAML rendering."""
 16  
 17  from __future__ import annotations
 18  
 19  import json
 20  
 21  import pytest
 22  from pydantic import BaseModel
 23  
 24  from opensandbox_cli.output import OutputFormatter
 25  
 26  # ---------------------------------------------------------------------------
 27  # Test models
 28  # ---------------------------------------------------------------------------
 29  
 30  
 31  class FakeItem(BaseModel):
 32      id: str
 33      name: str
 34      score: int
 35  
 36  
 37  # ---------------------------------------------------------------------------
 38  # JSON output
 39  # ---------------------------------------------------------------------------
 40  
 41  
 42  class TestJsonOutput:
 43      def test_print_dict(self, capsys: pytest.CaptureFixture[str]) -> None:
 44          fmt = OutputFormatter("json", color=False)
 45          fmt.print_dict({"key": "value", "num": 42})
 46          captured = capsys.readouterr()
 47          data = json.loads(captured.out)
 48          assert data == {"key": "value", "num": 42}
 49  
 50      def test_print_model(self, capsys: pytest.CaptureFixture[str]) -> None:
 51          fmt = OutputFormatter("json", color=False)
 52          item = FakeItem(id="abc", name="test", score=100)
 53          fmt.print_model(item)
 54          captured = capsys.readouterr()
 55          data = json.loads(captured.out)
 56          assert data["id"] == "abc"
 57          assert data["name"] == "test"
 58          assert data["score"] == 100
 59  
 60      def test_print_models(self, capsys: pytest.CaptureFixture[str]) -> None:
 61          fmt = OutputFormatter("json", color=False)
 62          items = [
 63              FakeItem(id="1", name="a", score=10),
 64              FakeItem(id="2", name="b", score=20),
 65          ]
 66          fmt.print_models(items, columns=["id", "name", "score"])
 67          captured = capsys.readouterr()
 68          data = json.loads(captured.out)
 69          assert len(data) == 2
 70          assert data[0]["id"] == "1"
 71          assert data[1]["name"] == "b"
 72  
 73      def test_success_renders_structured_json(self, capsys: pytest.CaptureFixture[str]) -> None:
 74          fmt = OutputFormatter("json", color=False)
 75          fmt.success("done")
 76          captured = capsys.readouterr()
 77          data = json.loads(captured.out)
 78          assert data == {"status": "ok", "message": "done"}
 79  
 80  
 81  # ---------------------------------------------------------------------------
 82  # YAML output
 83  # ---------------------------------------------------------------------------
 84  
 85  
 86  class TestYamlOutput:
 87      def test_print_dict(self, capsys: pytest.CaptureFixture[str]) -> None:
 88          fmt = OutputFormatter("yaml", color=False)
 89          fmt.print_dict({"key": "value"})
 90          captured = capsys.readouterr()
 91          assert "key: value" in captured.out
 92  
 93      def test_print_model(self, capsys: pytest.CaptureFixture[str]) -> None:
 94          fmt = OutputFormatter("yaml", color=False)
 95          item = FakeItem(id="x", name="y", score=5)
 96          fmt.print_model(item)
 97          captured = capsys.readouterr()
 98          assert "id: x" in captured.out
 99          assert "name: y" in captured.out
100          assert "score: 5" in captured.out
101  
102  
103  # ---------------------------------------------------------------------------
104  # Table output
105  # ---------------------------------------------------------------------------
106  
107  
108  class TestTableOutput:
109      def test_print_dict_contains_values(self, capsys: pytest.CaptureFixture[str]) -> None:
110          fmt = OutputFormatter("table", color=False)
111          fmt.print_dict({"host": "example.com", "port": 8080}, title="Config")
112          captured = capsys.readouterr()
113          assert "example.com" in captured.out
114          assert "8080" in captured.out
115          assert "Config" in captured.out
116  
117      def test_print_dict_none_renders_dash(self, capsys: pytest.CaptureFixture[str]) -> None:
118          fmt = OutputFormatter("table", color=False)
119          fmt.print_dict({"key": None})
120          captured = capsys.readouterr()
121          assert "-" in captured.out
122  
123      def test_print_models_shows_headers(self, capsys: pytest.CaptureFixture[str]) -> None:
124          fmt = OutputFormatter("table", color=False)
125          items = [FakeItem(id="1", name="a", score=10)]
126          fmt.print_models(items, columns=["id", "name", "score"], title="Items")
127          captured = capsys.readouterr()
128          assert "ID" in captured.out
129          assert "NAME" in captured.out
130          assert "SCORE" in captured.out
131  
132      def test_print_text_ignores_format(self, capsys: pytest.CaptureFixture[str]) -> None:
133          fmt = OutputFormatter("json", color=False)
134          fmt.print_text("hello world")
135          captured = capsys.readouterr()
136          assert captured.out.strip() == "hello world"