How to Test Multi-Vendor Marketplace Checkout
Short answer
Marketplaces combine checkout, inventory, shipping, and payouts—failure modes multiply. E2E must probe split cart payment allocation, commission per vendor_id, and vendor-specific shipping after Stripe payment succeeds—not a single order total alone.
Part of Testing Guides by business flow.
Who this is for
Multi-vendor platforms (Etsy-like, B2B marketplaces, food delivery) with split carts, Stripe Connect, or internal ledger payouts.
Why testing marketplaces matters
- Seller trust — wrong commission or delayed payout.
- Buyer experience — single checkout charge but split shipping confusion.
- Compliance — KYC-gated vendors still selling when probe says suspended.
Complexity map
| Scenario | Edge case | Why tests break | Approach |
|---|---|---|---|
| Split cart | Two vendors | Single payout wrong | Probe ledger lines per vendor |
| Commission % | Tiered by category | Wrong take rate | Seed category; probe fee |
| Vendor shipping | Different carriers | Buyer one rate shown | Probe per-vendor ship lines |
| Connect transfer | Delayed transfer | Seller UI wrong | Poll transfer probe |
| Vendor suspended | Still in cart | Checkout allowed | Seed suspended; probe block |
| Partial cancel | One vendor line | Refund split wrong | See returns guide |
| Tax per vendor | Nexus differs | Wrong tax split | Probe tax by vendor |
| Single vendor cart | Regression | Split logic breaks | Control scenario |
| Platform fee cap | Max fee | Undercharge | Probe fee clamp |
| Currency | Vendor paid EUR | FX wrong | Probe settlement currency |
| Inventory per vendor | Vendor A OOS | Whole cart blocked? | Probe partial checkout policy |
Arrange: multi-vendor catalog
// POST /api/test/seed-marketplace
// { runId, vendors: [{ id: 'v1', commission: 0.15 }, { id: 'v2', commission: 0.10 }] }
const { vendorA, vendorB, skuA, skuB } = await request.post('/api/test/seed-marketplace', {
data: { runId },
}).then(r => r.json());
Split checkout E2E
await page.goto('/cart');
await page.getByTestId(`add-${skuA}`).click();
await page.getByTestId(`add-${skuB}`).click();
await page.goto(`/checkout?runId=${runId}`);
await completeStripeCheckout(page, runId);
const ledger = await request.get(`/api/test/probes/payouts/${runId}`).then(r => r.json());
expect(ledger.entries).toHaveLength(2);
expect(ledger.entries.find(e => e.vendorId === vendorA).commission).toBeCloseTo(0.15, 2);
expect(ledger.platformFee + ledger.entries.reduce((s, e) => s + e.net, 0)).toBe(ledger.gross);
Vendor shipping rules
Seed vendor A flat $5, vendor B free over $50; cart with both—probe two shipping sub-lines or combined policy per product rules.
Stripe Connect notes
Use Connect test accounts; transfers may async—expect.poll on transfer probe. Document Stripe Connect testing.
Connect transfer probe
await expect.poll(async () => {
const t = await request.get(`/api/test/probes/connect-transfers/${runId}`).then(r => r.json());
return t.every(entry => entry.status === 'paid');
}, { timeout: 45_000 }).toBe(true);
Buyer-facing order confirmation
After payment, probe per-vendor sub-orders if buyers receive split confirmations:
const orders = await request.get(`/api/test/probes/orders/${runId}`).then(r => r.json());
expect(orders.childOrders).toHaveLength(2);
expect(new Set(orders.childOrders.map(o => o.vendorId))).toEqual(new Set([vendorA, vendorB]));
CI checklist
- Seed marketplace catalog per
runId—never shared vendor SKUs across workers - Pass
metadata.e2e_runon platform charge for teardown correlation - Probe ledger before UI confirmation email specs
- Run split-cart scenario on every PR; Connect transfer poll optional on nightly
- Teardown test Connect accounts when your integration creates many per run
Anti-patterns
| Anti-pattern | Why it fails | Better approach |
|---|---|---|
| Single-vendor only | Split math untested | Two-vendor minimum |
| Assert order total | Payout wrong | Probe ledger |
| Shared vendor ids | Parallel collision | runId in vendor seed |
| Skip suspended vendor | Fraud path | Negative probe |
Example scenario
Situation: Buyer checks out cart with items from two vendors in one payment.
Expected outcome: Single charge; ledger shows correct commission and net per vendor.
Why UI-only automation breaks: Order confirmation shows one vendor; second seller never notified.
- Arrange: Seed two vendors with distinct commission rates and SKUs.
- Act: Single checkout with 4242.
- Assert: Probe payout ledger + vendor notification flags per vendor_id.
TestChimp workflow: Track vendor_id × payout_rule in TrueCoverage when new sellers onboard.
Same Arrange/Act/Assert pattern as expired-coupon checkout.
Connect scenarios to your QA workflow
Capture business rules in markdown test plans and enforce them with seed routes and probe Assert. Link SmartTests with // @Scenario: for requirement traceability. Use /testchimp test on PRs; /testchimp explore on SmartTest paths for non-functional gaps (ExploreChimp).
Related scenarios
- Inventory — per-vendor stock
- Shipping — vendor rates
- Stripe payments — Connect charges
External references
Frequently asked questions
How do I test split payouts in E2E?
Checkout cart with items from two seeded vendors, complete payment, probe ledger shows correct commission and net per vendor_id.
Do I need Stripe Connect test accounts?
If prod uses Connect, yes—create connected accounts in test mode and probe transfer ids. Internal ledger marketplaces probe your payout table instead.
How do vendor shipping rules combine at checkout?
Probe shipping line structure—per-vendor sub-lines or platform-combined rate—matching prod policy; seed vendors with different rules.
What if one vendor is out of stock?
Test prod policy: block whole cart vs allow partial checkout; probe inventory and order lines accordingly.
How do partial refunds work multi-vendor?
Refund one vendor line; probe refund splits commission reversal per vendor—see returns guide.
Suspended vendor still listed—how to test?
Seed vendor status suspended; probe checkout rejects or removes lines; API must not accept direct SKU buy URL.
How do we cover all active vendors?
TrueCoverage on vendor_id × payout_rule for top sellers. Run /testchimp evolve when new payout tiers ship—not every long-tail vendor needs E2E.
Apply these patterns in your repo
Run `/testchimp init` to connect TestChimp to your repo, then `/testchimp test` on PRs to turn these patterns into maintained SmartTests. Use `/testchimp evolve` when you want to expand coverage as your app grows.