Bird
Raised Fist0
Cypresstesting~15 mins

Asserting request properties in Cypress - Deep Dive

Choose your learning style10 modes available
Overview - Asserting request properties
What is it?
Asserting request properties means checking that the details of a network request made by your web app are correct during testing. This includes verifying the URL, method, headers, body, and response. It helps ensure your app talks to servers as expected. This is done automatically in tests using Cypress, a tool for web testing.
Why it matters
Without asserting request properties, bugs in how your app communicates with servers can go unnoticed. This can cause wrong data to be sent or received, leading to broken features or security issues. By checking requests, you catch problems early, saving time and improving user experience.
Where it fits
Before this, you should understand basic Cypress test writing and how web requests work. After learning this, you can explore advanced network stubbing, response mocking, and performance testing in Cypress.
Mental Model
Core Idea
Asserting request properties is like checking the details on a letter before sending it to make sure it has the right address, content, and postage.
Think of it like...
Imagine mailing a letter: you check the envelope to confirm the address, stamp, and message inside are correct before sending it. Similarly, asserting request properties checks the request details before trusting the app's behavior.
┌─────────────────────────────┐
│       Test triggers action  │
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│  Network request is sent     │
│  (URL, method, headers, body)│
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│  Cypress captures request    │
│  and asserts properties      │
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│  Test passes if assertions   │
│  match expected values       │
└─────────────────────────────┘
Build-Up - 6 Steps
1
FoundationUnderstanding network requests basics
🤔
Concept: Learn what a network request is and its main parts like URL, method, headers, and body.
When your web app talks to a server, it sends a network request. This request has a URL (where it goes), a method (like GET or POST), headers (extra info), and sometimes a body (data sent). Understanding these parts helps you know what to check in tests.
Result
You can identify the key parts of any network request your app makes.
Knowing the parts of a request is essential before you can check if they are correct in tests.
2
FoundationBasics of Cypress network interception
🤔
Concept: Learn how Cypress can listen to network requests your app makes during tests.
Cypress can watch network requests using cy.intercept(). You tell Cypress what requests to watch by URL or method. Then, you can wait for these requests and check their details.
Result
You can capture network requests in your test code.
Capturing requests is the first step to checking their properties automatically.
3
IntermediateAsserting request URL and method
🤔Before reading on: do you think you can check both URL and method in one assertion or need separate ones? Commit to your answer.
Concept: Learn to check that the request goes to the right URL and uses the correct HTTP method.
Use cy.intercept() with an alias, then cy.wait() for that alias. The intercepted request object has properties like request.url and request.method. Use expect() assertions to check these. Example: cy.intercept('POST', '/api/login').as('loginRequest') // trigger login action cy.wait('@loginRequest').then(({ request }) => { expect(request.url).to.include('/api/login') expect(request.method).to.equal('POST') })
Result
Test passes only if the request URL contains '/api/login' and method is POST.
Checking URL and method ensures your app calls the right server endpoint with the correct action.
4
IntermediateChecking request headers and body content
🤔Before reading on: do you think headers and body are always present in every request? Commit to your answer.
Concept: Learn to assert that request headers and body data match expected values.
Headers carry extra info like content type or authorization. The body contains data sent, often JSON. Example: cy.intercept('POST', '/api/login').as('loginRequest') // trigger login cy.wait('@loginRequest').then(({ request }) => { expect(request.headers).to.have.property('content-type', 'application/json') expect(request.body).to.deep.equal({ username: 'user1', password: 'pass123' }) })
Result
Test passes only if headers and body exactly match expected values.
Verifying headers and body prevents bugs like sending wrong data or missing authentication.
5
AdvancedAsserting response properties and status codes
🤔Before reading on: do you think asserting request properties includes checking server responses? Commit to your answer.
Concept: Learn to check the server's response to your request, including status code and body.
After intercepting a request, you can also check the response. Example: cy.intercept('POST', '/api/login').as('loginRequest') // trigger login cy.wait('@loginRequest').then(({ response }) => { expect(response.statusCode).to.equal(200) expect(response.body).to.have.property('token') })
Result
Test passes only if server responds with status 200 and includes a token.
Checking responses ensures the server behaves as expected, not just the request.
6
ExpertHandling dynamic request properties in assertions
🤔Before reading on: do you think you should assert exact values for all request properties even if some change each time? Commit to your answer.
Concept: Learn strategies to assert requests when some properties vary, like timestamps or tokens.
Some request parts change every time (like IDs or timestamps). Use partial matching or custom checks. Example: cy.wait('@loginRequest').then(({ request }) => { expect(request.body).to.include.keys('username') expect(request.body.timestamp).to.be.a('string') }) Or use regex or custom functions to check dynamic values without failing tests.
Result
Tests pass reliably even when some request data changes each run.
Knowing how to handle dynamic data prevents flaky tests and false failures.
Under the Hood
Cypress uses the browser's network layer to intercept HTTP requests and responses. When cy.intercept() is called, Cypress hooks into the browser's fetch and XMLHttpRequest APIs. It captures request details before sending and response details after receiving. This allows Cypress to expose these details to test code for assertions.
Why designed this way?
Intercepting requests at the browser level allows Cypress to observe real app behavior without modifying app code. This design avoids false positives from mocks and lets tests verify actual network traffic. Alternatives like server-side proxies were more complex and less reliable.
┌───────────────┐
│  Test code    │
│  calls cy.intercept() ──────┐
└───────┬───────┘             │
        │                     ▼
