我已经创建了一个基本的todolist组件,并正在为其编写一些测试,但我想知道如何模拟本地存储正在使用我当前拥有的代码收集数据的测试,或者是否需要创建一个自定义钩子来模拟。理想情况下,我不想这样做,但感觉这将是使用渲染挂钩的唯一方法。
This is my current code for todolist:
import { useEffect, useState } from 'react';
import { Container, TextInput, Button, List } from '@mantine/core';
import { Tasks } from '../types';
const TodoList = () => {
const [task, setTask] = useState('');
const [todoList, setTodoList] = useState<Tasks[]>([]);
const handleChange = (event: any): void => {
setTask(event.target.value);
};
const handleDelete = (taskToDelete: any) => {
const deleted = todoList.filter((t) => t.taskName !== taskToDelete);
setTodoList(deleted);
localStorage.setItem('localTasks', JSON.stringify(deleted));
};
useEffect(() => {
if (localStorage.getItem('localTasks')) {
const storedList = JSON.parse(localStorage.getItem('localTasks') || '{}');
setTodoList(storedList);
}
}, []);
const addTask = () => {
const newTask = {
taskName: task,
};
setTodoList([...todoList, newTask]);
localStorage.setItem('localTasks', JSON.stringify([...todoList, newTask]));
setTask('');
};
return (
<Container>
<TextInput
type="text"
name="task"
placeholder="enter a task"
onChange={handleChange}
value={task}
/>
<Button onClick={addTask} data-testid="add">
Add Task
</Button>
{todoList.map((todo, key) => (
<Container key={key}>
<List
data-testid="todos"
icon={
<Button
onClick={() => {
handleDelete(todo.taskName);
}}
>
X
</Button>
}
>
<List.Item>{todo.taskName}</List.Item>
</List>
</Container>
))}
</Container>
);
};
export default TodoList;
更新代码以将日期id添加到待办事项:文章源自玩技e族-https://www.playezu.com/179068.html
import { Button, Container, List, TextInput } from '@mantine/core';
import type { ChangeEvent } from 'react';
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
const TodoList = () => {
const isMounted = useRef(false);
const [task, setTask] = useState('');
const [todoList, setTodoList] = useState<Array<{ taskName: string; id: number }>>([]);
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setTask(event.target.value);
};
const handleDelete = () => {
setTodoList((prevTodoList) => prevTodoList.filter((todo, index) => index !== todo.id));
};
const addTask = () => {
setTodoList((prevTodoList) =>
prevTodoList.concat({
taskName: task,
id: new Date().getTime(),
}),
);
setTask('');
};
useLayoutEffect(() => {
const localTasks = JSON.parse(localStorage.getItem('localTasks') || '[]');
if (localTasks.length > 0) setTodoList(localTasks);
}, []);
useEffect(() => {
if (isMounted.current) {
localStorage.setItem('localTasks', JSON.stringify(todoList));
} else {
isMounted.current = true;
}
}, [todoList]);
return (
<Container aria-label="container">
<TextInput
type="text"
name="task"
placeholder="enter a task"
onChange={handleChange}
value={task}
/>
<Button type="button" onClick={addTask} data-testid="add-todo" name="add-button">
Add Task
</Button>
{todoList.map((todo, key) => (
<Container key={key}>
<List
data-testid={`todo-${key}`}
icon={
<Button
data-testid={`delete-todo-${todo.id}`}
type="button"
aria-label="delete-button"
onClick={() => {
handleDelete(todo.id);
}}
>
X
</Button>
}
>
<List.Item>{todo.taskName}</List.Item>
</List>
</Container>
))}
</Container>
);
};
export default TodoList;
文章源自玩技e族-https://www.playezu.com/179068.html文章源自玩技e族-https://www.playezu.com/179068.html
未知地区 1F
在这种情况下,我建议不要嘲笑 本地存储 而是按原样测试。
托多利斯特。tsx公司
import { Button, Container, List, TextInput } from "@mantine/core";
import type { ChangeEvent, ReactElement } from "react";
import { useEffect, useLayoutEffect, useRef, useState } from "react";
const TodoList = (): ReactElement => {
const isMounted = useRef(false);
const [task, setTask] = useState("");
const [todoList, setTodoList] = useState<Array<{ taskName: string }>>([]);
const handleChange = (event: ChangeEvent<HTMLInputElement>): void => {
setTask(event.target.value);
};
// filter by index instead of by value (duplicate values can exist)
// ideally you would use uniquely generated ids instead of by index
const handleDelete = (key: number): void => {
setTodoList((prevTodoList) =>
prevTodoList.filter((_t, idx) => idx !== key)
);
};
// concatenate new task into the todo list
// Array.concat() creates a new array
const addTask = (): void => {
setTodoList((prevTodoList) =>
prevTodoList.concat({
taskName: task,
})
);
setTask("");
};
// on initial layout, update todo list if localTasks exist in 本地存储
useLayoutEffect((): void => {
const localTasks = JSON.parse(本地存储.getItem("localTasks") || "[]");
if (localTasks.length > 0) setTodoList(localTasks);
}, []);
// on initial render, bypass updating local storage
// on secondary/subsequent renders, update local storage with todoList
useEffect((): void => {
if (isMounted.current) {
本地存储.setItem("localTasks", JSON.stringify(todoList));
} else {
isMounted.current = true;
}
}, [todoList]);
return (
<Container data-testid="container">
<TextInput
data-testid="task-input"
type="text"
name="task"
placeholder="enter a task"
onChange={handleChange}
value={task}
/>
<Button type="button" onClick={addTask} data-testid="add-todo">
Add Task
</Button>
{todoList.map((todo, key) => (
<Container key={key}>
<List
data-testid={`todo-${key}`}
icon={
<Button
data-testid={`delete-todo-${key}`}
type="button"
onClick={() => {
handleDelete(key);
}}
>
X
</Button>
}
>
<List.Item>{todo.taskName}</List.Item>
</List>
</Container>
))}
</Container>
);
};
export default TodoList;
托多利斯特。测验tsx公司
import { fireEvent, render, screen } from "@testing-library/react";
import TodoList from "./TodoList";
describe("TodoList", () => {
it("renders without errors", () => {
render(<TodoList />);
expect(screen.getByTestId("container")).toBeInTheDocument();
});
it("adds a task to the list and stores it to 本地存储", () => {
render(<TodoList />);
fireEvent.change(screen.getByTestId("task-input"), { target: { value: "123" } });
fireEvent.click(screen.getByTestId("add-todo"));
expect(screen.getByTestId("todo-0")).toBeInTheDocument();
const localTasks = JSON.parse(本地存储.getItem("localTasks") || "[]");
expect(localTasks).toEqual([{ taskName: "123" }]);
});
it("removes a task from the list and removes it from 本地存储", () => {
render(<TodoList />);
fireEvent.click(screen.getByTestId("delete-todo-0"));
expect(screen.queryByTestId("todo-0")).not.toBeInTheDocument();
const localTasks = JSON.parse(本地存储.getItem("localTasks") || "[]");
expect(localTasks).toEqual([]);
});
});
后果
PASS src/托多利斯特。测验tsx公司
TodoList
✓ renders without errors (82 ms)
✓ adds a task to the list and stores it to 本地存储 (23 ms)
✓ removes a task from the list and removes it from 本地存储 (10 ms)
————–|———|———-|———|———|——————-
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
————–|———|———-|———|———|——————-
All files | 100 | 100 | 100 | 100 |
托多利斯特。tsx公司 | 100 | 100 | 100 | 100 |
————–|———|———-|———|———|——————-
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 1.073 s