Jest'te bir düğme tıklamasını simüle edin


84

Bir düğme tıklamasını simüle etmek çok kolay / standart bir işlem gibi görünüyor. Yine de, Jest.js testlerinde çalışmasını sağlayamıyorum.

Bu denediğim şeydi (ve bunu jQuery kullanarak yapıyorum), ancak hiçbir şeyi tetiklemedi

import { mount } from 'enzyme';

page = <MyCoolPage />;
pageMounted = mount(page);

const button = pageMounted.find('#some_button');
expect(button.length).toBe(1); // It finds it alright
button.simulate('click'); // Nothing happens

Hiçbir şey yapmadığını nereden biliyorsun? Düğme tıklamasının gerçekleşip gerçekleşmediğini görmek için yanında neyi kontrol ediyorsunuz?
Toby

İyi soru. Hata alanının görünmesini bekliyorum: const field = pageMounted.find ('# bildirim'); beklenti (alan.uzunluk) .toBe (1);
foobar

Hrm. console.warnJest konsolunda çalışıp çalışmadığını görmek için onClick'i çalıştıran işleve bir eklediniz mi?
Toby

Lütfen MyCoolPage bileşenin kodunu ekleyebilir misiniz , yoksa asıl sorunun ne olduğunu anlamak zordur.
Andreas Köberle

1
İpuçları için teşekkür ederim arkadaşlar. Sorularınız sayesinde sorunumu buldum. Temelde basit bir düğmeyle küçük bir test yaptım ve işe yaradı: MyCoolPage = (<button type = "submit" id = "cool_button" onClick = {() => {console.warn ('Tıklandım');}> Soğuk Düğmesi </button>); Daha sonra düğmemin redux-formuna ait olduğunu fark ettim, bu yüzden onClick yoktu, onun yerine onSubmit, bu yüzden button.simulate ('submit'); sorunu çözdü. Geri bildiriminiz için tekrar teşekkürler!
foobar

Yanıtlar:


138

# 1 Jest'i Kullanmak

Click olayını test etmek için Jest sahte geri arama işlevini şu şekilde kullanıyorum:

import React from 'react';
import { shallow } from 'enzyme';
import Button from './Button';

describe('Test Button component', () => {
  it('Test click event', () => {
    const mockCallBack = jest.fn();

    const button = shallow((<Button onClick={mockCallBack}>Ok!</Button>));
    button.find('button').simulate('click');
    expect(mockCallBack.mock.calls.length).toEqual(1);
  });
});

Ayrıca enzim adlı bir modül kullanıyorum . Enzyme, React Bileşenlerinizi onaylamayı ve seçmeyi kolaylaştıran bir test aracıdır

# 2 Sinon Kullanımı

Ayrıca, bağımsız bir test casusu olan Sinon adlı başka bir modül , JavaScript için saplamalar ve alaylar kullanabilirsiniz. Şöyle görünüyor:

import React from 'react';
import { shallow } from 'enzyme';
import sinon from 'sinon';

import Button from './Button';

describe('Test Button component', () => {
  it('simulates click events', () => {
    const mockCallBack = sinon.spy();
    const button = shallow((<Button onClick={mockCallBack}>Ok!</Button>));

    button.find('button').simulate('click');
    expect(mockCallBack).toHaveProperty('callCount', 1);
  });
});

# 3 Kendi Casusunuzu Kullanmak

Son olarak, kendi saf casusunuzu yapabilirsiniz (Bunun için geçerli bir nedeniniz yoksa bu yaklaşımı önermiyorum).

function MySpy() {
  this.calls = 0;
}

MySpy.prototype.fn = function () {
  return () => this.calls++;
}

it('Test Button component', () => {
  const mySpy = new MySpy();
  const mockCallBack = mySpy.fn();

  const button = shallow((<Button onClick={mockCallBack}>Ok!</Button>));

  button.find('button').simulate('click');
  expect(mySpy.calls).toEqual(1);
});

1
Ayrıntılı cevap için teşekkür ederim Saman! Bu, onClick yöntemini doğrudan test ettiğiniz bileşene aktarabildiğiniz zaman çok kullanışlıdır ve kodunuzu bunun için bir referans olarak kullanacağım :). Örneğimde, gerçekten onClick'i geçemediğimi ve düğmenin tıklandığını bilmek için diğer ipuçlarına güvenmem gerektiğini düşünüyorum.
foobar

İlk örneğinizin arkasında , girdi öğesinin özniteliğiyle eşleşen bir onChangeişlev için nasıl test yazabileceğimize dair bir örnek verebilir misiniz ? Teşekkürler! valuevalue
blankface

7
Bu aslında neyi test ediyor?
Omortis

1
handleClickTıklandığında yöntemimi çağıran bir düğmem var. handleClickDüğme tıklandığında gerçekten çağrılanı nasıl test ederim ?
Jeremy Moritz

React için soruyu yanıtlasa da, bu yanıtın çoğu, bir düğme tıklamasını simüle etmekten çok alay etmekle ilgilidir.
Brady Dowling

21

Kabul edilen yanıttaki çözümler kullanımdan kaldırılıyor

# 4 Doğrudan prop çağırma

