diff --git a/tests/test_api_surface.py b/tests/test_api_surface.py new file mode 100644 index 0000000..6575e14 --- /dev/null +++ b/tests/test_api_surface.py @@ -0,0 +1,73 @@ +"""Przypina powierzchnię API - panel jest osobnym klientem, więc kontrakt musi być stabilny.""" + +from __future__ import annotations + +import tempfile +import unittest + +from zyrarbot.application import Application +from zyrarbot.settings import Settings + +EXPECTED_ENDPOINTS = { + ("get", "/api/status"), + ("post", "/api/play"), + ("post", "/api/play_file"), + ("post", "/api/pause"), + ("post", "/api/resume"), + ("post", "/api/skip"), + ("post", "/api/stop"), + ("post", "/api/volume"), + ("post", "/api/loop"), + ("post", "/api/loop_playlist"), + ("post", "/api/loop_cycle"), + ("post", "/api/jump"), + ("post", "/api/remove"), + ("post", "/api/reorder"), + ("post", "/api/queue/plays"), + ("get", "/api/uploads"), + ("post", "/api/upload"), + ("delete", "/api/uploads/{filename}"), + ("post", "/api/connect"), + ("post", "/api/disconnect"), + ("post", "/api/settings/text_channel"), + ("post", "/api/settings/default_plays"), +} + + +class ApiSurfaceTest(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + cls._workdir = tempfile.TemporaryDirectory() + settings = Settings( + discord_token="test", + config_dir=f"{cls._workdir.name}/config", + uploads_dir=f"{cls._workdir.name}/uploads", + static_dir=f"{cls._workdir.name}/static", + ) + cls.spec = Application(settings).api.openapi() + + @classmethod + def tearDownClass(cls) -> None: + cls._workdir.cleanup() + + def _declared(self) -> set[tuple[str, str]]: + return { + (method, path) + for path, operations in self.spec["paths"].items() + for method in operations + } + + def test_all_expected_endpoints_are_declared(self): + self.assertEqual(set(), EXPECTED_ENDPOINTS - self._declared()) + + def test_no_endpoint_added_without_updating_this_test(self): + # Panel jest odrębnym klientem - nowa trasa powinna trafić tu świadomie. + self.assertEqual(set(), self._declared() - EXPECTED_ENDPOINTS) + + def test_openapi_document_is_well_formed(self): + self.assertTrue(self.spec["openapi"].startswith("3.")) + self.assertIn("ŻyrarBOT", self.spec["info"]["title"]) + + +if __name__ == "__main__": + unittest.main()