Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add support for automated tests for frontend with Jest and tests for HomeLoggedOut and NetworkHeader components #136

Merged
merged 9 commits into from
Jan 10, 2023
7 changes: 7 additions & 0 deletions frontend/__tests__/unit/HomeLoggedOut.snapshot.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { render } from "@testing-library/react";
import HomeLoggedOut from "../../src/components/HomeLoggedOut";

it("renders HomeLoggedOut unchanged", () => {
const { container } = render(<HomeLoggedOut />);
expect(container).toMatchSnapshot();
});
59 changes: 59 additions & 0 deletions frontend/__tests__/unit/HomeLoggedOut.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { render, screen } from "@testing-library/react";
import HomeLoggedOut from "../../src/components/HomeLoggedOut";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import { Router } from "react-router-dom";
import { createMemoryHistory } from "history";
import { act } from "react-dom/test-utils";
import axios from "axios";
import MockAdapter from "axios-mock-adapter";

let mock = new MockAdapter(axios);

describe("HomeLoggedOut", () => {
test("renders HomeLoggedOut when authentication is enabled", () => {
const history = createMemoryHistory();
const goSpy = jest.spyOn(history, "go");

mock.onGet("/auth/login").reply(200, { enabled: true });

render(
<Router history={history}>
<HomeLoggedOut />
</Router>
);

const projectDescription = screen.getByRole("heading", {
name: "ZeroUI - ZeroTier Controller Web UI - is a web user interface for a self-hosted ZeroTier network controller.",
});

const loginMessage = screen.getByText(/Please Log In to continue/i);

expect(projectDescription).toBeInTheDocument();
expect(loginMessage).toBeInTheDocument();
expect(goSpy).not.toHaveBeenCalled();
});

test("renders HomeLoggedOut when authentication is disabled", async () => {
const history = createMemoryHistory();
const goSpy = jest.spyOn(history, "go");

mock.onGet("/auth/login").reply(200, { enabled: false });

await act(async () => {
render(
<Router history={history}>
<HomeLoggedOut />
</Router>
);
});

const projectDescription = screen.getByRole("heading", {
name: "ZeroUI - ZeroTier Controller Web UI - is a web user interface for a self-hosted ZeroTier network controller.",
});

const loginMessage = screen.getByText(/Please Log In to continue/i);

expect(projectDescription).toBeInTheDocument();
expect(loginMessage).toBeInTheDocument();
expect(goSpy).toHaveBeenCalled();
});
});
8 changes: 8 additions & 0 deletions frontend/__tests__/unit/NetworkHeader.snapshot.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { render } from "@testing-library/react";
import NetworkHeader from "../../src/components/NetworkHeader";
import { testNetwork } from "./NetworkHeader.test";

it("renders HomeLoggedOut unchanged", () => {
const { container } = render(<NetworkHeader network={testNetwork} />);
expect(container).toMatchSnapshot();
});
97 changes: 97 additions & 0 deletions frontend/__tests__/unit/NetworkHeader.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { render, screen } from "@testing-library/react";
import NetworkHeader from "../../src/components/NetworkHeader";

export const testNetwork = {
id: "0d303702cd0f1fc6",
clock: 1672834445703,
description: "Test Network",
rulesSource:
"\n# This is a default rule set that allows IPv4 and IPv6 traffic but otherwise\n# behaves like a standard Ethernet switch.\n\n#\n# Allow only IPv4, IPv4 ARP, and IPv6 Ethernet frames.\n#\ndrop\n not ethertype ipv4\n and not ethertype arp\n and not ethertype ipv6\n;\n\n#\n# Uncomment to drop non-ZeroTier issued and managed IP addresses.\n#\n# This prevents IP spoofing but also blocks manual IP management at the OS level and\n# bridging unless special rules to exempt certain hosts or traffic are added before\n# this rule.\n#\n#drop\n# not chr ipauth\n#;\n\n# Accept anything else. This is required since default is 'drop'.\naccept;\n",
tagsByName: {},
capabilitiesByName: {},
config: {
authTokens: [null],
authorizationEndpoint: "",
capabilities: [],
clientId: "",
creationTime: 1672676611179,
dns: [],
enableBroadcast: true,
id: "0d303702cd0f1fc6",
ipAssignmentPools: [
{
ipRangeEnd: "172.30.101.254",
ipRangeStart: "172.30.101.1",
},
],
mtu: 2800,
multicastLimit: 32,
name: "new-net-11166",
nwid: "0d303702cd0f1fc6",
private: true,
routes: [
{
target: "172.30.101.0/24",
via: null,
},
],
rules: [
{
etherType: 2048,
not: true,
or: false,
type: "MATCH_ETHERTYPE",
},
{
etherType: 2054,
not: true,
or: false,
type: "MATCH_ETHERTYPE",
},
{
etherType: 34525,
not: true,
or: false,
type: "MATCH_ETHERTYPE",
},
{
type: "ACTION_DROP",
},
{
type: "ACTION_ACCEPT",
},
],
ssoEnabled: false,
tags: [],
v4AssignMode: {
zt: true,
},
v6AssignMode: {
"6plane": false,
rfc4193: false,
zt: false,
},
},
};

