• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

waitFor() nie zwracający komponentu w automatycznych testach [Jest, React]

Cloud VPS
0 głosów
223 wizyt
pytanie zadane 30 lipca 2021 w JavaScript przez Oskar Szkurłat Bywalec (2,780 p.)

Cześć, zacząłem się uczyć robić automatyczne testy w oparciu o jest dla reacta. Jednak co chwilę napotykam niezbyt zrozumiałe dla mnie sytuację, jedną z nich jest problem przedstawiony poniżej.

Mam komponent App i w nim komponent LoginPage (LoginPage korzysta z propsów App, stąd te moje wywołanie obu w metodzie render()). Test polega na sprawdzeniu czy po wciśnięciu przycisku strona jest przerenderowana i pojawił się komunikat - proste prawda :D? Brak danych logowania - to błędne dane. Jednak problem tkwi w tym, że nie rozumiem dlaczego waitFor nie zwraca mi obiektu, tylko undefined, pomimo, że na debug() widzę, że obiekt się przerenderował i że istnieje poszukiwany przeze mnie komunikat o błędzie. Próbowałem dwojako: dobrać się do niego za pomocą testId oraz getByText, obie metody zwracają to samo. Troszkę to wygląda dla mnie tak, jakbym pomimo przerenderowania komponentu, w teście sprawdzał poprzedni stan? 

import { render, fireEvent, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import App from '../../App'
import LoginPage from './LoginPage'

test('error-login-text', async () => {
    const { getByText, getByTestId, debug } = render(
        <App>
            <LoginPage />
        </App>
    )

    const button = getByTestId('login-button')
    fireEvent.click(button)

    console.log('_________', 'Przed renderowaniem', '_________')
    debug()
    const errorText = await waitFor(() => {
        getByTestId('login-error')
    })
    console.log('_________', 'Po wyrenderowaniu', '_________')
    debug()
    console.log('_________', 'Wynik', '_________',
        '\n', errorText)
    expect(errorText.children[0]).toEqual('Incorrect login data!')


})
<form>
                <input
                    id="email"
                    type="text"
                    placeholder="Enter your email"
                    onChange={onLogin}
                    value={props.emailValue}
                />
                <input
                    id="password"
                    type="password"
                    placeholder="Enter your password"
                    onChange={onPassword}
                    password={props.passwordValue}
                />
                <button
                    data-testid='login-button'
                    type="submit"
                    onClick={props.onSubmit}
                >
                    Login
                </button>
                {props.failedLogin === true ?
                    <p
                        data-testid='login-error'
                    >
                        Incorrect login data!
                    </p> : <></>}
            </form>

Z góry dzięki.

1 odpowiedź

+1 głos
odpowiedź 30 lipca 2021 przez ScriptyChris Mędrzec (190,190 p.)
wybrane 30 lipca 2021 przez Oskar Szkurłat
 
Najlepsza
const errorText = await waitFor(() => {
    getByTestId('login-error')
})

A próbowałeś zapisać return przed getByTestId (albo nie używać klamer dla funkcji strzałkowej)? Sądząc po dokumentacji metody waitFor ona zwraca promisa, który rozwiązuje się do wartości zwróconej przez callback. Callback w obecnym kształcie zwraca undefined, bo nie ma tam return'a.

komentarz 30 lipca 2021 przez Oskar Szkurłat Bywalec (2,780 p.)
edycja 30 lipca 2021 przez Oskar Szkurłat

Hmm w sumie nie próbowałem, ale właśnie skoro to promise, to czy na pewno mogę użyć return w nim? Sprawdzę troszkę później i potwierdzę czy pomogło, dzięki póki co ;)

 

//Edit: Sprawdziłem od razu, cholera jasna xD to było to, dziękuję ślicznie, w życiu bym sam nie zauważył, wystarczyło klamry usunąć (czyli returna zwrócić)... chociaż jeszcze poprawka, bo .children[0] też było źle, ale pomogło przełączenie getByText

Dla potomnych:

import { render, fireEvent, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import App from '../../App'
import LoginPage from './LoginPage'

test('error-login-text', async () => {
    const { getByText, getByTestId, debug } = render(
        <App>
            <LoginPage />
        </App>
    )
    const button = getByTestId('login-button')
    fireEvent.click(button)

    console.log('_________', 'Przed renderowaniem', '_________')
    debug()
    const errorText = await waitFor(() => getByText('Incorrect login data!'))
    console.log('_________', 'Po wyrenderowaniu', '_________')
    debug()
    console.log('_________', 'Wynik', '_________',
        '\n', errorText)
    expect(errorText).toBeInTheDocument()

})

 

1
komentarz 30 lipca 2021 przez ScriptyChris Mędrzec (190,190 p.)

skoro to promise, to czy na pewno mogę użyć return w nim?

Nie bardzo rozumiem, co ma promise do niemożności zwrócenia go z funkcji? Promise sam w sobie to jest obiekt, który reprezentuje ewentualną przyszłą wartość (jeśli zostanie spełniony) lub przyczynę odrzucenia (jeśli wystąpi błąd albo celowo zostanie odrzucony) w momencie jego rozwiązania. Możesz więc zwracać promise z funkcji, przekazywać go jako parametr, przypisywać do zmiennej, ma on swoje propertisy i metody.

Podobne pytania

+1 głos
1 odpowiedź 234 wizyt
+1 głos
1 odpowiedź 394 wizyt
+2 głosów
0 odpowiedzi 343 wizyt
pytanie zadane 3 grudnia 2021 w JavaScript przez lzrd Nowicjusz (160 p.)

93,453 zapytań

142,448 odpowiedzi

322,717 komentarzy

62,829 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...