Merge pull request #136 from davidlag0/test/front_end_tests

test: add support for automated tests for frontend with Jest and tests for HomeLoggedOut and NetworkHeader components
This commit is contained in:
dec0dOS 2023-01-10 12:48:19 +00:00 committed by GitHub
commit 13b9cbbe7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 2157 additions and 31 deletions

View file

@ -0,0 +1,7 @@
import { render } from "@testing-library/react";
import HomeLoggedOut from "components/HomeLoggedOut";
it("renders HomeLoggedOut unchanged", () => {
const { container } = render(<HomeLoggedOut />);
expect(container).toMatchSnapshot();
});

View file

@ -0,0 +1,59 @@
import { render, screen } from "@testing-library/react";
import HomeLoggedOut from "components/HomeLoggedOut";
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();
});
});

View file

@ -0,0 +1,8 @@
import { render } from "@testing-library/react";
import NetworkHeader from "components/NetworkHeader";
import { testNetwork } from "./NetworkHeader.test";
it("renders HomeLoggedOut unchanged", () => {
const { container } = render(<NetworkHeader network={testNetwork} />);
expect(container).toMatchSnapshot();
});

View file

@ -0,0 +1,97 @@
import { render, screen } from "@testing-library/react";
import NetworkHeader from "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();
});
});

View file

@ -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>
`;

View file

@ -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
frontend/jest.config.js Normal file
View file

@ -0,0 +1,32 @@
// Add any custom config to be passed to Jest
const customJestConfig = {
setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
moduleDirectories: ["node_modules", "<rootDir>/", "src"],
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
frontend/jest.setup.js Normal file
View file

@ -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";

View file

@ -23,12 +23,19 @@
"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": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"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": "jest --coverage --testPathPattern='unit'"
},
"homepage": "/app",
"proxy": "http://127.0.0.1:4000",

1913
yarn.lock

File diff suppressed because it is too large Load diff