Resource library

Automation Interview

Cypress Interview Questions for 2 Years Experience

Prepare Cypress interview questions for 2 years experience with core concepts, TypeScript examples, network stubbing, debugging scenarios, and model answers.

27 min read | 2,828 words

TL;DR

For a two-year Cypress interview, master how commands are queued, how queries and assertions retry, how subjects flow, and how to write independent tests with stable selectors. Practice `cy.intercept()`, fixtures, hooks, custom commands, TypeScript configuration, and scenario-based debugging with clear evidence.

Key Takeaways

  • At two years, interviewers expect command-queue, subject, retryability, selector, assertion, and test-isolation fundamentals.
  • Strong answers connect a Cypress API to a concrete failure mode instead of repeating definitions.
  • Use cy.intercept for controlled browser traffic and prove UI behavior as well as request details.
  • Explain hooks, fixtures, environment values, and custom commands without creating hidden shared state.
  • Know when an end-to-end test, component test, API check, or manual investigation is the better layer.
  • Prepare one small TypeScript repository and several honest debugging stories you can trace from symptom to verified fix.
  • Never claim that fixed waits, forced clicks, broad exception suppression, or retries are normal flake solutions.

Cypress interview questions 2 years experience candidates receive usually test whether daily automation habits are sound. You should be able to write a clear spec, explain the command queue and retryability, choose stable selectors, stub a network response, keep tests independent, and debug a failure without reaching first for a fixed wait.

Two years does not mean memorizing every command. It means having enough hands-on context to explain what Cypress does, what the application does, and where a test can become unreliable. Interviewers often start with a simple API definition and then add a realistic condition such as delayed data, duplicate text, a failed request, or CI-only behavior.

This guide gives you a preparation map, runnable TypeScript patterns, scenario questions, coding exercises, and model answers. Adapt the examples to your real project rather than presenting them as work you did.

TL;DR

Interview area What a strong two-year answer demonstrates
Cypress execution Commands are queued, subjects are yielded, and chains are not ordinary Promises
Retryability Queries and assertions retry, while state-changing commands run once
Locators Stable owned attributes and scoped, intention-revealing queries
Network Intercepts registered before traffic, narrow matching, alias waits, visible outcome
Isolation Each test creates or restores its required state and survives independent execution
Framework basics Typed configuration, focused helpers, small command catalog, safe secrets
Debugging Evidence from Command Log, request details, screenshots, console, and CI environment

1. What Cypress interview questions 2 years experience roles test

A two-year engineer is usually expected to own individual automation stories with review, diagnose common failures, and contribute to an existing framework. The interview should not require the same portfolio governance or migration strategy expected from a staff engineer. It should reveal whether you understand the code you run every week.

Expect questions in four forms:

  1. Definition: "What is retryability?"
  2. Comparison: "What is the difference between .then() and .should()?"
  3. Coding: "Stub this request and verify the table."
  4. Scenario: "This passes locally but fails in CI. What do you inspect?"

A weak answer names a tool. A stronger answer states the behavior, a valid use, and a risk. For example: "cy.intercept() observes or stubs matching browser requests. I register it before the action, use a narrow route matcher, alias it, and assert the UI outcome. I do not treat a stubbed test as proof that the real backend is integrated."

Be ready to explain one test from setup to teardown. Identify where test data comes from, how the browser reaches the initial state, how selectors are chosen, what request is expected, what the assertion proves, and what artifacts appear on failure. If another engineer cannot run the test alone or understand its failure, the framework has a problem.

Interviewers also evaluate communication. State assumptions before coding, use safe synthetic data, and say when a requirement is unclear. Accuracy beats speed.

2. Understand the Cypress command queue and retryability

Cypress commands are enqueued for later execution. They yield subjects to the next command in a chain, but they do not synchronously return application values and are not normal Promises to await.

This code is wrong:

let heading = ''

cy.get('h1').then(($heading) => {
  heading = $heading.text()
})

expect(heading).to.equal('Dashboard')

The normal expect runs while Cypress is still building its queue, so heading has not been assigned. Keep dependent work inside the chain or use a Cypress assertion:

cy.get('h1').should('have.text', 'Dashboard')

cy.get('h1').invoke('text').then((heading) => {
  expect(heading).to.equal('Dashboard')
})

Queries such as cy.get() and .find() link with assertions and retry until they pass or time out. Non-query commands execute once. Actions such as .click() include actionability checks, but Cypress does not repeatedly click just because a later assertion fails.

