Cypress part 5







Introduction to Cypress App – A Beginner’s Guide to Testing

Introduction to Cypress App – A Beginner’s Guide to Testing

Introduction
Cypress is a powerful and user-friendly testing framework designed for modern web applications. This guide will introduce you to Cypress, covering essential concepts, querying elements, handling asynchronous commands, and best practices for writing stable tests.

What You’ll Learn

  • Cypress rules for efficient testing
  • How to query and interact with elements
  • Understanding Cypress’ asynchronous nature
  • Making reliable assertions in tests

Why Use Cypress?

Cypress simplifies test automation by providing:

  • ✔️ Easy setup – No additional dependencies required
  • ✔️ Real-time execution – Tests run directly in the browser
  • ✔️ Automatic waits – No need for manual wait statements
  • ✔️ Readable syntax – Intuitive commands for better test writing

Writing Your First Cypress Test

Here’s an example end-to-end test for creating a new post:


describe('Post Resource', () => {
  it('Creating a New Post', () => {
    cy.visit('/posts/new');  
    cy.get("input.post-title").type("My First Post");  
    cy.get("input.post-body").type("Hello, world!");  
    cy.contains("Submit").click();  
    cy.get("h1").should("contain", "My First Post");  
  });
});
    

How This Works:

  1. Visits /posts/new
  2. Fills out the title and content
  3. Clicks the “Submit” button
  4. Confirms that the post appears correctly

Querying Elements in Cypress

Cypress uses jQuery-like selectors to find elements:


cy.get('.my-selector') // Select by class
cy.get('#element-id') // Select by ID
    

You can also query by text content for a more user-friendly approach:


cy.contains('New Post') // Finds an element containing the text "New Post"
cy.get('.main').contains('Submit') // Finds the "Submit" button within .main
    

Best Practice: Avoid selecting elements based on dynamically generated classes or styles.


Handling Missing Elements

Unlike jQuery, Cypress automatically retries queries until:

  • The element appears
  • The timeout is reached

cy.get('#element', { timeout: 10000 }); // Waits up to 10 seconds
    

This reduces flakiness in tests by handling:

  • ✅ Slow-loading DOM elements
  • ✅ Delayed API responses
  • ✅ Framework rendering delays

Handling Asynchronous Commands

Cypress commands do not return elements synchronously like jQuery. Instead, they use promises:

❌ This won’t work:


const $cyElement = cy.get('.element'); // Cypress commands are async!
    

✅ Use .then() to handle async behavior:


cy.get('.element').then(($el) => {
  doSomething($el);
});
    

Cypress waits for elements to appear and ensures stability before executing further commands.


Customizing Timeouts for Stability

Cypress allows global and per-command timeouts to handle slow elements:

🔹 Per-command timeout:


cy.get('.slow-element', { timeout: 8000 });
    

🔹 Global timeout setting:


Cypress.config('defaultCommandTimeout', 10000);
    

Tip: Avoid setting unnecessarily long timeouts, as it can slow down your test execution.

Chaining Commands in Cypress

Understanding Cypress Command Chains

Cypress manages a Promise chain on your behalf, allowing seamless chaining of commands. Each command yields a ‘subject’ to the next command in the chain. While developers do not need to work with Promises explicitly, understanding them is beneficial.

Interacting With Elements

Cypress enables interaction with page elements using action commands like .click() and .type(). These commands are chained with cy.get() or cy.contains(). For example:

cy.get('textarea.post-body').type('This is an excellent post.')

Here, .type() acts on the element returned by cy.get().

Other useful action commands include:

  • .blur() – Makes a focused element lose focus.
  • .focus() – Focuses on a DOM element.
  • .clear() – Clears an input or textarea field.
  • .check() – Selects checkbox(es) or radio buttons.
  • .uncheck() – Deselects checkbox(es).
  • .select() – Selects an <option> within a <select>.
  • .dblclick() – Performs a double-click.
  • .rightclick() – Performs a right-click.

Cypress ensures elements are in an “actionable” state before interacting with them:

  • Not hidden
  • Not covered
  • Not disabled
  • Not animating

Asserting About Elements

Assertions allow verification of element states:

cy.get(':checkbox').should('be.disabled')
cy.get('form').should('have.class', 'form-horizontal')
cy.get('input').should('not.have.value', 'US')

Cypress automatically waits until these assertions pass.

Subject Management

Each Cypress command yields a subject for the next command. Examples:

cy.clearCookies() // Yields null
cy.get('.main-container').contains('Headlines').click()
  • .click() requires a DOM element.
  • .contains() searches within the previous subject unless chained directly from cy.

Using .then() to Act on a Subject

Use .then() to manipulate subjects within a chain:

