Files

152 lines
6.9 KiB
Markdown
Raw Permalink Normal View History

# E2E marketing suite (Descrybe v2)
**Date:** 2026-08-04
**App:** API `http://127.0.0.1:8080` + worker (OPENAI_* from `root `.env` / `/integrations/ai``) + web `:5174`
**LLM:** Green Chat `overloaded-local` at `http://192.168.50.181:8767/v1` (used when `OPENAI_*` is set)
**Tenant:** `demo@descrybe.local` / `DemoPass123!` → **Local Demo Co** (Enterprise, ~1M AI credits, `can_use_ai=true`)
No secrets are recorded here (OPENAI key length only: 64). Cookie jar used locally: `artifacts/e2e-marketing-cookies.txt` / session WebRequest (gitignored / local only). Results snapshot: `artifacts/e2e-marketing-matrix.json`.
## Scope
| Area | What is exercised |
|------|-------------------|
| **Brand kit** | `PUT/GET /api/brand` — tone, dos/donts, preferred terms, formula tips |
| **SEO AI** | `GET /api/seo/recommendations`, `POST /api/seo/apply` with `mode=ai` |
| **Campaigns AI** | `POST /api/campaigns` → `POST /api/campaigns/{id}/generate` `mode=ai` (+ template control) |
| **Email dry-run** | Configure provider if needed; `POST /api/email/send` with `force_dry_run=true`; campaign `POST .../send` with `dry_run=true` |
| **Content calendar** | `GET /api/marketing/calendar`, `POST /api/marketing/calendar/prepare` |
| **Green Chat** | TCP + `GET {OPENAI_BASE_URL}/models` before AI steps |
If `OPENAI_*` is unset or Green Chat is unreachable, AI steps are **SKIP**; template campaign generate and brand/email dry-run still run.
## Results (this run)
| Step | Result | Notes |
|------|--------|-------|
| Green Chat reachability | **PASS** | `OPENAI_BASE_URL=http://192.168.50.181:8767/v1`, model `overloaded-local`, `/v1/models` OK |
| Login | **PASS** | Local Demo Co, Enterprise, remaining ≈ 999996, `can_use_ai=true` |
| Brand kit PUT+GET | **PASS** | Tips include tone, preferred terms (`wireless`,`premium`), donts |
| Brand kit in AI prompts | **PASS** | Brand terms present in SEO + campaign copy |
| Sample product | **PASS** | `d2c309ed-…` Sample Gadget |
| SEO apply `mode=ai` | **PASS** | ~1s; title `Sample Gadget \| Premium Wireless Performance`; `credits_charged=2` |
| SEO recommendations | **PASS** | Report with recommendations / overall score |
| Campaign generate `mode=ai` | **PASS** | ~7s; `status=ready`, `generation_mode=ai`, unsubscribe footer present |
| Campaign generate `mode=template` | **PASS** | Black Friday subject filled without LLM |
| Email integration GET | **PASS** | Was unconfigured before stub SMTP |
| Email provider configure (SMTP stub) | **PASS** | Local stub so dry-run path can load transport |
| Email send `force_dry_run` | **PASS** | `dry_run=true`, reason `force_dry_run`, result status `dry_run` |
| Campaign send `dry_run` | **PASS** | Blast path with `dry_run=true` (no delivery) |
| Marketing calendar prepare | **PASS** | `preset_id=black_friday` → export feed “Black Friday 2026” |
**Overall: PASS** against LAN Green Chat.
### Failure fixed during this run
| Issue | Cause | Fix |
|-------|--------|-----|
| Calendar prepare **404** | Wrong path `/api/marketing/prepare` | Use **`POST /api/marketing/calendar/prepare`** with body `{ "preset_id": "black_friday", "format": "csv" }` |
### Notes (not failures)
- `POST /api/integrations/email/test` against the stub SMTP (`127.0.0.1:2525`) returns `failed` / send failed when **not** dry-running — expected. Prefer **`force_dry_run`** on `/api/email/send` or set `EMAIL_DRY_RUN=true` and restart API.
- Credits live under `GET /api/auth/me` → `credits` and the session billing routes `GET /api/billing/credits`, `GET /api/billing/usage`, `GET /api/billing/plans` (same tenant session + company context).
## Prerequisites
1. Postgres up (`make up` / docker compose on `:5433`).
2. API + worker running with env loaded from `root `.env` / `/integrations/ai`` (must include `OPENAI_BASE_URL`, `OPENAI_API_KEY`, `OPENAI_MODEL` for AI).
3. Web optional for UI; this suite is API/session E2E.
4. Demo user seeded (`make seed` / `seed-demo`).
5. Green Chat listening on LAN (`Test-NetConnection 192.168.50.181 -Port 8767`).
## Commands (PowerShell)
```powershell
$base = "http://127.0.0.1:8080"
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
try { Invoke-WebRequest "$base/api/auth/me" -WebSession $session -UseBasicParsing | Out-Null } catch {}
$csrf = ($session.Cookies.GetCookies($base) | Where-Object Name -eq descrybe_csrf).Value
$login = '{"email":"demo@descrybe.local","password":"DemoPass123!"}'
Invoke-WebRequest "$base/api/auth/login" -Method POST -WebSession $session `
-Headers @{ "X-CSRF-Token" = $csrf; "Content-Type" = "application/json" } -Body $login -UseBasicParsing | Out-Null
$csrf = ($session.Cookies.GetCookies($base) | Where-Object Name -eq descrybe_csrf).Value
function ApiJson($method, $path, $obj) {
Invoke-RestMethod "$base$path" -Method $method -WebSession $session -TimeoutSec 120 `
-Headers @{ "X-CSRF-Token" = $csrf; "Content-Type" = "application/json" } `
-Body ($obj | ConvertTo-Json -Depth 8 -Compress)
}
# Brand kit
ApiJson PUT /api/brand @{
voice_tone = "confident concise"
dos = @("Lead with benefit")
donts = @("No hype")
preferred_terms = @("wireless","premium")
}
# SEO AI
ApiJson POST /api/seo/apply @{
product_id = "d2c309ed-fa99-4785-aa72-4f7d180f1f85"
mode = "ai"
}
# Campaign AI
$c = ApiJson POST /api/campaigns @{
name = "E2E Spring"
template_key = "spring"
use_default_prompt = $true
}
ApiJson POST "/api/campaigns/$($c.id)/generate" @{ mode = "ai" }
# Email dry-run (configure stub SMTP first if configured=false)
ApiJson PUT /api/integrations/email @{
provider = "smtp"
from_email = "noreply@descrybe.local"
from_name = "Descrybe E2E"
domain = "descrybe.local"
smtp_host = "127.0.0.1"
smtp_port = "2525"
smtp_user = "e2e"
smtp_password = "e2e-not-used"
is_enabled = $true
}
ApiJson POST /api/email/send @{
to = @("demo@descrybe.local")
subject = "E2E dry-run"
text = "Should not deliver"
mode = "test"
force_dry_run = $true
}
ApiJson POST "/api/campaigns/$($c.id)/send" @{
confirm = $true
recipients = @("demo@descrybe.local")
dry_run = $true
}
# Content calendar
Invoke-RestMethod "$base/api/marketing/calendar" -WebSession $session
ApiJson POST /api/marketing/calendar/prepare @{
preset_id = "black_friday"
format = "csv"
}
```
Green Chat probe (no app session):
```powershell
# Load OPENAI_* from root `.env` / `/integrations/ai` — do not print the key
Test-NetConnection 192.168.50.181 -Port 8767
curl.exe -sS -H "Authorization: Bearer $env:OPENAI_API_KEY" http://192.168.50.181:8767/v1/models
```
## Related
- [ai-full-smoke.md](ai-full-smoke.md) — broader AI smoke (enhance / EPREL)
- [green-chat-smoke.md](green-chat-smoke.md) — LAN Green Chat connectivity
- [green-chat-llm.md](green-chat-llm.md) — OPENAI_* wiring
- [email-sending.md](email-sending.md) — providers, `EMAIL_DRY_RUN`, blast confirm
- [marketing-suite-user-guide.md](marketing-suite-user-guide.md) — UI flows
- [demo-user.md](demo-user.md) — demo credentials