.should(callback) retries its callback, so the callback must be safe to run more than once. Do not put a side effect, API mutation, or click inside it. .then(callback) runs once when the prior chain resolves and is suitable for transforming a value or starting conditional setup that does not need assertion retrying.

A reliable pattern ends a chain after an action and starts a fresh query:

cy.get('[data-cy="save"]').click()
cy.get('[data-cy="status"]').should('have.text', 'Saved')

This lets the second query observe a re-rendered element. It is a simple answer that demonstrates you understand more than syntax.

3. Write stable selectors, actions, and assertions

A selector is a test contract. Prefer stable attributes controlled by your team, such as data-cy="submit-order", when the element has no clear accessible identity. Use semantic text and role-oriented queries when the project's supported query library makes the user-facing intent clearer. Avoid generated classes, deeply nested CSS, and indexes that change with layout.

Scope duplicate content to a stable container:

cy.contains('[data-cy="order-row"]', 'ORD-1042')
  .within(() => {
    cy.contains('button', 'Cancel').should('be.enabled').click()
  })

cy.contains('[data-cy="order-row"]', 'ORD-1042')
  .should('contain.text', 'Cancelled')

The action checks should reflect user behavior. Cypress waits for an element to be actionable before .click(). A forced click bypasses several checks and can hide an overlay, disabled state, or wrong viewport. Use { force: true } only for a documented interaction that truly cannot be performed normally, and explain why.

Assertions should prove the requirement. "Element exists" is weaker than "the user sees the correct order status." Choose should('be.visible'), should('have.value', ...), should('contain.text', ...), or a safe request assertion based on the outcome.

Avoid one giant chain across multiple application transitions. Re-query after actions that can re-render. Put assertion context near the business state, and keep failure messages understandable.

If you are comparing Cypress with another browser tool, read Selenium vs Cypress for test automation, then explain the tradeoff without declaring a universal winner.

4. Use cy.intercept for deterministic network scenarios

cy.intercept() can spy on or stub browser requests. Register it before the request begins, match narrowly, give it an alias, and assert both the request and the UI result.

describe('orders', () => {
  it('shows an order returned by the API', () => {
    cy.intercept(
      {
        method: 'GET',
        pathname: '/api/orders',
      },
      {
        statusCode: 200,
        body: [
          { id: 'ORD-1042', status: 'Ready' },
        ],
      },
    ).as('getOrders')

    cy.visit('/orders')

    cy.wait('@getOrders').then(({ response }) => {
      expect(response?.statusCode).to.equal(200)
    })

    cy.contains('[data-cy="order-row"]', 'ORD-1042')
      .should('contain.text', 'Ready')
  })
})

The route and response are application contracts. This test proves how the UI renders a controlled response, not whether the deployed API works. Keep a smaller number of unstubbed integration journeys for frontend-backend compatibility.

A negative scenario should assert recovery:

cy.intercept('GET', '/api/orders', {
  statusCode: 503,
  body: { code: 'ORDERS_UNAVAILABLE' },
}).as('ordersFailure')

cy.visit('/orders')
cy.wait('@ordersFailure')

cy.contains('[role="alert"]', 'Orders are temporarily unavailable')
  .should('be.visible')
cy.contains('button', 'Try again').should('be.enabled')

Know that cy.request() sends an HTTP request through Cypress rather than the application browser UI. It is useful for setup and API assertions, but cy.intercept() does not generally prove a cy.request() call. The Cypress cy.intercept examples provide focused patterns for route matchers and aliases.

In an interview, clarify whether the requested test is a stubbed UI scenario, a real end-to-end path, or an API test. That question demonstrates good test intent.

5. Manage hooks, fixtures, and test isolation

Use hooks for consistent setup that every test in the scope requires. A beforeEach() can visit the initial page or create fresh test data. Do not hide unrelated workflows in a global hook because the test becomes hard to understand and slower to debug.

type User = {
  id: string
  name: string
  role: 'viewer' | 'editor'
}

describe('user details', () => {
  beforeEach(() => {
    cy.fixture<User>('users/editor.json').as('editor')
  })

  it('shows the editor role', function () {
    cy.intercept('GET', '/api/users/current', {
      statusCode: 200,
      body: this.editor,
    }).as('currentUser')

    cy.visit('/profile')
    cy.wait('@currentUser')

    cy.get('[data-cy="user-name"]').should('have.text', this.editor.name)
    cy.get('[data-cy="user-role"]').should('have.text', 'editor')
  })
})

The function syntax is intentional when using Mocha's this context. An arrow function does not bind that context. Alternatively, avoid this and continue inside a .then() chain.

