如何在功能组件中测试状态更新? (父组件中的状态,子组件中的更新逻辑)

问题描述 投票:0回答:1

我在组件TodoItem.js]中具有称为changeStatusdeleteItem的函数

单击按钮(类名称为btn-info

)时,将调用changeStatus函数,它将待办事项的“完成”状态更改为相反(默认为false,因此应转到true)。

单击按钮(类名称为btn-danger

时),将调用deleteItem函数,并将其从todos数组中删除。

待办事项的状态在App.js中,从中将todos

数组和setTodos函数向下传递到TodoItemList,后者呈现TodoItem组件并传递todossetTodos 到TodoItem。
import React, { useState } from "react";
import AddItemBar from "./components/AddItemBar";
import TodoItemList from "./components/TodoItemList";
import "./App.css";
import { v4 as uuidv4 } from "uuid";

const App = () => {
  // Initial state for todos
  const [todos, setTodos] = useState([
    { id: uuidv4(), name: "Learn React", complete: false },
    { id: uuidv4(), name: "Graduate from school", complete: false },
    { id: uuidv4(), name: "Get a cool web development job", complete: false },
    { id: uuidv4(), name: "Learn more new technologies", complete: false },
    { id: uuidv4(), name: "Enjoy working life", complete: false }
  ]);

  return (
    <div className="container appbox">
      <TodoItemList todos={todos} setTodos={setTodos} />
      <AddItemBar todos={todos} setTodos={setTodos} />
    </div>
  );
};

export default App;

TodoItemList只是循环遍历todos

数组,并为每个数组项呈现一个TodoItem,将单独的todo,todos数组和setTodos函数传递给TodoItem:
import React from "react";
import TodoItem from "./TodoItem";

const TodoItemList = ({ todos, setTodos }) => {
  var items = [];

  // Create todo item list
  todos.forEach(todo => {
    items.push(
      <TodoItem key={todo.id} todo={todo} todos={todos} setTodos={setTodos} />
    );
  });

  return items;
};

export default TodoItemList;

TodoItem.js组件:

import React from "react";

const TodoItem = ({ todo, todos, setTodos }) => {
  // Todo item color and text changes based on todo.complete state
  var color = todo.complete === true ? "lightgreen" : "bisque";
  var text = todo.complete === true ? "Complete" : "Incomplete";

  // Change completed status for clicked item
  const changeStatus = id => {
    var todoItems = todos.slice();
    for (let i = 0; i < todos.length; i++) {
      if (todoItems[i].id === id) {
        var newComplete = !todoItems[i].complete;
        todoItems[i].complete = newComplete;
      }
    }

    setTodos(todoItems);
  };

  // Remove todo item
  const deleteItem = id => {
    const newTodos = [...todos];

    var removeIndex = newTodos
      .map(todo => {
        return todo.id;
      })
      .indexOf(id);

    newTodos.splice(removeIndex, 1);

    setTodos(newTodos);
  };

  return (
    <div
      className="row mt-2 mr-1 ml-1 todoItem"
      style={{ backgroundColor: color }}
    >
      <h5 className="col-sm text-center">{todo.name}</h5>
      <button
        className="btn btn-info col-sm-3"
        onClick={() => changeStatus(todo.id)}
      >
        {text}
      </button>
      <button
        className="btn btn-danger col-sm-2"
        onClick={() => deleteItem(todo.id)}
      >
        Delete
      </button>
    </div>
  );
};

export default TodoItem;


现在如何在TodoItem中测试这些功能的副作用?

到目前为止,这是TodoItem.test.js文件,它仅测试UI(所有都通过),但不测试状态更新:

import React from "react";
import TodoItem from "./TodoItem";
import { v4 as uuidv4 } from "uuid";
import { shallow } from "enzyme";

describe("<TodoItem />", () => {
  it("should render without problems", () => {
    const todo = { id: uuidv4(), name: "Learn React", complete: false };
    shallow(<TodoItem todo={todo} />);
  });

  it("shallow wrapper instance should be null", () => {
    const todo = { id: uuidv4(), name: "Learn React", complete: false };
    const wrapper = shallow(<TodoItem todo={todo} />);
    const instance = wrapper.instance();

    expect(instance).toEqual(null);
  });

  it("should have todo text", () => {
    const todo = { id: uuidv4(), name: "Learn React", complete: false };
    const wrapper = shallow(<TodoItem todo={todo} />);
    expect(wrapper.find("h5").length).toEqual(1);
  });

  it("should have a complete button", () => {
    const todo = { id: uuidv4(), name: "Learn React", complete: false };
    const wrapper = shallow(<TodoItem todo={todo} />);
    expect(wrapper.find("button.btn-info").length).toEqual(1);
  });

  it("should have a delete button", () => {
    const todo = { id: uuidv4(), name: "Learn React", complete: false };
    const wrapper = shallow(<TodoItem todo={todo} />);
    expect(wrapper.find("button.btn-danger").length).toEqual(1);
  });
});

我已经读过,直接测试功能本身是有害的,所以我只想测试副作用:

  • changeStatus:测试todo.complete是否从false更改为true
  • deleteItem
  • :测试是否从todos数组中删除该项目

我在组件TodoItem.js中有一个名为changeStatus和deleteItem的函数,当单击一个按钮(带有btn-info的className时,将调用changeStatus函数并更改todo ...

reactjs unit-testing jestjs enzyme
1个回答
0
投票

确定,因此在搜索Google一段时间后,我发现当前无法通过Jest / Enzyme测试功能组件的状态。

© www.soinside.com 2019 - 2024. All rights reserved.