How do a Cypress `cy.intercept()` routeMatcher's `url`, `path` and `pathname` differ?
answer
- One field sees the whole request URL
- Two fields differ only by the query string
- Only one field gets a second matching attempt
- Query parameters can be matched by name
- Host and port are separate matcher fields
basics
~10 sIn a Cypress routeMatcher, url is the full request URL including protocol and host, path is everything after the hostname with the query string, and pathname is that path without the query string.
solid answer
~40 sCypress parses the outgoing request and matches each `routeMatcher` field against its own piece of it. For `https://weather.example.com/api/forecast?station=KSEA`, `url` sees the whole string, `path` sees `/api/forecast?station=KSEA`, and `pathname` sees `/api/forecast`. `url` is the only field with a fallback: a pattern is tried against the full URL and then against the path, which is why a host-less glob such as `/api/forecast*` is portable across `localhost`, staging and production. Once a query string carries several parameters or encoded characters, prefer `pathname` plus a `query` object — `pathname` never contains the query string, so escaping and parameter order stop mattering, and each `query` value is itself a glob or `RegExp`. Set `hostname`, `port` or `https` when a route must be pinned to one origin.
go deeper
Recall the three names and what each one covers, and that a routeMatcher can pin far more than a URL string can.
Explain the parsed pieces Cypress compares against, and why url alone is loose about host and port while pathname is exact about the path.
Show when you would move a route off a full-URL glob onto pathname plus query, and justify it by the encoded query strings and parameter ordering that break globs in real suites.
Own the portability question: which fields a suite may pin so specs run unchanged against local, preview and production origins, and where pinning a host is a deliberate safety rail.
A Cypress `routeMatcher` describes a request by parts. Before matching, Cypress parses the outgoing URL and builds a *matchable* object from it, then compares each property you set against the corresponding piece. Getting `url`, `path` and `pathname` straight is what stops a route from matching too much or nothing at all. ## What each field sees For the request `GET https://weather.example.com:8443/api/forecast?station=KSEA&units=metric`: | Field | Value it is matched against | | --- | --- | | `url` | `https://weather.example.com:8443/api/forecast?station=KSEA&units=metric` | | `path` | `/api/forecast?station=KSEA&units=metric` | | `pathname` | `/api/forecast` | | `query` | `{ station: 'KSEA', units: 'metric' }` | | `hostname` | `weather.example.com` | | `port` | `8443` | | `https` | `true` | `url` is the whole thing. `path` is everything after the hostname **including** the query string. `pathname` is the same minus the query string. `query` is the parsed query object, matched key by key. ## The url field's extra fallback `url` is the only field with a second chance. A glob or `RegExp` given as `url` is tried against the full URL first, and if that fails it is tried again against `path`. Nothing else behaves this way — a pattern set on `pathname` is only ever compared to the pathname. That fallback is what makes host-less patterns portable, and it is also why `url` can feel loose: `cy.intercept('/api/forecast*')` will match on any host and any port your dashboard happens to be served from. When you *want* that, `url` is the right field. When you want the route pinned, say so explicitly with `hostname`, `port` or `https`. ## Why pathname plus query beats a long URL glob Once a query string carries encoded characters or several parameters whose order is not guaranteed, a full-URL glob becomes a puzzle: you have to escape the `?`, tolerate parameters arriving in either order, and cope with percent-encoding. Splitting the two concerns removes all of that: ```js // brittle: the glob has to be right about every character after the path cy.intercept('/api/forecast\\?station=KSEA&units=metric') // sturdier: the path is matched structurally, the parameters by name cy.intercept({ method: 'GET', pathname: '/api/forecast', query: { station: 'KSEA', units: 'metric' }, }) ``` - `pathname` never contains the query string, so encoded parameters cannot interfere with path-segment matching. - Each `query` value is itself a string matcher, so `query: { station: 'K*' }` or `query: { units: /metric|imperial/ }` are both legal. - Properties you leave out are not consulted, so the second route above still matches when a third parameter appears — a full-URL glob usually would not. ## Field-specific rules that surprise people 1. **`hostname` is validated.** A string `hostname` must be a real host or domain name. `hostname: 'https://weather.example.com'` throws with *"`hostname` must be a valid host name or domain name"*; pass just `weather.example.com`, or a `RegExp` when you need a pattern. 2. **`headers` keys are lowercased.** HTTP header field names are case-insensitive, so Cypress lowercases the matcher; naming the same header twice in different cases is rejected as a duplicate. 3. **`query` compares each parameter to a single value.** It therefore cannot express a repeated, array-style parameter such as `?ids[]=1&ids[]=2`. Match those with a `RegExp` `url`, or with a request handler that reads the repeated values through the browser's `URLSearchParams.getAll()`. 4. **`port` takes a number or an array of numbers**, and `https` is a plain boolean — neither is a string matcher, so globs do not apply to them. ## Choosing a field - Matching a whole family of endpoints across hosts? `url` with a glob. - Matching one endpoint precisely, whatever its parameters? `pathname`. - Distinguishing two calls to the same endpoint? `pathname` plus `query`. - Keeping a route off third-party traffic? Add `hostname`, and `https` or `port` if the environment makes them meaningful.
- Why does a Cypress `cy.intercept()` `query` matcher fail to match `/api/stations?ids[]=1&ids[]=2`?The `query` matcher compares each named parameter against a single string value, so a repeated, array-style parameter has no single value to compare and the route never matches. Match that request with a `RegExp` on `url` instead, or intercept on `pathname` and read the repeated values in a request handler through the browser's `URLSearchParams.getAll()`.
- What happens if you pass `hostname: 'https://weather.example.com'` to a Cypress routeMatcher?It throws with a message that `hostname` must be a valid host name or domain name. `hostname` is validated as a host, not parsed as a URL, so the scheme has to go. Pass `weather.example.com`, and if you genuinely need a pattern across subdomains, pass a `RegExp` instead of a string — regular expressions skip that validation.
saying these in an interview costs you the question
- Thinks pathname includes the query string
- Believes every matcher field falls back to the path
- Puts a full URL with scheme into the hostname field
- Expects a query matcher to handle repeated array parameters
- Assumes port must be given as a string matcher