Enzim simülasyonunun sürüm 4'te kaldırılması gerekiyordu. Ana sürdürücü, doğrudan prop işlevlerini çağırmayı öneriyor, bu da simülasyonun dahili olarak yaptığı şeydir. Çözümlerden biri, bu sahne donanımlarını çağırmanın doğru şeyi yaptığını doğrudan test etmektir; veya örnek yöntemlerin alayını yapabilir, prop işlevlerinin onları çağırdığını test edebilir ve örnek yöntemlerini birim test edebilirsiniz.

Örneğin, tıklama arayabilirsiniz:

wrapper.find('Button').prop('onClick')() 

Veya

wrapper.find('Button').props().onClick() 

Kullanımdan kaldırma hakkında bilgi: .simulate () # 2173'ün kullanımdan kaldırılması


Hangi önceki cevap? Yoksa birden fazla mı (hangileri?)?
Peter Mortensen

1
@PeterMortensen Cevabı netleştirdim. Kabul edilen yanıt, kullanımdan kaldırılacak olan enzim simülasyonunu kullanmaktır.
Siyah

wrapper.update()enzim bir değişikliğin olduğunu fark edemeyebileceğinden, bunlardan birinin ardından aramanız gerekebilir.
Hinrich

onClickPervanesi olmayan bir düğmeye ne dersiniz ? Bir type="submit"içindeki bir düğme gibi <form />? Evet onSubmit, formda arayabilir - ama bu ideal değil. Kullanıcılar düğmeyi tıklayacak ve test etmek istediğiniz şey bu.
Oli

Teşekkürler @ Siyah, hayat kurtarıcı!
Anas Latique

12

Jest'i kullanarak bunu şu şekilde yapabilirsiniz:

test('it calls start logout on button click', () => {
    const mockLogout = jest.fn();
    const wrapper = shallow(<Component startLogout={mockLogout}/>);
    wrapper.find('button').at(0).simulate('click');
    expect(mockLogout).toHaveBeenCalled();
});

7
Testlerinizde, tıklandığında ve ardından testte bu düğmeye tıklandığında sahte bir geri arama ile eksiksiz bir düğme oluşturmanın değeri nedir? Gördüğüm test örneklerinin çoğu gibi, bunu yaparken gerçek kodunuzun tek bir satırını bile test etmediniz.
Jeremy Moritz

2
@JeremyMoritz bu yüzden birim testlerindeki noktayı veya mantığı anlamıyorum.
user3808307

0

Tıklamada yazılan işleyiciyi aramak için buna benzer bir şey kullanabilirsiniz:

import { shallow } from 'enzyme'; // Mount is not required

page = <MyCoolPage />;
pageMounted = shallow(page);

// The below line will execute your click function
pageMounted.instance().yourOnClickFunction();

0

Kardeş yorumlarında önerilen çözümlere ek olarak, test yaklaşımınızı biraz değiştirebilir ve tüm sayfayı tek seferde test edemezsiniz (derin bir alt bileşenler ağacı ile), ancak izole bir bileşen testi yapabilirsiniz. Bu onClick()ve benzer olayların test edilmesini basitleştirecektir (aşağıdaki örneğe bakın).

Fikir yalnızca test etmektir biri bir defada ve en bileşeni hepsi bir arada bunların. Bu durumda, tüm alt bileşenler jest.mock () işlevi kullanılarak alay edilecektir .

Jest ve react-test-renderer kullanılarak onClick()izole edilmiş bir SearchFormbileşende olayın nasıl test edilebileceğine dair bir örnek .

import React from 'react';
import renderer from 'react-test-renderer';
import { SearchForm } from '../SearchForm';

describe('SearchForm', () => {
  it('should fire onSubmit form callback', () => {
    // Mock search form parameters.
    const searchQuery = 'kittens';
    const onSubmit = jest.fn();

    // Create test component instance.
    const testComponentInstance = renderer.create((
      <SearchForm query={searchQuery} onSearchSubmit={onSubmit} />
    )).root;

    // Try to find submit button inside the form.
    const submitButtonInstance = testComponentInstance.findByProps({
      type: 'submit',
    });
    expect(submitButtonInstance).toBeDefined();

    // Since we're not going to test the button component itself
    // we may just simulate its onClick event manually.
    const eventMock = { preventDefault: jest.fn() };
    submitButtonInstance.props.onClick(eventMock);

    expect(onSubmit).toHaveBeenCalledTimes(1);
    expect(onSubmit).toHaveBeenCalledWith(searchQuery);
  });
});

0

Bir düğme bileşenini kendim için biraz test etmem gerekiyordu. Bu testler benim için çalışıyor ;-)

import { shallow } from "enzyme";
import * as React from "react";
import Button from "../button.component";

describe("Button Component Tests", () => {
    it("Renders correctly in DOM", () => {
        shallow(
            <Button text="Test" />
        );
    });
    it("Expects to find button HTML element in the DOM", () => {
        const wrapper = shallow(<Button text="test"/>)
        expect(wrapper.find('button')).toHaveLength(1);
    });

    it("Expects to find button HTML element with className test in the DOM", () => {
        const wrapper = shallow(<Button className="test" text="test"/>)
        expect(wrapper.find('button.test')).toHaveLength(1);
    });

    it("Expects to run onClick function when button is pressed in the DOM", () => {
        const mockCallBackClick = jest.fn();
        const wrapper = shallow(<Button onClick={mockCallBackClick} className="test" text="test"/>);
        wrapper.find('button').simulate('click');
        expect(mockCallBackClick.mock.calls.length).toEqual(1);
    });
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.