This project showcases CRUD operations mocking using MSW (Mock Service Worker) to simulate API responses. It facilitates seamless testing and development by providing mocked data interactions, handling user inputs, and simulating dynamic API behavior for a comprehensive testing environment.
Our objective in this example is to create a basic Task Management application using CRUD capabilities. While implementing these improvements:
We'll have learnt. The websites below provide information on using this program.
The application actually consists of 2 basic elements. TaskApp and its corresponding TaskHandler
In the TaskApp application, we first define the State definitions. The state that holds all the tasks, a state where you will enter a new task and finally the update time.
const [tasks, setTasks] = React.useState(null);
const [currentTitle, setCurrentTitle] = React.useState("");
const [lastUpdatedAt, setLastUpdatedAt] = React.useState(null);
Fetching all Task
const fetchTasks = () => {
fetch(`${restApiUri}/tasks`)
.then((res) => res.json())
.then(setTasks)
.then(() => setLastUpdatedAt(Date.now()));
};
We ensure that this is fetched 1 time when loading the first page
React.useEffect(() => {
fetchTasks();
}, []);
Create a new Task function
const handleCreateTask = (event) => {
event.preventDefault();
fetch(`${restApiUri}/tasks`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: currentTitle,
}),
}).then(() => {
setCurrentTitle("");
fetchTasks();
});
};
Update Existing Task
const updateTask = (id, nextTask) => {
fetch(`${restApiUri}/tasks/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(nextTask),
}).then(fetchTasks);
};
Delete Existing Task
const deleteTask = (id) => {
fetch(`${restApiUri}/tasks/${id}`, { method: "DELETE" }).then(fetchTasks);
};
Input Field where you can enter a new Task
<header className={`relative ${hasTasks ? "shadow-sm" : ""}`}>
<form onSubmit={handleCreateTask}>
<Input
name="title"
value={currentTitle}
onChange={({ target }) => setCurrentTitle(target.value)}
autoComplete="off"
placeholder="Enter Task Name"
/>
</form>
</header>
Task List
<ul>
{tasks.map((task) => (
<li
key={task.id}
style={{
display: "flex",
justifyContent: "space-between",
padding: "0.5rem 1rem",
}}
>
<span>
<Checkbox
checked={task.isDone}
onChange={({ target }) => {
updateTask(task.id, {
title: task.title,
isDone: target.checked,
});
}}
/>
<span
style={{ cursor: "pointer", marginLeft: "1rem" }}
contentEditable={!task.isDone}
suppressContentEditableWarning={true}
onKeyPress={(event) => {
if (event.key === "Enter") {
event.preventDefault();
event.currentTarget.blur();
}
}}
onBlur={({ target }) => {
updateTask(task.id, {
title: target.textContent,
});
}}
>
{task.isDone ? <s>{task.title}</s> : task.title}
</span>
</span>
<Trash onClick={() => deleteTask(task.id)} />
</li>
))}
</ul>
Footer Area (Refetch Button and LastUpdate Info)
<footer>
<Button onClick={fetchTasks}>
<ArrowsClockwise />
Refetch
</Button>
<Typography.Paragraph>
Last synced{" "}
{new Date(lastUpdatedAt).toLocaleTimeString("en-US", {
seconds: "2-digit",
minutes: "2-digit",
hours: "2-digit",
day: "2-digit",
month: "long",
year: "numeric",
})}
</Typography.Paragraph>
</footer>