Bird
Raised Fist0
Cypresstesting~15 mins

cy.prev() and cy.next() in Cypress - Deep Dive

Choose your learning style10 modes available
Overview - cy.prev() and cy.next()
What is it?
cy.prev() and cy.next() are commands in Cypress, a tool for testing web pages. They help you find elements that come just before or after a chosen element in the page's structure. This lets you check or interact with nearby elements easily during tests. They work by moving through the page's HTML elements in order.
Why it matters
Web pages often have elements placed next to each other, like buttons or links. Testing only one element is not enough if you want to check how they relate or behave together. Without cy.prev() and cy.next(), testers would write more complex code to find nearby elements, making tests slower and harder to read. These commands make tests simpler and more reliable.
Where it fits
Before learning cy.prev() and cy.next(), you should understand basic Cypress commands like cy.get() to select elements. After mastering these, you can learn more advanced traversal commands and how to combine them with assertions to build strong tests.
Mental Model
Core Idea
cy.prev() and cy.next() let you move step-by-step to the element immediately before or after a chosen element in the page's structure.
Think of it like...
Imagine a row of books on a shelf. If you pick one book, cy.prev() is like looking at the book to its left, and cy.next() is like looking at the book to its right.
Selected Element
   │
   ▼
┌─────────┐   ┌─────────┐   ┌─────────┐
│ Previous│←─│ Selected│→─│  Next   │
│ Element │   │ Element │   │ Element │
└─────────┘   └─────────┘   └─────────┘
Build-Up - 7 Steps
1
FoundationBasic Element Selection with cy.get()
🤔
Concept: Learn how to select elements on a page using Cypress's cy.get() command.
Use cy.get('selector') to find elements matching the CSS selector. For example, cy.get('button') finds all buttons on the page.
Result
You get a list of elements matching the selector, ready for further commands.
Understanding how to select elements is the foundation for using traversal commands like cy.prev() and cy.next().
2
FoundationUnderstanding DOM Element Order
🤔
Concept: Learn that elements in a web page are arranged in a specific order called the DOM (Document Object Model).
The DOM is like a tree or list of elements in the order they appear in the HTML. Elements next to each other in the DOM are siblings.
Result
You know that elements have neighbors before and after them in the DOM order.
Knowing the DOM order helps you understand what cy.prev() and cy.next() will select.
3
IntermediateUsing cy.prev() to Find Previous Sibling
🤔Before reading on: do you think cy.prev() selects the parent element or the previous sibling? Commit to your answer.
Concept: cy.prev() selects the element immediately before the current element at the same level in the DOM tree.
Example: cy.get('.item').eq(1).prev() finds the element before the second '.item'. It only looks at siblings, not parents or children.
Result
You get the previous sibling element of the selected element.
Understanding that cy.prev() moves sideways in the DOM, not up or down, helps avoid confusion.
4
IntermediateUsing cy.next() to Find Next Sibling
🤔Before reading on: does cy.next() select the next sibling or the first child? Commit to your answer.
Concept: cy.next() selects the element immediately after the current element at the same level in the DOM tree.
Example: cy.get('.item').eq(1).next() finds the element after the second '.item'. It only looks at siblings, not parents or children.
Result
You get the next sibling element of the selected element.
Knowing cy.next() moves to the next sibling helps you navigate the page structure precisely.
5
IntermediateCombining cy.prev() and cy.next() with Assertions
🤔Before reading on: can you use cy.prev() or cy.next() directly with assertions like .should()? Commit to your answer.
Concept: You can chain cy.prev() or cy.next() with assertions to check properties of neighboring elements.
Example: cy.get('.active').prev().should('have.class', 'inactive') This checks if the previous sibling has class 'inactive'.
Result
Tests become more expressive and check relationships between elements.
Combining traversal with assertions makes tests more powerful and closer to real user scenarios.
6
AdvancedHandling Missing Previous or Next Elements
🤔Before reading on: what happens if cy.prev() or cy.next() finds no element? Does the test fail immediately or continue? Commit to your answer.
Concept: If there is no previous or next sibling, cy.prev() or cy.next() yields an empty set, which can cause assertions to fail.
Example: cy.get('.first-item').prev().should('exist') will fail because '.first-item' has no previous sibling. You can check length or existence before assertions.
Result
You learn to write safer tests that handle edge cases gracefully.
Knowing how Cypress behaves with missing elements prevents confusing test failures.
7
ExpertUsing cy.prev() and cy.next() in Complex DOM Structures
🤔Before reading on: do cy.prev() and cy.next() cross nested element boundaries or only work on direct siblings? Commit to your answer.
Concept: cy.prev() and cy.next() only navigate direct siblings, not nested or parent elements, so complex DOMs require careful selection.
In nested lists or tables, cy.prev() and cy.next() won't jump between different levels. You may need cy.parent(), cy.children(), or cy.closest() combined with traversal. Example: cy.get('td.selected').next() finds the next cell in the same row, but not in another row.
Result
You understand the limits of these commands and how to combine them for complex tests.
Knowing traversal boundaries helps avoid bugs and write precise selectors in real-world applications.
Under the Hood
cy.prev() and cy.next() work by accessing the DOM element's sibling properties. Internally, Cypress uses the browser's native DOM API to get the previousElementSibling or nextElementSibling of the current element. These commands wrap the found element(s) back into Cypress's chainable object for further commands or assertions.
Why designed this way?
The design follows the natural structure of the DOM, which organizes elements as nodes with siblings. Using native DOM sibling properties is efficient and intuitive for testers. Alternatives like searching the entire DOM would be slower and less predictable. This design keeps traversal simple and focused on immediate neighbors.
Selected Element
   │
   ▼
