In Selenium, what does By.partialLinkText match that By.linkText does not?
answer
- One tag, and only one, is eligible
- What the user sees, not the markup
- One compares the whole thing
- The other only needs a piece of it
- Exact match is trimmed and case sensitive
basics
~10 sSubstrings. Both strategies look only at anchor elements and compare their visible text, but By.linkText needs the whole trimmed text to equal the value, while By.partialLinkText matches any anchor whose text contains it.
solid answer
~40 sBoth `By.linkText` and `By.partialLinkText` are genuine W3C locator strategies, and both begin by collecting every `<a>` element in the search context. No other tag can match, so a `<button>` or a `<span>` styled as a link is invisible to them. For each anchor they take the *rendered* text — the same value `WebElement.getText()` returns — so markup and CSS-hidden text do not count. `By.linkText` trims leading and trailing whitespace and then requires exact, case-sensitive equality. `By.partialLinkText` runs a containment test instead, so `By.partialLinkText("recall")` matches an anchor reading `Send recall reminder` and another reading `Cancel recall`. Every exact match is also a partial match; the reverse is not true.
go deeper
Recall that both strategies only ever see anchor elements and that one needs the whole visible text while the other needs a fragment. Being able to state the anchor-only rule out loud is most of the answer.
Explain the algorithm: collect the anchors, read the rendered text rather than the markup, trim then compare for equality, or test containment. Note that the comparison is case sensitive.
Show how you diagnose a link-text lookup that finds nothing on a page where the text is visible, working from element type through rendered text to nested badge markup before blaming timing.
Be able to explain why the specification carries two text strategies at all: CSS has no text matcher, so text addressing had to be built into the protocol rather than layered on top of a selector engine.
## Both strategies start by collecting anchors `By.linkText` and `By.partialLinkText` are two of the five locator strategies the **W3C WebDriver** specification defines, so in Selenium they are sent to the remote end as the keywords `link text` and `partial link text` with no client-side rewriting. Their specified algorithms begin identically: call `querySelectorAll` on the start node with the argument `"a"`, then filter that list by text. That first step is the fact most candidates miss. The candidate set is **anchor elements only**. On a dental-practice recall list, this markup is reachable by link text: ```html <a href="/recall/4821/remind">Send recall reminder</a> ``` and none of these ever are, however they are styled: ```html <button type="submit">Send recall reminder</button> <span class="link" data-action="remind">Send recall reminder</span> <input type="submit" value="Send recall reminder"> ``` ## Rendered text, not markup The value compared is not the anchor's `innerHTML` and not its source text. The specification says to use the value **Get Element Text** would return for the element — the same string `WebElement.getText()` gives you. That has three consequences: - Whitespace in the source is collapsed the way the browser renders it, so a link split across three source lines still matches its one-line displayed text. - Text hidden by CSS is not part of the rendered text, so a screen-reader-only span inside the anchor does not have to appear in your value. - Nested markup disappears. `<a href="/recall/4821"><strong>Amelia</strong> Fox</a>` renders as `Amelia Fox`, and that is what both strategies compare against. ## Exact versus substring | | `link text` | `partial link text` | |---|---|---| | Candidate elements | `a` elements only | `a` elements only | | Text compared | rendered text | rendered text | | Whitespace trim | leading and trailing whitespace removed first | no trim step | | Match test | string equality with the value | value must be contained in the text | | Case sensitivity | case sensitive | case sensitive | Neither strategy does anything clever with case, accents or normalisation. `By.linkText("send recall reminder")` does not match an anchor rendering `Send recall reminder`. ## Working the recall list Given a recall table whose rows each carry `Send recall reminder`, `Book hygiene appointment` and `Cancel recall`: 1. `By.linkText("Send recall reminder")` requires the whole trimmed rendered text to equal that string. An anchor reading `Send recall reminder (overdue)` does not match. 2. `By.partialLinkText("recall")` matches both `Send recall reminder` and `Cancel recall`, because containment is tested against the whole rendered string, not against word boundaries. 3. `By.partialLinkText("Send recall reminder")` matches everything `By.linkText` would, plus anything with that text as a substring. Every exact match is also a partial match, never the other way round. ## The failure mode to recognise When a link-text lookup finds nothing on a page where the text is plainly on screen, work through the causes in this order: - **Is the element an `<a>` at all?** A `<button>`, a `<div role="link">` or an `<input type="submit">` is structurally invisible to these strategies. This is the single most common cause. - **Does the rendered text match exactly, including case?** Copy the value out of the rendered page rather than the source. - **Is there extra rendered text inside the anchor?** A badge span such as `<span>2</span>` inside the anchor becomes part of the rendered text and breaks an exact match, while `By.partialLinkText` survives it. - **Are you using the right strategy for the shape of the text?** Anything that varies at runtime — a patient name, an overdue count — has to be handled by containment or by a different strategy entirely. ## What these strategies are not They are not shorthand for a CSS or XPath expression, and they are not rewritten before the request. Unlike `By.id`, `By.name` and `By.className`, which have no wire keyword and are converted to `css selector` by the client, `By.linkText` and `By.partialLinkText` extend the W3C-aligned base class and are executed by the remote end using their own algorithms. There is no CSS selector that expresses them: CSS has no text-content matcher, which is exactly why the specification carries these two strategies separately. Two further properties follow from the algorithms themselves: - **The value is text, not a selector.** It is compared character for character, so dots, brackets, hyphens and quotes inside it carry no special meaning and need no escaping, unlike the values `By.id` and `By.className` hand to their CSS fallbacks. - **Neither strategy has a CSS equivalent.** `By.id`, `By.name` and `By.className` are rewritten into `css selector` precisely because an equivalent selector exists for each of them. No CSS selector matches on rendered text, which is why these two had to be standardised as keywords of their own.
- Does By.partialLinkText trim whitespace the way By.linkText does?No. The specification trims the rendered text before the equality test for `link text`, but the `partial link text` algorithm runs a plain containment test on the untrimmed rendered text. The difference rarely shows in practice, because a substring search over padded text still finds the substring.
- How do you target a link-styled button in a recall table with these strategies?You cannot. Both algorithms collect `a` elements and nothing else, so a `<button>` never enters the candidate set however it is styled. `By.linkText` will report no match for a structural reason, not a text one, and the element has to be addressed by some other strategy.
- What happens when two anchors share the same partial text?Both are candidates. `partial link text` returns every anchor whose rendered text contains the value, so `By.partialLinkText("recall")` collects the reminder link and the cancel link alike. Narrowing to one of them is a matter of choosing a more specific value or a different strategy.
saying these in an interview costs you the question
- Says By.linkText matches any element showing that text
- Thinks By.partialLinkText matches against the href, not the text
- Believes link text reads raw HTML including hidden markup
- Claims By.linkText does a substring match like partial does
- Assumes both strategies are rewritten into CSS before sending