Spaces:
Build error
Build error
| """Tests for the sentence composer fallback path (no API keys configured).""" | |
| from __future__ import annotations | |
| import pytest | |
| from signbridge.composer.sentence import _naive_join, _strip_quotes, compose_sentence | |
| class TestNaiveJoin: | |
| def test_empty(self) -> None: | |
| assert _naive_join([]) == "" | |
| def test_single_lowercase_gloss(self) -> None: | |
| assert _naive_join(["hello"]) == "Hello." | |
| def test_single_letter(self) -> None: | |
| assert _naive_join(["A"]) == "A." | |
| def test_fingerspelled_word(self) -> None: | |
| assert _naive_join(["L", "U", "C", "A", "S"]) == "Lucas." | |
| def test_fingerspelled_then_gloss(self) -> None: | |
| # "L U C A S" + "hello" → "Lucas hello." | |
| assert _naive_join(["L", "U", "C", "A", "S", "hello"]) == "Lucas hello." | |
| def test_gloss_with_underscore(self) -> None: | |
| # thank_you should render as "thank you" | |
| assert "thank you" in _naive_join(["thank_you"]).lower() | |
| def test_existing_punctuation_not_doubled(self) -> None: | |
| # Naive join always appends '.', but never twice. | |
| out = _naive_join(["hello"]) | |
| assert out.count(".") == 1 | |
| class TestStripQuotes: | |
| def test_no_quotes(self) -> None: | |
| assert _strip_quotes("hello") == "hello" | |
| def test_double_quotes(self) -> None: | |
| assert _strip_quotes('"hello"') == "hello" | |
| def test_single_quotes(self) -> None: | |
| assert _strip_quotes("'hello'") == "hello" | |
| def test_internal_quotes_preserved(self) -> None: | |
| assert _strip_quotes('"he said \'hi\'"') == "he said 'hi'" | |
| class TestComposeSentenceFallback: | |
| """Without API keys, compose should fall back to _naive_join.""" | |
| def test_empty(self) -> None: | |
| assert compose_sentence([]) == "" | |
| def test_falls_back_to_naive(self) -> None: | |
| # No AMD/OpenAI keys → falls back to _naive_join | |
| result = compose_sentence(["H", "I"]) | |
| assert result == "Hi." | |
| def test_falls_back_for_glosses(self) -> None: | |
| result = compose_sentence(["hello", "name", "L", "U", "C", "A", "S"]) | |
| assert "Lucas" in result | |
| assert "hello" in result.lower() | |
| assert "name" in result.lower() | |
| class TestComposeSentenceWithMockProvider: | |
| """When an API key is set we ATTEMPT to call the provider, but on failure | |
| we still fall back. We simulate a working provider by monkeypatching the | |
| OpenAI client.""" | |
| def test_provider_returns_clean_sentence(self, monkeypatch: pytest.MonkeyPatch) -> None: | |
| monkeypatch.setenv("SIGNBRIDGE_PROVIDER", "openai") | |
| monkeypatch.setenv("OPENAI_API_KEY", "test-key") | |
| # Stub OpenAI client at the module level | |
| from signbridge.composer import sentence as sentence_mod | |
| class _FakeChoice: | |
| def __init__(self, content: str) -> None: | |
| self.message = type("M", (), {"content": content})() | |
| class _FakeResp: | |
| def __init__(self, content: str) -> None: | |
| self.choices = [_FakeChoice(content)] | |
| class _FakeChat: | |
| def __init__(self, content: str) -> None: | |
| self._content = content | |
| self.completions = self | |
| def create(self, **_: object) -> _FakeResp: | |
| return _FakeResp(self._content) | |
| class _FakeClient: | |
| def __init__(self, content: str) -> None: | |
| self.chat = _FakeChat(content) | |
| monkeypatch.setattr( | |
| sentence_mod, | |
| "_resolve_client", | |
| lambda: (_FakeClient("My name is Lucas."), "test-model"), | |
| ) | |
| out = compose_sentence(["name", "L", "U", "C", "A", "S"]) | |
| assert out == "My name is Lucas." | |
| def test_provider_failure_falls_back(self, monkeypatch: pytest.MonkeyPatch) -> None: | |
| from signbridge.composer import sentence as sentence_mod | |
| class _FailingClient: | |
| class _FailingChat: | |
| completions = type( | |
| "_C", | |
| (), | |
| {"create": staticmethod(lambda **_: (_ for _ in ()).throw(RuntimeError("boom")))}, | |
| )() | |
| chat = _FailingChat() | |
| monkeypatch.setattr( | |
| sentence_mod, "_resolve_client", lambda: (_FailingClient(), "test") | |
| ) | |
| out = compose_sentence(["hello"]) | |
| assert out == "Hello." # fell back to naive | |