test_platform_config.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import os
  2. import sys
  3. PLUGIN_ROOT = os.path.abspath(os.path.dirname(__file__))
  4. sys.path.insert(0, PLUGIN_ROOT)
  5. sys.path.insert(0, os.environ.get("HERMES_ROOT", "/opt/hermes"))
  6. from platform_config import (
  7. ChattoConfiguration,
  8. _get_env_or_extra_int,
  9. _get_env_or_extra_list,
  10. _get_env_or_extra_str,
  11. _get_env_or_extra_str_opt,
  12. _get_env_or_extra_truthy,
  13. _split_str_to_list,
  14. )
  15. class TestPlatformConfigHelpers:
  16. """Test Chatto configuration helper functions."""
  17. def test_get_env_or_extra_str_prefers_env(self, monkeypatch):
  18. monkeypatch.setenv("CHATTO_TEST", " env-value ")
  19. assert _get_env_or_extra_str("CHATTO_TEST", "extra-value") == "env-value"
  20. def test_get_env_or_extra_str_uses_extra_when_no_env(self, monkeypatch):
  21. monkeypatch.delenv("CHATTO_TEST", raising=False)
  22. assert _get_env_or_extra_str("CHATTO_TEST", " extra-value ") == "extra-value"
  23. def test_get_env_or_extra_str_returns_empty_when_missing(self, monkeypatch):
  24. """The non-optional helper coerces a missing value to "" — use
  25. _get_env_or_extra_str_opt() when None has to stay distinguishable."""
  26. monkeypatch.delenv("CHATTO_TEST", raising=False)
  27. assert _get_env_or_extra_str("CHATTO_TEST", None) == ""
  28. def test_get_env_or_extra_str_opt_returns_none_when_missing(self, monkeypatch):
  29. monkeypatch.delenv("CHATTO_TEST", raising=False)
  30. assert _get_env_or_extra_str_opt("CHATTO_TEST", None) is None
  31. def test_get_env_or_extra_str_opt_prefers_env(self, monkeypatch):
  32. monkeypatch.setenv("CHATTO_TEST", " env-value ")
  33. assert _get_env_or_extra_str_opt("CHATTO_TEST", "extra-value") == "env-value"
  34. def test_get_env_or_extra_truthy_parses_truthy_values(self, monkeypatch):
  35. monkeypatch.setenv("CHATTO_TEST", " yes ")
  36. assert _get_env_or_extra_truthy("CHATTO_TEST", None) is True
  37. def test_get_env_or_extra_truthy_uses_extra_when_no_env(self, monkeypatch):
  38. monkeypatch.delenv("CHATTO_TEST", raising=False)
  39. assert _get_env_or_extra_truthy("CHATTO_TEST", " true ") is True
  40. def test_get_env_or_extra_truthy_uses_default_false(self, monkeypatch):
  41. monkeypatch.delenv("CHATTO_TEST", raising=False)
  42. assert _get_env_or_extra_truthy("CHATTO_TEST", "false") is False
  43. def test_get_env_or_extra_truthy_default_true_when_none_and_no_extra(
  44. self, monkeypatch
  45. ):
  46. monkeypatch.delenv("CHATTO_TEST", raising=False)
  47. assert _get_env_or_extra_truthy("CHATTO_TEST", None, default=True) is True
  48. def test_get_env_or_extra_truthy_default_false_when_none_and_no_extra(
  49. self, monkeypatch
  50. ):
  51. monkeypatch.delenv("CHATTO_TEST", raising=False)
  52. assert _get_env_or_extra_truthy("CHATTO_TEST", None, default=False) is False
  53. def test_get_env_or_extra_truthy_explicit_bool_true(self, monkeypatch):
  54. monkeypatch.delenv("CHATTO_TEST", raising=False)
  55. assert _get_env_or_extra_truthy("CHATTO_TEST", True, default=False) is True
  56. def test_get_env_or_extra_truthy_explicit_bool_false(self, monkeypatch):
  57. monkeypatch.delenv("CHATTO_TEST", raising=False)
  58. assert _get_env_or_extra_truthy("CHATTO_TEST", False, default=True) is False
  59. def test_split_str_to_list_handles_comma_separated_values(self):
  60. assert _split_str_to_list("a,b, c ,d") == ["a", "b", "c", "d"]
  61. def test_get_env_or_extra_list_prefers_env(self, monkeypatch):
  62. monkeypatch.setenv("CHATTO_TEST", " one,two , three")
  63. assert _get_env_or_extra_list("CHATTO_TEST", ["ignored", "list"]) == [
  64. "one",
  65. "two",
  66. "three",
  67. ]
  68. def test_get_env_or_extra_list_uses_extra_list(self, monkeypatch):
  69. monkeypatch.delenv("CHATTO_TEST", raising=False)
  70. assert _get_env_or_extra_list("CHATTO_TEST", ["a", " b "]) == ["a", "b"]
  71. def test_get_env_or_extra_list_uses_extra_string(self, monkeypatch):
  72. monkeypatch.delenv("CHATTO_TEST", raising=False)
  73. assert _get_env_or_extra_list("CHATTO_TEST", "x,y") == ["x", "y"]
  74. def test_get_env_or_extra_list_returns_empty_for_none(self, monkeypatch):
  75. monkeypatch.delenv("CHATTO_TEST", raising=False)
  76. assert _get_env_or_extra_list("CHATTO_TEST", None) == []
  77. def test_get_env_or_extra_int_prefers_env(self, monkeypatch):
  78. monkeypatch.setenv("CHATTO_TEST", " 45 ")
  79. assert _get_env_or_extra_int("CHATTO_TEST", 300, default=300) == 45
  80. def test_get_env_or_extra_int_uses_extra_when_no_env(self, monkeypatch):
  81. monkeypatch.delenv("CHATTO_TEST", raising=False)
  82. assert _get_env_or_extra_int("CHATTO_TEST", 60, default=300) == 60
  83. def test_get_env_or_extra_int_parses_extra_string(self, monkeypatch):
  84. """config.yaml values arrive as strings when set via env-style files."""
  85. monkeypatch.delenv("CHATTO_TEST", raising=False)
  86. assert _get_env_or_extra_int("CHATTO_TEST", "90", default=300) == 90
  87. def test_get_env_or_extra_int_falls_back_to_default_for_junk(self, monkeypatch):
  88. monkeypatch.setenv("CHATTO_TEST", "soon-ish")
  89. assert _get_env_or_extra_int("CHATTO_TEST", None, default=300) == 300
  90. def test_get_env_or_extra_int_treats_yaml_bool_as_missing(self, monkeypatch):
  91. """A YAML true/false is not a number — silently take the default."""
  92. monkeypatch.delenv("CHATTO_TEST", raising=False)
  93. assert _get_env_or_extra_int("CHATTO_TEST", True, default=300) == 300
  94. def test_get_env_or_extra_int_defaults_when_both_missing(self, monkeypatch):
  95. monkeypatch.delenv("CHATTO_TEST", raising=False)
  96. assert _get_env_or_extra_int("CHATTO_TEST", None, default=300) == 300
  97. class TestMentionRoomFields:
  98. """The mention lists derive env names from their config keys and resolve
  99. to empty lists when nothing is set — channels are opt-in."""
  100. def test_env_names_derive_from_the_config_keys(self):
  101. assert (
  102. ChattoConfiguration.require_mention_rooms.env_name
  103. == "CHATTO_REQUIRE_MENTION_ROOMS"
  104. )
  105. assert (
  106. ChattoConfiguration.optional_mention_rooms.env_name
  107. == "CHATTO_OPTIONAL_MENTION_ROOMS"
  108. )
  109. def test_lists_default_to_empty_without_any_configuration(self, monkeypatch):
  110. for var in (
  111. "CHATTO_REQUIRE_MENTION_ROOMS",
  112. "CHATTO_OPTIONAL_MENTION_ROOMS",
  113. ):
  114. monkeypatch.delenv(var, raising=False)
  115. cfg = ChattoConfiguration(
  116. pconfig=PlatformConfigStub(extra={"base_url": "https://chat.test"})
  117. )
  118. assert cfg.require_mention_rooms.value == []
  119. assert cfg.optional_mention_rooms.value == []
  120. def test_lists_resolve_from_env_comma_separated(self, monkeypatch):
  121. monkeypatch.setenv("CHATTO_REQUIRE_MENTION_ROOMS", " room-1 , room-2 ")
  122. cfg = ChattoConfiguration(
  123. pconfig=PlatformConfigStub(extra={"base_url": "https://chat.test"})
  124. )
  125. assert cfg.require_mention_rooms.value == ["room-1", "room-2"]
  126. class PlatformConfigStub:
  127. """Just the attribute ChattoConfiguration reads off a PlatformConfig."""
  128. def __init__(self, extra):
  129. self.extra = extra