From 4bc2a251cf73c4917c5857e9f79f1b9780fd14b4 Mon Sep 17 00:00:00 2001
From: David Laganiere <40720561+davidlag0@users.noreply.github.com>
Date: Sat, 29 Apr 2023 11:44:59 -0400
Subject: [PATCH 1/4] test(NetworkConfig): fully cover NetworkConfig.js
---
.../unit/utils/NetworkConfig.test.js | 30 +++++++++++++++++++
frontend/src/utils/NetworkConfig.js | 4 +--
2 files changed, 32 insertions(+), 2 deletions(-)
create mode 100644 frontend/__tests__/unit/utils/NetworkConfig.test.js
diff --git a/frontend/__tests__/unit/utils/NetworkConfig.test.js b/frontend/__tests__/unit/utils/NetworkConfig.test.js
new file mode 100644
index 00000000..5bf2dcac
--- /dev/null
+++ b/frontend/__tests__/unit/utils/NetworkConfig.test.js
@@ -0,0 +1,30 @@
+import * as NetworkConfig from "utils/NetworkConfig";
+
+jest.spyOn(Math, "random").mockReturnValue(0.5);
+jest.spyOn(Date, "now").mockImplementation(() => 1487076708000);
+
+describe("NetworkConfig", () => {
+ it("getRandomInt()", () => {
+ expect(NetworkConfig.getRandomInt(1, 10)).toBe(5);
+ expect(NetworkConfig.getRandomInt(2, 2)).toBe(2);
+ expect(NetworkConfig.getRandomInt("test", 10)).toBe(NaN);
+ expect(NetworkConfig.getRandomInt(1, "test")).toBe(NaN);
+ expect(NetworkConfig.getRandomInt("test", "test")).toBe(NaN);
+ });
+
+ it("generateNetworkConfig()", () => {
+ expect(NetworkConfig.generateNetworkConfig()).toStrictEqual({
+ config: {
+ name: "new-net-08000",
+ private: true,
+ v6AssignMode: { "6plane": false, rfc4193: false, zt: false },
+ v4AssignMode: { zt: true },
+ routes: [{ flags: 0, metric: 0, target: "172.30.127.0/24", via: null }],
+ ipAssignmentPools: [
+ { ipRangeEnd: "172.30.127.254", ipRangeStart: "172.30.127.1" },
+ ],
+ enableBroadcast: true,
+ },
+ });
+ });
+});
diff --git a/frontend/src/utils/NetworkConfig.js b/frontend/src/utils/NetworkConfig.js
index 7a34c05e..ace86ae6 100644
--- a/frontend/src/utils/NetworkConfig.js
+++ b/frontend/src/utils/NetworkConfig.js
@@ -1,6 +1,6 @@
export function generateNetworkConfig() {
const randSubnetPart = getRandomInt(0, 254).toString();
- const randNamePart = new Date().getTime();
+ const randNamePart = new Date(Date.now()).getTime();
return {
config: {
name: "new-net-" + randNamePart.toString().substring(8),
@@ -26,7 +26,7 @@ export function generateNetworkConfig() {
};
}
-function getRandomInt(min, max) {
+export function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
From e2e3d303c1a977a4e51da0c5e2444839a1336b21 Mon Sep 17 00:00:00 2001
From: David Laganiere <40720561+davidlag0@users.noreply.github.com>
Date: Mon, 12 Jun 2023 08:26:48 -0400
Subject: [PATCH 2/4] test(Bar): add tests to almost fully cover
---
.../__tests__/unit/components/Bar.test.jsx | 100 +++++++++++++++++-
.../__snapshots__/Bar.test.jsx.snap | 67 ++++++++++++
2 files changed, 164 insertions(+), 3 deletions(-)
diff --git a/frontend/__tests__/unit/components/Bar.test.jsx b/frontend/__tests__/unit/components/Bar.test.jsx
index 446d349c..3ea3c39b 100644
--- a/frontend/__tests__/unit/components/Bar.test.jsx
+++ b/frontend/__tests__/unit/components/Bar.test.jsx
@@ -1,7 +1,8 @@
-import { render } from "@testing-library/react";
+import { render, screen } from "@testing-library/react";
import Bar from "components/Bar";
-import { Router } from "react-router-dom";
+import { MemoryRouter, Route, Router } from "react-router-dom";
import { createMemoryHistory } from "history";
+import userEvent from "@testing-library/user-event";
// Useful reference: https://bholmes.dev/blog/mocking-browser-apis-fetch-localstorage-dates-the-easy-way-with-jest/
@@ -10,10 +11,10 @@ let mockStorage = {};
describe("Bar", () => {
beforeAll(() => {
global.Storage.prototype.getItem = jest.fn((key) => mockStorage[key]);
+ global.Storage.prototype.clear = jest.fn(() => (mockStorage = {}));
});
beforeEach(() => {
- // make sure the fridge starts out empty for each test
mockStorage = {};
});
@@ -44,4 +45,97 @@ describe("Bar", () => {
);
expect(container).toMatchSnapshot();
});
+
+ it("renders Bar unchanged when logged in, after clicking button to open menu", async () => {
+ const history = createMemoryHistory();
+ const user = userEvent.setup();
+ mockStorage["loggedIn"] = true;
+
+ const { container } = render(
+
+
+
+ );
+
+ const menuButton = screen.getByRole("button", {
+ name: "",
+ });
+
+ await user.click(menuButton);
+
+ const logOutMenuItem = screen.getByRole("menuitem", {
+ name: "Log out",
+ });
+ expect(logOutMenuItem).toBeInTheDocument();
+
+ expect(container).toMatchSnapshot();
+ });
+
+ test("open and close menu when logged in", async () => {
+ const history = createMemoryHistory();
+ const user = userEvent.setup();
+ mockStorage["loggedIn"] = true;
+
+ render(
+
+
+
+ );
+
+ const menuButton = screen.getByRole("button", {
+ name: "",
+ });
+
+ // Open menu
+ await user.click(menuButton);
+
+ const logOutMenuItem = screen.getByRole("menuitem", {
+ name: "Log out",
+ });
+ expect(logOutMenuItem).toBeInTheDocument();
+
+ // Close menu
+ await user.keyboard("{Escape}");
+
+ expect(logOutMenuItem).not.toBeInTheDocument();
+ });
+
+ test("open menu and click on 'Log out'", async () => {
+ const user = userEvent.setup();
+ mockStorage["loggedIn"] = true;
+ let testLocation;
+
+ render(
+
+
+
+
+ {
+ testLocation = location;
+ return null;
+ }}
+ />
+
+ );
+
+ const menuButton = screen.getByRole("button", {
+ name: "",
+ });
+
+ // Open menu
+ await user.click(menuButton);
+
+ const logOutMenuItem = screen.getByRole("menuitem", {
+ name: "Log out",
+ });
+ expect(logOutMenuItem).toBeInTheDocument();
+
+ // Click on 'Log out'
+ await user.click(logOutMenuItem);
+
+ expect(Object.keys(mockStorage).length).toBe(0);
+ expect(testLocation.pathname).toBe("/");
+ });
});
diff --git a/frontend/__tests__/unit/components/__snapshots__/Bar.test.jsx.snap b/frontend/__tests__/unit/components/__snapshots__/Bar.test.jsx.snap
index 6a4346cd..305795d3 100644
--- a/frontend/__tests__/unit/components/__snapshots__/Bar.test.jsx.snap
+++ b/frontend/__tests__/unit/components/__snapshots__/Bar.test.jsx.snap
@@ -56,6 +56,73 @@ exports[`Bar renders Bar unchanged when logged in 1`] = `
`;
+exports[`Bar renders Bar unchanged when logged in, after clicking button to open menu 1`] = `
+
+`;
+
exports[`Bar renders Bar unchanged when logged out 1`] = `
Date: Sun, 13 Aug 2023 14:14:26 -0400
Subject: [PATCH 3/4] chore: update scripts for tests
---
frontend/package.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/frontend/package.json b/frontend/package.json
index 11846814..875358a2 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -37,7 +37,8 @@
"start": "BROWSER=none react-scripts start",
"build": "react-scripts build",
"analyze": "source-map-explorer 'build/static/js/*.js'",
- "test:unit": "jest --coverage --testPathPattern='unit'"
+ "test:unit": "jest --coverage --testPathPattern='unit' --silent",
+ "test": "jest --coverage"
},
"homepage": "/app",
"proxy": "http://127.0.0.1:4000",
From 514a86831fb04aed6207537bfa80859c55564ef9 Mon Sep 17 00:00:00 2001
From: David Laganiere <40720561+davidlag0@users.noreply.github.com>
Date: Sun, 13 Aug 2023 14:21:21 -0400
Subject: [PATCH 4/4] test(HomeLoggedIn): add test for 100% coverage
---
.../unit/components/HomeLoggedIn.test.jsx | 44 ++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/frontend/__tests__/unit/components/HomeLoggedIn.test.jsx b/frontend/__tests__/unit/components/HomeLoggedIn.test.jsx
index 28779523..5a8734da 100644
--- a/frontend/__tests__/unit/components/HomeLoggedIn.test.jsx
+++ b/frontend/__tests__/unit/components/HomeLoggedIn.test.jsx
@@ -1,9 +1,11 @@
import { render, screen } from "@testing-library/react";
import HomeLoggedIn from "components/HomeLoggedIn";
-import { Router } from "react-router-dom";
+import { MemoryRouter, Route, Router } from "react-router-dom";
import { createMemoryHistory } from "history";
import { testNetwork } from "../../data/network";
+import userEvent from "@testing-library/user-event";
import API from "utils/API";
+import { act } from "react-dom/test-utils";
import MockAdapter from "axios-mock-adapter";
describe("HomeLoggedIn", () => {
@@ -43,4 +45,44 @@ describe("HomeLoggedIn", () => {
expect(container).toMatchSnapshot();
});
+
+ it("creates a new network when the 'Create A Network' button is clicked", async () => {
+ jest.spyOn(Math, "random").mockReturnValue(0.5);
+ jest.spyOn(Date, "now").mockImplementation(() => 1487076708000);
+
+ let mock = new MockAdapter(API);
+ const user = userEvent.setup();
+ let testLocation;
+ const networkId = "testid";
+
+ // For the API call with the initial render
+ mock.onGet("network").reply(200, []);
+
+ // For the API call after the 'Create A Network' button is clicked
+ mock.onPost("/network").reply(200, { config: { id: "testid" } });
+
+ await act(async () => {
+ render(
+
+
+
+
+ {
+ testLocation = location;
+ return null;
+ }}
+ />
+
+ );
+ });
+
+ const createANetworkButton = screen.getByRole("button", {
+ name: "Create A Network",
+ });
+
+ await user.click(createANetworkButton);
+ expect(testLocation.pathname).toBe("/network/testid");
+ });
});