feat(FN-2660): refine TodoView empty state and edit flow
- Reset list/item draft state when switching lists or entering a conflicting edit mode - Hide the empty-state prompt while creating a new list and improve list accessibility semantics with role and aria-current attributes - Add Escape handling to clear pending new-item text and improve mobile checkbox/scrollbar styling in TodoView CSS - Expand TodoView tests to cover trimming behavior, draft clearing, empty-state transitions, and selected-list accessibility
This commit is contained in:
@@ -192,6 +192,20 @@ describe("TodoView", () => {
|
||||
expect(state.createItem).toHaveBeenCalledWith("Pack bags");
|
||||
});
|
||||
|
||||
it("pressing Escape in add-item input clears the pending draft", () => {
|
||||
const state = createMockTodoLists();
|
||||
mockUseTodoLists.mockReturnValue(state);
|
||||
|
||||
render(<TodoView addToast={addToast} />);
|
||||
|
||||
const input = screen.getByTestId("new-item-input") as HTMLInputElement;
|
||||
fireEvent.change(input, { target: { value: "Pack bags" } });
|
||||
fireEvent.keyDown(input, { key: "Escape" });
|
||||
|
||||
expect(state.createItem).not.toHaveBeenCalled();
|
||||
expect(input.value).toBe("");
|
||||
});
|
||||
|
||||
it("clicking checkbox calls toggleItem with item ID", () => {
|
||||
const state = createMockTodoLists();
|
||||
mockUseTodoLists.mockReturnValue(state);
|
||||
@@ -258,13 +272,102 @@ describe("TodoView", () => {
|
||||
expect(state.deleteItem).toHaveBeenCalledWith("item-1");
|
||||
});
|
||||
|
||||
it("shows new list input when empty state create button is clicked", () => {
|
||||
it("trims surrounding whitespace before creating a list", () => {
|
||||
const state = createMockTodoLists();
|
||||
mockUseTodoLists.mockReturnValue(state);
|
||||
|
||||
render(<TodoView addToast={addToast} />);
|
||||
fireEvent.click(screen.getByTestId("add-list-button"));
|
||||
|
||||
const input = screen.getByTestId("new-list-input");
|
||||
fireEvent.change(input, { target: { value: " Weekend " } });
|
||||
fireEvent.keyDown(input, { key: "Enter" });
|
||||
|
||||
expect(state.createList).toHaveBeenCalledWith("Weekend");
|
||||
});
|
||||
|
||||
it("trims surrounding whitespace before creating an item", () => {
|
||||
const state = createMockTodoLists();
|
||||
mockUseTodoLists.mockReturnValue(state);
|
||||
|
||||
render(<TodoView addToast={addToast} />);
|
||||
const input = screen.getByTestId("new-item-input");
|
||||
fireEvent.change(input, { target: { value: " Pack bags " } });
|
||||
fireEvent.keyDown(input, { key: "Enter" });
|
||||
|
||||
expect(state.createItem).toHaveBeenCalledWith("Pack bags");
|
||||
});
|
||||
|
||||
it("trims surrounding whitespace before renaming a list", () => {
|
||||
const state = createMockTodoLists();
|
||||
mockUseTodoLists.mockReturnValue(state);
|
||||
|
||||
render(<TodoView addToast={addToast} />);
|
||||
fireEvent.click(screen.getByTestId("rename-list-button-list-1"));
|
||||
|
||||
const input = screen.getByTestId("rename-list-input-list-1");
|
||||
fireEvent.change(input, { target: { value: " Renamed List " } });
|
||||
fireEvent.keyDown(input, { key: "Enter" });
|
||||
|
||||
expect(state.renameList).toHaveBeenCalledWith("list-1", "Renamed List");
|
||||
});
|
||||
|
||||
it("trims surrounding whitespace before saving an item edit", () => {
|
||||
const state = createMockTodoLists();
|
||||
mockUseTodoLists.mockReturnValue(state);
|
||||
|
||||
render(<TodoView addToast={addToast} />);
|
||||
|
||||
fireEvent.click(screen.getByText("Buy groceries"));
|
||||
const input = screen.getByTestId("edit-item-input-item-1");
|
||||
fireEvent.change(input, { target: { value: " Buy vegetables " } });
|
||||
fireEvent.keyDown(input, { key: "Enter" });
|
||||
|
||||
expect(state.updateItem).toHaveBeenCalledWith("item-1", { text: "Buy vegetables" });
|
||||
});
|
||||
|
||||
it("clicking another list cancels an in-progress list rename", () => {
|
||||
mockUseTodoLists.mockReturnValue(createMockTodoLists());
|
||||
|
||||
render(<TodoView addToast={addToast} />);
|
||||
fireEvent.click(screen.getByTestId("rename-list-button-list-1"));
|
||||
expect(screen.getByTestId("rename-list-input-list-1")).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByTestId("todo-list-list-2"));
|
||||
|
||||
expect(screen.queryByTestId("rename-list-input-list-1")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("clears inline item edit when selected list changes", () => {
|
||||
const initialState = createMockTodoLists({ selectedListId: "list-1" });
|
||||
mockUseTodoLists.mockReturnValue(initialState);
|
||||
|
||||
const { rerender } = render(<TodoView addToast={addToast} />);
|
||||
fireEvent.click(screen.getByText("Buy groceries"));
|
||||
expect(screen.getByTestId("edit-item-input-item-1")).toBeInTheDocument();
|
||||
|
||||
mockUseTodoLists.mockReturnValue(createMockTodoLists({ selectedListId: "list-2" }));
|
||||
rerender(<TodoView addToast={addToast} />);
|
||||
|
||||
expect(screen.queryByTestId("edit-item-input-item-1")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows new list input and hides empty-state prompt when create list is clicked", () => {
|
||||
mockUseTodoLists.mockReturnValue(createMockTodoLists({ lists: [], items: [], selectedListId: null }));
|
||||
|
||||
render(<TodoView addToast={addToast} />);
|
||||
fireEvent.click(screen.getByRole("button", { name: "Create List" }));
|
||||
|
||||
expect(screen.getByTestId("new-list-input")).toBeInTheDocument();
|
||||
expect(screen.queryByText("No todo lists yet. Create one to get started.")).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Create List" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("marks the selected list with aria-current", () => {
|
||||
render(<TodoView addToast={addToast} />);
|
||||
|
||||
expect(screen.getByTestId("todo-list-list-1")).toHaveAttribute("aria-current", "true");
|
||||
expect(screen.getByTestId("todo-list-list-2")).not.toHaveAttribute("aria-current", "true");
|
||||
});
|
||||
|
||||
it("applies active class to selected list", () => {
|
||||
|
||||
Reference in New Issue
Block a user