new-site/scripts/tests/e2e_standard_delays.py
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers,
document generators, FCC compliance tools, Canada CRTC formation,
Ansible infrastructure, and deployment scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 06:54:22 -05:00

336 lines
15 KiB
Python

"""
E2E test: Standard-vs-Expedited 3-business-day delay system.
Tests:
1. business_days_from_now helper (skip weekends + holidays)
2. CRTC handler _maybe_defer_for_standard:
- Expedited orders bypass the delay
- Standard orders get defer_until set 3 business days out
- On second call after delay expires, the defer is cleared and pipeline resumes
- On second call before delay expires, returns True (still deferred)
3. Formation _check_standard_delay (same matrix)
4. Idempotency: each checkpoint is independent
Usage:
python3 -m scripts.tests.e2e_standard_delays
"""
from __future__ import annotations
import logging
import os
import sys
import uuid
from datetime import datetime, timedelta, timezone
from pathlib import Path
from dotenv import load_dotenv
env_path = Path(__file__).parent / ".env.test"
if env_path.exists():
load_dotenv(env_path)
LOG = logging.getLogger("tests.delays")
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(name)s] %(levelname)s %(message)s",
stream=sys.stdout,
)
DEV_DB_URL = os.environ.get(
"DEV_DATABASE_URL",
"postgresql://pw:pw_dev_2026@207.174.124.71:5433/performancewest",
)
PASS = 0
FAIL = 0
RESULTS: list[dict] = []
def check(label: str, ok: bool, detail: str = ""):
global PASS, FAIL
if ok:
PASS += 1
LOG.info(" PASS: %s", label)
else:
FAIL += 1
LOG.info(" FAIL: %s%s", label, detail)
RESULTS.append({"label": label, "ok": ok, "detail": detail})
# ──────────────────────────────────────────────────────────────────────
# Test 1: business_days_from_now helper
# ──────────────────────────────────────────────────────────────────────
def test_business_days():
LOG.info("\n=== Test 1: business_days helper ===")
from scripts.workers.business_days import business_days_from_now, is_business_day
from datetime import datetime as dt, date
# Mon → Thu (3 biz days, no weekends)
result = business_days_from_now(3, dt(2026, 4, 13))
check("Mon Apr 13 + 3 = Thu Apr 16", result.date() == date(2026, 4, 16), str(result.date()))
# Fri → Wed (skips weekend)
result = business_days_from_now(3, dt(2026, 4, 17))
check("Fri Apr 17 + 3 = Wed Apr 22", result.date() == date(2026, 4, 22), str(result.date()))
# Crossing Memorial Day (Mon May 25)
result = business_days_from_now(3, dt(2026, 5, 22))
check("Fri May 22 + 3 skips Memorial Day = Thu May 28", result.date() == date(2026, 5, 28), str(result.date()))
# Crossing Christmas + Boxing Day
result = business_days_from_now(3, dt(2026, 12, 24))
check("Thu Dec 24 + 3 skips Christmas/Boxing = Wed Dec 30", result.date() == date(2026, 12, 30), str(result.date()))
# is_business_day basic checks
check("Sat is not business day", not is_business_day(date(2026, 4, 18)))
check("Sun is not business day", not is_business_day(date(2026, 4, 19)))
check("Mon is business day", is_business_day(date(2026, 4, 13)))
check("Christmas is not business day", not is_business_day(date(2026, 12, 25)))
# ──────────────────────────────────────────────────────────────────────
# Test 2: CRTC _maybe_defer_for_standard
# ──────────────────────────────────────────────────────────────────────
def _create_test_crtc_order(uid: str) -> str:
"""Insert a fake CRTC order row for testing."""
import psycopg2
conn = psycopg2.connect(DEV_DB_URL)
cur = conn.cursor()
order_number = f"CA-TEST-{uid.upper()}"
cur.execute(
"""INSERT INTO canada_crtc_orders (
order_number, customer_name, customer_email, company_type,
director_name, director_address, services_description, geographic_coverage,
mailbox_address, regulatory_contact_name, regulatory_contact_email,
regulatory_contact_phone, service_fee_cents, government_fee_cents,
total_cents, status, payment_status, identity_session_id,
incorporation_province
) VALUES (%s, 'Test Carrier', %s, 'numbered', 'Test Director',
'{"street": "100 Test St"}',
'test services', 'BC', 'test address', 'reg', 'reg@test.com',
'+10000000000', 389900, 25000, 414900, 'received', 'paid',
NULL, 'BC')""",
(order_number, f"delay-test+{uid}@performancewest.net"),
)
conn.commit()
conn.close()
return order_number
def _cleanup_test_crtc_order(order_number: str):
import psycopg2
conn = psycopg2.connect(DEV_DB_URL)
cur = conn.cursor()
cur.execute("DELETE FROM canada_crtc_orders WHERE order_number = %s", (order_number,))
conn.commit()
conn.close()
def _invoke_defer_helper_in_container(order_data: dict, checkpoint: str) -> bool:
"""Invoke _maybe_defer_for_standard on the dev workers container via docker exec.
Pipes Python source via stdin to avoid shell escaping issues.
Returns the helper's True/False return value.
"""
import json
import subprocess
payload_json_str = json.dumps(order_data)
checkpoint_str = json.dumps(checkpoint)
py_lines = [
"import sys, json",
"sys.path.insert(0, '/app')",
"from scripts.workers.services.canada_crtc import CanadaCRTCHandler",
"handler = CanadaCRTCHandler()",
f"order = json.loads({payload_json_str!r})",
f"checkpoint = {checkpoint_str}",
"result = handler._maybe_defer_for_standard(order, checkpoint)",
"print('DEFER_RESULT:', result)",
]
py_code = "\n".join(py_lines) + "\n"
cmd = (
"ssh -p 22022 deploy@207.174.124.71 "
"'docker exec -i performancewest-dev-workers-1 python3 -'"
)
result = subprocess.run(
cmd, shell=True, input=py_code,
capture_output=True, text=True, timeout=30,
)
output = result.stdout + result.stderr
for line in output.splitlines():
if line.startswith("DEFER_RESULT:"):
val = line.split(":", 1)[1].strip()
return val == "True"
LOG.warning("Could not parse defer result from output: %s", output[:500])
return False
def test_crtc_defer_helper():
LOG.info("\n=== Test 2: CRTC _maybe_defer_for_standard (via dev workers container) ===")
uid = uuid.uuid4().hex[:8]
order_number = _create_test_crtc_order(uid)
try:
# Test A: Expedited order should NOT be deferred
expedited_order = {"name": order_number, "custom_expedited": True}
result = _invoke_defer_helper_in_container(expedited_order, "post_did_pre_incorporation")
check("Expedited: returns False (no delay)", result is False)
# Test B: Standard order should be deferred (first call)
standard_order = {"name": order_number, "custom_expedited": False}
result = _invoke_defer_helper_in_container(standard_order, "post_did_pre_incorporation")
check("Standard first call: returns True (deferred)", result is True)
# Verify defer_until was set in DB
import psycopg2
conn = psycopg2.connect(DEV_DB_URL)
cur = conn.cursor()
cur.execute(
"SELECT defer_until, automation_note, automation_status FROM canada_crtc_orders WHERE order_number = %s",
(order_number,),
)
row = cur.fetchone()
defer_until, note, status = row
check("DB: defer_until is set", defer_until is not None)
check("DB: automation_note matches checkpoint", note == "post_did_pre_incorporation", str(note))
check("DB: automation_status = Deferred", status == "Deferred", str(status))
check("DB: defer_until is in future", defer_until > datetime.now(timezone.utc) if defer_until else False)
conn.close()
# Test C: Second call (still in defer window) should return True (still deferred)
result = _invoke_defer_helper_in_container(standard_order, "post_did_pre_incorporation")
check("Standard second call (still pending): returns True", result is True)
# Test D: Manually advance defer_until to past, then call again — should clear and return False
conn = psycopg2.connect(DEV_DB_URL)
cur = conn.cursor()
past = datetime.now(timezone.utc) - timedelta(hours=1)
cur.execute(
"UPDATE canada_crtc_orders SET defer_until = %s WHERE order_number = %s",
(past, order_number),
)
conn.commit()
conn.close()
result = _invoke_defer_helper_in_container(standard_order, "post_did_pre_incorporation")
check("Standard after defer expired: returns False (resume)", result is False)
# Verify defer_until was cleared
conn = psycopg2.connect(DEV_DB_URL)
cur = conn.cursor()
cur.execute(
"SELECT defer_until, automation_status FROM canada_crtc_orders WHERE order_number = %s",
(order_number,),
)
row = cur.fetchone()
check("DB: defer_until cleared after resume", row[0] is None)
check("DB: automation_status reset to Pending", row[1] == "Pending", str(row[1]))
conn.close()
# Test E: Different checkpoint = independent defer
result = _invoke_defer_helper_in_container(standard_order, "post_email_pre_letter")
check("Different checkpoint: independent defer (returns True)", result is True)
finally:
_cleanup_test_crtc_order(order_number)
# ──────────────────────────────────────────────────────────────────────
# Test 3: Verify CRTC pipeline source has defer points
# ──────────────────────────────────────────────────────────────────────
def test_crtc_pipeline_has_defer_points():
LOG.info("\n=== Test 3: CRTC pipeline source verification ===")
src = Path(__file__).parent.parent / "workers" / "services" / "canada_crtc.py"
text = src.read_text()
check("Has _maybe_defer_for_standard method", "def _maybe_defer_for_standard" in text)
check("Defer 1: post_did_pre_incorporation", '"post_did_pre_incorporation"' in text)
check("Defer 2: post_email_pre_letter", '"post_email_pre_letter"' in text)
check("Defer 3: post_delivery_pre_compliance", '"post_delivery_pre_compliance"' in text)
check("Step 7 idempotency: binder_already_compiled", "binder_already_compiled" in text)
check("Step 8 idempotency: binder_already_uploaded", "binder_already_uploaded" in text)
check("Step 9 idempotency: binder_already_emailed", "binder_already_emailed" in text)
# ──────────────────────────────────────────────────────────────────────
# Test 4: Verify Formation pipeline source has defer points
# ──────────────────────────────────────────────────────────────────────
def test_formation_pipeline_has_defer_points():
LOG.info("\n=== Test 4: Formation pipeline source verification ===")
src = Path(__file__).parent.parent / "workers" / "job_server.py"
text = src.read_text()
check("Has _check_standard_delay function", "def _check_standard_delay" in text)
check("file_entity defer: post_name_pre_filing", '"post_name_pre_filing"' in text)
check("obtain_ein defer: post_filing_pre_ein", '"post_filing_pre_ein"' in text)
check("generate_docs defer: post_ein_pre_docs", '"post_ein_pre_docs"' in text)
check("import business_days_from_now", "from scripts.workers.business_days import business_days_from_now" in text)
# ──────────────────────────────────────────────────────────────────────
# Test 5: Migration verification
# ──────────────────────────────────────────────────────────────────────
def test_migration_columns():
LOG.info("\n=== Test 5: Migration 039 columns ===")
import psycopg2
conn = psycopg2.connect(DEV_DB_URL)
cur = conn.cursor()
cur.execute("""
SELECT column_name FROM information_schema.columns
WHERE table_name = 'canada_crtc_orders'
AND column_name IN ('defer_until', 'automation_note', 'binder_compiled_at', 'binder_uploaded_at', 'binder_emailed_at')
ORDER BY column_name
""")
cols = {r[0] for r in cur.fetchall()}
conn.close()
check("defer_until column exists", "defer_until" in cols)
check("automation_note column exists", "automation_note" in cols)
check("binder_compiled_at column exists", "binder_compiled_at" in cols)
check("binder_uploaded_at column exists", "binder_uploaded_at" in cols)
check("binder_emailed_at column exists", "binder_emailed_at" in cols)
# ──────────────────────────────────────────────────────────────────────
# Main
# ──────────────────────────────────────────────────────────────────────
def main():
LOG.info("=" * 60)
LOG.info(" STANDARD-VS-EXPEDITED DELAY E2E TEST")
LOG.info("=" * 60)
test_business_days()
test_migration_columns()
test_crtc_defer_helper()
test_crtc_pipeline_has_defer_points()
test_formation_pipeline_has_defer_points()
LOG.info("\n" + "=" * 60)
LOG.info(" RESULTS: %d passed, %d failed, %d total", PASS, FAIL, PASS + FAIL)
LOG.info("=" * 60)
if FAIL > 0:
LOG.info("\n Failed checks:")
for r in RESULTS:
if not r["ok"]:
LOG.info(" X %s%s", r["label"], r["detail"])
sys.exit(1 if FAIL > 0 else 0)
if __name__ == "__main__":
main()