Fixtures are static data files, not a database reset system. They are good for controlled request bodies and reusable inputs. Dynamic records should be created through an approved API or task and use unique identifiers.

Test isolation means each test can run alone and in any order. Do not rely on a prior test to create an account, leave a page open, or set local storage. Cypress resets browser state between tests under its isolation model. Use cy.session() for a deliberately cached login setup when appropriate, with a distinct session ID and a meaningful validate callback.

The Cypress cy.fixture examples cover typed data and request stubbing without turning fixtures into hidden global state.

6. Explain configuration, environment values, and custom commands

Modern Cypress configuration uses defineConfig() in cypress.config.ts:

import { defineConfig } from 'cypress'

export default defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
    specPattern: 'cypress/e2e/**/*.cy.ts',
    retries: {
      runMode: 2,
      openMode: 0,
    },
  },
  defaultCommandTimeout: 8_000,
})

Do not claim that retries fix flaky tests. They can help detect and contain intermittent failures while the team investigates, but a passing retry still signals instability. Keep retry configuration visible and review failed attempts.

Use Cypress.env('name') for non-secret test configuration available to browser-side test code. Do not expose production secrets or service-role credentials to the browser process, command log, screenshots, or committed files.

Create a custom command only for a repeated, stable domain operation that benefits from the Cypress queue. A login command can cache an approved test session:

Cypress.Commands.add('loginAsEditor', () => {
  return cy.session(
    ['editor'],
    () => {
      cy.request('POST', '/api/test/login', {
        role: 'editor',
      })
    },
    {
      validate() {
        cy.request('/api/me').its('status').should('eq', 200)
      },
    },
  )
})

The endpoints are application-specific. Keep login separate from feature navigation, make the session key represent identity, and do not log tokens. For design detail, see Cypress custom commands.

Plain functions are better for pure data building. Do not add a command just to wrap one cy.get() or move every page action into a global support file.

7. Distinguish end-to-end, component, and API coverage

Cypress can run end-to-end tests and component tests with framework-specific mounting adapters. The correct layer depends on the risk.

Question Preferred starting layer
Does this component render validation for several prop states? Component test
Does checkout work through browser, frontend, API, and persistence? Focused end-to-end test
Does the orders endpoint reject an invalid status transition? API or service test
Does a payment provider callback update the order UI? Contract plus focused end-to-end test
Is the requirement visually ambiguous? Exploratory testing before automation

Component tests provide fast, controlled rendering of UI states. End-to-end tests prove deployed wiring and critical journeys but cost more to set up and debug. API tests cover many data and error combinations without browser overhead. A good suite uses these layers together.

At two years, you do not need to design an enterprise portfolio from scratch, but you should avoid putting every case into an end-to-end spec. Explain which user risk requires the browser and what can be checked closer to the code.

A simple component example depends on the installed framework adapter:

import { mount } from 'cypress/react'
import { SaveButton } from '../../src/SaveButton'

it('disables saving while a request is pending', () => {
  mount(<SaveButton pending={true} onSave={cy.stub()} />)
  cy.contains('button', 'Saving').should('be.disabled')
})

Use the adapter and project configuration that match the application. Do not claim cy.mount() exists automatically unless the support setup registers it. The Cypress component testing example explains that setup boundary.

8. Debug common Cypress failures and CI-only behavior

Start from evidence. The Command Log shows the last successful command and yielded subject. Inspect the matched request, response, screenshot, current URL, browser console, application logs, test data ID, and CI environment configuration.

For "element not found," ask:

  • Is the test on the expected route and authenticated?
  • Did the required request complete with the expected status?
  • Is the selector stable and unique?
  • Is the element inside an iframe or shadow root?
  • Did a feature flag or viewport change the UI?
  • Did an earlier action fail silently?

For a detached element, query it again after the action that caused a re-render. For an intercepted click, find the overlay or disabled state rather than forcing the action. For a timeout, identify which condition never became true instead of increasing the timeout globally.

CI-only failures often come from environment URLs, missing variables, browser or viewport differences, shared test data, CPU pressure, or an application dependency. Reproduce using the same run mode and browser. Use unique data per test and unique artifact names.

Do not add an uncaught-exception handler that always returns false. It can hide real product crashes. Do not swallow failed requests or convert every assertion failure to a warning. A reliable test fails for a clear reason and leaves useful evidence.

When you describe a flake you fixed, explain the symptom, evidence, root cause, code or product change, and repeated verification. Avoid invented pass-rate percentages.

9. Cypress interview questions 2 years experience preparation plan