┌───────────────┐
│ Cypress Chain │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ DOM Element   │
│ (current)    │
└──────┬────────┘
       │
 ┌─────┴─────┐
 │           │
 ▼           ▼
prevSibling nextSibling
  │           │
  ▼           ▼
DOM Element DOM Element
Myth Busters - 4 Common Misconceptions
Quick: Does cy.prev() select the parent element of the current element? Commit to yes or no.
Common Belief:cy.prev() selects the parent element of the current element.
Tap to reveal reality
Reality:cy.prev() selects only the previous sibling element, not the parent.
Why it matters:Confusing parent with previous sibling leads to wrong element selection and test failures.
Quick: If cy.next() finds no next sibling, does it throw an error immediately? Commit to yes or no.
Common Belief:cy.next() throws an error if there is no next sibling element.
Tap to reveal reality
Reality:cy.next() returns an empty set if no next sibling exists; it does not throw an error immediately.
Why it matters:Assuming an error causes testers to write unnecessary try-catch or miss handling empty results, causing flaky tests.
Quick: Can cy.prev() and cy.next() cross nested element boundaries to find siblings at different levels? Commit to yes or no.
Common Belief:cy.prev() and cy.next() can find siblings even if they are nested inside different parent elements.
Tap to reveal reality
Reality:They only find siblings at the same DOM level, not across nested parents.
Why it matters:Misunderstanding this causes tests to fail silently or select wrong elements in complex layouts.
Quick: Does chaining cy.prev() or cy.next() multiple times move multiple steps? Commit to yes or no.
Common Belief:You can chain cy.prev().prev() to move multiple elements backward.
Tap to reveal reality
Reality:Chaining works, but each call only moves one step; multiple calls are needed for multiple steps.
Why it matters:Knowing this helps write clear traversal steps and avoid confusion about how far you move in one call.
Expert Zone
1
cy.prev() and cy.next() only consider element nodes, ignoring text or comment nodes, which can affect traversal in some HTML structures.
2
When multiple elements are selected, cy.prev() and cy.next() operate on each element individually, returning a combined set of siblings, which can lead to unexpected results if not handled carefully.
3
Using cy.prev() or cy.next() with filters (like .filter()) allows precise control over which sibling elements to select, enabling complex traversal logic.
When NOT to use
Avoid using cy.prev() and cy.next() when you need to navigate up or down the DOM tree (parents or children). Instead, use cy.parent(), cy.children(), or cy.closest() for those cases. Also, for non-sibling elements or complex queries, use cy.get() with specific selectors.
Production Patterns
In real-world tests, cy.prev() and cy.next() are often used to verify UI states that depend on element order, like checking if a highlighted item is next to a selected one. They are combined with assertions to test dynamic lists, menus, or form fields where relative position matters.
Connections
Linked List Data Structure
Similar pattern of moving to previous or next nodes in a sequence.
Understanding cy.prev() and cy.next() is like traversing nodes in a linked list, which helps grasp ordered navigation in programming.
Breadcrumb Navigation in UI Design
Both involve moving stepwise through a sequence or path.
Knowing how cy.prev() and cy.next() work helps understand how breadcrumb navigation tracks user position step-by-step.
Human Reading Order in Text
Both follow a linear order to move forward or backward through content.
Recognizing that cy.prev() and cy.next() mimic natural reading order helps design tests that reflect real user interactions.
Common Pitfalls
#1Trying to use cy.prev() to select a parent element.
Wrong approach:cy.get('.child').prev().should('have.class', 'parent')
Correct approach:cy.get('.child').parent().should('have.class', 'parent')
Root cause:Misunderstanding that prev() moves sideways to siblings, not upwards to parents.
#2Assuming cy.next() will find nested elements inside the next sibling.
Wrong approach:cy.get('.item').next('.nested').should('exist')
Correct approach:cy.get('.item').next().find('.nested').should('exist')
Root cause:Confusing sibling traversal with descendant searching.
#3Not handling the case when prev() or next() returns no elements, causing test failures.
Wrong approach:cy.get('.first').prev().should('exist')
Correct approach:cy.get('.first').prev().should('have.length', 0)
Root cause:Not checking for empty results before assertions.
Key Takeaways
cy.prev() and cy.next() let you move to the immediate previous or next sibling element in the DOM.
They only work on siblings at the same level, not parents or children.
These commands simplify tests that need to check relationships between neighboring elements.
Handling cases where no previous or next sibling exists is important to avoid test failures.
Combining traversal with assertions makes tests more expressive and closer to real user behavior.

