remark-gfm passes checked as undefined for unchecked task items, so the
Base UI Checkbox mounted uncontrolled and permanently ignored the
checked=true arriving after "Check all tasks" rewrote the memo content.
Coerce the prop to a boolean so the checkbox is always controlled.
Also drop the `${updateTime}` suffixes from memo React keys and the
comment editor cache key: a protobuf-es Timestamp stringifies to
"[object Object]", so the suffix was a constant — the keys were
effectively name-only already, and now say so honestly.
Fixes usememos/memos#6143
59 lines
2.3 KiB
TypeScript
59 lines
2.3 KiB
TypeScript
import { render, screen } from "@testing-library/react";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import { TaskListItem } from "@/components/MemoContent/TaskListItem";
|
|
|
|
// Regression test for usememos/memos#6143 ("Check all tasks not working").
|
|
//
|
|
// remark-gfm passes `checked: undefined` for unchecked task items (`- [ ]`).
|
|
// Base UI's Checkbox locks controlled/uncontrolled mode at mount, so a checkbox
|
|
// that mounts with `checked === undefined` becomes uncontrolled and silently
|
|
// ignores `checked=true` arriving later — exactly what happens after
|
|
// "Check all tasks" rewrites the memo content and the markdown re-renders.
|
|
// TaskListItem must coerce `checked` to a boolean so the checkbox is always
|
|
// controlled.
|
|
|
|
const mockUpdateMemo = vi.hoisted(() => vi.fn());
|
|
|
|
vi.mock("@/hooks/useMemoQueries", () => ({
|
|
useUpdateMemo: () => ({ mutate: mockUpdateMemo }),
|
|
}));
|
|
|
|
vi.mock("@/components/MemoView/MemoViewContext", () => ({
|
|
useMemoViewContext: () => ({
|
|
memo: {
|
|
name: "memos/1",
|
|
content: "- [ ] task one",
|
|
relations: [],
|
|
attachments: [],
|
|
reactions: [],
|
|
},
|
|
}),
|
|
useMemoViewDerived: () => ({
|
|
readonly: false,
|
|
}),
|
|
}));
|
|
|
|
describe("<TaskListItem /> check-all regression (#6143)", () => {
|
|
it("reflects checked=true arriving after mounting unchecked (Check all tasks)", () => {
|
|
// remark-gfm renders `- [ ]` with `checked` undefined.
|
|
const { rerender } = render(<TaskListItem checked={undefined} node={undefined} />);
|
|
|
|
const checkbox = screen.getByRole("checkbox");
|
|
expect(checkbox).toHaveAttribute("aria-checked", "false");
|
|
|
|
// "Check all tasks" updates memo content; the markdown re-renders with checked=true.
|
|
rerender(<TaskListItem checked={true} node={undefined} />);
|
|
expect(checkbox).toHaveAttribute("aria-checked", "true");
|
|
});
|
|
|
|
it("reflects checked reverting to undefined (Uncheck all tasks)", () => {
|
|
const { rerender } = render(<TaskListItem checked={true} node={undefined} />);
|
|
|
|
const checkbox = screen.getByRole("checkbox");
|
|
expect(checkbox).toHaveAttribute("aria-checked", "true");
|
|
|
|
// remark-gfm passes undefined (not false) for `- [ ]` items.
|
|
rerender(<TaskListItem checked={undefined} node={undefined} />);
|
|
expect(checkbox).toHaveAttribute("aria-checked", "false");
|
|
});
|
|
});
|