In Selenium, why does WebElement.sendKeys append rather than replace an input's existing value?
answer
- The command emulates a person typing
- Nothing in it resets the field
- Focus decides where the caret lands
- Caret set after the current value length
- clear() is the separate resetting command
basics
~20 sSend Keys never resets the field. When the input is not already focused the driver focuses it and puts the caret after the existing text, then types character by character, so the new characters land on the end.
solid answer
~40 sThe Element Send Keys command emulates a person typing, and a person typing into a box that already holds text does not empty it first. If the element is not the active element the remote end focuses it and sets the insertion caret using the current value length as both the selection start and end, so the caret sits after the existing text; if the element already had focus the caret is left exactly where it was. The characters then arrive through a key input source as `keyDown`/`keyUp` pairs. To replace a value you call `WebElement.clear()` first, which invokes the HTML clear algorithm rather than typing, or you type over a selection.
code
java · 24 linesimport org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class KbSearchTyping {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("https://helpdesk.example.com/kb");
WebElement search = driver.findElement(By.id("kb-search"));
search.sendKeys("printer");
search.sendKeys(" jam");
System.out.println("field now holds: printer jam");
search.clear();
search.sendKeys("vpn client", Keys.ENTER);
} finally {
driver.quit();
}
}
}go deeper
Recall the habit: call clear before sendKeys whenever you mean to replace a value, and never assume a field starts empty just because the previous test finished.
Explain the mechanics. Say that the caret is placed after the existing value when the element was not focused, that the characters arrive as key events, and that clear is a different command with a different mechanism.
Show how this bites in a shared-fixture suite: reused fields, restored drafts and autofill all leave text behind, and the resulting concatenated query fails somewhere far from the typing step.
Own the convention. Decide once whether the team replaces values by clearing or by typing over a selection, and make the reason - what each approach actually dispatches - part of review rather than folklore.
## What Element Send Keys does before a single character arrives `WebElement.sendKeys(CharSequence... keysToSend)` maps to the **Element Send Keys** command. Before it types anything the remote end scrolls the element into view, waits for it to become **keyboard-interactable** (an element with a focusable area), and, if the element is not already the active element, runs the focusing steps on it. Nothing in that sequence resets the field. The command's name is honest: it *sends keys*, in the same sense that a person sitting at the keyboard sends keys. ## Where the caret goes, and therefore where the text lands 1. If the element did **not** already have focus, the driver focuses it and sets the text insertion caret using the current length of the element's value as **both** the start and the end of the selection - that is, immediately after the existing text. 2. The string is then broken into grapheme clusters and dispatched through a key input source: a `keyDown` and a `keyUp` for each typeable character, with a synthetic shift press around characters that need one. 3. If the element **did** already have focus, the caret is not repositioned; the characters go wherever the caret happens to sit, which after a previous `sendKeys` is the end of what you typed last. So on a helpdesk knowledge-base search box, `search.sendKeys("printer")` followed by `search.sendKeys(" jam")` leaves `printer jam`, and a second test that reuses the same field without resetting it leaves `printer jamvpn`. There is no step anywhere in the command that would have produced `vpn` alone. ## `clear()` is a different mechanism, not a convenience `WebElement.clear()` maps to **Element Clear**, and it does not type. For a mutable form control it runs the focusing steps, invokes the HTML clear algorithm that resets the control's value, and then runs the unfocusing steps. There is no key input source involved at all, so no per-character key events are produced. It also has a genuine no-op path: if the field is already empty and satisfies its constraints, the steps abort **before** focusing, so `clear()` on an empty box does not even move focus. | Aspect | `sendKeys("vpn")` | `clear()` | |---|---|---| | Mechanism | A key input source, one `keyDown`/`keyUp` pair per character | The HTML clear algorithm sets the value directly | | Existing text | Left in place; new text is appended at the caret | Reset to empty | | Focus | Focuses if not already active, and leaves it focused | Focuses, clears, then unfocuses | | Already-satisfied case | Types normally into an empty field | Aborts without focusing at all | | Non-editable target | Rejected as not interactable | Rejected with an invalid element state error | ## Keys that are not characters The same call carries non-printing keys, because `Keys` implements `CharSequence` and each constant is a single private-use code point: - `Keys.ENTER` (U+E007) and `Keys.RETURN` (U+E006) commit a search the way a keyboard user would. - `Keys.TAB` (U+E004) moves focus on, which is how you leave a field so its blur-driven validation runs. - `Keys.BACK_SPACE` (U+E003) deletes one character at the caret, the only per-keystroke way to shorten a value. - `Keys.chord(CharSequence...)` concatenates its arguments and appends `Keys.NULL` (U+E000); the remote end treats that null as the signal to release any modifier it is still holding. One Java-side detail is worth carrying into an interview: `RemoteWebElement.sendKeys` joins the varargs with `String.join("", keysToSend)` and sends **one** command. `search.sendKeys("printer jam", Keys.ENTER)` is a single Element Send Keys carrying the text plus U+E007, not two round trips. ## Ordering rules that survive contact with a real suite - Call `clear()` before `sendKeys` whenever you mean to *replace* a value; assume nothing about the field's starting state. - Never reuse a search box across steps and hope it is empty - a previous step, an autofill, or a restored draft all leave text behind. - Send the committing key in the same call as the text when you want one command, and in a separate call when you want to inspect the field between typing and committing. - Passing an empty varargs array throws `IllegalArgumentException` from the Java client before any command is sent, so an accidental `sendKeys()` fails loudly rather than silently doing nothing.
- What happens if you call sendKeys twice in a row without the element ever losing focus?The caret is only repositioned when the element was not already the active element, so the second call types from wherever the caret was left - the end of the first call's text. You get one concatenated value, and no focus or blur handling runs between the two calls.
- How does a single sendKeys call carry both text and the Enter key?`Keys` implements `CharSequence` and each constant is one private-use code point, so `Keys.ENTER` is just U+E007. The Java client joins the varargs into one string and sends a single Element Send Keys command, which dispatches the printable characters and then the Enter key through the same key input source.
- Does sendKeys do anything before it types?Yes. It scrolls the element into view, waits for it to become keyboard-interactable, and focuses it if it is not already the active element. Only then does it dispatch key events. None of those steps empties the field.
saying these in an interview costs you the question
- Believes sendKeys replaces whatever the field already held
- Thinks clear is only a tidiness habit, not a reset
- Assumes the caret always starts at position zero
- Says Keys.ENTER needs its own separate sendKeys call
- Expects sendKeys to fail on a field that is not empty