Skip to content

Commit

Permalink
feat(reservedip): Add reserved ips to redux store MAASENG-2983 (#5427)
Browse files Browse the repository at this point in the history
- Created types for reserved IPs
- Created store slice for reserved IPs
- Created reducers for reserved IPs
- Created selectors for reserved IPs
- Integrated reserved ip table with store
- Removed legacy `StaticDHCPLease` type
- Refactored `useStaticDHCPLease` to `useReservedIps`, integrated with store
- Created util to get node URL from system ID and node type
- Deleted legacy `staticDHCPLease` factory
- Created `reservedIp` and `reservedIpState` factories
- Created `ReservedIp` type
- Created `ReservedIpNodeSummary` type
  • Loading branch information
ndv99 authored May 15, 2024
1 parent 31635f8 commit 9774222
Show file tree
Hide file tree
Showing 31 changed files with 904 additions and 108 deletions.
8 changes: 8 additions & 0 deletions src/__snapshots__/root-reducer.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@ exports[`rootReducer > should reset app to initial state on LOGOUT_SUCCESS, exce
"saving": false,
"statuses": {},
},
"reservedip": {
"errors": null,
"items": [],
"loaded": false,
"loading": false,
"saved": false,
"saving": false,
},
"resourcepool": {
"errors": null,
"items": [],
Expand Down
89 changes: 89 additions & 0 deletions src/app/store/reservedip/action.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { actions } from "./slice";

it("can create an action for fetching reserved IPs", () => {
expect(actions.fetch()).toEqual({
type: "reservedip/fetch",
meta: {
model: "reservedip",
method: "list",
},
payload: null,
});
});

it("can create an action for creating a reserved IP", () => {
const params = {
comment: "It's an IP address",
ip: "192.168.0.2",
mac_address: "00:00:00:00:00:00",
subnet: 1,
};

expect(actions.create(params)).toEqual({
type: "reservedip/create",
meta: {
model: "reservedip",
method: "create",
},
payload: {
params,
},
});
});

it("can create an action for deleting a reserved IP", () => {
expect(actions.delete(1)).toEqual({
type: "reservedip/delete",
meta: {
model: "reservedip",
method: "delete",
},
payload: {
params: {
id: 1,
},
},
});
});

it("can create an action for updating a reserved IP", () => {
const params = {
id: 1,
comment: "It's an IP address",
ip: "192.168.0.2",
mac_address: "00:00:00:00:00:00",
subnet: 1,
};

expect(actions.update(params)).toEqual({
type: "reservedip/update",
meta: {
model: "reservedip",
method: "update",
},
payload: {
params,
},
});
});

it("can clean up", () => {
expect(actions.cleanup()).toEqual({
type: "reservedip/cleanup",
});
});

it("can create an action for getting a reserved IP", () => {
expect(actions.get(1)).toEqual({
type: "reservedip/get",
meta: {
model: "reservedip",
method: "get",
},
payload: {
params: {
id: 1,
},
},
});
});
1 change: 1 addition & 0 deletions src/app/store/reservedip/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default, actions as reservedIpActions } from "./slice";
215 changes: 215 additions & 0 deletions src/app/store/reservedip/reducers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
import reducers, { actions } from "./slice";

import * as factory from "@/testing/factories";

it("should return the initial state", () => {
expect(reducers(undefined, { type: "" })).toEqual(
factory.reservedIpState({
errors: null,
loading: false,
loaded: false,
items: [],
saved: false,
saving: false,
})
);
});

it("should correctly reduce cleanup", () => {
const initialState = factory.reservedIpState({
errors: { key: "Key already exists" },
saved: true,
saving: true,
});
expect(reducers(initialState, actions.cleanup())).toEqual(
factory.reservedIpState({
errors: null,
saved: false,
saving: false,
})
);
});

describe("fetch reducers", () => {
it("should correctly reduce fetchStart", () => {
const initialState = factory.reservedIpState({ loading: false });
expect(reducers(initialState, actions.fetchStart())).toEqual(
factory.reservedIpState({
loading: true,
})
);
});

it("should correctly reduce fetchSuccess", () => {
const initialState = factory.reservedIpState({
loading: true,
loaded: false,
items: [],
});
const items = [factory.reservedIp(), factory.reservedIp()];
expect(reducers(initialState, actions.fetchSuccess(items))).toEqual(
factory.reservedIpState({
loading: false,
loaded: true,
items,
})
);
});

it("should correctly reduce fetchError", () => {
const initialState = factory.reservedIpState({
loading: true,
loaded: false,
items: [],
});
expect(reducers(initialState, actions.fetchError("Error"))).toEqual(
factory.reservedIpState({
loading: false,
errors: "Error",
})
);
});
});

describe("create reducers", () => {
it("should correctly reduce createStart", () => {
const initialState = factory.reservedIpState({ saving: false });
expect(reducers(initialState, actions.createStart())).toEqual(
factory.reservedIpState({
saving: true,
})
);
});

it("should correctly reduce createSuccess", () => {
const initialState = factory.reservedIpState({
saving: true,
saved: false,
});

const reservedIp = factory.reservedIp();
expect(
reducers(
initialState,
actions.createSuccess(factory.reservedIp(reservedIp))
)
).toEqual(
factory.reservedIpState({
saving: false,
saved: true,
items: [reservedIp],
})
);
});

it("should correctly reduce createError", () => {
const initialState = factory.reservedIpState({
saving: true,
saved: false,
});
expect(reducers(initialState, actions.createError("Error"))).toEqual(
factory.reservedIpState({
saving: false,
errors: "Error",
})
);
});

it("should correctly reduce createNotify", () => {
const items = [factory.reservedIp(), factory.reservedIp()];
const initialState = factory.reservedIpState({
items: [items[0]],
});
expect(reducers(initialState, actions.createNotify(items[1]))).toEqual(
factory.reservedIpState({
items,
})
);
});
});

describe("delete reducers", () => {
it("should correctly reduce deleteStart", () => {
const initialState = factory.reservedIpState({ saving: false });
expect(reducers(initialState, actions.deleteStart())).toEqual(
factory.reservedIpState({
saving: true,
})
);
});

it("should correctly reduce deleteSuccess", () => {
const initialState = factory.reservedIpState({
saving: true,
saved: false,
});
expect(reducers(initialState, actions.deleteSuccess({ id: 1 }))).toEqual(
factory.reservedIpState({
saving: false,
saved: true,
})
);
});

it("should correctly reduce deleteError", () => {
const initialState = factory.reservedIpState({
saving: true,
saved: false,
});
expect(reducers(initialState, actions.deleteError("Error"))).toEqual(
factory.reservedIpState({
saving: false,
errors: "Error",
})
);
});

it("should correctly reduce deleteNotify", () => {
const items = [factory.reservedIp(), factory.reservedIp()];
const initialState = factory.reservedIpState({
items,
});
expect(
reducers(initialState, actions.deleteNotify(items[0].id)).items
).toEqual([items[1]]);
});
});

describe("get reducers", () => {
it("should correctly reduce getStart", () => {
const initialState = factory.reservedIpState({ items: [], loading: false });
expect(reducers(initialState, actions.getStart())).toEqual(
factory.reservedIpState({
loading: true,
})
);
});

it("should correctly reduce getSuccess", () => {
const newReservedIp = factory.reservedIp();
const reservedIpState = factory.reservedIpState({
items: [],
loading: true,
});
expect(
reducers(reservedIpState, actions.getSuccess(newReservedIp))
).toEqual(
factory.reservedIpState({
items: [newReservedIp],
loading: false,
})
);
});

it("should correctly reduce getError", () => {
const initialState = factory.reservedIpState({
loading: true,
});
expect(reducers(initialState, actions.getError("Error"))).toEqual(
factory.reservedIpState({
loading: false,
errors: "Error",
})
);
});
});
Loading

0 comments on commit 9774222

Please sign in to comment.