Build a compact repository you can explain in ten minutes. Include a typed configuration, two independent specs, one cy.intercept() success and failure path, one fixture, one narrowly justified custom command, and CI execution. Add a README that states the application assumptions and commands.

Practice this seven-part walkthrough:

  1. State the business risk.
  2. Explain setup and test data.
  3. Show the selector contract.
  4. Trace the Cypress chain and yielded subjects.
  5. Describe network control.
  6. Explain the final assertion.
  7. Show failure artifacts and cleanup.

Prepare four real stories: a flaky test, a defect found by automation, a selector or testability improvement, and a CI failure. Use situation, task, action, result, and lesson, but speak naturally. If the team fixed the issue together, describe your contribution accurately.

For coding practice, implement a table assertion, intercept a 500 response, turn a fixed wait into an observable condition, and repair a test that shares state. Say your assumptions aloud before typing.

Do not memorize model answers word for word. Use them to check concepts, then answer with the tools and architecture you actually used. If you have not used component testing or cy.session() in a project, explain what you understand and how you would validate it instead of claiming experience.

Interview Questions and Answers

Q: Are Cypress commands Promises?

No. Cypress commands are enqueued and yield subjects to later commands. They use .then() syntax, but they are not normal Promises to await or combine freely with synchronous variables.

Q: What is retryability in Cypress?

Queries link together and retry with assertions until the assertion passes or times out. Non-query commands execute once because repeating actions could change application state. I use observable assertions instead of fixed sleeps.

Q: What is the difference between .should() and .then()?

.should() assertions and callbacks can retry, so the callback must be free of side effects. .then() runs once after the prior subject resolves and is suitable for one-time transformation or dependent logic. I choose based on whether the condition needs retrying.

Q: How do you choose selectors?

I prefer stable product-owned attributes or clear accessible semantics. I scope duplicate content to a stable container and avoid generated CSS classes, long DOM paths, and arbitrary indexes.

Q: What does cy.intercept() do?

It spies on or stubs matching browser network traffic. I register it before the request, match method and path narrowly, alias it, and assert the UI outcome as well as relevant safe request or response details.

Q: What is the difference between cy.request() and cy.intercept()?

cy.request() actively sends an HTTP request through Cypress, often for setup or API validation. cy.intercept() observes or changes browser requests made by the application. I do not assume intercepting proves a separate cy.request() call.

Q: Why should tests be independent?

An independent test runs alone, in any order, and after another test fails. It creates or restores its own preconditions, which improves debugging, parallel execution, and trust in the suite.

Q: When do you use a custom command?

I use one for a repeated, stable domain operation that benefits from the Cypress queue. I keep the command typed and narrow, return a useful subject, and prefer a plain function for pure data logic.

Q: How do you handle a page that loads slowly?

I wait on the specific request or DOM state that represents readiness. I inspect why it is slow and use a local evidence-based timeout only when necessary, rather than adding cy.wait(milliseconds).

Q: How do you debug an element covered by another element?

I inspect the screenshot and DOM to identify the overlay, animation, sticky header, or wrong responsive element. I wait for the blocking state to end or fix the product interaction. A forced click is not my default.

Q: What should happen after a Cypress test fails in CI?

The run should preserve useful, safe artifacts such as the command failure, screenshot, matched request context, browser, and test data ID. I reproduce in the same environment shape, classify product, test, data, or infrastructure cause, and verify the fix.

Q: When would you use component testing?

I use it for focused UI behavior across controlled states without the full deployed stack. I keep a smaller set of end-to-end tests for critical wiring and journeys, and use API or unit tests for broader lower-layer logic.

Common Mistakes

  • Saying Cypress commands are ordinary Promises.
  • Assigning a command result to a normal variable and reading it synchronously.
  • Using cy.wait(5000) as normal synchronization.
  • Forcing every difficult click instead of finding the blocking state.
  • Registering an intercept after visiting the page that sends the request.
  • Matching a broad wildcard and waiting on the wrong request.
  • Depending on test order or a shared account record.
  • Hiding several workflows in a global beforeEach().
  • Using arrow functions with Mocha this fixture aliases.
  • Creating custom commands for pure functions or one-line selectors.
  • Saying retries fix flakiness.
  • Disabling uncaught exceptions globally.
  • Describing every check as an end-to-end test.
  • Claiming experience with APIs you have only read about.
  • Inventing metrics or blaming CI without evidence.

Conclusion

Cypress interview questions 2 years experience candidates face reward reliable fundamentals. Explain the command queue, retryability, subject flow, selectors, network control, isolation, fixtures, configuration, and debugging with examples you understand.

