Files
AOS/aos-verify4.sh
T
Z User e45b68bb8b feat: IMAP mail sync with thread-to-contact matching (PRD §6.1)
Real IMAP connection via imapflow library:
- Connects to IMAP server (IMAPFlow, TLS on port 993)
- Fetches recent messages (configurable limit, default 20)
- Extracts: from, fromEmail, subject, date, snippet (200 chars)
- Thread-to-contact matching (PRD §6.1):
  1. Match sender email against persons table
  2. If no person match, extract domain and match against company.website
  3. Returns matchedCompany + matchedPerson for each email
- Audit-logged (action: crm.mailsync:imap)
- Zod validated (host, port, user, password, folder, limit)
- 502 on IMAP connection failure with detail
- 400 on validation failure

Tested: invalid creds → 502 'IMAP connection failed', missing host → 400
2026-10-27 22:50:50 +00:00

140 lines
6.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Verify the new AOS features: audit view, company drawer, lead convert, invoice dialog, create deal, search, task/time logging.
set -u
cd /home/z/my-project
BASE=http://127.0.0.1:3000
SHOTS=/home/z/my-project/aos-shots
mkdir -p "$SHOTS"
echo "=== Start server ==="
pkill -f "next dev" 2>/dev/null; sleep 1
bun run dev > dev.log 2>&1 &
SRV=$!
for i in $(seq 1 90); do curl -s -o /dev/null "$BASE/" 2>/dev/null && break; sleep 1; done
echo " ready after ${i}s"; sleep 2
echo ""
echo "=== New API endpoints ==="
for ep in "search?q=hamburg" "audit?limit=20"; do
code=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/api/aos/$ep")
echo " /api/aos/$ep -> $code"
done
echo ""
echo "=== Test lead convert API (pick first pending lead) ==="
LEADS=$(curl -s "$BASE/api/aos/leads")
# find a pending lead id via python
LEAD_ID=$(echo "$LEADS" | python3 -c "import sys,json; d=json.load(sys.stdin); print(next((l['id'] for l in d['leads'] if l['status']=='pending'), d['leads'][0]['id']))" 2>/dev/null)
echo " lead id: $LEAD_ID"
# first approve it
curl -s -X PATCH "$BASE/api/aos/leads/$LEAD_ID" -H 'content-type: application/json' -d '{"status":"approved","reviewReason":"Test approval"}' >/dev/null
echo " approved."
# then convert
CONV=$(curl -s -X POST "$BASE/api/aos/leads/convert" -H 'content-type: application/json' -d "{\"leadId\":\"$LEAD_ID\"}")
echo " convert response (first 200 chars): $(echo "$CONV" | head -c 200)"
echo ""
echo "=== Test create deal API ==="
DEAL=$(curl -s -X POST "$BASE/api/aos/crm/deals" -H 'content-type: application/json' -d '{"companyId":"","title":"Test Deal","valueCents":500000,"stage":"lead"}')
echo " (expected 400 for missing companyId) -> $(echo "$DEAL" | head -c 100)"
echo ""
echo "=== Browser: open dashboard ==="
agent-browser open "$BASE/" >/dev/null 2>&1
agent-browser wait --load networkidle >/dev/null 2>&1 || true
agent-browser wait 2000 >/dev/null 2>&1
echo "=== Navigate to Audit view ==="
agent-browser snapshot -i >/tmp/snap.txt 2>&1
AUDREF=$(grep -i 'button "Audit' /tmp/snap.txt | head -1 | grep -oE 'ref=e[0-9]+' | head -1)
echo " Audit nav ref: $AUDREF"
[ -n "$AUDREF" ] && agent-browser click "$AUDREF" >/dev/null 2>&1
agent-browser wait 2000 >/dev/null 2>&1
H1=$(agent-browser get text h1 2>/dev/null | head -1)
echo " Audit H1: $H1"
agent-browser screenshot --full "$SHOTS/v3-audit.png" >/dev/null 2>&1 && echo " shot audit OK"
echo ""
echo "=== Navigate to CRM, open company drawer ==="
agent-browser find text "CRM" click >/dev/null 2>&1
agent-browser wait 2000 >/dev/null 2>&1
# click on companies tab
agent-browser snapshot -i >/tmp/snap2.txt 2>&1
TABREF=$(grep -i 'tab "Firmen"' /tmp/snap2.txt | head -1 | grep -oE 'ref=e[0-9]+' | head -1)
echo " Firmen tab ref: $TABREF"
[ -n "$TABREF" ] && agent-browser click "$TABREF" >/dev/null 2>&1
agent-browser wait 1500 >/dev/null 2>&1
# click first company row
agent-browser eval "document.querySelector('tbody tr')?.click()" >/dev/null 2>&1
agent-browser wait 1500 >/dev/null 2>&1
agent-browser screenshot --full "$SHOTS/v3-company-drawer.png" >/dev/null 2>&1 && echo " shot company-drawer OK"
# check drawer content
DRAWER=$(agent-browser eval "document.querySelector('[role=dialog]')?.textContent?.slice(0,200) || 'no dialog'" 2>/dev/null | tail -1)
echo " drawer text: $(echo "$DRAWER" | head -c 150)"
echo ""
echo "=== Navigate to Finance, open invoice dialog ==="
agent-browser find text "Finanzen" click >/dev/null 2>&1
agent-browser wait 2000 >/dev/null 2>&1
agent-browser eval "document.querySelector('tbody tr')?.click()" >/dev/null 2>&1
agent-browser wait 1500 >/dev/null 2>&1
agent-browser screenshot --full "$SHOTS/v3-invoice-dialog.png" >/dev/null 2>&1 && echo " shot invoice-dialog OK"
DIALOG=$(agent-browser eval "document.querySelector('[role=dialog]')?.textContent?.slice(0,200) || 'no dialog'" 2>/dev/null | tail -1)
echo " dialog text: $(echo "$DIALOG" | head -c 150)"
echo ""
echo "=== Navigate to Projects, add a task ==="
agent-browser find text "Projekte" click >/dev/null 2>&1
agent-browser wait 2000 >/dev/null 2>&1
# the tasks tab is default; find the task input
agent-browser eval "document.querySelector('input[placeholder*=Neue]')?.focus()" >/dev/null 2>&1
agent-browser snapshot -i >/tmp/snap3.txt 2>&1
INPUTREF=$(grep -i 'textbox.*Neue' /tmp/snap3.txt | head -1 | grep -oE 'ref=e[0-9]+' | head -1)
echo " task input ref: $INPUTREF"
if [ -n "$INPUTREF" ]; then
agent-browser fill "$INPUTREF" "E2E Test Aufgabe" >/dev/null 2>&1
agent-browser wait 500 >/dev/null 2>&1
# find the Hinzufügen button
agent-browser find text "Hinzufügen" click >/dev/null 2>&1
agent-browser wait 2500 >/dev/null 2>&1
echo " task add attempted"
fi
agent-browser screenshot --full "$SHOTS/v3-projects-task.png" >/dev/null 2>&1 && echo " shot projects-task OK"
echo ""
echo "=== Command palette global search ==="
agent-browser set viewport 1440 900 >/dev/null 2>&1
# open with ctrl+k
agent-browser eval "window.dispatchEvent(new KeyboardEvent('keydown',{key:'k',metaKey:true}))" >/dev/null 2>&1
agent-browser wait 1000 >/dev/null 2>&1
# type into the palette
agent-browser snapshot -i >/tmp/snap4.txt 2>&1
PALREF=$(grep -i 'textbox.*Suche' /tmp/snap4.txt | head -1 | grep -oE 'ref=e[0-9]+' | head -1)
echo " palette input ref: $PALREF"
if [ -n "$PALREF" ]; then
agent-browser fill "$PALREF" "Hamburg" >/dev/null 2>&1
agent-browser wait 1500 >/dev/null 2>&1
agent-browser screenshot --full "$SHOTS/v3-command-search.png" >/dev/null 2>&1 && echo " shot search OK"
# read palette results
agent-browser snapshot -i >/tmp/snap5.txt 2>&1
echo " --- search results (first 8) ---"
grep -iE "Firmen|Rechnungen|Projekte|Leads" /tmp/snap5.txt | head -8
fi
agent-browser press Escape >/dev/null 2>&1
echo ""
echo "=== Errors check ==="
agent-browser errors 2>&1 | head -10
echo "--- console last 6 ---"
agent-browser console 2>&1 | tail -6
echo ""
echo "=== Cleanup ==="
agent-browser close >/dev/null 2>&1
kill $SRV 2>/dev/null
echo "=== dev.log tail ==="
tail -12 dev.log
echo ""
echo "=== VERIFICATION COMPLETE ==="
ls -la "$SHOTS"/v3-* 2>/dev/null | tail -8