skip to content

What are the three ways to call Cypress's `cy.intercept()`, and what does each match?

level: juniorimportance: must knowfreq 78%

answer

  1. Three call shapes, one command
  2. The URL is not the only matcher
  3. Omitting one argument is very permissive
  4. An object matcher ANDs its properties
  5. There is a url-plus-matcher merge form

basics

~10 s

Cypress accepts cy.intercept(url), cy.intercept(method, url) and cy.intercept(routeMatcher). A bare url matches every HTTP method; the method form narrows it to one; the routeMatcher object matches fields such as pathname, query and headers together.

solid answer

~40 s

`cy.intercept()` has three matching signatures. `cy.intercept('/api/forecast*')` takes a URL — a string treated as a glob, or a `RegExp` — and matches it on **any** HTTP method, which is the usual first surprise. `cy.intercept('GET', '/api/forecast*')` adds a method, so a `POST` to the same path no longer matches. `cy.intercept({ method: 'GET', pathname: '/api/forecast', query: { station: 'KSEA' } })` passes a `routeMatcher` object: every property you set must match, and properties you leave out are ignored rather than treated as wildcards you forgot. There is also a merge form, `cy.intercept(url, routeMatcher, handler)`, that layers extra matcher fields onto a URL and requires the handler as its third argument. An empty object or an unknown property throws, so a typo fails loudly instead of matching nothing.

code

javascript · 13 lines
javascript
cy.intercept('/api/forecast*')

cy.intercept('GET', '/api/forecast*')

cy.intercept({
  method: 'GET',
  pathname: '/api/forecast',
  query: { station: 'KSEA' },
})

cy.intercept('/api/stations*', { times: 1 }, (req) => {
  req.continue()
})

go deeper

for a junior

Be ready to write all three call shapes from memory and to say out loud that a URL-only intercept matches every HTTP method, not just GET.

for a middle

Explain that a string url is glob-matched against the full URL and then against the path, and that routeMatcher properties are ANDed rather than ORed.

for a senior

Show judgement about which signature belongs in a spec: when a method is worth pinning, and when a path serving several verbs makes a bare URL route a source of confusing extra matches.

for a principal

Be able to argue for a single house signature across a large suite, weighing readability of the short forms against the precision the object form gives when APIs move host or grow query parameters.

`cy.intercept()` registers a **route** — a description of the network requests a Cypress test cares about. Everything you pass *before* the optional response argument is matching: it decides which of the weather dashboard's requests belong to this route. Cypress accepts that description in three shapes, plus one merge form. ## The three signatures | Signature | Example | What it matches | | --- | --- | --- | | `cy.intercept(url)` | `cy.intercept('/api/forecast*')` | that URL on **every** HTTP method | | `cy.intercept(method, url)` | `cy.intercept('GET', '/api/forecast*')` | that URL, restricted to `GET` | | `cy.intercept(routeMatcher)` | `cy.intercept({ method: 'GET', pathname: '/api/forecast' })` | every property set on the object, ANDed | The `url` argument is a **string glob** or a **`RegExp`** — never a plain substring. A string is first compared for equality, then glob-matched (Cypress uses the minimatch library with `{ matchBase: true }`, exposed to you as `Cypress.minimatch`) against the **full request URL**, and finally against the **request path** as a fallback. That fallback is why a host-less pattern such as `/api/forecast*` matches `https://weather.example.com/api/forecast?station=KSEA`, `http://localhost:8080/api/forecast?station=KSEA`, and the same route on staging. Cypress reads the first argument as a method only when it genuinely **is** one — `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`, and `QUERY`, which Cypress added in 15.20.0. So `cy.intercept('/api/stations', handler)` is unambiguously the `(url, handler)` overload. ## Why leaving the method out bites A method-less route is the widest thing you can register, and on a dashboard where one path serves several verbs it quietly catches more than you meant: ```js cy.intercept('/api/alerts*') // spies on GET /api/alerts?station=KSEA // ...and on POST /api/alerts, when the user dismisses an alert ``` - Add the method whenever a path serves more than one verb. - A method-less route is fine, and often preferable, when the path is read-only. - In the object form, `method` is a string matcher too, so `method: '+(PUT|PATCH)'` — a minimatch alternation group — or a `RegExp` both work. Those only work inside a `routeMatcher`; the `(method, url)` overload accepts real HTTP method names only. ## The routeMatcher object Every property is optional and **all the ones you set must match**; they are ANDed together, and properties you leave out are simply not consulted. The object is where you match on things a URL string cannot express: - `method`, `url` — the same two things the short signatures set. - `path` (everything after the hostname, query string included) and `pathname` (the same, without the query string). - `hostname`, `port` (a number or an array of numbers), `https` (a boolean). - `query` and `headers` — dictionaries whose *values* are themselves globs or regular expressions. - `auth` — the username and password from HTTP Basic credentials. - `middleware` and `times`, which change **when** and **how often** the route is consulted rather than what it matches. - `resourceType`, deprecated since Cypress 14. Two validation rules are worth committing to memory, because both fail loudly rather than silently: 1. `cy.intercept({})` throws — *"The RouteMatcher does not contain any keys. You must pass something to match on."* There is no "match everything" empty object. 2. An unrecognised property throws and prints the valid list, so a typo such as `pathName` surfaces immediately instead of matching nothing. ## The merge form There is a fourth call shape that layers extra matcher fields onto a URL: ```js cy.intercept('/api/forecast*', { middleware: true }, (req) => { /* ... */ }) ``` `cy.intercept(url, routeMatcher, handler)` merges the two matchers, so the object must **not** also carry a `url` key, and the handler is **required** as the third argument — passing only two arguments here throws rather than registering a spy. ## Choosing between them 1. Reach for `cy.intercept(method, url)` by default: it is the shortest thing that says which verb and which path, and it reads well in a spec. 2. Move to the object when the URL alone is ambiguous — two calls to `/api/forecast` that differ only by a `query` parameter, or a poller you want to separate by a request header. 3. Prefer `pathname` plus `query` over a long full-URL glob once the query string carries encoded values; the glob has to get every character right, while `pathname` never sees the query string at all. All intercepts are cleared before every test, so each of these is registered fresh per test and nothing you match in one spec leaks into the next.

  • What does Cypress do when a `cy.intercept()` routeMatcher carries a property it does not recognise?
    It throws immediately when the command runs, reporting the offending property and printing the full list of valid `RouteMatcher` properties. That turns a typo such as `pathName` for `pathname` into a visible failure at registration instead of a route that silently matches nothing for the rest of the spec.
  • Why does `cy.intercept('/api/alerts*')` also match a POST that the weather dashboard sends to `/api/alerts`?
    Because `method` defaults to matching every HTTP method. The one-argument signature constrains only the URL, so `GET`, `POST`, `PUT`, `DELETE` and the rest all match. Pass the method explicitly — `cy.intercept('GET', '/api/alerts*')` — or set `method` in a routeMatcher object whenever a path serves more than one verb.

saying these in an interview costs you the question

  • Thinks cy.intercept always requires an HTTP method argument
  • Assumes a bare URL string only matches GET requests
  • Believes every routeMatcher property must be set to match
  • Expects cy.intercept({}) to match all requests
  • Treats the url string as a plain substring match