┌───────▼────────┐    ┌───────────────────┐
│ Browser network│────│  App sends request│
│ layer hooks    │    └───────────────────┘
└───────┬────────┘             │
        │                     ▼
┌───────▼────────┐    ┌───────────────────┐
│ Cypress captures│────│ Server responds   │
│ request & resp │    └───────────────────┘
└───────┬────────┘             │
        │                     ▼
┌───────▼────────┐
│ Test code gets │
│ request & resp │
│ details for    │
│ assertions     │
└────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does asserting a request URL guarantee the request body is correct? Commit to yes or no.
Common Belief:If the request URL is correct, the whole request must be correct.
Tap to reveal reality
Reality:The URL can be right but the body or headers might be wrong or missing.
Why it matters:Relying only on URL checks can miss bugs where wrong data is sent, causing failures in backend processing.
Quick: Can you assert request properties without intercepting the request first? Commit to yes or no.
Common Belief:You can check request details anytime without setting up interception.
Tap to reveal reality
Reality:You must intercept the request with cy.intercept() to capture its details for assertions.
Why it matters:Trying to assert without interception leads to tests that never see the request, causing false passes or errors.
Quick: Do request properties always stay the same between test runs? Commit to yes or no.
Common Belief:Request properties are always fixed and predictable in tests.
Tap to reveal reality
Reality:Some properties like tokens or timestamps change each run and need flexible assertions.
Why it matters:Failing to handle dynamic data causes flaky tests that fail unpredictably.
Quick: Does asserting response status code guarantee the request was sent correctly? Commit to yes or no.
Common Belief:If the response status is good, the request must have been correct.
Tap to reveal reality
Reality:A good response can come even if the request had unexpected data, due to server defaults or errors.
Why it matters:Only checking response status can miss subtle request bugs that cause wrong app behavior.
Expert Zone
1
Cypress intercepts requests asynchronously, so timing your assertions with cy.wait() is crucial to avoid race conditions.
2
Headers can be case-insensitive and sometimes normalized by browsers, so exact string matches may fail; use flexible checks.
3
When multiple requests match an intercept, Cypress returns the first by default; use unique aliases or filters to target the right one.
When NOT to use
Asserting request properties is less useful when testing purely UI behavior without network calls or when using full API mocks. In those cases, focus on UI state or mock responses instead.
Production Patterns
In real projects, teams use request assertions to verify critical API calls during login, payments, or data submission. They combine assertions with stubbing to isolate tests and catch regressions early.
Connections
API Contract Testing
Builds-on
Asserting request properties in Cypress helps verify that the app respects the API contract, ensuring frontend and backend agree on data formats and endpoints.
HTTP Protocol
Same pattern
Understanding HTTP methods, headers, and status codes is essential to correctly assert request properties and interpret server responses.
Quality Control in Manufacturing
Analogous process
Just like inspecting parts on a production line to ensure they meet specifications, asserting request properties inspects network calls to ensure they meet expected standards.
Common Pitfalls
#1Failing to wait for the intercepted request before asserting.
Wrong approach:cy.intercept('GET', '/api/data').as('getData') // trigger action expect(cy.get('@getData')).to.exist
Correct approach:cy.intercept('GET', '/api/data').as('getData') // trigger action cy.wait('@getData').then(({ request }) => { expect(request.url).to.include('/api/data') })
Root cause:Not using cy.wait() means assertions run before the request happens, causing false failures.
#2Asserting exact request body when it contains dynamic values.
Wrong approach:expect(request.body).to.deep.equal({ user: 'abc', timestamp: '2023-06-01T12:00:00Z' })
Correct approach:expect(request.body).to.include({ user: 'abc' }) expect(request.body.timestamp).to.be.a('string')
Root cause:Trying to match dynamic data exactly causes flaky tests that fail when values change.
#3Checking request headers with wrong casing.
Wrong approach:expect(request.headers['Content-Type']).to.equal('application/json')
Correct approach:expect(request.headers['content-type']).to.equal('application/json')
Root cause:HTTP headers are case-insensitive but JavaScript object keys are case-sensitive, causing mismatches.
Key Takeaways
Asserting request properties means checking the details of network calls your app makes during tests to ensure correctness.
Cypress intercepts requests at the browser level, letting you capture and assert URL, method, headers, body, and response.
Proper timing with cy.wait() and handling dynamic data are key to reliable assertions.
Ignoring request assertions risks missing bugs in how your app communicates with servers, leading to broken features.
Expert use includes flexible matching, understanding HTTP details, and combining assertions with stubbing for robust tests.

