skip to content

What does Cypress's .as('total', { type: 'static' }) store that a default alias does not?

level: middleimportance: nice to knowfreq 24%

answer

  1. The option nobody reads until they need it
  2. Freshness is a choice, not a fixed rule
  3. Second argument to .as() is an options object
  4. One setting makes an alias stop re-deriving
  5. No effect on routes, spies and stubs

basics

~20 s

A static alias stores the resolved value once, at the moment .as() runs, instead of the query chain that produced it. cy.get('@total') then returns that frozen value on every read rather than re-deriving it from the page.

solid answer

~40 s

`.as()` accepts an options object whose only key is `type`, and it defaults to `'query'`. A query alias records the chain of queries that produced the subject, and `cy.get('@total')` re-runs that chain on every read — which is what you want for a DOM element that re-renders under the test. `{ type: 'static' }` resolves the subject once when `.as()` executes and stores the value itself, so later reads return exactly what was there at alias time even if the page has moved on. That makes it the tool for capturing a before value you intend to compare with an after value. Two limits are worth remembering: `type` accepts only `'query'` or `'static'` and errors on anything else, and it has no effect when you alias an intercepted route, a spy or a stub.

go deeper

for a junior

You are unlikely to be asked this, but knowing that Cypress's .as() takes a second options argument at all is a good sign you have read the command's documentation rather than copied a snippet.

for a middle

Be able to say what a Cypress alias stores by default, what the static type replaces it with, and give one honest use for freezing a value rather than re-deriving it.

for a senior

Show judgement about when freezing is right. Capturing a before value for a comparison is a fair use; freezing a DOM element you will click later is a trap you pay for on the next re-render.

for a principal

The wider point is that Cypress makes freshness an explicit per-alias decision. A written team rule about which subjects may be frozen is cheaper than relitigating it in every code review.

## The option, and its default `.as()` takes an optional second argument: an options object whose only key is `type`. ```javascript cy.get('[data-cy=loan-count]').invoke('text').as('countBefore', { type: 'static' }) ``` As of Cypress 16, `type` accepts exactly two values, `'query'` and `'static'`, and it defaults to `'query'`. Anything else is rejected immediately with `.as() only accepts a type of 'query' or 'static'`, and a second argument that is not a plain object is rejected with `.as() only accepts an options object for its second argument`. There is no third mode and no project-wide default to change. ## What each type stores - **`'query'`, the default,** stores the *subject chain* — the sequence of queries that produced the subject. Every later `cy.get('@countBefore')` re-runs that chain against the page as it stands at that moment. - **`'static'`** resolves the chain once, when `.as()` executes, and stores the resulting value. Later reads hand back that stored value unchanged, whatever has happened to the page since. The difference only shows up when the underlying thing changes. If the subject is a constant, the two behave identically and the option is noise. ## When freezing is the right call The honest use is a **before-and-after comparison**, which is otherwise awkward in a runner where you cannot assign a command's result to a variable: 1. Capture the value you want to compare, aliased with `{ type: 'static' }`, before you touch anything — a borrow count, a shelf total, a timestamp the page renders once. 2. Do the thing that changes it: borrow a book, return one, apply a catalogue filter. 3. Read the frozen alias and the live element together inside a `.then()` callback and assert on the pair. Without `'static'`, step three would re-read the element through the stored chain and you would be comparing the new value with itself. ## When it is the wrong call - **A DOM element you will act on again.** A static element alias stores the jQuery object captured at alias time. Once the application re-renders that row, later reads hand back a node the page has already replaced. Leave element aliases on the default. - **An intercepted route, a spy or a stub.** `type` has no effect on these at all. Cypress stores them through their own mechanism, so `{ type: 'static' }` beside `cy.intercept(...).as('search')` changes nothing. - **As a habit.** Freezing by default removes the property that makes aliases pleasant in a re-rendering application: that a name keeps meaning the current thing. ## What it looks like in the Command Log A static alias is labelled with its type appended to the name — `@countBefore (static)` — while a default alias shows only `@countBefore`. That marker is worth knowing, because it is the one place the choice is visible when you are reading someone else's failing run, and it tells you whether a stale-looking value was frozen deliberately or is a bug. ## Quick comparison | | default `{ type: 'query' }` | `{ type: 'static' }` | |---|---|---| | what is stored | the subject chain | the resolved value | | a later read | re-runs the chain | returns the stored value | | after a re-render | finds the current element | holds the captured one | | agrees with `this.name` | only while nothing changes | always | | effect on routes, spies, stubs | none | none | ## Relationship to `this.name` `this.name` was always a snapshot: Cypress writes the resolved subject onto Mocha's test context when `.as()` runs and never touches it again. So `{ type: 'static' }` does not change `this.name` — it changes `cy.get('@name')` so that the two read paths agree. Read the other way round, the default `'query'` type is the whole reason `cy.get('@name')` and `this.name` can disagree, and knowing that is usually more useful in an interview than the option itself. Neither type extends the alias's life. A static alias is cleared before the next test exactly like a query alias. The option decides what a name **means** while the test runs, not how long the name exists, which is why reaching for `'static'` never helps with a value you want in the next test.

  • When is a static Cypress alias the wrong choice?
    Whenever the subject is a DOM element the test will touch again. A static element alias freezes the jQuery object captured at alias time, so a later read hands back a node the application has already replaced and the command acts on something that is no longer on the page. Leave element aliases on the default `{ type: 'query' }` so each read re-queries.
  • Does { type: 'static' } change what this.total holds in a Cypress test?
    No. `this.total` is already a snapshot taken when `.as()` ran, whichever type you pass. The option only changes `cy.get('@total')`: with `'static'` the two read paths agree, and with the default `'query'` they can disagree the moment the underlying subject changes.

saying these in an interview costs you the question

  • Thinks every Cypress alias caches its value by default
  • Passes type: 'value' or type: 'snapshot' to .as()
  • Expects { type: 'static' } to change an intercept alias
  • Uses a static alias for an element that re-renders
  • Believes a static alias survives into the next test