Bird
Raised Fist0
Cypresstesting~15 mins

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

Choose your learning style10 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.

Practice

(1/5)
1. What does cy.first() do in Cypress testing?
easy
A. Selects all elements matching a selector
B. Selects the last element from a group of matched elements
C. Selects the first element from a group of matched elements
D. Selects an element by its CSS class

Solution

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

    cy.first() is used to pick the very first element from a list of elements found by a selector.
  2. Step 2: Compare with other options

    Options A, B, and C describe different behaviors: last element, selecting by class, or selecting all elements, which are not what cy.first() does.
  3. Final Answer:

    Selects the first element from a group of matched elements -> Option C
  4. Quick Check:

    cy.first() = first element [OK]
Hint: Remember: first() picks the very first element [OK]
Common Mistakes:
  • Confusing first() with last()
  • Thinking first() selects by class or id
  • Assuming first() selects all elements
2. Which of the following is the correct syntax to select the third element in a list using Cypress?
easy
A. cy.get('li').eq(2)
B. cy.get('li').eq(3)
C. cy.get('li').first(3)
D. cy.get('li').last(3)

Solution

  1. Step 1: Recall zero-based indexing in eq()

    The eq() command uses zero-based index, so the third element is at index 2.
  2. Step 2: Check syntax correctness

    cy.get('li').eq(2) uses eq(2) correctly. Options A, C, and D either use wrong index or invalid syntax.
  3. Final Answer:

    cy.get('li').eq(2) -> Option A
  4. Quick Check:

    Third element index = 2 [OK]
Hint: Remember eq() uses zero-based index, so third is eq(2) [OK]
Common Mistakes:
  • Using eq(3) for the third element
  • Trying to pass a number to first() or last()
  • Confusing eq() with first() or last()
3. Given the following HTML:
<ul>
  <li>Apple</li>
  <li>Banana</li>
  <li>Cherry</li>
  <li>Date</li>
</ul>

What text will cy.get('li').last().invoke('text') return?
medium
A. "Cherry"
B. "Apple"
C. "Banana"
D. "Date"

Solution

  1. Step 1: Identify what cy.last() selects

    cy.last() picks the last element in the matched list, which is the <li> containing "Date".
  2. Step 2: Understand invoke('text')

    This command extracts the text content of the selected element, so it returns "Date".
  3. Final Answer:

    "Date" -> Option D
  4. Quick Check:

    last() element text = "Date" [OK]
Hint: last() picks last element's text content [OK]
Common Mistakes:
  • Selecting first element text instead of last
  • Confusing zero-based index with last()
  • Expecting eq(3) to return "Date" without zero-based indexing
4. Consider this Cypress code snippet:
cy.get('button').eq(5).click()

It throws an error: "Cannot read property 'click' of undefined". What is the most likely cause?
medium
A. There are fewer than 6 buttons on the page, so eq(5) returns undefined
B. The syntax of eq() is incorrect; it should be eq[5]
C. click() cannot be chained after eq()
D. The selector 'button' is invalid

Solution

  1. Step 1: Understand eq() index and element count

    eq(5) tries to select the 6th element (index 5). If fewer than 6 buttons exist, it returns undefined.
  2. Step 2: Analyze error message

    The error "Cannot read property 'click' of undefined" means the element does not exist, so click() fails.
  3. Final Answer:

    There are fewer than 6 buttons on the page, so eq(5) returns undefined -> Option A
  4. Quick Check:

    Index out of range = undefined element [OK]
Hint: Check element count before using eq(index) [OK]
Common Mistakes:
  • Using wrong eq() syntax
  • Assuming click() can't chain after eq()
  • Ignoring zero-based index causing out-of-range
5. You want to click the second-to-last item in a list of elements matched by cy.get('.item'). Which Cypress command chain correctly achieves this?
hard
A. cy.get('.item').eq(cy.get('.item').its('length').then(len => len - 2)).click()
B. cy.get('.item').eq(-2).click()
C. cy.get('.item').eq(-1).click({ force: true })
D. cy.get('.item').eq(cy.get('.item').length - 2).click()

Solution

  1. Step 1: Recall eq() indexing in Cypress

    Cypress eq(n) supports negative indices: eq(-1) is last, eq(-2) is second-to-last.
  2. Step 2: Compare options

    Options A and B have invalid syntax passing chainables to eq(). cy.get('.item').eq(-1).click({ force: true }) uses eq(-1) for last item. cy.get('.item').eq(-2).click() correctly uses eq(-2).
  3. Final Answer:

    cy.get('.item').eq(-2).click() -> Option B
  4. Quick Check:

    eq(-2) = second-to-last [OK]
Hint: eq() supports negative indices: -2 for second-to-last [OK]
Common Mistakes:
  • Using negative index in eq() incorrectly (e.g., -1 instead of -2)
  • Trying to subtract length directly without .then()
  • Passing Cypress chainable as eq() argument
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