Practice

(1/5)
1. What is the primary purpose of using cy.intercept in Cypress tests?
easy
A. To watch and control network requests during test execution
B. To create UI elements dynamically
C. To write CSS styles for the application
D. To generate random test data automatically

Solution

  1. Step 1: Understand cy.intercept role

    cy.intercept is used to monitor or stub network requests in Cypress tests.
  2. Step 2: Identify correct purpose

    It helps watch and control HTTP requests, not UI or styling tasks.
  3. Final Answer:

    To watch and control network requests during test execution -> Option A
  4. Quick Check:

    cy.intercept = watch/control requests [OK]
Hint: Remember: intercept = watch network calls [OK]
Common Mistakes:
  • Confusing intercept with UI manipulation
  • Thinking intercept generates test data
  • Mixing intercept with CSS styling
2. Which of the following is the correct syntax to assert that a request method is POST inside a cy.intercept callback?
easy
A. assert(req.method == 'POST')
B. assert.equal(req.method, 'GET')
C. expect(req.method).equals('post')
D. expect(req.method).to.equal('POST')

Solution

  1. Step 1: Identify correct assertion syntax

    Cypress uses Chai assertions like expect(value).to.equal(expected).
  2. Step 2: Match method and case sensitivity

    HTTP methods are uppercase strings, so 'POST' must be exact.
  3. Final Answer:

    expect(req.method).to.equal('POST') -> Option D
  4. Quick Check:

    expect().to.equal() with exact case [OK]
Hint: Use expect().to.equal() with exact method case [OK]
Common Mistakes:
  • Using lowercase 'post' instead of 'POST'
  • Using assert syntax instead of expect
  • Checking wrong method like 'GET'
3. Given the following code snippet, what will the assertion check inside the intercept callback?
cy.intercept('POST', '/api/login', (req) => {
  expect(req.body).to.have.property('username', 'admin')
})
medium
A. The request headers must include username 'admin'
B. The request body must include a username property with value 'admin'
C. The response body must have username 'admin'
D. The request URL must contain 'username=admin'

Solution

  1. Step 1: Analyze the assertion target

    The assertion checks req.body for a property named 'username' with value 'admin'.
  2. Step 2: Understand request vs response and headers

    It does not check URL, response, or headers, only the request body.
  3. Final Answer:

    The request body must include a username property with value 'admin' -> Option B
  4. Quick Check:

    expect(req.body).to.have.property('username', 'admin') [OK]
