0
0
Cypresstesting~15 mins

cy.first(), cy.last(), cy.eq() in Cypress - Deep Dive

Choose your learning style9 modes available
Overview - cy.first(), cy.last(), cy.eq()
What is it?
cy.first(), cy.last(), and cy.eq() are commands in Cypress, a tool for testing web applications. They help you select specific elements from a group of matched elements on a web page. cy.first() picks the first element, cy.last() picks the last, and cy.eq() picks an element at a specific position.
Why it matters
When testing web pages, you often get many elements matching a selector. Without these commands, you might test the wrong element or all elements at once, which can cause errors or unclear tests. These commands let you focus on exactly one element, making tests precise and reliable.
Where it fits
Before learning these commands, you should know how to select elements using basic Cypress commands like cy.get(). After mastering these, you can learn about chaining commands, assertions, and more complex element interactions.
Mental Model
Core Idea
These commands let you pick exactly one element from a group by choosing the first, last, or a specific position.
Think of it like...
Imagine you have a row of books on a shelf. cy.first() is like picking the first book on the left, cy.last() is the last book on the right, and cy.eq(2) is picking the third book from the left (counting starts at zero).
Elements matched by selector:
[Element0] [Element1] [Element2] ... [ElementN]

cy.first() -> [Element0]
cy.last()  -> [ElementN]
cy.eq(2)   -> [Element2]
Build-Up - 7 Steps
1
FoundationSelecting Multiple Elements with cy.get()
🤔
Concept: Learn how Cypress finds multiple elements on a page using selectors.
Use cy.get('selector') to find all elements matching that selector. For example, cy.get('li') finds all list items on the page.
Result
You get a collection of elements, not just one.
Understanding that cy.get() returns multiple elements is key before learning how to pick one from them.
2
FoundationWhy Pick One Element from Many?
🤔
Concept: Tests often need to interact with or check one specific element, not all at once.
If you want to click the first button in a list, you must tell Cypress exactly which one. Otherwise, it might click all or fail.
Result
You see the need for commands that select a single element from many.
Knowing why single-element selection matters helps you appreciate cy.first(), cy.last(), and cy.eq().
3
IntermediateUsing cy.first() to Pick the First Element
🤔Before reading on: do you think cy.first() selects the first element in the DOM or the last? Commit to your answer.
Concept: cy.first() narrows down the matched elements to only the first one.
Example: cy.get('li').first().click() This clicks the first list item found by cy.get('li').
Result
Only the first element is clicked, not all.
Understanding that .first() filters the collection to one element prevents accidental actions on multiple elements.
4
IntermediateUsing cy.last() to Pick the Last Element
🤔Before reading on: does cy.last() select the last element in the matched set or the first? Commit to your answer.
Concept: cy.last() picks the last element from the matched group.
Example: cy.get('button').last().should('be.visible') This checks visibility of the last button on the page.
Result
Only the last button is checked, not others.
Knowing .last() helps when the element you want is at the end of a list or group.
5
IntermediateUsing cy.eq() to Pick an Element by Index
🤔Before reading on: does cy.eq(0) select the first or second element? Commit to your answer.
Concept: cy.eq(index) selects the element at the given zero-based index from the matched elements.
Example: cy.get('div').eq(2).should('contain', 'Hello') This checks the third div contains 'Hello'.
Result
Only the third div is checked, not others.
Understanding zero-based indexing is crucial to use .eq() correctly and avoid off-by-one errors.
6
AdvancedChaining Selection Commands for Precision
🤔Before reading on: can you chain cy.first() after cy.eq()? What happens? Commit to your answer.
Concept: You can chain these commands to narrow down elements step-by-step, but some chains may be redundant or cause errors.
Example: cy.get('ul').eq(1).find('li').first().click() This clicks the first list item inside the second unordered list.
Result
You interact with a very specific element inside nested groups.
Knowing how to chain these commands lets you write precise tests for complex page structures.
7
ExpertHandling Dynamic Elements and Timing Issues
🤔Before reading on: do you think cy.first() waits for elements to appear or just picks immediately? Commit to your answer.
Concept: Cypress commands automatically wait for elements to appear, but using .first(), .last(), or .eq() on dynamic content requires understanding timing and retries.
If elements load slowly, cy.get('li').first() waits until at least one li appears. But if the list changes, the selected element might shift. Use assertions or retries carefully.
Result
Tests become stable even with changing page content.
Understanding Cypress's automatic waiting combined with these commands prevents flaky tests in real-world apps.
Under the Hood
When you use cy.get(), Cypress queries the page and returns a list of elements matching the selector. Commands like .first(), .last(), and .eq() filter this list to a single element by picking the element at the start, end, or a specific index. Cypress wraps this element in a special object that allows further commands and assertions. These commands also integrate with Cypress's retry logic, so they wait for elements to appear before failing.
Why designed this way?
Web pages often have many similar elements. Selecting one precisely is essential for reliable tests. The design follows common programming patterns of filtering collections by position, making it intuitive. Alternatives like selecting by unique IDs are not always possible, so these commands provide flexible, position-based selection.
cy.get('selector')
    │
    ▼
