82 lines
4.0 KiB
Python
82 lines
4.0 KiB
Python
import io
|
|
import json
|
|
import os
|
|
import tempfile
|
|
import unittest
|
|
from contextlib import redirect_stdout
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
from production_analytics.cli.__main__ import main
|
|
from production_analytics.enlyze.exploration import ExplorationResponse
|
|
|
|
|
|
class CliTests(unittest.TestCase):
|
|
@patch.dict(os.environ, {"ENLYZE_BASE_URL": "https://enlyze.example"}, clear=True)
|
|
@patch("production_analytics.cli.__main__.ExplorationClient.get")
|
|
def test_raw_prints_and_saves_sanitized_response(self, get_mock: object) -> None:
|
|
get_mock.return_value = ExplorationResponse( # type: ignore[attr-defined]
|
|
status_code=200,
|
|
path="/verified/path",
|
|
headers={"Content-Type": "application/json"},
|
|
body={"api_token": "secret", "authorization": "Bearer secret", "value": 4.2},
|
|
)
|
|
with tempfile.TemporaryDirectory() as temporary_directory:
|
|
output = io.StringIO()
|
|
with redirect_stdout(output):
|
|
result = main(
|
|
[
|
|
"enlyze",
|
|
"raw",
|
|
"/verified/path",
|
|
"--save-fixture",
|
|
"example.json",
|
|
"--fixture-dir",
|
|
temporary_directory,
|
|
"--save-raw",
|
|
"raw-example.json",
|
|
"--raw-dir",
|
|
temporary_directory,
|
|
]
|
|
)
|
|
fixture = json.loads((Path(temporary_directory) / "example.json").read_text())
|
|
raw_capture = json.loads((Path(temporary_directory) / "raw-example.json").read_text())
|
|
|
|
self.assertEqual(result, 0)
|
|
self.assertEqual(fixture["response"]["body"]["api_token"], "<redacted-secret>")
|
|
self.assertEqual(fixture["response"]["body"]["authorization"], "<redacted-secret>")
|
|
self.assertNotIn("Bearer secret", output.getvalue())
|
|
self.assertEqual(raw_capture["response"]["body"]["api_token"], "secret")
|
|
|
|
def test_raw_rejects_unsafe_fixture_name(self) -> None:
|
|
with patch.dict(os.environ, {"ENLYZE_BASE_URL": "https://enlyze.example"}, clear=True):
|
|
with patch("production_analytics.cli.__main__.ExplorationClient.get") as get_mock:
|
|
get_mock.return_value = ExplorationResponse(200, "/path", {}, {})
|
|
output = io.StringIO()
|
|
with redirect_stdout(output):
|
|
result = main(["enlyze", "raw", "/path", "--save-fixture", "../unsafe.json"])
|
|
|
|
self.assertEqual(result, 1)
|
|
self.assertIn("plain filename", output.getvalue())
|
|
|
|
@patch.dict(os.environ, {"ENLYZE_BASE_URL": "https://enlyze.example"}, clear=True)
|
|
@patch("production_analytics.cli.__main__.ExplorationClient.post_json")
|
|
def test_timeseries_builds_schema_supported_read_only_post(self, post_mock: object) -> None:
|
|
post_mock.return_value = ExplorationResponse( # type: ignore[attr-defined]
|
|
200, "/v2/timeseries", {}, {"metadata": {"next_cursor": None}, "data": {"columns": [], "records": []}}
|
|
)
|
|
with tempfile.TemporaryDirectory() as temporary_directory:
|
|
result = main(
|
|
[
|
|
"enlyze", "timeseries", "--machine", "machine-id", "--start", "2026-01-01T00:00:00+00:00",
|
|
"--end", "2026-01-01T00:10:00+00:00", "--variable", "variable-id", "--resampling-interval", "10",
|
|
"--resampling-method", "avg", "--save-fixture", "timeseries.json", "--fixture-dir", temporary_directory,
|
|
]
|
|
)
|
|
fixture = json.loads((Path(temporary_directory) / "timeseries.json").read_text())
|
|
|
|
self.assertEqual(result, 0)
|
|
self.assertEqual(post_mock.call_args.args[0], "/v2/timeseries") # type: ignore[attr-defined]
|
|
self.assertEqual(post_mock.call_args.args[1]["resampling_interval"], 10) # type: ignore[attr-defined]
|
|
self.assertEqual(fixture["request"]["method"], "POST")
|