feat: Add package type support and per-intake takenBy (#89)
## Package Type Feature - Add 'blister' and 'bottle' package types for medications - Bottle type uses totalPills for capacity and looseTablets for current stock - Blister type continues to use packCount/blistersPerPack/pillsPerBlister - Add doseUnit field for flexible dosing (mg, ml, IU, etc.) - Full UI support in medication form and detail modal ## Per-Intake TakenBy - Move takenBy from medication level to individual intakes - Each intake schedule can now be assigned to a different person - Update scheduler-utils to handle per-intake takenBy - Update SharedSchedule to filter by per-intake takenBy - Backward compatible with existing medication data ## UI Improvements - Add PasswordInput component with show/hide toggle - Centralize stockThresholds in AppContext for consistent status display - Fix SharedSchedule sync issues with per-intake takenBy - Improve mobile editing experience ## Technical - Add migrations 0004 and 0005 for schema changes - Update all relevant tests (1064 tests passing) - Maintain backward compatibility with ALTER migrations
This commit is contained in:
@@ -7,6 +7,8 @@ const defaultSettings: StockThresholds = {
|
||||
lowStockDays: 7,
|
||||
normalStockDays: 30,
|
||||
highStockDays: 90,
|
||||
criticalStockDays: 3,
|
||||
expiryWarningDays: 30,
|
||||
};
|
||||
|
||||
const mockMedication: Medication = {
|
||||
|
||||
@@ -7,10 +7,12 @@ const defaultForm: FormState = {
|
||||
name: "",
|
||||
genericName: "",
|
||||
takenBy: [],
|
||||
packageType: "blister",
|
||||
packCount: "1",
|
||||
blistersPerPack: "1",
|
||||
pillsPerBlister: "1",
|
||||
looseTablets: "0",
|
||||
totalPills: "",
|
||||
pillWeightMg: "",
|
||||
expiryDate: "",
|
||||
notes: "",
|
||||
@@ -23,6 +25,16 @@ const defaultForm: FormState = {
|
||||
startTime: "09:00",
|
||||
},
|
||||
],
|
||||
intakes: [
|
||||
{
|
||||
usage: "1",
|
||||
every: "1",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "09:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
@@ -44,6 +56,9 @@ const defaultProps = {
|
||||
onSetBlisterValue: vi.fn(),
|
||||
onAddBlister: vi.fn(),
|
||||
onRemoveBlister: vi.fn(),
|
||||
onSetIntakeValue: vi.fn(),
|
||||
onAddIntake: vi.fn(),
|
||||
onRemoveIntake: vi.fn(),
|
||||
onHandleValueChange: vi.fn(),
|
||||
refillPacks: 0,
|
||||
onRefillPacksChange: vi.fn(),
|
||||
@@ -185,14 +200,14 @@ describe("MobileEditModal", () => {
|
||||
expect(screen.getByText(/form\.blisters\.addIntake/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("calls onAddBlister when add intake clicked", () => {
|
||||
const onAddBlister = vi.fn();
|
||||
render(<MobileEditModal {...defaultProps} onAddBlister={onAddBlister} />);
|
||||
it("calls onAddIntake when add intake clicked", () => {
|
||||
const onAddIntake = vi.fn();
|
||||
render(<MobileEditModal {...defaultProps} onAddIntake={onAddIntake} />);
|
||||
|
||||
const addBtn = screen.getByText(/form\.blisters\.addIntake/i);
|
||||
fireEvent.click(addBtn);
|
||||
|
||||
expect(onAddBlister).toHaveBeenCalledTimes(1);
|
||||
expect(onAddIntake).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("renders modal content", () => {
|
||||
@@ -261,6 +276,24 @@ describe("MobileEditModal blister management", () => {
|
||||
{ usage: "1", every: "1", startDate: "2024-01-01", startTime: "09:00" },
|
||||
{ usage: "2", every: "7", startDate: "2024-01-01", startTime: "10:00" },
|
||||
],
|
||||
intakes: [
|
||||
{
|
||||
usage: "1",
|
||||
every: "1",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "09:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
{
|
||||
usage: "2",
|
||||
every: "7",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "10:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
render(<MobileEditModal {...defaultProps} form={form} />);
|
||||
@@ -269,34 +302,52 @@ describe("MobileEditModal blister management", () => {
|
||||
expect(blisterRows.length).toBe(2);
|
||||
});
|
||||
|
||||
it("calls onRemoveBlister when remove button clicked", () => {
|
||||
const onRemoveBlister = vi.fn();
|
||||
it("calls onRemoveIntake when remove button clicked", () => {
|
||||
const onRemoveIntake = vi.fn();
|
||||
const form = {
|
||||
...defaultForm,
|
||||
blisters: [
|
||||
{ usage: "1", every: "1", startDate: "2024-01-01", startTime: "09:00" },
|
||||
{ usage: "2", every: "7", startDate: "2024-01-01", startTime: "10:00" },
|
||||
],
|
||||
intakes: [
|
||||
{
|
||||
usage: "1",
|
||||
every: "1",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "09:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
{
|
||||
usage: "2",
|
||||
every: "7",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "10:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
render(<MobileEditModal {...defaultProps} form={form} onRemoveBlister={onRemoveBlister} />);
|
||||
render(<MobileEditModal {...defaultProps} form={form} onRemoveIntake={onRemoveIntake} />);
|
||||
|
||||
const removeButtons = document.querySelectorAll(".blister-row button.danger");
|
||||
if (removeButtons.length > 0) {
|
||||
fireEvent.click(removeButtons[0]);
|
||||
expect(onRemoveBlister).toHaveBeenCalled();
|
||||
expect(onRemoveIntake).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
|
||||
it("calls onSetBlisterValue when changing blister field", () => {
|
||||
const onSetBlisterValue = vi.fn();
|
||||
it("calls onSetIntakeValue when changing blister field", () => {
|
||||
const onSetIntakeValue = vi.fn();
|
||||
|
||||
render(<MobileEditModal {...defaultProps} onSetBlisterValue={onSetBlisterValue} />);
|
||||
render(<MobileEditModal {...defaultProps} onSetIntakeValue={onSetIntakeValue} />);
|
||||
|
||||
const usageInputs = document.querySelectorAll('.blister-row input[type="number"]');
|
||||
if (usageInputs.length > 0) {
|
||||
fireEvent.change(usageInputs[0], { target: { value: "2" } });
|
||||
expect(onSetBlisterValue).toHaveBeenCalled();
|
||||
expect(onSetIntakeValue).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { PasswordInput } from "../../components/PasswordInput";
|
||||
|
||||
describe("PasswordInput", () => {
|
||||
it("renders password input with hidden text by default", () => {
|
||||
render(<PasswordInput id="test-password" value="secret123" onChange={() => {}} />);
|
||||
|
||||
const input = document.getElementById("test-password") as HTMLInputElement;
|
||||
expect(input).toBeInTheDocument();
|
||||
expect(input.type).toBe("password");
|
||||
});
|
||||
|
||||
it("toggles password visibility when eye button is clicked", () => {
|
||||
render(<PasswordInput id="test-password" value="secret123" onChange={() => {}} />);
|
||||
|
||||
const input = document.getElementById("test-password") as HTMLInputElement;
|
||||
const toggleButton = screen.getByRole("button", { name: /show password/i });
|
||||
|
||||
// Initially password is hidden
|
||||
expect(input.type).toBe("password");
|
||||
|
||||
// Click to show password
|
||||
fireEvent.click(toggleButton);
|
||||
expect(input.type).toBe("text");
|
||||
|
||||
// Click again to hide password
|
||||
fireEvent.click(toggleButton);
|
||||
expect(input.type).toBe("password");
|
||||
});
|
||||
|
||||
it("calls onChange when input value changes", () => {
|
||||
const handleChange = vi.fn();
|
||||
render(<PasswordInput id="test-password" value="" onChange={handleChange} />);
|
||||
|
||||
const input = document.getElementById("test-password") as HTMLInputElement;
|
||||
fireEvent.change(input, { target: { value: "newpassword" } });
|
||||
|
||||
expect(handleChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("passes through required attribute", () => {
|
||||
render(<PasswordInput id="test-password" value="" onChange={() => {}} required />);
|
||||
|
||||
const input = document.getElementById("test-password") as HTMLInputElement;
|
||||
expect(input.required).toBe(true);
|
||||
});
|
||||
|
||||
it("passes through minLength and maxLength attributes", () => {
|
||||
render(<PasswordInput id="test-password" value="" onChange={() => {}} minLength={8} maxLength={128} />);
|
||||
|
||||
const input = document.getElementById("test-password") as HTMLInputElement;
|
||||
expect(input.minLength).toBe(8);
|
||||
expect(input.maxLength).toBe(128);
|
||||
});
|
||||
|
||||
it("passes through placeholder attribute", () => {
|
||||
render(<PasswordInput id="test-password" value="" onChange={() => {}} placeholder="Enter password" />);
|
||||
|
||||
const input = document.getElementById("test-password") as HTMLInputElement;
|
||||
expect(input.placeholder).toBe("Enter password");
|
||||
});
|
||||
|
||||
it("passes through autoComplete attribute", () => {
|
||||
render(<PasswordInput id="test-password" value="" onChange={() => {}} autoComplete="new-password" />);
|
||||
|
||||
const input = document.getElementById("test-password") as HTMLInputElement;
|
||||
expect(input.autocomplete).toBe("new-password");
|
||||
});
|
||||
|
||||
it("toggle button has correct aria-label", () => {
|
||||
render(<PasswordInput id="test-password" value="" onChange={() => {}} />);
|
||||
|
||||
const toggleButton = screen.getByRole("button", { name: /show password/i });
|
||||
expect(toggleButton).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(toggleButton);
|
||||
|
||||
const hideButton = screen.getByRole("button", { name: /hide password/i });
|
||||
expect(hideButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("toggle button has tabIndex -1 to prevent focus during form navigation", () => {
|
||||
render(<PasswordInput id="test-password" value="" onChange={() => {}} />);
|
||||
|
||||
const toggleButton = screen.getByRole("button");
|
||||
expect(toggleButton.tabIndex).toBe(-1);
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,8 @@ const defaultSettings: StockThresholds = {
|
||||
lowStockDays: 7,
|
||||
normalStockDays: 30,
|
||||
highStockDays: 90,
|
||||
criticalStockDays: 3,
|
||||
expiryWarningDays: 30,
|
||||
};
|
||||
|
||||
const mockMedication: Medication = {
|
||||
|
||||
@@ -139,6 +139,13 @@ const createMockAppContext = (overrides = {}) => ({
|
||||
coverage: { all: [], low: [] },
|
||||
coverageByMed: {},
|
||||
depletionByMed: {},
|
||||
stockThresholds: {
|
||||
lowStockDays: 7,
|
||||
normalStockDays: 30,
|
||||
highStockDays: 90,
|
||||
criticalStockDays: 7,
|
||||
expiryWarningDays: 30,
|
||||
},
|
||||
manuallyExpandedDays: new Set(),
|
||||
manuallyCollapsedDays: new Set(),
|
||||
toggleDayCollapse: vi.fn(),
|
||||
@@ -400,8 +407,8 @@ describe("DashboardPage structure", () => {
|
||||
|
||||
// Should have all expected table columns
|
||||
expect(screen.getByText(/table\.name/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/table\.fullBlisters/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/table\.openBlister/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/table\.stock(?!Details)/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/table\.stockDetails/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/table\.daysLeft/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/table\.runsOut/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/table\.expiry/i)).toBeInTheDocument();
|
||||
|
||||
@@ -57,6 +57,7 @@ const createMockContext = (overrides = {}) => ({
|
||||
setRefillLoose: vi.fn(),
|
||||
refillSaving: false,
|
||||
submitRefill: vi.fn(),
|
||||
coverageByMed: {},
|
||||
...overrides,
|
||||
});
|
||||
|
||||
@@ -65,12 +66,24 @@ const createMockFormHook = (overrides = {}) => ({
|
||||
form: {
|
||||
name: "",
|
||||
genericName: "",
|
||||
packageType: "blister" as const,
|
||||
packCount: "0",
|
||||
blistersPerPack: "0",
|
||||
pillsPerBlister: "1",
|
||||
looseTablets: "0",
|
||||
totalPills: "",
|
||||
takenBy: [],
|
||||
blisters: [{ usage: "1", every: "1", startDate: new Date().toISOString().slice(0, 10), startTime: "09:00" }],
|
||||
intakes: [
|
||||
{
|
||||
usage: "1",
|
||||
every: "1",
|
||||
startDate: new Date().toISOString().slice(0, 10),
|
||||
startTime: "09:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
],
|
||||
expiryDate: "",
|
||||
notes: "",
|
||||
pillWeightMg: "",
|
||||
@@ -93,6 +106,9 @@ const createMockFormHook = (overrides = {}) => ({
|
||||
addBlister: vi.fn(),
|
||||
removeBlister: vi.fn(),
|
||||
setBlisterValue: vi.fn(),
|
||||
addIntake: vi.fn(),
|
||||
removeIntake: vi.fn(),
|
||||
setIntakeValue: vi.fn(),
|
||||
resetForm: vi.fn(),
|
||||
startEdit: vi.fn(),
|
||||
showEditModal: false,
|
||||
@@ -328,9 +344,9 @@ describe("MedicationsPage form interactions", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("calls addBlister when clicking add schedule button", () => {
|
||||
const addBlister = vi.fn();
|
||||
mockFormHookValue = createMockFormHook({ addBlister });
|
||||
it("calls addIntake when clicking add schedule button", () => {
|
||||
const addIntake = vi.fn();
|
||||
mockFormHookValue = createMockFormHook({ addIntake });
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
@@ -338,11 +354,11 @@ describe("MedicationsPage form interactions", () => {
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
// Find add blister button
|
||||
// Find add intake button
|
||||
const addBtn = screen.queryByText(/form\.blisters\.add/i) || screen.queryByText(/\+/);
|
||||
if (addBtn) {
|
||||
fireEvent.click(addBtn);
|
||||
expect(addBlister).toHaveBeenCalled();
|
||||
expect(addIntake).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -393,12 +409,24 @@ describe("MedicationsPage editing", () => {
|
||||
form: {
|
||||
name: "Aspirin",
|
||||
genericName: "Acetylsalicylic acid",
|
||||
packageType: "blister" as const,
|
||||
packCount: "1",
|
||||
blistersPerPack: "2",
|
||||
pillsPerBlister: "10",
|
||||
looseTablets: "5",
|
||||
totalPills: "",
|
||||
takenBy: ["John"],
|
||||
blisters: [{ usage: "1", every: "1", startDate: "2024-01-01", startTime: "09:00" }],
|
||||
intakes: [
|
||||
{
|
||||
usage: "1",
|
||||
every: "1",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "09:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
],
|
||||
expiryDate: "2025-12-31",
|
||||
notes: "Take with food",
|
||||
pillWeightMg: "",
|
||||
@@ -558,14 +586,24 @@ describe("MedicationsPage blister management", () => {
|
||||
expect(blisterSections.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("calls setBlisterValue when changing blister field", () => {
|
||||
const setBlisterValue = vi.fn();
|
||||
it("calls setIntakeValue when changing blister field", () => {
|
||||
const setIntakeValue = vi.fn();
|
||||
mockFormHookValue = createMockFormHook({
|
||||
form: {
|
||||
...createMockFormHook().form,
|
||||
blisters: [{ usage: "1", every: "1", startDate: "2024-01-01", startTime: "09:00" }],
|
||||
intakes: [
|
||||
{
|
||||
usage: "1",
|
||||
every: "1",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "09:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
setBlisterValue,
|
||||
setIntakeValue,
|
||||
});
|
||||
|
||||
render(
|
||||
@@ -578,7 +616,7 @@ describe("MedicationsPage blister management", () => {
|
||||
const blisterInputs = document.querySelectorAll('.blister-inputs input[type="number"]');
|
||||
if (blisterInputs.length > 0) {
|
||||
fireEvent.change(blisterInputs[0], { target: { value: "2" } });
|
||||
expect(setBlisterValue).toHaveBeenCalled();
|
||||
expect(setIntakeValue).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -591,9 +629,9 @@ describe("MedicationsPage add blister", () => {
|
||||
mockFormHookValue = createMockFormHook();
|
||||
});
|
||||
|
||||
it("calls addBlister when clicking add intake button", () => {
|
||||
const addBlister = vi.fn();
|
||||
mockFormHookValue = createMockFormHook({ addBlister });
|
||||
it("calls addIntake when clicking add intake button", () => {
|
||||
const addIntake = vi.fn();
|
||||
mockFormHookValue = createMockFormHook({ addIntake });
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
@@ -603,7 +641,7 @@ describe("MedicationsPage add blister", () => {
|
||||
|
||||
const addIntakeBtn = screen.getByRole("button", { name: /form\.blisters\.addIntake/i });
|
||||
fireEvent.click(addIntakeBtn);
|
||||
expect(addBlister).toHaveBeenCalled();
|
||||
expect(addIntake).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -619,6 +657,24 @@ describe("MedicationsPage remove blister", () => {
|
||||
{ usage: "1", every: "1", startDate: "2024-01-01", startTime: "09:00" },
|
||||
{ usage: "2", every: "7", startDate: "2024-01-01", startTime: "20:00" },
|
||||
],
|
||||
intakes: [
|
||||
{
|
||||
usage: "1",
|
||||
every: "1",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "09:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
{
|
||||
usage: "2",
|
||||
every: "7",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "20:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -635,8 +691,8 @@ describe("MedicationsPage remove blister", () => {
|
||||
expect(removeButtons.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("calls removeBlister when clicking remove button", () => {
|
||||
const removeBlister = vi.fn();
|
||||
it("calls removeIntake when clicking remove button", () => {
|
||||
const removeIntake = vi.fn();
|
||||
mockFormHookValue = createMockFormHook({
|
||||
form: {
|
||||
...createMockFormHook().form,
|
||||
@@ -644,8 +700,26 @@ describe("MedicationsPage remove blister", () => {
|
||||
{ usage: "1", every: "1", startDate: "2024-01-01", startTime: "09:00" },
|
||||
{ usage: "2", every: "7", startDate: "2024-01-01", startTime: "20:00" },
|
||||
],
|
||||
intakes: [
|
||||
{
|
||||
usage: "1",
|
||||
every: "1",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "09:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
{
|
||||
usage: "2",
|
||||
every: "7",
|
||||
startDate: "2024-01-01",
|
||||
startTime: "20:00",
|
||||
takenBy: "",
|
||||
intakeRemindersEnabled: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
removeBlister,
|
||||
removeIntake,
|
||||
});
|
||||
|
||||
render(
|
||||
@@ -657,7 +731,7 @@ describe("MedicationsPage remove blister", () => {
|
||||
const removeButtons = document.querySelectorAll(".blister-row .danger");
|
||||
if (removeButtons.length > 0) {
|
||||
fireEvent.click(removeButtons[0]);
|
||||
expect(removeBlister).toHaveBeenCalled();
|
||||
expect(removeIntake).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -670,19 +744,25 @@ describe("MedicationsPage intake reminders toggle", () => {
|
||||
mockFormHookValue = createMockFormHook();
|
||||
});
|
||||
|
||||
it("renders intake reminders checkbox", () => {
|
||||
it("renders intake reminders checkbox per intake", () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<MedicationsPage />
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(screen.getByText(/form\.blisters\.remind/i)).toBeInTheDocument();
|
||||
// Now each intake row has its own reminder checkbox with the bell icon
|
||||
// Desktop form uses class "full blisters" container
|
||||
const blistersContainer = document.querySelector(".blisters");
|
||||
expect(blistersContainer).toBeInTheDocument();
|
||||
// Check for the inline-checkbox that controls intake reminders in each blister row
|
||||
const intakeCheckbox = document.querySelector(".blister-row .inline-checkbox");
|
||||
expect(intakeCheckbox).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("can toggle intake reminders", () => {
|
||||
const setForm = vi.fn();
|
||||
mockFormHookValue = createMockFormHook({ setForm });
|
||||
it("can toggle intake reminders per intake", () => {
|
||||
const setIntakeValue = vi.fn();
|
||||
mockFormHookValue = createMockFormHook({ setIntakeValue });
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
@@ -690,10 +770,11 @@ describe("MedicationsPage intake reminders toggle", () => {
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
const checkbox = document.querySelector('.inline-checkbox input[type="checkbox"]');
|
||||
// Each blister row has inline-checkbox for intake reminders
|
||||
const checkbox = document.querySelector('.blister-row .inline-checkbox input[type="checkbox"]');
|
||||
if (checkbox) {
|
||||
fireEvent.click(checkbox);
|
||||
expect(setForm).toHaveBeenCalled();
|
||||
expect(setIntakeValue).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user