#!/usr/bin/env node /** * Smoke-test CollabSupport HTTP endpoints used by ServChan. * * Usage: * CS_API_BASE=https://bot.joesjavajoint.com/CollabSupport \ * SMOKE_WO_ID=356369551 SMOKE_STORE_NUM=2254 \ * node scripts/smoke-collab-support.js */ import 'dotenv/config'; const base = (process.env.CS_API_BASE_INTERNAL || process.env.CS_API_BASE || '').replace(/\/+$/, ''); const woId = process.env.SMOKE_WO_ID || '356369551'; const storeNum = process.env.SMOKE_STORE_NUM || '2254'; const timeoutMs = Number(process.env.SMOKE_TIMEOUT_MS) || 30_000; const USAGE_MARKERS = [ '**Work Order Summary Usage:**', '**Work Order History Usage:**', 'Please provide a 2–4 digit store number.', ]; function looksLikeUsage(text) { return USAGE_MARKERS.some((m) => text.includes(m)); } async function fetchCheck(label, url, { expectJson = false, validate, expectStatus } = {}) { const started = Date.now(); const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeoutMs); try { const res = await fetch(url, { signal: controller.signal, headers: expectJson ? { Accept: 'application/json' } : undefined, }); const elapsed = Date.now() - started; const body = expectJson ? await res.json() : await res.text(); const issues = []; if (expectStatus !== undefined) { if (res.status !== expectStatus) issues.push(`expected HTTP ${expectStatus}, got ${res.status}`); } else if (!res.ok) { issues.push(`HTTP ${res.status}`); } if (expectStatus === undefined && !expectJson && typeof body === 'string' && body.trim().length === 0) { issues.push('empty markdown body'); } if (expectStatus === undefined && !expectJson && typeof body === 'string' && looksLikeUsage(body)) { issues.push('looks like usage/help text, not data'); } if (validate) { const v = validate(body, res); if (v) issues.push(v); } const pass = issues.length === 0; console.log(`${pass ? 'PASS' : 'FAIL'} ${label}`); console.log(` ${url}`); console.log(` → ${res.status} (${elapsed}ms)${issues.length ? ` — ${issues.join('; ')}` : ''}`); return pass; } catch (err) { const elapsed = Date.now() - started; const msg = err.name === 'AbortError' ? 'timeout' : err.message; console.log(`FAIL ${label}`); console.log(` ${url}`); console.log(` → error (${elapsed}ms): ${msg}`); return false; } finally { clearTimeout(timer); } } async function main() { if (!base) { console.error('CS_API_BASE is required (e.g. https://bot.joesjavajoint.com/CollabSupport)'); process.exit(1); } console.log(`CollabSupport smoke test → ${base}`); console.log(`WO=${woId} store=${storeNum}\n`); const results = []; results.push(await fetchCheck( 'wosummary', `${base}/wosummary?woId=${encodeURIComponent(woId)}`, { validate: (body) => body.includes('Work Order Summary') ? null : 'missing summary header', } )); results.push(await fetchCheck( 'wohistory (summary)', `${base}/wohistory?storeNum=${encodeURIComponent(storeNum)}`, { validate: (body) => body.includes('Work Order History') ? null : 'missing history header', } )); results.push(await fetchCheck( 'wohistory (detailed)', `${base}/wohistory?storeNum=${encodeURIComponent(storeNum)}&mode=detailed`, { validate: (body) => body.includes('Work Order History') ? null : 'missing history header', } )); results.push(await fetchCheck( 'avStatus (summary)', `${base}/avStatus?storeNum=${encodeURIComponent(storeNum)}`, { validate: (body) => (body.length > 50 ? null : 'response too short'), } )); results.push(await fetchCheck( 'avStatus (detailed)', `${base}/avStatus?storeNum=${encodeURIComponent(storeNum)}&mode=detailed`, { validate: (body) => (body.length > 50 ? null : 'response too short'), } )); results.push(await fetchCheck( 'woAttachments (JSON)', `${base}/woAttachments?woId=${encodeURIComponent(woId)}`, { expectJson: true, validate: (data) => { if (typeof data.success !== 'boolean') return 'missing success field'; if (typeof data.count !== 'number') return 'missing count field'; if (!Array.isArray(data.attachments)) return 'missing attachments array'; return null; }, } )); // Validation endpoint — should 400 results.push(await fetchCheck( 'wosummary invalid (expect 400)', `${base}/wosummary?woId=abc`, { expectStatus: 400 } )); const passed = results.filter(Boolean).length; const total = results.length; console.log(`\n${passed}/${total} checks passed`); process.exit(passed === total ? 0 : 1); } main();