Use shared modals and combine selected-day actions
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { ReminderSettings } from "./components/ReminderSettings";
|
||||
import { Modal } from "./components/design-system/Modal";
|
||||
import {
|
||||
afterAll,
|
||||
afterEach,
|
||||
@@ -10,7 +11,7 @@ import {
|
||||
test,
|
||||
} from "bun:test";
|
||||
import { Window } from "happy-dom";
|
||||
import { act } from "react";
|
||||
import { act, StrictMode, useState } from "react";
|
||||
import { MemoryRouter, useLocation, useNavigate } from "react-router";
|
||||
import type { Root } from "react-dom/client";
|
||||
import { App } from "./App";
|
||||
@@ -117,6 +118,54 @@ const buttonNamed = (name: string) => [...container.querySelectorAll<HTMLButtonE
|
||||
.find(button => button.textContent === name || button.getAttribute("aria-label") === name)!;
|
||||
|
||||
describe("homepage", () => {
|
||||
test("development Strict Mode does not restore background focus while a modal is open", async () => {
|
||||
await act(async () => root.render(<StrictMode><Modal id="strict-modal" title="Editor" onClose={() => {}} initialFocus="input"><input aria-label="Draft" /></Modal></StrictMode>));
|
||||
await new Promise(resolve => dom.requestAnimationFrame(() => dom.requestAnimationFrame(resolve)));
|
||||
expect(document.activeElement).toBe(container.querySelector("input"));
|
||||
expect(container.querySelector<HTMLDialogElement>("dialog")?.open).toBe(true);
|
||||
expect(document.documentElement.style.overflow).toBe("hidden");
|
||||
});
|
||||
test("settings open as a modal and Escape restores the opener and scrolling", async () => {
|
||||
connectAccount();
|
||||
await render("/");
|
||||
const opener = buttonNamed("Settings");
|
||||
opener.focus();
|
||||
await act(async () => opener.click());
|
||||
const dialog = container.querySelector<HTMLDialogElement>("dialog#account-settings")!;
|
||||
expect(dialog.open).toBe(true);
|
||||
expect(dialog.contains(document.activeElement)).toBe(true);
|
||||
expect(document.documentElement.style.overflow).toBe("hidden");
|
||||
await act(async () => dialog.dispatchEvent(new dom.Event("cancel", { cancelable: true }) as unknown as Event));
|
||||
await new Promise(resolve => dom.requestAnimationFrame(resolve));
|
||||
expect(container.querySelector("dialog")).toBeNull();
|
||||
expect(document.activeElement).toBe(opener);
|
||||
expect(document.documentElement.style.overflow).toBe("");
|
||||
});
|
||||
|
||||
test("modal dismissal waits for saves and nested dialogs retain the scroll lock", async () => {
|
||||
function Harness() {
|
||||
const [nested, setNested] = useState(true);
|
||||
const [busy, setBusy] = useState(true);
|
||||
return <Modal id="outer" title="Outer" onClose={() => {}}>
|
||||
{nested && <Modal id="inner" title="Inner" busy={busy} onClose={() => setNested(false)}>
|
||||
<button onClick={() => setBusy(false)}>Finish save</button>
|
||||
</Modal>}
|
||||
</Modal>;
|
||||
}
|
||||
await act(async () => root.render(<Harness />));
|
||||
const inner = container.querySelector<HTMLDialogElement>("#inner")!;
|
||||
await act(async () => inner.dispatchEvent(new dom.Event("cancel", { cancelable: true }) as unknown as Event));
|
||||
expect(inner.open).toBe(true);
|
||||
expect(inner.querySelector<HTMLButtonElement>('[aria-label="Close dialog"]')?.disabled).toBe(true);
|
||||
await act(async () => buttonNamed("Finish save").click());
|
||||
await act(async () => inner.dispatchEvent(new dom.Event("cancel", { cancelable: true }) as unknown as Event));
|
||||
expect(container.querySelector("#inner")).toBeNull();
|
||||
expect(container.querySelector<HTMLDialogElement>("#outer")?.open).toBe(true);
|
||||
expect(document.documentElement.style.overflow).toBe("hidden");
|
||||
await act(async () => root.render(null));
|
||||
expect(document.documentElement.style.overflow).toBe("");
|
||||
});
|
||||
|
||||
test("archived habits expose history and restore to the dashboard", async () => {
|
||||
const f = connectAccount();
|
||||
f.setTime("2026-09-03T12:00:00Z");
|
||||
@@ -143,6 +192,7 @@ describe("homepage", () => {
|
||||
await f.json(`/habits/${habit.id}`, "PATCH", { method: "count", target: 10, unit: "pages" });
|
||||
await render("/");
|
||||
await act(async () => container.querySelector<HTMLButtonElement>('[aria-label^="2026-09-03:"]')!.click());
|
||||
expect(buttonNamed("Edit selected check-in").closest(".ds-date-inspector")?.textContent).toContain("September 3, 2026");
|
||||
await act(async () => buttonNamed("Edit selected check-in").click());
|
||||
const past = [...container.querySelectorAll<HTMLInputElement>('input[type="checkbox"]')].find(input => input.closest("label")?.textContent === "Completed on this date")!;
|
||||
expect(past).toBeDefined();
|
||||
|
||||
Reference in New Issue
Block a user