Build one small TypeScript suite, practice the scenario answers aloud, and prepare honest stories from your work. The goal is not to recite the largest command list. It is to show that you can create a trustworthy test, diagnose why it failed, and communicate the next action clearly.

Interview Questions and Answers

What is Cypress?

Cypress is a JavaScript and TypeScript tool for browser-based end-to-end and component testing. It provides browser automation, a command queue, retryable queries and assertions, network control, and interactive debugging. I use it as one layer in a broader quality strategy.

Are Cypress commands Promises?

No. Commands are queued and yield subjects through Cypress chains. They may use `.then()` syntax, but I do not await them as normal Promises or read their results synchronously.

How does Cypress retryability work?

Queries link and retry with their assertions until they pass or time out. Non-query commands execute once because repeated actions can create side effects. I wait on observable states instead of fixed time.

What is the difference between should and then?

A `.should()` assertion or callback can run repeatedly, so it must not contain unsafe side effects. A `.then()` callback runs once after the prior command resolves and is useful for transformation or one-time dependent work.

How do you choose a Cypress selector?

I use stable owned attributes or accessible user-facing semantics, then scope duplicate content to a meaningful container. I avoid generated classes, long CSS paths, and indexes that are unrelated to requirements.

What is cy.intercept used for?

`cy.intercept()` observes or stubs matching browser requests. I register it before traffic begins, match narrowly, alias it, and verify the resulting UI plus safe request or response details.

How is cy.request different from cy.intercept?

`cy.request()` sends a request directly through Cypress and is useful for setup or API checks. `cy.intercept()` observes or changes requests made by the browser application. A stubbed intercept does not prove real backend integration.

How do you use fixtures?

I load static test data with `cy.fixture()` and either use it within the chain or alias it with the correct Mocha function context. Fixtures are immutable inputs in my design, not shared dynamic records.

Why must Cypress tests be independent?

Independent tests can run alone and in any order, which makes failures reproducible and parallel execution safer. Each test establishes its own browser and server-side preconditions and does not depend on a prior test.

When should you create a custom command?

I create a custom command for a stable reused domain operation that needs the Cypress queue. I keep it typed, narrow, and explicit about its yielded subject. Pure transformations remain plain TypeScript functions.

How do you replace a fixed wait?

I identify the real readiness signal, such as a request alias, loading indicator removal, enabled control, or final status. Cypress then waits only as long as needed and fails with evidence about the missing condition.

How do you debug a covered element?

I inspect which element receives the click and why, such as an overlay, animation, sticky header, or duplicate responsive control. I wait for or fix that state rather than defaulting to a forced click.

How do you investigate a CI-only Cypress failure?

I compare browser, viewport, environment variables, URLs, data, resource pressure, and application dependencies. I inspect the command log and safe artifacts, reproduce under the CI configuration, classify the cause, and verify the focused fix.

When would you use a Cypress component test?

I use component testing for focused rendering and interaction across controlled UI states. I retain end-to-end tests for critical deployed wiring and use API or unit tests for broad business logic and data combinations.

Frequently Asked Questions

What Cypress questions are asked for two years of experience?

Expect the command queue, retryability, selectors, assertions, hooks, fixtures, `cy.intercept()`, `cy.request()`, custom commands, test isolation, and common debugging scenarios. Coding tasks often involve a form, table, or controlled API response.

How much JavaScript should I know for a Cypress interview?

Be comfortable with functions, objects, arrays, destructuring, modules, callbacks, async concepts, and basic TypeScript types. You should also understand why Cypress chains are not normal Promises.

Should I memorize all Cypress commands?

No. Know the common commands deeply and be able to read official documentation for less common APIs. Interviewers value correct execution-model reasoning and debugging judgment more than a memorized list.

Are scenario-based Cypress questions important at two years?

Yes. Prepare delayed requests, covered elements, detached DOM nodes, duplicate text, test data collision, CI-only failure, and API error scenarios. Explain the evidence you would gather before changing the test.

Do I need a Cypress framework project for the interview?

A small project is very useful because it proves you can connect configuration, data, commands, specs, reporting, and CI. Keep it simple enough that you can explain every file and tradeoff.

How should I explain Cypress retryability?

Queries and assertions can retry together until the assertion passes or times out, while non-query commands execute once. Use observable conditions and keep side effects out of retrying callbacks.

What is a good answer when I have not used a Cypress feature?

Say that you have not used it in production, explain your current understanding, and describe how you would validate it in the official documentation and a small experiment. Do not invent project experience.

Related Guides