Hint: Check if property is in req.body, not URL or headers [OK]
Common Mistakes:
  • Confusing request body with URL query
  • Checking response instead of request
  • Looking at headers instead of body
4. Identify the error in this Cypress intercept assertion:
cy.intercept('GET', '/api/data', (req) => {
  expect(req.headers['Content-Type']).to.equal('application/json')
})
medium
A. The assertion syntax is incorrect
B. The method should be POST, not GET
C. Headers keys are case-insensitive; 'Content-Type' should be 'content-type'
D. The intercept callback must use res instead of req

Solution

  1. Step 1: Check header key case sensitivity

    HTTP headers are case-insensitive, but Cypress normalizes header keys to lowercase in the req.headers object. The code uses 'Content-Type' which is incorrect; it should be 'content-type'.
  2. Step 2: Validate other parts

    Method GET is valid, assertion syntax is correct, and req is proper for request interception.
  3. Final Answer:

    Headers keys are case-insensitive; 'Content-Type' should be 'content-type' -> Option C
  4. Quick Check:

    Cypress req.headers use lowercase keys [OK]
Hint: Cypress req.headers uses lowercase keys [OK]
Common Mistakes:
  • Using wrong HTTP method
  • Misusing response object instead of request
  • Incorrect assertion syntax
5. You want to assert that a POST request to /api/submit contains a JSON body with a non-empty email property and a header Authorization starting with 'Bearer '. Which is the best way to write this assertion inside cy.intercept?
hard
A. cy.intercept('POST', '/api/submit', (req) => { expect(req.body.email).to.be.a('string').and.not.be.empty expect(req.headers.authorization).to.match(/^Bearer /) })
B. cy.intercept('POST', '/api/submit', (req) => { expect(req.body.email).to.exist expect(req.headers.authorization).to.include('Bearer') })
C. cy.intercept('POST', '/api/submit', (req) => { assert.isString(req.body.email) assert.include(req.headers.authorization, 'Bearer') })
D. cy.intercept('POST', '/api/submit', (req) => { expect(req.body.email).to.be.empty expect(req.headers.authorization).to.equal('Bearer') })

Solution

  1. Step 1: Check email property assertion

    cy.intercept('POST', '/api/submit', (req) => { expect(req.body.email).to.be.a('string').and.not.be.empty expect(req.headers.authorization).to.match(/^Bearer /) }) asserts email is a non-empty string using to.be.a('string').and.not.be.empty, which is precise.
  2. Step 2: Check Authorization header assertion

    cy.intercept('POST', '/api/submit', (req) => { expect(req.body.email).to.be.a('string').and.not.be.empty expect(req.headers.authorization).to.match(/^Bearer /) }) uses regex to.match(/^Bearer /) to ensure header starts with 'Bearer ', which is exact and case-sensitive.
  3. Step 3: Compare other options

    cy.intercept('POST', '/api/submit', (req) => { expect(req.body.email).to.exist expect(req.headers.authorization).to.include('Bearer') }) uses correct lowercase header key, but .to.exist only checks existence (could be empty or falsy), and .to.include checks substring anywhere, not prefix.
    cy.intercept('POST', '/api/submit', (req) => { assert.isString(req.body.email) assert.include(req.headers.authorization, 'Bearer') }) uses non-standard assert style and misses non-empty check; include not prefix.
    cy.intercept('POST', '/api/submit', (req) => { expect(req.body.email).to.be.empty expect(req.headers.authorization).to.equal('Bearer') }) incorrectly expects empty email and exact 'Bearer' match only.
  4. Final Answer:

    expect(req.body.email).to.be.a('string').and.not.be.empty
    expect(req.headers.authorization).to.match(/^Bearer /)
    -> Option A
  5. Quick Check:

    Use precise type and regex assertions for properties [OK]
Hint: Use type checks and regex for precise property assertions [OK]
Common Mistakes:
  • Ignoring case sensitivity in headers
  • Checking only existence, not content
  • Using wrong assertion style inconsistently
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard