Skip to main content

How to Test Shipping Rates and Fulfillment Status

Short answer

Shipping miscalculations erode margin; stale fulfillment status drives WISMO tickets. Test rate tables and carrier selection with seeded addresses and cart weights, probe shipping line items at checkout, and assert fulfillment state transitions (allocated → shipped → delivered) via backend probes—not tracking link visibility alone.

Part of Testing Guides by business flow.

Who this is for

Ecommerce teams with zone-based rates, live carrier APIs (UPS, FedEx, Shippo), free-shipping thresholds, or split shipments from inventory nodes.

Why testing shipping matters

  • Conversion — surprise surcharges at checkout abandon carts.
  • Margin — free-shipping threshold off by $0.01 ships unprofitably.
  • Support — "Where is my order?" when status stuck at processing.

Complexity map

ScenarioEdge caseWhy tests breakApproach
Zone tableRemote postal codeSurcharge surpriseSeed address; probe rate
Free shipping thresholdSubtotal $49.99 vs $50Wrong free flagTwo seeded cart totals
Weight tierHeavy itemRate jumpSeed cart weight fixture
Carrier API timeout30s hangSpinner foreverStub carrier; probe fallback
Split shipmentTwo warehousesOne trackingProbe packages[] length
PO box restrictionCarrier blocksCheckout allowedProbe validation error
InternationalCustoms not includedDisputeProbe duties disclaimer flag
Pickup in storeZero shippingWrong rateProbe method=pickup
Label purchasePost-pay asyncStatus lagPoll fulfillment probe
Address validateSmarty/USPSInvalid acceptedProbe normalized address
Express vs groundUser selects expressWrong service codeProbe selected_service

Free shipping threshold

test('shipping free above threshold', async ({ request, page }) => {
await request.post('/api/test/seed-cart', {
data: { runId, subtotalCents: 4999, thresholdCents: 5000 },
});
await page.goto(`/checkout?runId=${runId}`);
let order = await request.get(`/api/test/probes/checkout-quote/${runId}`).then(r => r.json());
expect(order.shippingCents).toBeGreaterThan(0);

await request.post('/api/test/seed-cart', {
data: { runId, subtotalCents: 5000, thresholdCents: 5000 },
});
await page.reload();
order = await request.get(`/api/test/probes/checkout-quote/${runId}`).then(r => r.json());
expect(order.shippingCents).toBe(0);
});

Remote zone surcharge

await request.post('/api/test/seed-shipping-fixture', {
data: { runId, postalCode: '99501', country: 'US', cartWeightOz: 32 },
});
await page.goto(`/checkout?runId=${runId}`);
const quote = await request.get(`/api/test/probes/shipping-rates/${runId}`).then(r => r.json());
expect(quote.zone).toBe('remote_alaska');
expect(quote.amount).toBe(quote.expectedRemoteRate); // from fixture config

Fulfillment status transitions

const { orderId } = await seedPaidOrder(request, runId);

await expect.poll(async () => {
return (await request.get(`/api/test/probes/fulfillment/${orderId}`).then(r => r.json())).status;
}).toBe('allocated');

await request.post('/api/test/simulate-carrier-event', {
data: { orderId, event: 'shipped', tracking: '1Z999TEST' },
});

await expect.poll(async () => {
return (await request.get(`/api/test/probes/fulfillment/${orderId}`).then(r => r.json())).status;
}).toBe('shipped');

Customer-facing tracking page is optional Assert—probe is authoritative.

Carrier timeout fallback

Stub carrier API in test env to return 504; assert checkout shows degraded message and probe allows standard flat rate fallback if that is prod policy.

Anti-patterns

Anti-patternWhy it failsBetter approach
Assert "$5.99" labelRate table changesProbe cents + zone id
Single ZIP onlyRemote zones untestedFixture matrix
Live carrier every PRFlaky + slowStub in CI; smoke nightly
Tracking link existsStatus still processingProbe fulfillment status

Example scenario

Situation: Cart subtotal crosses free-shipping threshold after coupon applied.

Expected outcome: Shipping line zero; total reflects discount + free ship consistently.

Why UI-only automation breaks: UI shows FREE shipping but probe charges standard rate on payment intent.

  1. Arrange: Seed cart at threshold-1 with valid coupon to threshold+.
  2. Act: Apply coupon at checkout.
  3. Assert: Probe shippingCents=0 and payment amount matches subtotal after discount.

TestChimp workflow: Track shipping_zone × carrier in TrueCoverage when express carrier use rises.

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).

External references

Frequently asked questions

How do I test free shipping thresholds?

Seed cart subtotal just below and above threshold in separate scenarios; probe shipping line item is zero or non-zero accordingly.

Should I call live carrier APIs in CI?

Stub or record fixtures for PR CI; optional nightly job hits sandbox carrier APIs for integration confidence.

How do I test split shipments?

Seed order lines from two warehouses, complete checkout, probe packages array length=2 with distinct tracking when each ships.

Fulfillment status vs tracking page—which to assert?

Probe backend fulfillment status for Assert; tracking page is secondary UX check.

How do I test remote zone surcharges?

Seed postal codes mapped to remote zones in your rate table fixture; probe zone id and amount—not only UI label.

PO box restrictions—how to test?

Seed PO box address with carrier that blocks; probe checkout validation error before payment.

Express carrier popular in prod but untested—what now?

Use TrueCoverage on shipping_zone × carrier. Run /testchimp evolve to add express scenarios when prod share grows.

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.

Start free on TestChimp · Book a demo