cy.get('#some-link').then(($el) => {
  const href = $el.prop('href').replace(/(#.*)/, '')
  return href
}).then((href) => {
  // Use modified href
})

Using Aliases for Reusability

Aliases store references for future use:

cy.get('.my-selector').as('myElement')
cy.get('@myElement').click()

This avoids stale elements and ensures elements are re-queried correctly.

Commands Are Asynchronous

Cypress commands do not execute immediately but are queued for execution. For example:

it('hides the thing when it is clicked', () => {
  cy.visit('/my/resource/path')
  cy.get(".hides-when-clicked").should("be.visible").click()
  cy.get('.hides-when-clicked').should('not.be.visible')
})

The test function queues commands, and Cypress executes them sequentially after the function exits.

Handling Async and Sync Code

Incorrect:

it('does not work as expected', () => {
  cy.visit('/my/resource/path')
  cy.get('.awesome-selector').click()
  let el = Cypress.$('.new-el') // Evaluates too soon
  if (el.length) {
    cy.get('.another-selector')
  } else {
    cy.get('.optional-selector')
  }
})

Correct usage with .then():

it('works correctly', () => {
  cy.visit('/my/resource/path')
  cy.get('.awesome-selector').click().then(() => {
    let el = Cypress.$('.new-el')
    if (el.length) {
      cy.get('.another-selector')
    } else {
      cy.get('.optional-selector')
    }
  })
})

By using .then(), Cypress ensures the code runs only after previous commands complete execution.

Understanding Cypress’ command chaining, subject management, and handling of asynchronous execution is crucial for writing stable and readable tests.

h1>Cypress Assertions

What Are Assertions?

Assertions describe the expected state of elements, objects, and applications in a test. Cypress automatically retries assertions until they pass or timeout, making them more reliable compared to other testing tools.

Example of Assertions in English:

“After clicking this button, I expect it to have an active class.”

Cypress Equivalent:

cy.get('button').click()
cy.get('button').should('have.class', 'active')

Even if the .active class is applied asynchronously, Cypress will wait and retry until the assertion passes.

Example: HTTP Request Assertion

“After making an API call, I expect the response to contain {name: 'Jane'}.”

Cypress Equivalent:

cy.request('/users/1').its('body').should('deep.eq', { name: 'Jane' })

When to Use Assertions?

Sometimes, explicit assertions are unnecessary. Consider the test below:

cy.visit('/home')
cy.get('.main-menu').contains('New Project').click()
cy.get('.title').type('My Awesome Project')
cy.get('form').submit()

Without explicit assertions, Cypress still verifies multiple conditions:

  • The page loads successfully.
  • Elements exist in the DOM.
  • Actions like .click() and .type() work as expected.
  • The form submission doesn’t fail.

Implicit Assertions

Many Cypress commands have built-in assertions:

  • cy.visit() expects a 200 status response.
  • cy.request() expects a valid response from the server.
  • cy.contains() waits for the element to exist.
  • cy.get(), .find(), .type(), .click(), and .its() all have automatic retries.

Example: Existence and Actionability

cy.get('button').click()

Cypress ensures:

  • The button exists in the DOM.
  • The button is actionable (not disabled or hidden) before clicking.

Example: Waiting for an Element to Disappear

cy.get('button.close').click()
cy.get('button.close').should('not.exist')
cy.get('#modal').should('not.exist')

Adding .should('not.exist') ensures Cypress does not wait for the element to appear but instead waits for it to be removed.


Writing Assertions

There are two main ways to write assertions in Cypress:

1. Using Cypress Commands (.should() and .and())

cy.get('tbody tr:first').should('have.class', 'active')

You can chain multiple assertions:

cy.get('#header a')
  .should('have.class', 'active')
  .and('have.attr', 'href', '/users')

2. Using Mocha Assertions (expect)

Useful for custom logic before asserting:

expect(true).to.be.true

Example: Complex Assertions

cy.get('p').should(($p) => {
  let texts = $p.map((i, el) => Cypress.$(el).text()).get()
  expect(texts).to.have.length(3)
  expect(texts).to.deep.eq([
    'Some text from first p',
    'More text from second p',
    'And even more text from third p',
  ])
})

Caution: Ensure .should() Callbacks Are Idempotent

Cypress retries .should() callbacks, so avoid functions that cause side effects.


Handling Timeouts

All assertions share the same timeout settings. Cypress automatically waits for assertions to pass before failing.

Example: Default Timeout

cy.get('.mobile-nav')

Cypress waits up to 4 seconds for .mobile-nav to appear.

Example: Custom Timeout

cy.get('.mobile-nav', { timeout: 10000 }).should('be.visible').and('contain', 'Home')

This extends the timeout to 10 seconds.


Summary

  • Cypress assertions retry automatically.
  • Implicit assertions exist in many Cypress commands.
  • .should() and .and() are preferred for inline assertions.
  • Use expect for more complex logic.
  • Cypress manages timeouts automatically, but they can be customized.

By understanding how assertions work in Cypress, you can write more stable, reliable tests.



Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *