Manual Test Runbook — G5: HubSpot Deal attachment
Owner: Sagar | Time: ~15 min | Sandbox: HubSpot developer account (never production)
Purpose
Validate that HubSpotAdapter patches a Deal's discovery_report_url
property correctly, that auth failures surface as errors, and that the
property exists in the HubSpot schema.
Prerequisites
- HubSpot developer/test portal access
- Private App created in that portal with scope
crm.objects.deals.write - Custom property
discovery_report_url(single-line text) exists on the Deal object - Test Deal exists in the portal; record its
dealId
Steps
1. Unit tests
- All tests pass (PATCH shape, error path, empty-token guard)
2. Live patch against the dev portal
export HUBSPOT_PRIVATE_APP_TOKEN='pat-na1-...' # from the dev portal
DEAL_ID='<test-deal-id>'
REPORT_URL='https://example.com/discovery-test.pdf'
node -e "
import('./dist/integrations/hubspot.js').then(async ({ HubSpotAdapter }) => {
const hs = new HubSpotAdapter(process.env.HUBSPOT_PRIVATE_APP_TOKEN);
await hs.setDealReportUrl(process.env.DEAL_ID || '$DEAL_ID', '$REPORT_URL');
console.log('ok');
}).catch((e) => { console.error(e); process.exit(1); });
"
- Script prints
ok - Open the Deal in HubSpot UI —
discovery_report_urlshows$REPORT_URL
3. Negative test — bad token
HUBSPOT_PRIVATE_APP_TOKEN='pat-not-valid' \
node -e "
import('./dist/integrations/hubspot.js').then(async ({ HubSpotAdapter }) => {
const hs = new HubSpotAdapter(process.env.HUBSPOT_PRIVATE_APP_TOKEN);
await hs.setDealReportUrl('1', 'u');
}).catch((e) => { console.error(String(e)); process.exit(0); });
"
- Prints an error containing
401
4. Property existence check
curl -sSf -H "Authorization: Bearer $HUBSPOT_PRIVATE_APP_TOKEN" \
https://api.hubapi.com/crm/v3/properties/deals/discovery_report_url
- Returns the property definition (200), not 404
- If 404, create the property — without it, every G5 run fails
Pass criteria
- Unit tests green
- Live PATCH succeeds against the dev portal
- Bad token surfaces as a non-zero exit
- Custom property exists in the schema
Failure modes & escalation
| Symptom | Likely cause | Action |
|---|---|---|
| 403 PROPERTY_DOESNT_EXIST | Custom property not created in portal | Create discovery_report_url (single-line text) on the Deal object |
| 401 | Token expired or wrong scope | Regenerate with crm.objects.deals.write scope |
| Deal exists but property is blank | Property scoped to a different pipeline | Verify Deal pipeline matches portal-wide property |
Sign-off
- Tester: ___ | Date: _ | Result: PASS / FAIL / N/A
- Notes: