// travel and mobility

A booking can cross a clock change and lose an hour. We test time, money and place.

Booking platforms fail on edges: a clock change, two people and one spot, a GPS fix on the wrong side of a line, a payout run twice. We test those edges on real devices.

Start a two-week pilot
ISO 27001:2022clients include Vulog and ITI Digital4.9 Clutch, 70 reviews$25-45/hour
// a bug I still remember
“The app worked with or without an account. I tested sign-up, forgot password, change password and log out, and checked that no data stayed on the device. Then, on the same phone, I logged out and opened Create Account again for a fresh account. The sign-up form was filled in with the previous account's name, email and password. There were requirements for logged-in and logged-out users, but none for how the app kept account data.”
Patricia Broscaru, QA engineer, travel and mobility
// what keeps you up at night, and what you get
"A customer arrives and the car or parking spot they booked isn't there."
Bookings tested across time zones, daylight-saving changes and two people booking the same last spot.Flows
"Payouts to our hosts or partners go out wrong."
Payments, refunds and partner payouts tested as one journey, down to the last cent.BugBoard
"The app works on one phone and in one city, and fails in the next."
The same journeys on iOS, Android and web, on real devices.embedded testers
// four places booking and mobility systems break
01 · daylight saving

A night booking is charged for the wrong hours

The booking stores local start and end times with no zone. When the clocks go back, a Saturday 22:00 to Sunday 08:00 booking really lasts 11 hours but is priced as 10. In spring the same booking is 9 hours. A start at 02:30 on the change night exists twice in autumn and never in spring.

also: venue zone differs from the user's phone zone
start (stored)Sat 22:00end (stored)Sun 08:00clock changeSun 03:00 to 02:00hours billed10hours elapsed11
20:00Z07:00Zstored as instant + zone11 hours
FAIL10 hours billed, 11 used
PASSafter the fix
how we test itRun bookings across both clock changes in the venue's zone and in a different phone zone. Compute expected duration from UTC instants.
await clock.setZone('Europe/Berlin')
const b = await book({ from: '2026-10-24T22:00',
                        to: '2026-10-25T08:00' })
expect(b.durationHours).toBe(11)               // got 10
expect(b.price).toBe(11 * HOURLY)
expect(await book({ from: '2026-10-25T02:30' })).toBeAmbiguous()
02 · payouts

A host is paid twice for one booking batch

The payout job sends the bank file, the bank accepts it, and the process dies before it marks the batch paid. The scheduler retries, builds a new file with a new message id, and the bank pays again. A separate defect: fees rounded per booking, then summed, differ from the fee rounded once per payout.

also: currency conversion rounding and fee splits
jobpayoutsbankdbrun batch 14send file, msg id A1acceptedmark batch paidretry batch 14send file, msg id B7accepted
FAILbatch 14 paid twice, 184.20 per host
how we test itKill the job after the bank accepts and before the database commit, retry, and assert one payment per host. Reconcile the bank file to bookings.
bank.acceptAll()
chaos.killAfter('bank.send', 'batch.markPaid')
await runPayouts(14); await runPayouts(14)
expect(bank.paymentsTo(host)).toHaveLength(1)    // got 2
expect(sum(bank.files())).toBe(sum(bookings.payable(14)))
03 · geofence

A trip cannot be ended inside the zone

A shared vehicle may only be returned inside a polygon. The check uses the raw GPS point and ignores the fix's accuracy radius. Parked 6 metres inside the edge with a 48 metre accuracy, the next fix lands 11 metres outside, and the end-of-trip is refused while the meter keeps running.

also: underground car parks with no fix at all
fix 1 inside zone, 6 m from edge accuracy +/- 48 m fix 2 outside zone, 11 m decision uses raw point, no margin end trip refused meter still running
TRIP STUCK OPENaccuracy radius ignored, fee keeps growing
how we test itWalk simulated GPS tracks along the boundary with realistic accuracy values. Assert stable decisions and a clear way out when the fix is poor.
for (const acc of [5, 20, 48, 100]) {
  const track = walkAlong(zone.edge, { insideBy: 6, accuracy: acc })
  const results = await endTripAt(track)
  expect(flips(results)).toBeLessThanOrEqual(1)   // no flapping
  expect(results.at(-1).canEnd || results.at(-1).fallback).toBe(true)
}
04 · availability

Two people book the last spot

The booking code reads availability, finds one spot, then inserts the booking. Two requests 40 milliseconds apart both read 1, both insert, and nothing in the database forbids it. Both customers get a confirmation. One of them arrives to a spot that is taken.

also: offline unlock on car-sharing when the phone has no signal
A reads1 left
B reads1 left
A booksinsert
B booksinsert
10:002 cars
OVERBOOKEDone spot, two customers
how we test itFire the two requests truly in parallel, hundreds of times. Exactly one must succeed, the other must get a clear refusal.
for (let i = 0; i < 500; i++) {
  const rs = await Promise.all([
    book(spot12, '10:00', userA), book(spot12, '10:00', userB)])
  expect(rs.filter(r => r.status === 201)).toHaveLength(1)  // got 2
  expect(rs.find(r => r.status !== 201).status).toBe(409)
}

Illustrative examples built from defect patterns we test for. Not client data.

// on every pull request

Your code is written in hours. Our pipeline keeps up.

Pull requestfrom your coding agent
Flowsjourneys and fault injection
Security Toolkit15 scanners + 20 own checks
QA engineerconfirms every finding
BugBoardrelease report, Jira sync
// the regulation, in testing terms
regimewhere it actually breakswhat we run
Package Travel DirectiveIf you sell packages: price changes and cancellations follow fixed rulesprice change after booking, cancellation and refund paths
PCI DSSCard data in logs, exports and partner filesPAN scans on logs and payout files, test-data scope
GDPR location dataTrip traces are personal data and tend to be kept foreverretention and deletion tests, access by role
European Accessibility ActWebsites, apps and e-tickets for air, bus, rail and waterborne transport are in scope; online bookings sold to consumers can fall under its e-commerce rulesWCAG AA audits of booking and e-ticket journeys
// proof

A parking marketplace before launch

104 test cases4 testersDST and payout defects found
  • Vulog, the car-sharing platform: "comprehensive testing across multiple platforms".
  • ITI Digital, travel software.
  • A parking marketplace: booking-time errors around daylight saving and problems in payouts, found before launch.
  • Finnair: digital products, tested in 2025.

The parking marketplace is not named.

BUG-0568 · bookings / pricing · examplehigh

Overnight booking charged 10 hours when the clocks go back

  1. Book a spot from Saturday 22:00 to Sunday 08:00 on the night clocks go back
  2. Check the price shown at checkout
  3. The price covers 10 hours, the booking lasts 11

Fix: Store start and end as UTC instants plus the venue's zone, and compute duration from the instants.

REQ-BOOK-05TC-1471 addedJira PARK-902

Two weeks on your booking and payout flows. Free if you're not happy.

Start a pilot