Я хочу проверить, добавляет ли messageListener данные к состоянию массива messages .Однако я получил несколько блоков по этому вопросу.1. Не удается протестировать методы внутри компонента без состояния 2. Перехватчики React нельзя использовать вне функции компонента.
Я не могу понять, как обойти это?Должен ли я использовать другой подход для тестирования этого?Должен ли я извлечь его в пользовательский хук?Я новичок как в ферментных, так и в реактивных хуках.Я в основном хочу проверить, если с учетом того, что socket.io получает событие MESSAGE, компонент добавит другой элемент в массив сообщений для отображения внутри MessageFeed.
Полный проект также можно увидеть на https://github.com/Hyllesen/react-chat
App.js
import React from "react";
import UsernameInput from "components/UsernameInput";
import MessageFeed from "components/MessageFeed";
import io from "socket.io-client";
import * as eventTypes from "eventTypes";
function joinWithUsername(username) {
const socket = io("http://localhost:3001");
socket.emit(eventTypes.USER_JOIN, { username });
socket.on(eventTypes.MESSAGE, messageListener);
}
function messageListener(data, setMessages) {
setMessages([...messages, data]);
}
const App = () => {
const [messages, setMessages] = React.useState([]);
return (
<div className="App">
<UsernameInput onSubmit={joinWithUsername} />
<MessageFeed messages={messages} />
</div>
);
};
export default App;
export { joinWithUsername, messageListener };
App.test.js
import React from "react";
import App, { joinWithUsername, messageListener } from "../App";
import { shallow } from "enzyme";
import io from "socket.io-client";
import * as eventTypes from "eventTypes";
let wrapper, setState, useStateSpy;
jest.mock("socket.io-client", () => {
const emit = jest.fn();
const on = jest.fn();
const socket = { emit, on };
return jest.fn(() => socket);
});
describe("App", () => {
beforeEach(() => {
wrapper = shallow(<App />);
setState = jest.fn();
useStateSpy = jest.spyOn(React, "useState");
useStateSpy.mockImplementation(init => [init, setState]);
});
afterEach(() => jest.clearAllMocks());
it("has a usernameinput component", () => {
expect(wrapper.find("UsernameInput").length).toBe(1);
});
it("has a joinWithUsername function", () => {
const usernameInput = wrapper.find("UsernameInput").props();
console.log(usernameInput.onSubmit);
expect(usernameInput.onSubmit).toBe(joinWithUsername);
});
it("connect to socket.io server", () => {
joinWithUsername("Bobby");
expect(io).toHaveBeenCalledWith("http://localhost:3001");
});
it("emits the USER_JOIN event", () => {
joinWithUsername("John");
const socket = io();
expect(socket.emit).toHaveBeenCalledWith(eventTypes.USER_JOIN, {
username: "John"
});
});
it("listens for the MESSAGE event", () => {
joinWithUsername("John");
const socket = io();
expect(socket.on).toHaveBeenCalledWith(eventTypes.MESSAGE, messageListener);
});
it("Appends a message to state when message is received", () => {
const testData = {
from: "John",
message: "Hello everyone!"
};
messageListener(testData);
expect(setState).toHaveBeenCalledWith(testData); //ReferenceError: setMessages is not defined
});
});