Skip to content

Commit 06997a9

Browse files
refactor(base): UsedStorageTable to GenericTable MAASENG-5265 (#5804)
1 parent 79fb1bc commit 06997a9

File tree

10 files changed

+324
-280
lines changed

10 files changed

+324
-280
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"build-storybook": "storybook build"
4747
},
4848
"dependencies": {
49-
"@canonical/maas-react-components": "1.33.3",
49+
"@canonical/maas-react-components": "1.33.4",
5050
"@canonical/macaroon-bakery": "1.3.2",
5151
"@canonical/react-components": "2.14.0",
5252
"@redux-devtools/extension": "3.3.0",

src/app/base/components/node/StorageTables/DatastoresTable/DatastoresTable.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const DatastoresTable = ({ canEditStorage, node }: Props): ReactElement => {
6565
noData="No datastores detected."
6666
sortBy={[{ id: "name", desc: false }]}
6767
style={{ marginBottom: "1.5rem" }}
68+
variant="regular"
6869
/>
6970
);
7071
};

src/app/base/components/node/StorageTables/DatastoresTable/useDatastoresTableColumns/useDatastoresTableColumns.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ const useDatastoresTableColumns = (
2525
{
2626
id: "name",
2727
accessorKey: "name",
28-
enableSorting: true,
28+
enableSorting: false,
2929
header: "Name",
3030
},
3131
{
3232
id: "size",
3333
accessorKey: "size",
34-
enableSorting: true,
34+
enableSorting: false,
3535
header: "Size",
3636
cell: ({
3737
row: {
@@ -44,13 +44,13 @@ const useDatastoresTableColumns = (
4444
{
4545
id: "fstype",
4646
accessorKey: "fstype",
47-
enableSorting: true,
47+
enableSorting: false,
4848
header: "Filesystem",
4949
},
5050
{
5151
id: "mountPoint",
5252
accessorKey: "mount_point",
53-
enableSorting: true,
53+
enableSorting: false,
5454
header: "Mount point",
5555
},
5656
...(isMachine

src/app/base/components/node/StorageTables/FilesystemsTable/FilesystemsTable.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ const FilesystemsTable = ({
9494
noData="No filesystems defined."
9595
sortBy={[{ id: "name", desc: false }]}
9696
style={{ marginBottom: "1.5rem" }}
97+
variant="regular"
9798
/>
9899
{canEditStorage && (
99100
<Tooltip message="Create a tmpfs or ramfs filesystem.">

src/app/base/components/node/StorageTables/FilesystemsTable/useFilesystemsTableColumns/useFileSystemsTableColumns.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const useFileSystemsTableColumns = (
2525
{
2626
id: "name",
2727
accessorKey: "name",
28-
enableSorting: true,
28+
enableSorting: false,
2929
header: "Name",
3030
cell: ({
3131
row: {
@@ -38,7 +38,7 @@ const useFileSystemsTableColumns = (
3838
{
3939
id: "size",
4040
accessorKey: "size",
41-
enableSorting: true,
41+
enableSorting: false,
4242
header: "Size",
4343
cell: ({
4444
row: {
@@ -51,13 +51,13 @@ const useFileSystemsTableColumns = (
5151
{
5252
id: "fstype",
5353
accessorKey: "fstype",
54-
enableSorting: true,
54+
enableSorting: false,
5555
header: "Filesystem",
5656
},
5757
{
5858
id: "mountPoint",
5959
accessorKey: "mount_point",
60-
enableSorting: true,
60+
enableSorting: false,
6161
header: "Mount point",
6262
},
6363
{
Lines changed: 122 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,145 @@
1-
import { MemoryRouter } from "react-router";
1+
import { describe } from "vitest";
22

33
import UsedStorageTable from "./UsedStorageTable";
44

55
import urls from "@/app/base/urls";
6+
import type { ControllerDetails } from "@/app/store/controller/types";
67
import { FilterControllers } from "@/app/store/controller/utils";
78
import { MIN_PARTITION_SIZE } from "@/app/store/machine/constants";
9+
import type { MachineDetails } from "@/app/store/machine/types";
810
import { FilterMachines } from "@/app/store/machine/utils";
11+
import type { RootState } from "@/app/store/root/types";
912
import { DiskTypes } from "@/app/store/types/enum";
13+
import type { Disk } from "@/app/store/types/node";
1014
import * as factory from "@/testing/factories";
11-
import { render, screen } from "@/testing/utils";
15+
import {
16+
mockIsPending,
17+
renderWithProviders,
18+
screen,
19+
waitFor,
20+
} from "@/testing/utils";
1221

13-
it("can show an empty message", () => {
14-
const node = factory.machineDetails({
15-
disks: [],
16-
system_id: "abc123",
17-
});
18-
render(
19-
<MemoryRouter>
20-
<UsedStorageTable node={node} />
21-
</MemoryRouter>
22-
);
23-
24-
expect(
25-
screen.getByText("No disk or partition has been fully utilised.")
26-
).toBeInTheDocument();
27-
});
28-
29-
it("only shows disks that are being used", () => {
30-
const [availableDisk, usedDisk] = [
31-
factory.nodeDisk({
32-
available_size: MIN_PARTITION_SIZE + 1,
33-
name: "available-disk",
34-
filesystem: null,
35-
type: DiskTypes.PHYSICAL,
36-
}),
37-
factory.nodeDisk({
38-
available_size: MIN_PARTITION_SIZE - 1,
39-
filesystem: null,
40-
name: "used-disk",
41-
type: DiskTypes.PHYSICAL,
42-
}),
43-
];
44-
const node = factory.machineDetails({
45-
disks: [availableDisk, usedDisk],
46-
system_id: "abc123",
47-
});
22+
describe("UsedStorageTable", () => {
23+
let state: RootState;
24+
let machine: MachineDetails;
25+
let controller: ControllerDetails;
26+
let availableDisk: Disk;
27+
let usedDisk: Disk;
4828

49-
render(
50-
<MemoryRouter>
51-
<UsedStorageTable node={node} />
52-
</MemoryRouter>
53-
);
54-
55-
expect(
56-
screen.getAllByRole("gridcell", { name: "Name & serial" })
57-
).toHaveLength(1);
58-
expect(
59-
screen.getByRole("gridcell", { name: "Name & serial" })
60-
).toHaveTextContent(usedDisk.name);
61-
});
62-
63-
it("can render storage tag links for a controller", () => {
64-
const node = factory.controllerDetails({
65-
disks: [
29+
beforeEach(() => {
30+
[availableDisk, usedDisk] = [
6631
factory.nodeDisk({
67-
available_size: MIN_PARTITION_SIZE - 1,
32+
available_size: MIN_PARTITION_SIZE + 1,
33+
name: "available-disk",
34+
filesystem: null,
6835
type: DiskTypes.PHYSICAL,
6936
tags: ["abc"],
7037
}),
71-
],
72-
});
73-
const filter = FilterControllers.filtersToQueryString({
74-
storage_tags: ["=abc"],
75-
});
76-
const href = `${urls.controllers.index}${filter}`;
77-
78-
render(
79-
<MemoryRouter>
80-
<UsedStorageTable node={node} />
81-
</MemoryRouter>
82-
);
83-
84-
expect(screen.getByRole("link", { name: "abc" })).toHaveAttribute(
85-
"href",
86-
href
87-
);
88-
});
89-
90-
it("can render storage tag links for a machine", () => {
91-
const node = factory.machineDetails({
92-
disks: [
9338
factory.nodeDisk({
9439
available_size: MIN_PARTITION_SIZE - 1,
40+
filesystem: null,
41+
name: "used-disk",
9542
type: DiskTypes.PHYSICAL,
9643
tags: ["abc"],
9744
}),
98-
],
45+
];
46+
machine = factory.machineDetails({
47+
disks: [availableDisk, usedDisk],
48+
system_id: "abc123",
49+
});
50+
controller = factory.controllerDetails({
51+
disks: [availableDisk, usedDisk],
52+
system_id: "abc123",
53+
});
54+
state = factory.rootState({
55+
machine: factory.machineState({
56+
items: [machine],
57+
}),
58+
controller: factory.controllerState({
59+
items: [controller],
60+
}),
61+
});
9962
});
100-
const filter = FilterMachines.filtersToQueryString({
101-
storage_tags: ["=abc"],
63+
64+
describe("display", () => {
65+
// TODO: enable test once used storages are fetched through v3
66+
it.skip("displays a loading component if storages are loading", async () => {
67+
mockIsPending();
68+
renderWithProviders(<UsedStorageTable node={machine} />, {
69+
state,
70+
});
71+
72+
await waitFor(() => {
73+
expect(screen.getByText("Loading...")).toBeInTheDocument();
74+
});
75+
});
76+
77+
it("displays a message when rendering an empty list", async () => {
78+
const noDiskMachine = factory.machineDetails({
79+
disks: [],
80+
system_id: "abc123",
81+
});
82+
state.machine.items = [noDiskMachine];
83+
renderWithProviders(<UsedStorageTable node={noDiskMachine} />, {
84+
state,
85+
});
86+
87+
await waitFor(() => {
88+
expect(
89+
screen.getByText("No disk or partition has been fully utilised.")
90+
).toBeInTheDocument();
91+
});
92+
});
93+
94+
it("displays the columns correctly", () => {
95+
renderWithProviders(<UsedStorageTable node={machine} />, {
96+
state,
97+
});
98+
99+
["Name", "Model", "Boot", "Size", "Type", "Health", "Used for"].forEach(
100+
(column) => {
101+
expect(
102+
screen.getByRole("columnheader", {
103+
name: new RegExp(`^${column}`, "i"),
104+
})
105+
).toBeInTheDocument();
106+
}
107+
);
108+
});
109+
110+
it("only shows disks that are being used", () => {
111+
renderWithProviders(<UsedStorageTable node={machine} />, { state });
112+
113+
expect(screen.getByText(usedDisk.name)).toBeInTheDocument();
114+
expect(screen.queryByText(availableDisk.name)).not.toBeInTheDocument();
115+
});
116+
117+
it("can render storage tag links for a machine", () => {
118+
const filter = FilterMachines.filtersToQueryString({
119+
storage_tags: ["=abc"],
120+
});
121+
const href = `${urls.machines.index}${filter}`;
122+
123+
renderWithProviders(<UsedStorageTable node={machine} />, { state });
124+
125+
expect(screen.getByRole("link", { name: "abc" })).toHaveAttribute(
126+
"href",
127+
href
128+
);
129+
});
130+
131+
it("can render storage tag links for a controller", () => {
132+
const filter = FilterControllers.filtersToQueryString({
133+
storage_tags: ["=abc"],
134+
});
135+
const href = `${urls.controllers.index}${filter}`;
136+
137+
renderWithProviders(<UsedStorageTable node={controller} />, { state });
138+
139+
expect(screen.getByRole("link", { name: "abc" })).toHaveAttribute(
140+
"href",
141+
href
142+
);
143+
});
102144
});
103-
const href = `${urls.machines.index}${filter}`;
104-
105-
render(
106-
<MemoryRouter>
107-
<UsedStorageTable node={node} />
108-
</MemoryRouter>
109-
);
110-
111-
expect(screen.getByRole("link", { name: "abc" })).toHaveAttribute(
112-
"href",
113-
href
114-
);
115145
});

0 commit comments

Comments
 (0)