Mô phỏng một lần nhấp vào nút trong Jest


83

Mô phỏng một lần nhấp vào nút có vẻ như là một hoạt động rất dễ dàng / tiêu chuẩn. Tuy nhiên, tôi không thể làm cho nó hoạt động trong các bài kiểm tra Jest.js.

Đây là những gì tôi đã thử (và cũng làm điều đó bằng cách sử dụng jQuery), nhưng nó dường như không kích hoạt bất cứ điều gì:

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

Làm sao bạn biết nó không làm gì cả? Bạn đang kiểm tra điều gì tiếp theo để xem liệu nhấp vào nút có xảy ra không?
Toby

Câu hỏi hay. Tôi hy vọng trường lỗi sẽ xuất hiện: const field = pageMounted.find ('# thông báo'); mong đợi (field.length) .toBe (1);
foobar

Hrm. Bạn đã thêm một console.warnvào hàm chạy onClick để xem nó có kích hoạt trong bảng điều khiển Jest không?
Toby

Bạn có thể vui lòng thêm mã cho MyCoolPage thành phần, nếu không, thật khó để tìm ra vấn đề thực sự là gì.
Andreas Köberle

1
Cảm ơn các bạn vì những lời khuyên. Tôi đã tìm thấy vấn đề của mình, nhờ câu hỏi của bạn. Về cơ bản, tôi đã thực hiện một thử nghiệm nhỏ với một nút đơn giản và nó hoạt động: MyCoolPage = (<button type = "submit" id = "cool_button" onClick = {() => {console.warn ('Tôi đã được nhấp vào');}> Nút tuyệt vời </button>); Sau đó, tôi nhận ra rằng nút của tôi thuộc về dạng redux, vì vậy nó không có onClick mà thay vào đó là onSubmit, vì vậy hãy thêm button.simulate ('submit'); đã giải quyết vấn đề. Cảm ơn một lần nữa cho phản hồi của bạn!
foobar

Câu trả lời:


134

# 1 Sử dụng Jest

Đây là cách tôi sử dụng hàm gọi lại giả Jest để kiểm tra sự kiện nhấp chuột:

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);
  });
});

Tôi cũng đang sử dụng một mô-đun có tên là enzyme . Enzyme là một tiện ích thử nghiệm giúp xác nhận và chọn các Thành phần React của bạn dễ dàng hơn

# 2 Sử dụng Sinon

Ngoài ra, bạn có thể sử dụng một mô-đun khác có tên là Sinon , là một phần mềm gián điệp thử nghiệm độc lập, sơ khai và mô phỏng cho JavaScript. Cái này nó thì trông như thế nào:

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 Sử dụng gián điệp của riêng bạn

Cuối cùng, bạn có thể thực hiện một điệp viên ngây thơ của riêng mình (tôi không khuyến khích cách làm này trừ khi bạn có lý do chính đáng cho việc đó).

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
Cảm ơn bạn đã trả lời chi tiết Saman! Điều này rất hữu ích khi bạn có thể chuyển trực tiếp phương thức onClick vào thành phần bạn đang thử nghiệm và tôi sẽ sử dụng mã của bạn làm tài liệu tham khảo cho điều đó :). Tôi nghĩ trong ví dụ của mình, mặc dù tôi thực sự không thể chuyển onClick và tôi phải dựa vào các manh mối khác để biết rằng nút đã được nhấp.
foobar

Ở mặt sau của ví dụ đầu tiên, bạn có thể đưa ra ví dụ về cách chúng ta có thể viết một bài kiểm tra cho một onChangehàm có thuộc tính valuecủa phần tử đầu vào valuekhông? Cảm ơn!
blankface

7
Điều này thực sự kiểm tra điều gì?
Omortis

1
Tôi có một nút gọi handleClickphương thức của mình khi được nhấp vào. Làm cách nào để kiểm tra nó handleClickthực sự được gọi khi nút được nhấp?
Jeremy Moritz

Mặc dù nó trả lời câu hỏi cho React, nhưng hầu hết câu trả lời này liên quan nhiều đến việc chế nhạo hơn là mô phỏng một lần nhấp vào nút.
Brady Dowling

19

Các giải pháp trong câu trả lời được chấp nhận sẽ không được dùng nữa

# 4 Gọi chỗ dựa trực tiếp

Enzyme mô phỏng được cho là sẽ bị loại bỏ trong phiên bản 4. Người bảo trì chính đang đề xuất trực tiếp gọi các hàm prop, đây là những gì mô phỏng thực hiện bên trong. Một giải pháp là kiểm tra trực tiếp xem việc gọi các đạo cụ đó có đúng không; hoặc bạn có thể mô phỏng các phương thức cá thể, kiểm tra xem các hàm prop có gọi chúng hay không và kiểm tra đơn vị các phương thức cá thể.

Bạn có thể gọi nhấp chuột, ví dụ:

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

Hoặc là

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

Thông tin về việc ngừng sử dụng: Ngừng sử dụng .simulate () # 2173


Câu trả lời nào trước đó? Hay là nhiều hơn một (những cái nào?)?
Peter Mortensen

@PeterMortensen Tôi đã làm rõ câu trả lời. Câu trả lời được chấp nhận là sử dụng mô phỏng enzyme, sẽ không được dùng nữa.
Đen

bạn có thể cần phải gọi wrapper.update()sau một trong những điều này, vì enzyme có thể không nhận thấy rằng một thay đổi đã xảy ra.
Hinrich

12

Sử dụng Jest, bạn có thể làm như sau:

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
Giá trị trong việc tạo một nút hoàn chỉnh trong các thử nghiệm của bạn với một lệnh gọi lại bị chế nhạo khi được nhấp và sau đó nhấp vào nút đó trong thử nghiệm là gì? Giống như hầu hết các ví dụ thử nghiệm mà tôi đã thấy, bạn thậm chí chưa kiểm tra một dòng mã thực của mình khi bạn làm điều này.
Jeremy Moritz

1
@JeremyMoritz đó là lý do tại sao tôi không hiểu điểm hoặc logic trong các bài kiểm tra đơn vị.
user3808307

0

Bạn có thể sử dụng một cái gì đó như thế này để gọi trình xử lý được viết khi nhấp chuột:

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

Ngoài các giải pháp được đề xuất trong các nhận xét của anh chị em, bạn có thể thay đổi cách tiếp cận kiểm tra của mình một chút và không kiểm tra toàn bộ trang cùng một lúc (với cây thành phần con sâu), nhưng thực hiện kiểm tra thành phần riêng biệt . Điều này sẽ đơn giản hóa việc thử nghiệm onClick()và các sự kiện tương tự (xem ví dụ bên dưới).

Ý tưởng là chỉ kiểm tra một thành phần tại một thời điểm và không phải tất cả chúng cùng nhau. Trong trường hợp này, tất cả các thành phần con sẽ được chế tạo bằng cách sử dụng hàm jest.mock () .

Dưới đây là một ví dụ về cách onClick()sự kiện có thể được kiểm tra trong một SearchFormthành phần biệt lập bằng cách sử dụng Jesttrình kết xuất phản ứng thử nghiệm .

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

Tôi cần tự kiểm tra một chút về thành phần nút. Những bài kiểm tra này phù hợp với tôi ;-)

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);
    });
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.