Practice

(1/5)
1. What does cy.prev() do in Cypress testing?
easy
A. Selects the element immediately after the current element
B. Selects all sibling elements of the current element
C. Selects the element immediately before the current element
D. Selects the parent element of the current element

Solution

  1. Step 1: Understand the purpose of cy.prev()

    cy.prev() is used to get the element immediately before the current element in the DOM.
  2. Step 2: Compare with other options

    cy.next() gets the element after, siblings means all at the same level, and parent is the container element. So only cy.prev() matches Selects the element immediately before the current element.
  3. Final Answer:

    Selects the element immediately before the current element -> Option C
  4. Quick Check:

    cy.prev() = previous element [OK]
Hint: Prev means previous element before current [OK]
Common Mistakes:
  • Confusing cy.prev() with cy.next()
  • Thinking it selects parent or all siblings
  • Assuming it selects elements after current
2. Which of the following is the correct syntax to get the next sibling element of a button with id submitBtn using Cypress?
easy
A. cy.get('#submitBtn').prev()
B. cy.get('#submitBtn').next()
C. cy.get('#submitBtn').parent()
D. cy.get('#submitBtn').children()

Solution

  1. Step 1: Identify the method to get next sibling

    To get the next sibling element, Cypress uses cy.next().
  2. Step 2: Match syntax with the element selector

    cy.get('#submitBtn').next() correctly selects the button and then its next sibling.
  3. Final Answer:

    cy.get('#submitBtn').next() -> Option B
  4. Quick Check:

    next() gets next sibling [OK]
Hint: Use .next() after .get() to get next sibling [OK]
Common Mistakes:
  • Using .prev() instead of .next()
  • Using .parent() which gets the container
  • Using .children() which gets child elements
3. Given the HTML structure:
<ul>
  <li>Item 1</li>
  <li id="selected">Item 2</li>
  <li>Item 3</li>
</ul>

What text will the following Cypress command get?
cy.get('#selected').prev().invoke('text')
medium
A. Error: No previous element
B. "Item 3"
C. "Item 2"
D. "Item 1"

Solution

  1. Step 1: Identify the current element and its previous sibling

    The element with id "selected" is the second <li> with text "Item 2". Its previous sibling is the first <li> with text "Item 1".
  2. Step 2: Understand what invoke('text') does

    This command gets the text content of the selected element, so it will return "Item 1".
  3. Final Answer:

    "Item 1" -> Option D
  4. Quick Check:

    prev() gets previous sibling text [OK]
Hint: prev() gets previous sibling's text [OK]
Common Mistakes:
  • Confusing prev() with next()
  • Expecting text of current element
  • Assuming error if previous exists
4. You wrote this Cypress code:
cy.get('.active').next().click()

But the test fails with an error saying Cannot read property 'click' of undefined. What is the most likely cause?
medium
A. There is no next sibling element after the element with class 'active'
B. The selector '.active' is incorrect
C. You should use prev() instead of next()
D. The click() method is not valid in Cypress

Solution

  1. Step 1: Analyze the error message

    The error says Cannot read property 'click' of undefined, meaning next() returned no element.
  2. Step 2: Understand what causes next() to return undefined

    If the current element has no next sibling, next() returns nothing, so calling click() fails.
  3. Final Answer:

    There is no next sibling element after the element with class 'active' -> Option A
  4. Quick Check:

    next() returns undefined if no next sibling [OK]
Hint: Check if next sibling exists before clicking [OK]
Common Mistakes:
  • Assuming selector is wrong without checking DOM
  • Using prev() instead of next() without reason
  • Thinking click() is invalid in Cypress
5. You want to verify that a list item with class selected has a previous sibling with text "Home" and a next sibling with text "Contact". Which Cypress code correctly checks this?
hard
A. cy.get('.selected').prev().should('have.text', 'Home'); cy.get('.selected').next().should('have.text', 'Contact')
B. cy.get('.selected').prev().should('have.text', 'Home').next().should('have.text', 'Contact')
C. cy.get('.selected').prev().should('have.text', 'Contact').next().next().should('have.text', 'Home')
D. cy.get('.selected').prev().next().should('have.text', 'Contact')

Solution

  1. Step 1: Understand chaining of prev() and next()

    Using prev() then next() on the same chain moves from previous element back to the selected element, not to the next sibling.
  2. Step 2: Separate commands for previous and next siblings

    To check previous and next siblings independently, use separate cy.get('.selected') calls with prev() and next().
  3. Final Answer:

    cy.get('.selected').prev().should('have.text', 'Home'); cy.get('.selected').next().should('have.text', 'Contact') -> Option A
  4. Quick Check:

    Use separate calls for prev() and next() [OK]
Hint: Use separate cy.get() for prev() and next() checks [OK]
Common Mistakes:
  • Chaining prev() and next() incorrectly
  • Using next().next() instead of next()
  • Assuming prev().next() gets next sibling
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