mirror of
https://github.com/Sea-Haven-Industries/afterhours-shift-manager.git
synced 2026-09-30 21:53:11 +00:00
* 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
90 lines
3.3 KiB
Python
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)
|