afterhours-shift-manager/tests/slack_bot/conftest.py
Adam Moussa 9544dd696a
fix(slack-bot): return 400 on malformed request bodies (#254)
Bolt parse_body raises JSONDecodeError for empty or non-JSON form
payload fields, which turned probe POSTs into unhandled Lambda 500s.

Fixes AFTERHOURS-SHIFT-MANAGER-2
2026-09-16 16:37:54 +00:00

82 lines
2.2 KiB
Python

"""Load src/slack-bot/app.py under a unique module name so it doesn't collide
with the other Lambdas' app.py modules in sys.modules, plus common test doubles."""
import importlib.util
import pathlib
import sys
from unittest.mock import MagicMock
import pytest
_ROOT = pathlib.Path(__file__).resolve().parents[2]
def _load(name, relpath):
spec = importlib.util.spec_from_file_location(name, _ROOT / relpath)
mod = importlib.util.module_from_spec(spec)
sys.modules[name] = mod
spec.loader.exec_module(mod)
return mod
@pytest.fixture
def slackbot_app():
return _load("slackbot_app", "src/slack-bot/app.py")
@pytest.fixture
def slackbot_handler(monkeypatch):
"""Load handler.py; skip Slack auth.test so request parsing is the unit."""
from slack_bolt import App
from slack_bolt.adapter.aws_lambda import SlackRequestHandler
slack_bot_dir = str(_ROOT / "src/slack-bot")
monkeypatch.syspath_prepend(slack_bot_dir)
saved = {name: sys.modules.get(name) for name in ("app", "handler")}
for name in saved:
sys.modules.pop(name, None)
mod = _load("slackbot_handler", "src/slack-bot/handler.py")
bolt_app = App(
token="xoxb-test",
signing_secret="test-secret",
process_before_response=True,
token_verification_enabled=False,
)
wrapped = SlackRequestHandler(app=bolt_app)
monkeypatch.setattr(mod, "_get_handler", lambda: wrapped)
yield mod
mod._slack_handler = None
for name, previous in saved.items():
if previous is None:
sys.modules.pop(name, None)
else:
sys.modules[name] = previous
@pytest.fixture
def respond():
return MagicMock(name="respond")
@pytest.fixture
def client():
return MagicMock(name="client")
@pytest.fixture
def routing_spy(slackbot_app, monkeypatch):
"""Replace the 3CX routing call with a spy so tests can assert on it
without touching the network."""
spy = MagicMock(name="_update_3cx_routing")
monkeypatch.setattr(slackbot_app, "_update_3cx_routing", spy)
return spy
@pytest.fixture
def text_of():
"""Helper: pull the `text=` kwarg from a mock's most recent call."""
def _get(mock):
return mock.call_args.kwargs.get("text", "")
return _get