afterhours-shift-manager/tests/slack_bot/test_app_home.py
Adam Moussa 26adb8e6c0
feat(api): collapse Slack, portal, and jobs onto Fargate (PLAT-216) (#259)
* feat(api): collapse Slack, portal, and jobs onto Fargate (PLAT-216)

Move HTTP and scheduled work onto one always-on Flask task so after-hours
loses Lambda cold start without changing the Cognito or roster contracts.

* fix(portal-api): keep CORS headers on unexpected 500s

Portal SPA error handling needs Access-Control-Allow-Origin even when
DynamoDB or other internals fail, otherwise the browser hides the 500.

* fix(api): retarget holidays per account and ship App Home changelog (PLAT-216)

* fix(iam): list ECS tasks and fail closed on non-prod Paychex (PLAT-216)

* fix(portal-api): serve portal JSON with an explicit JSON content type
2026-09-21 19:13:30 +00:00

90 lines
3.3 KiB
Python

"""Tests for the App Home tab (about page + What's New)."""
from freezegun import freeze_time
from shared.blocks import build_home_view
def _headers(view):
return [b["text"]["text"] for b in view["blocks"] if b["type"] == "header"]
class TestBuildHomeView:
def test_includes_about_and_commands(self):
view = build_home_view()
assert view["type"] == "home"
assert "After-Hours Shift Manager" in _headers(view)
assert "/oncall" in str(view["blocks"])
def test_omits_whats_new_without_version(self):
view = build_home_view()
assert all("What's New" not in h for h in _headers(view))
def test_includes_whats_new_with_version(self):
view = build_home_view(
"1.10.0", "**Self-announcing** releases.", "June 11, 2026"
)
assert "What's New in v1.10.0" in _headers(view)
# Notes are converted from Markdown to Slack mrkdwn.
assert "*Self-announcing*" in str(view["blocks"])
assert any(b.get("type") == "context" for b in view["blocks"])
def test_publish_home_publishes_latest_entry(slackbot_app, client):
text = "## v1.10.0 — June 11, 2026\n\n**New stuff.**\n\n## v1.9.2 — June 1, 2026\n\nOld.\n"
slackbot_app.publish_home(client, "U_ALICE", text)
client.views_publish.assert_called_once()
kwargs = client.views_publish.call_args.kwargs
assert kwargs["user_id"] == "U_ALICE"
assert kwargs["view"]["type"] == "home"
assert "What's New in v1.10.0" in str(kwargs["view"])
assert "v1.9.2" not in str(kwargs["view"]) # only the newest entry
def test_changelog_paths_include_package_copy(slackbot_app):
paths = slackbot_app._changelog_paths()
assert any(p.endswith("src/slack-bot/CHANGELOG.md") for p in paths)
def test_changelog_text_reads_package_copy(slackbot_app):
slackbot_app._changelog_text.cache_clear()
text = slackbot_app._changelog_text()
assert text
assert "## " in text
def test_publish_home_degrades_without_changelog(slackbot_app, client):
slackbot_app.publish_home(client, "U_BOB", "")
view = client.views_publish.call_args.kwargs["view"]
assert all("What's New" not in str(b) for b in view["blocks"])
def test_publish_home_includes_admin_section_for_admin(
slackbot_app, schedule, seed, client
):
seed.config(admin_users=["U_ADMIN"])
seed.override("2026-12-25", "114", "Alice")
seed.holiday("2026-12-25", slots=2, label="Christmas")
with freeze_time("2026-06-01"):
slackbot_app.publish_home(client, "U_ADMIN", "", schedule)
view = client.views_publish.call_args.kwargs["view"]
assert "Admin" in _headers(view)
assert "admin_open_override_modal" in str(view["blocks"])
assert "Christmas" in str(view["blocks"])
def test_publish_home_omits_admin_section_for_non_admin(
slackbot_app, schedule, seed, client
):
seed.config(admin_users=["U_ADMIN"])
slackbot_app.publish_home(client, "U_BOB", "", schedule)
view = client.views_publish.call_args.kwargs["view"]
assert "Admin" not in _headers(view)
assert "admin_open_override_modal" not in str(view["blocks"])
def test_publish_home_without_schedule_has_no_admin_section(slackbot_app, client):
slackbot_app.publish_home(client, "U_ADMIN", "")
view = client.views_publish.call_args.kwargs["view"]
assert "Admin" not in _headers(view)