In Selenium, why can navigate().refresh() after submitting an insurance-claim form create a duplicate claim?
answer
- A reload is defined by the request
- Method and body come back with it
- GET replays harmlessly, POST does not
- The confirmation was the POST response
basics
~10 sA reload repeats the request that produced the current document. If the confirmation page was rendered straight from the form's POST, refreshing sends that POST again and the server records a second claim.
solid answer
~50 s`driver.navigate().refresh()` sends the W3C **Refresh** command, which tells the browser to reload the current document — and a reload repeats the request that produced it, same method and same body. When the claim confirmation is the direct response to `POST /claims`, that reload is another `POST /claims` with the same fields, so a second claim is created while the test still sees a confirmation page and passes. `navigate().back()` followed by `navigate().forward()` can land on the same entry with the same effect. The fix is to stop reloading after a submit: capture `driver.getCurrentUrl()` and re-open it with `navigate().to(...)`, which is a `GET`, or have the application answer the submission with a redirect so the confirmation has its own `GET` address. A browser may interpose a resubmission prompt first, but that is a warning, not a safety net.
code
java · 22 linesimport org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class ClaimSubmissionReopen {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("https://claims.example.test/intake");
driver.findElement(By.id("policy-number")).sendKeys("POL-40218");
driver.findElement(By.id("submit-claim")).click();
String confirmationUrl = driver.getCurrentUrl();
driver.navigate().to(confirmationUrl);
System.out.println(driver.getCurrentUrl());
} finally {
driver.quit();
}
}
}go deeper
Know that refresh means reload, and that reloading a page you reached by submitting a form can send that submission again. Do not reach for a reload just because a page looks incomplete.
Explain the mechanism: the browser re-issues the request that produced the current document, method and body included, so a page rendered from a POST replays the POST while a page reached by a GET does not.
Show you have lived with the consequence — duplicate records in a shared environment, a passing test that doubles its data — and offer the fixes: capture the address and re-open it, or push the application towards answering the submission with a redirect.
Own the rule for the suite: no step reloads a page produced by a non-idempotent request, and the application exposes a GET address for every state a test must return to. Decide who owns the fix when it does not.
## What `refresh()` actually asks the browser to do `driver.navigate().refresh()` sends the W3C WebDriver **Refresh** command, `POST /session/{sessionId}/refresh`. The word "refresh" makes it sound like a repaint, but a browser reload is defined in terms of the request: the browser **re-issues the request that produced the current document**, with the same method and the same body. If that request was a `GET`, the reload is a harmless `GET`. If it was a `POST`, the reload is another `POST` carrying the same form fields. That single fact is the whole answer. Nothing in Selenium replays your test steps; the browser replays one HTTP request, and which request it replays is decided entirely by how the tab reached the page it is showing. ## Why the intake form creates a second claim Take a claim intake suite whose last step submits the form: 1. The test fills the intake form and clicks Submit. 2. The browser sends `POST /claims` with the policy number, incident date and loss description. 3. The server creates claim `CLM-8842` and **renders the confirmation page directly in that response**, with no redirect. 4. The tab's current document is now, precisely, "the response to `POST /claims`". 5. The test calls `navigate().refresh()`, meaning only to re-check the confirmation. 6. The browser re-sends `POST /claims` with an identical body, and the server creates `CLM-8843`. The test may still go green — a confirmation page is on screen — while quietly doubling the records it created. That is what makes this a production problem rather than a red test: the damage is in the data, not in the report. | How the current document was produced | What a reload re-sends | Effect on the claim intake | |---|---|---| | `GET /claims/CLM-8842` | The same `GET` | Page re-renders, nothing is created | | `POST /claims` rendered directly | The same `POST`, body included | A second claim, or a duplicate-key error | | `POST /claims` answered with a redirect | The `GET` of the redirect target | Page re-renders, nothing is created | ## The history calls reach the same entry `navigate().back()` followed by `navigate().forward()` can land the tab back on that POST-produced entry and trigger the same replay. "Go back and come forward again" is therefore not a safer substitute for a reload; it is the same hazard reached by two commands instead of one. Any step that returns a suite to a page produced by a non-idempotent request deserves the same scrutiny as the reload does. ## The browser's prompt is a warning, not a fix Browsers do not silently replay a `POST`: they interpose a confirmation before resubmitting, and the exact shape of that guard differs between browsers and between headed and headless runs. Two consequences for a suite: - Where the prompt appears, the navigation does not complete on its own and the run can stall until the dialog is dealt with. Dialog handling is a separate part of Selenium's API. - Where the prompt is answered, dismissed automatically or simply absent, the `POST` goes through and the duplicate claim is created. Either way the prompt is a signal that the step is unsafe. Do not design around answering it. ## Writing the step so it is safe to repeat - **Never use `refresh()` as a synchronisation hammer.** "The page looked incomplete, so I reloaded it" is how this defect is usually introduced. - **Capture the address, then re-open it.** Read `driver.getCurrentUrl()` immediately after the submit and re-visit it with `driver.navigate().to(url)`. That is a `GET`, and a `GET` can never replay the submission. - **Prefer a redirect in the application.** When `POST /claims` answers with a redirect to `/claims/CLM-8842/confirmation`, the confirmation has its own `GET` address and reloading is safe for users and tests alike. Testers who hit this are often the first to notice the application is missing that redirect. - **Assert on the created record's identity.** Pulling the claim reference out of the confirmation and asserting on it catches a duplicate that a "the confirmation is visible" assertion never will. - **Reserve `refresh()` for pages the tab reached by a `GET`** — a claim list, a dashboard, a status page — where replaying the request is exactly what you want. ## How it shows up when you were not expecting it The symptoms are recognisable once you have seen them: two claims a minute apart with identical field values; a unique-constraint error on the second attempt where the first attempt passed; a confirmation whose reference number changes every time you reload it; or a failure that only appears on the machine where the suite reloads a page before retrying a step. All of them point back to reloading a document that a `POST` produced.
- When is calling navigate().refresh() in a test perfectly safe?When the current document was produced by a `GET` — a claim list, a dashboard, a status page. Reloading repeats that `GET` and creates nothing. The hazard belongs to documents produced by a non-idempotent request, so the question to ask before every reload is how the tab reached this page.
- Does back() followed by forward() avoid the resubmission problem?No. Both are history commands, and either can land the tab on the entry a `POST` produced, so the browser faces the same choice: replay the submission or prompt. Re-opening the confirmation's own address with `navigate().to(...)` is the only one of these guaranteed to be a `GET`.
- How would you prove a suite has been silently creating duplicate claims?Look for groups of records with identical field values and near-identical timestamps for a single run, and have the intake step capture the claim reference it received so a second reference after a reload is an outright failure. A unique constraint on a natural key turns the silent duplicate loud.
Refreshing after a submit is like handing the clerk the same signed claim form a second time: the browser is not showing you a saved copy, it is filing the form again.
saying these in an interview costs you the question
- Believing refresh only repaints and never sends a request
- Using refresh as a wait when a page looks incomplete
- Assuming the browser's resubmission prompt makes the step safe
- Thinking back then forward avoids replaying the POST
- Calling the test green because a confirmation page rendered again