reactjs - Testovanie odstraňovania položiek z React kontrolovaného zoznamu pomocou Cypress


Vytvoril som zoznam v Reacte, z ktorého môžu používatelia odstrániť položky kliknutím na tlačidlo.

Odstránenie sa rieši takto:

 const handleRemove = (index: number) => {
   onChange(fieldName, (prevState) => {
     return {
       ...prevState,
       [fieldName]: prevState[fieldName].filter((_: any, i: number) => i !== index),
     };
   });
 };

Keď to testujem manuálne, funguje to dobre, ale keď to testujem s Cypressom, mazanie položiek nefunguje podľa očakávania, niektoré položky zostanú. (Predpokladám), že problém je v tom, že Cypress stláča každý „tlačidlo mazania zoznamu“ súčasne a mazanie položiek podľa indexu sa nedá spoľahlivo použiť, keď sa zoznam rýchlo mení. V reálnom živote to nemôže spôsobiť žiadne problémy, však?

Ak to dokáže, ako by som mal prepracovať logiku mazania?

Ak to však nie je veľký problém, ako môžem prepisovať svoj test Cypress, aby počkal pár milisekúnd, kým React spraví svoje s aktualizáciami stavu?

Toto som vymyslel po niekoľkých hodinách hrabania sa:

cy.get(".fa-solid.fa-minus").each((element, index) => {
      cy.wait(index * 3).then(() => {
        element.trigger("click");
      });
});

Odpoveď č. 1

Slučka each() spracováva príliš rýchlo, aby aplikácia mohla dokončiť každú akciu vymazania.

Vnútorná slučka potrebuje aserciu na potvrdenie, že akcia bola dokončená. Cypress čaká na túto asercie pred vykonaním ďalšej iterácie.

V nižšie uvedenom príklade overenie kontroluje, či sa dĺžka zoznamu znížila.

V prípade absencie úplného príkladu som použil nasledujúcu komponentu:

import React from 'react';
import {useState} from 'react'

const initialList = ['Cypress', 'Javascript', 'Typescript']

export const List = () => {
  const [list, setList] = useState(initialList)

  const handleRemove = (index) => {
    setList(prevState => prevState.filter((_, i) => i !== index))
  }

  return (
    <ul>
      {list.map(function(item, index) {
        return <>
          <li key={item}>{item}</li>
          <button onClick={() => handleRemove(index)}>Delete</button>
        </>
      })}
    </ul>
  )
}

Toto je test

const itemList = ['Cypress', 'Javascript', 'Typescript']

const selector = 'button:contains("Delete this one")'

cy.get(selector)
  .each(($el, index, $list) => {
    cy.get(selector).first().click()

    // wait for action to complete

    // using list count
    cy.get(selector).should('have.length', $list.length - index -1)

    // or using item text
    cy.contains(itemList[index]).should('not.exist') 
  })

cy.get(selector).should('not.exist')       // all gone

Toto je protokol pre úspešný test

Súvisiace články