Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions web/src/components/storage/ConfigureDeviceMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,11 @@ export default function ConfigureDeviceMenu(): React.ReactNode {
usedCount={usedDevicesCount}
/>
}
disksIntro={_("Choose a disk to define partitions or to mount")}
mdRaidsIntro={_("Choose a RAID device to define partitions or to mount")}
volumeGroupsIntro={_("Choose a volume group to define logical volumes")}
tabIntros={{
disks: _("Choose a disk to define partitions or to mount"),
mdRaids: _("Choose a RAID device to define partitions or to mount"),
volumeGroups: _("Choose a volume group to define logical volumes"),
}}
onCancel={closeDeviceSelector}
onConfirm={([device]) => {
addDevice(device);
Expand Down
178 changes: 172 additions & 6 deletions web/src/components/storage/DeviceSelectorModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ describe("DeviceSelectorModal", () => {
<DeviceSelectorModal
disks={[sda, sdb]}
selected={sda}
disksSideEffects={<p>Disk selection note</p>}
sideEffects={{ disks: <p>Disk selection note</p> }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
Expand All @@ -224,7 +224,7 @@ describe("DeviceSelectorModal", () => {
<DeviceSelectorModal
mdRaids={[md0]}
selected={sda}
mdRaidsSideEffects={<p>RAID selection note</p>}
sideEffects={{ mdRaids: <p>RAID selection note</p> }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
Expand All @@ -241,7 +241,7 @@ describe("DeviceSelectorModal", () => {
<DeviceSelectorModal
volumeGroups={[vg0]}
selected={sda}
volumeGroupsSideEffects={<p>LVM selection note</p>}
sideEffects={{ volumeGroups: <p>LVM selection note</p> }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
Expand All @@ -258,7 +258,7 @@ describe("DeviceSelectorModal", () => {
<DeviceSelectorModal
disks={[sda]}
selected={sda}
disksSideEffects={<p>Disk selection note</p>}
sideEffects={{ disks: <p>Disk selection note</p> }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
Expand Down Expand Up @@ -295,7 +295,7 @@ describe("DeviceSelectorModal", () => {
it("shows the create link in the empty LVM state when newVolumeGroupLinkText is given", async () => {
const { user } = installerRender(
<DeviceSelectorModal
newVolumeGroupLinkText="Define a new LVM"
newDeviceLinkTexts={{ volumeGroups: "Define a new LVM" }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
Expand Down Expand Up @@ -327,7 +327,7 @@ describe("DeviceSelectorModal", () => {
const { user } = installerRender(
<DeviceSelectorModal
volumeGroups={[vg0]}
newVolumeGroupLinkText="Define a new LVM"
newDeviceLinkTexts={{ volumeGroups: "Define a new LVM" }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
Expand Down Expand Up @@ -396,6 +396,172 @@ describe("DeviceSelectorModal", () => {
});
});

describe("tabIntros", () => {
it("shows intro text in the Disks tab when devices are present", () => {
installerRender(
<DeviceSelectorModal
disks={[sda]}
tabIntros={{ disks: <p>Disk intro text</p> }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
screen.getByText("Disk intro text");
});

it("shows intro text in the RAID tab when devices are present", async () => {
const { user } = installerRender(
<DeviceSelectorModal
mdRaids={[md0]}
tabIntros={{ mdRaids: <p>RAID intro text</p> }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
await user.click(screen.getByRole("tab", { name: "RAID" }));
screen.getByText("RAID intro text");
});

it("shows intro text in the LVM tab when devices are present", async () => {
const { user } = installerRender(
<DeviceSelectorModal
volumeGroups={[vg0]}
tabIntros={{ volumeGroups: <p>LVM intro text</p> }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
await user.click(screen.getByRole("tab", { name: "LVM" }));
screen.getByText("LVM intro text");
});

it("does not show intro text when tab is empty", async () => {
const { user } = installerRender(
<DeviceSelectorModal
tabIntros={{ mdRaids: <p>RAID intro text</p> }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
await user.click(screen.getByRole("tab", { name: "RAID" }));
expect(screen.queryByText("RAID intro text")).toBeNull();
});
});

describe("custom empty states", () => {
it("shows custom empty state title for Disks tab", () => {
installerRender(
<DeviceSelectorModal
emptyStateTitles={{ disks: "Custom disk title" }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
screen.getByText("Custom disk title");
});

it("shows custom empty state body for RAID tab", async () => {
const { user } = installerRender(
<DeviceSelectorModal
emptyStateBodies={{ mdRaids: "Custom RAID body text" }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
await user.click(screen.getByRole("tab", { name: "RAID" }));
screen.getByText("Custom RAID body text");
});

it("shows custom empty state for LVM tab", async () => {
const { user } = installerRender(
<DeviceSelectorModal
emptyStateTitles={{ volumeGroups: "No VGs available" }}
emptyStateBodies={{ volumeGroups: "Cannot format volume groups" }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
await user.click(screen.getByRole("tab", { name: "LVM" }));
screen.getByText("No VGs available");
screen.getByText("Cannot format volume groups");
});

it("falls back to default empty state when custom not provided", () => {
installerRender(
<DeviceSelectorModal title="Select" onCancel={onCancelMock} onConfirm={onConfirmMock} />,
);
screen.getByText("No disks found");
screen.getByText("No disks are available for selection.");
});
});

describe("newDeviceLinkTexts", () => {
// RAID device creation is not yet implemented (no STORAGE.mdRaid.add route exists)
it.skip("shows create link for RAID in empty state", async () => {
const { user } = installerRender(
<DeviceSelectorModal
newDeviceLinkTexts={{ mdRaids: "Create new RAID" }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
await user.click(screen.getByRole("tab", { name: "RAID" }));
screen.getByRole("link", { name: "Create new RAID" });
});

it("shows create link for LVM in empty state", async () => {
const { user } = installerRender(
<DeviceSelectorModal
newDeviceLinkTexts={{ volumeGroups: "Create new LVM" }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
await user.click(screen.getByRole("tab", { name: "LVM" }));
screen.getByRole("link", { name: "Create new LVM" });
});

// RAID device creation is not yet implemented (no STORAGE.mdRaid.add route exists)
it.skip("shows create link for RAID when devices exist", async () => {
const { user } = installerRender(
<DeviceSelectorModal
mdRaids={[md0]}
newDeviceLinkTexts={{ mdRaids: "Add another RAID" }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
await user.click(screen.getByRole("tab", { name: "RAID" }));
screen.getByRole("link", { name: "Add another RAID" });
});

it("shows both tabIntros and newDeviceLinkTexts together", async () => {
const { user } = installerRender(
<DeviceSelectorModal
volumeGroups={[vg0]}
tabIntros={{ volumeGroups: <p>Choose a volume group</p> }}
newDeviceLinkTexts={{ volumeGroups: "Create new VG" }}
title="Select"
onCancel={onCancelMock}
onConfirm={onConfirmMock}
/>,
);
await user.click(screen.getByRole("tab", { name: "LVM" }));
screen.getByText("Choose a volume group");
screen.getByRole("link", { name: "Create new VG" });
});
});

describe("actions", () => {
it("triggers onCancel when user selects Cancel", async () => {
const { user } = installerRender(
Expand Down
Loading
Loading