describe("NetworkHeader", () => {
test("renders NetworkHeader with a test network", () => {
render(<NetworkHeader network={testNetwork} />);

const networkId = screen.getByRole("heading", {
name: "0d303702cd0f1fc6",
level: 5,
});

const networkName = screen.getByRole("heading", {
name: "new-net-11166",
level: 6,
});

const networkDescription = screen.getByText(/Test Network/);

expect(networkId).toBeInTheDocument();
expect(networkName).toBeInTheDocument();
expect(networkDescription).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders HomeLoggedOut unchanged 1`] = `
<div>
<div
class="MuiGrid-root MuiGrid-container MuiGrid-direction-xs-column MuiGrid-align-items-xs-center MuiGrid-justify-content-xs-center"
style="min-height: 50vh;"
>
<div
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-10"
>
<h5
class="MuiTypography-root MuiTypography-h5"
>
<span>
ZeroUI - ZeroTier Controller Web UI - is a web user interface for a self-hosted ZeroTier network controller.
</span>
</h5>
<p
class="MuiTypography-root MuiTypography-body1"
>
<span>
Please Log In to continue
</span>
</p>
</div>
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders HomeLoggedOut unchanged 1`] = `
<div>
<div
class="MuiGrid-root MuiGrid-item"
>
<h5
class="MuiTypography-root MuiTypography-h5"
>
<span>
0d303702cd0f1fc6
</span>
</h5>
<h6
class="MuiTypography-root MuiTypography-h6"
style="font-style: italic;"
>
<span>
new-net-11166
</span>
</h6>
<span>
Test Network
</span>
</div>
</div>
`;
32 changes: 32 additions & 0 deletions frontend/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Add any custom config to be passed to Jest
const customJestConfig = {
setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
moduleDirectories: ["node_modules", "<rootDir>/"],
transform: {
// Use babel-jest to transpile tests with the below presets
// https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
"^.+\\.(js|jsx|ts|tsx)$": [
"babel-jest",
{
presets: [
"@babel/preset-env",
[
"@babel/preset-react",
{
runtime: "automatic",
},
],
],
},
],
},
testEnvironment: "jest-environment-jsdom",
moduleNameMapper: {
"^uuid$": require.resolve("uuid"),
"^@fontsource/roboto$": "identity-obj-proxy",
"\\.(png)$": "identity-obj-proxy",
},
testPathIgnorePatterns: ["<rootDir>/cypress/"],
};

module.exports = customJestConfig;
6 changes: 6 additions & 0 deletions frontend/jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Optional: configure or set up a testing framework before each test.
// If you delete this file, remove `setupFilesAfterEnv` from `jest.config.js`

// Used for __tests__/testing-library.js
// Learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom/extend-expect";
7 changes: 6 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@
"styled-components": "^5.3.5"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "12.1.5",
"axios-mock-adapter": "^1.21.2",
"jest-transform-css": "^6.0.0",
"source-map-explorer": "^2.5.2"
},
"scripts": {
"start": "BROWSER=none react-scripts start",
"build": "react-scripts build",
"analyze": "source-map-explorer 'build/static/js/*.js'"
"analyze": "source-map-explorer 'build/static/js/*.js'",
"test:unit": "npx jest --coverage --testPathPattern='unit'"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that it would be better to install jest in devDependencies and use it directly. ZeroUI uses the yarn package manager, so it's a bit confusing to see the npx.

Thanks!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sorry about this! I realized another package was missing too after adding Jest so I added that other package as well (jest-environment-jsdom). Let me know if you see anything else that needs to be changed!

},
"homepage": "/app",
"proxy": "http://127.0.0.1:4000",
Expand Down
Loading