programme-pulse-chat/tests/test_prompts.py
DJP b70d148b94 Productionise Programme Pulse
Backend
- Routes moved under /api/, JWT bearer auth via @before_request
- DEV_AUTH_BYPASS escape hatch for local dev
- In-memory chat history and report state replaced with Postgres tables
  (preferences, chat_messages, reports, feedback_events) keyed on user
- SQLAlchemy 2.x + Alembic migrations run on container start
- Graceful Airtable failure handling — bad creds no longer 500 the API
- Per-user data isolation via g.user_email from validated token

Frontend
- React + Vite + TypeScript SPA at /programme-pulse/
- MSAL.js (PKCE, sessionStorage, ID token to backend)
- VITE_DEV_AUTH_BYPASS mirrors backend bypass for local dev
- Streaming chat via fetch ReadableStream + SSE parsing
- Charts via chart.js, markdown via react-markdown + remark-gfm
- Full UI parity with the original templates/index.html

Deploy (optical-dev split-build pattern)
- Dockerfile + docker-compose.yml (name: programme-pulse pinned;
  app + Postgres; 127.0.0.1 binding only)
- deploy/apache-programme-pulse.conf.tmpl with flushpackets=on for SSE
- deploy/deploy.sh mirrors OSOP — port auto-pick (5051..5099),
  apache conf render, frontend build in throwaway node container,
  rsync to /var/www/html/programme-pulse, /api/health poll

Tests
- 49 passing; new tests for DB-backed preferences and JWT auth helpers
- SQLite-backed test fixture in tests/conftest.py

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 11:08:28 -04:00

52 lines
1.8 KiB
Python

import json
from src.prompts import build_chat_system_prompt, build_manager_summary_prompt, build_full_report_prompt
SAMPLE_TASKS = [
{
"id": "rec1", "task": "Build reporting tool", "progress": "In Progress",
"priority": "P1", "rag": "Red", "owner": "Tony Coppola", "owners": ["Tony Coppola"],
"related_item": "Reporting", "category": ["Airtable"], "start_date": "",
"end_date": "2026-04-30", "deadline": "2026-04-25", "doing": "",
"blocked_by": "", "blocking": "", "notes": "On track", "hours": None,
}
]
SAMPLE_ANALYSIS = {
"total": 1, "active_total": 1,
"progress_counts": {"In Progress": 1},
"priority_counts": {"P1": 1},
"red_flags": [],
"p1_watchlist": [SAMPLE_TASKS[0]],
"by_owner": {"Tony Coppola": [SAMPLE_TASKS[0]]},
"overdue": [],
}
def test_build_chat_system_prompt_includes_task_data():
prompt = build_chat_system_prompt(SAMPLE_TASKS)
assert "Build reporting tool" in prompt
assert "Tony Coppola" in prompt
def test_build_chat_system_prompt_includes_instructions():
prompt = build_chat_system_prompt(SAMPLE_TASKS)
assert "shorthand" in prompt.lower() or "plain language" in prompt.lower()
def test_build_manager_summary_prompt_includes_p1_watchlist():
prompt = build_manager_summary_prompt(SAMPLE_ANALYSIS)
assert "P1" in prompt or "Watch List" in prompt
def test_build_manager_summary_prompt_has_required_sections():
prompt = build_manager_summary_prompt(SAMPLE_ANALYSIS)
assert "Programme Overview" in prompt
assert "Blockers" in prompt
def test_build_full_report_prompt_has_required_sections():
prompt = build_full_report_prompt(SAMPLE_ANALYSIS)
assert "Executive Summary" in prompt
assert "Team Breakdown" in prompt
assert "Red Flags" in prompt
assert "Overdue" in prompt