[Element0, Element1, Element2, ..., ElementN]
    │
    ├─ .first() → [Element0]
    ├─ .last()  → [ElementN]
    └─ .eq(i)  → [Elementi]
    │
    ▼
Single element wrapped for next commands
Myth Busters - 4 Common Misconceptions
Quick: Does cy.first() select the first element in the entire page or the first in the matched set? Commit to your answer.
Common Belief:cy.first() always selects the very first element in the whole page regardless of the selector.
Tap to reveal reality
Reality:cy.first() selects the first element only from the elements matched by the previous command, not the entire page.
Why it matters:Misunderstanding this can cause tests to target wrong elements, leading to false passes or failures.
Quick: Does cy.eq(1) select the second element or the first? Commit to your answer.
Common Belief:cy.eq(1) selects the first element because counting starts at 1.
Tap to reveal reality
Reality:cy.eq() uses zero-based indexing, so cy.eq(1) selects the second element.
Why it matters:Off-by-one errors cause tests to check or interact with wrong elements, making debugging harder.
Quick: Does chaining cy.first() after cy.eq() make sense? Commit to your answer.
Common Belief:You can chain cy.first() after cy.eq() to get the first element of the selected one.
Tap to reveal reality
Reality:cy.eq() returns a single element, so chaining cy.first() after it is redundant and may cause errors.
Why it matters:Misusing chaining leads to confusing test code and unexpected failures.
Quick: Does cy.last() wait for elements to appear before selecting? Commit to your answer.
Common Belief:cy.last() immediately selects the last element without waiting.
Tap to reveal reality
Reality:Cypress commands, including cy.last(), automatically wait for elements to appear before acting.
Why it matters:Knowing this prevents unnecessary waits or retries and helps write stable tests.
Expert Zone
1
Using cy.eq() with negative indexes is not supported; you must calculate the index manually.
2
When elements dynamically change order or count, relying on position-based selectors can cause flaky tests; prefer stable attributes when possible.
3
Chaining .find() after .eq() narrows the scope correctly, but chaining .eq() after .find() requires careful indexing to avoid mistakes.
When NOT to use
Avoid using cy.first(), cy.last(), or cy.eq() when elements have unique identifiers or attributes; instead, select elements directly by those unique selectors for more stable tests.
Production Patterns
In real-world tests, these commands are often combined with .find() and assertions to target nested elements precisely, such as clicking the first button inside a specific card or verifying the last item in a dynamic list.
Connections
Array Indexing in Programming
cy.eq() uses zero-based indexing like arrays in many programming languages.
Understanding array indexing helps avoid off-by-one errors when selecting elements by position.
CSS Pseudo-classes :first-child and :last-child
cy.first() and cy.last() conceptually match CSS selectors that pick first or last child elements.
Knowing CSS selectors helps understand how Cypress commands filter elements by position.
Queue Management in Operations
Selecting first or last elements is like managing queues where you pick the first or last person waiting.
This connection shows how position-based selection is a common pattern in many fields beyond programming.
Common Pitfalls
#1Selecting an element without narrowing down the matched set.
Wrong approach:cy.get('button').click()
Correct approach:cy.get('button').first().click()
Root cause:Assuming cy.get() returns a single element when it actually returns many, causing clicks on multiple buttons or test failures.
#2Using cy.eq() with wrong index due to misunderstanding zero-based counting.
Wrong approach:cy.get('li').eq(3).click() // intending to click 4th item but list has only 3 items
Correct approach:cy.get('li').eq(2).click() // clicks the 3rd item correctly
Root cause:Confusing human counting (starting at 1) with programming indexing (starting at 0).
#3Chaining cy.first() after cy.eq() causing errors.
Wrong approach:cy.get('div').eq(0).first().click()
Correct approach:cy.get('div').eq(0).click()
Root cause:Trying to select the first element of a single element, which is redundant and invalid.
Key Takeaways
cy.first(), cy.last(), and cy.eq() help select one element from many matched elements by position.
They rely on zero-based indexing and the order of elements in the matched set, not the entire page.
Using these commands makes tests more precise and prevents accidental actions on multiple elements.
Understanding how to chain these commands allows targeting nested or complex page structures.
Knowing Cypress's automatic waiting combined with these commands helps write stable tests for dynamic content.