Double submit testing
People click buttons twice, out of habit or because nothing seemed to happen after the first click. If a form creates an order, a payment or a record, each of those habits can create two. The bug is old and well known, and it still ships, because a calm tester on a fast connection never triggers it.
How to trigger it
- A fast double-click on the submit button. Not two separate clicks: a real double-click.
- Three or four quick clicks: some protection stops the second click and not the third.
- Enter, then a click. Keyboard submit and button click often go through different code.
- A slow network. In the browser's developer tools, on the Network tab, set throttling to a slow profile and click again while the first request is still running. This is the realistic case: the user clicks again because nothing happened yet.
- After the confirmation, press the browser's Back button and submit again, or reload the confirmation page and accept the "resend" prompt if the browser shows one.
How to see the result
The screen often hides the duplicate: it shows one confirmation, the last one. Look underneath:
- The Network tab: count the requests that went out after your clicks.
- The order history, the admin list, or a second confirmation email, if the system has them.
- Order numbers. If two orders were created, do they have different numbers? Numbers built from the current time (to the second) can repeat when two orders arrive in the same second, which is exactly what a double-click produces. Two orders sharing a number is a second bug on top of the first.
What protection looks like
Knowing the fix helps you test it properly, because each layer fails differently.
| Layer | What it does | How it fails |
|---|---|---|
| Disable the button on the first click | Stops most double-clicks on the page | Enter still submits; the button is re-enabled too early; a direct request skips the page |
| Show a pending state | Stops the "nothing happened, click again" reflex | Not shown on slow networks, which is when it matters |
| A one-time token sent with the order (an idempotency key) | The server accepts each token once, so a repeat is recognised as the same order | The token is regenerated on every click, so it never repeats |
| A server-side check for duplicates | Catches repeats from any source | Too narrow (only identical requests) or too wide (blocks real repeat purchases) |
Page-level protection alone is not enough: anything sent from outside the page, including a retry from a flaky network, goes straight to the server. If you can resend a request from the developer tools (see the guide on what the server trusts), resend the order and see whether a second one appears.
Reporting it
A good report names the trigger precisely ("double-click on Place order, normal network"), the evidence (two requests, two order numbers, or one number used twice) and the effect on the user (two charges). "Clicking twice sometimes makes two orders" is true but hard to act on.
Open the practice form
More guides: checkout totals · what the server trusts · REST API test cases · all guides