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

[WIP]: refactor(): bootzooka ui #901

Merged
merged 1 commit into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ui/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
public
3 changes: 3 additions & 0 deletions ui/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"printWidth": 120
}
59 changes: 33 additions & 26 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,53 @@
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:8080",
"engines": {
"node": ">=16"
},
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.0.4",
"@testing-library/user-event": "^7.1.2",
"@types/axios": "^0.14.0",
"@types/jest": "^24.0.0",
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^12.0.0",
"@testing-library/user-event": "^14.3.0",
"@types/jest": "^26.0.0",
"@types/node": "^16.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-icons": "^3.0.0",
"@types/react-router-bootstrap": "^0.24.5",
"@types/react-router-dom": "^5.1.6",
"@types/yup": "^0.29.8",
"axios": "^0.21.2",
"@types/react-router-dom": "^5.3.3",
"@types/yup": "^0.29.14",
"axios": "^0.27.2",
"bootstrap": "^4.5.2",
"formik": "^2.2.0",
"immer": "^9.0.6",
"jest-environment-jsdom-sixteen": "^1.0.3",
"noop-ts": "^1.0.3",
"react": "^16.13.1",
"eslint-config-prettier": "^8.5.0",
"formik": "^2.2.9",
"immer": "^9.0.15",
"prettier": "^2.7.1",
"react": "^17.0.0",
"react-bootstrap": "^1.3.0",
"react-dom": "^16.13.1",
"react-dom": "^17.0.0",
"react-icons": "^3.11.0",
"react-router-bootstrap": "^0.25.0",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.0",
"react-use-promise-matcher": "^1.3.0",
"typescript": "^4.0.3",
"yup": "^0.29.3"
"react-router-dom": "^6.3.0",
"react-scripts": "^4.0.0",
"react-use-promise-matcher": "^1.4.2",
"typescript": "^4.7.4",
"yup": "^0.32.11"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jest-environment-jsdom-sixteen",
"test:coverage": "react-scripts test --coverage --env=jest-environment-jsdom-sixteen --watchAll=false",
"test:ci": "CI=true react-scripts test --env=jest-environment-jsdom-sixteen --maxWorkers 2",
"test": "react-scripts test",
"test:coverage": "react-scripts test --coverage --watchAll=false",
"test:ci": "CI=true react-scripts test --maxWorkers 2",
"lint": "eslint --ext .ts,.tsx . && prettier --write ./src",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
"extends": [
"react-app",
"react-app/jest",
"prettier"
]
},
"jest": {
"collectCoverageFrom": [
Expand Down
3 changes: 1 addition & 2 deletions ui/src/contexts/UserContext/UserContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from "react";
import immer from "immer";
import noop from "noop-ts";

export interface UserDetails {
createdOn: string;
Expand Down Expand Up @@ -56,7 +55,7 @@ export const UserContext = React.createContext<{
dispatch: React.Dispatch<UserAction>;
}>({
state: initialUserState,
dispatch: noop,
dispatch: () => {},
});

export const UserContextProvider: React.FC = ({ children }) => {
Expand Down
18 changes: 7 additions & 11 deletions ui/src/main/Main/Main.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import React from "react";
import { render } from "@testing-library/react";
import Main from "./Main";
import { UserContext, initialUserState } from "../../contexts/UserContext/UserContext";
import { Router } from "react-router-dom";
import { createMemoryHistory } from "history";

const history = createMemoryHistory({ initialEntries: [""] });
import { MemoryRouter } from "react-router-dom";

const dispatch = jest.fn();

Expand All @@ -15,35 +11,35 @@ beforeEach(() => {

test("shows loader on unspecified logged in status", () => {
const { getByRole } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContext.Provider value={{ state: initialUserState, dispatch }}>
<Main />
</UserContext.Provider>
</Router>
</MemoryRouter>
);

expect(getByRole("loader")).toBeInTheDocument();
});

test("shows app on logged in status", () => {
const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContext.Provider value={{ state: { ...initialUserState, loggedIn: true }, dispatch }}>
<Main />
</UserContext.Provider>
</Router>
</MemoryRouter>
);

expect(getByText("Welcome to Bootzooka!")).toBeInTheDocument();
});

test("shows app on logged out status", () => {
const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContext.Provider value={{ state: { ...initialUserState, loggedIn: false }, dispatch }}>
<Main />
</UserContext.Provider>
</Router>
</MemoryRouter>
);

expect(getByText("Welcome to Bootzooka!")).toBeInTheDocument();
Expand Down
21 changes: 9 additions & 12 deletions ui/src/main/Main/useLocalStoragedApiKey.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import React from "react";
import { render, fireEvent } from "@testing-library/react";
import useLocalStoragedApiKey from "./useLocalStoragedApiKey";
import { UserContextProvider, UserContext, UserAction } from "../../contexts/UserContext/UserContext";
import { Router } from "react-router-dom";
import { createMemoryHistory } from "history";

const history = createMemoryHistory({ initialEntries: [""] });
import { MemoryRouter } from "react-router-dom";

const TestComponent: React.FC<{ actions?: UserAction[]; label?: string }> = ({ actions, label }) => {
const { state, dispatch } = React.useContext(UserContext);
Expand All @@ -32,11 +29,11 @@ test("handles not stored api key", () => {
localStorage.removeItem("apiKey");

const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContextProvider>
<TestComponent />
</UserContextProvider>
</Router>
</MemoryRouter>
);

expect(getByText("loggedIn:false")).toBeInTheDocument();
Expand All @@ -47,11 +44,11 @@ test("handles stored api key", () => {
localStorage.setItem("apiKey", "test-api-key");

const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContextProvider>
<TestComponent />
</UserContextProvider>
</Router>
</MemoryRouter>
);

expect(getByText("loggedIn:null")).toBeInTheDocument();
Expand All @@ -62,7 +59,7 @@ test("handles user logging in", () => {
localStorage.removeItem("apiKey");

const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContextProvider>
<TestComponent
actions={[
Expand All @@ -75,7 +72,7 @@ test("handles user logging in", () => {
label="log in"
/>
</UserContextProvider>
</Router>
</MemoryRouter>
);

fireEvent.click(getByText("log in"));
Expand All @@ -89,7 +86,7 @@ test("handles user logging out", () => {
localStorage.setItem("apiKey", "test-api-key");

const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContextProvider>
<TestComponent
actions={[
Expand All @@ -104,7 +101,7 @@ test("handles user logging out", () => {
label="log in and out"
/>
</UserContextProvider>
</Router>
</MemoryRouter>
);

fireEvent.click(getByText("log in and out"));
Expand Down
17 changes: 7 additions & 10 deletions ui/src/main/Main/useLoginOnApiKey.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ import React from "react";
import { render, fireEvent, act } from "@testing-library/react";
import useLoginOnApiKey from "./useLoginOnApiKey";
import { UserContextProvider, UserContext, UserAction } from "../../contexts/UserContext/UserContext";
import { Router } from "react-router-dom";
import { createMemoryHistory } from "history";
import { MemoryRouter } from "react-router-dom";
import userService from "../../services/UserService/UserService";

const history = createMemoryHistory({ initialEntries: [""] });

jest.mock("../../services/UserService/UserService");

const TestComponent: React.FC<{ actions?: UserAction[]; label?: string }> = ({ actions, label }) => {
Expand Down Expand Up @@ -35,11 +32,11 @@ test("default state", () => {
localStorage.removeItem("apiKey");

const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContextProvider>
<TestComponent />
</UserContextProvider>
</Router>
</MemoryRouter>
);

expect(getByText("loggedIn:null")).toBeInTheDocument();
Expand All @@ -54,11 +51,11 @@ test("handles set correct api key", async () => {
});

const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContextProvider>
<TestComponent actions={[{ type: "SET_API_KEY", apiKey: "test-api-key" }]} label="set api key" />
</UserContextProvider>
</Router>
</MemoryRouter>
);

await act(async () => {
Expand All @@ -74,11 +71,11 @@ test("handles set wrong api key", async () => {
(userService.getCurrentUser as jest.Mock).mockRejectedValueOnce(new Error("Test Error"));

const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContextProvider>
<TestComponent actions={[{ type: "SET_API_KEY", apiKey: "test-api-key" }]} label="set api key" />
</UserContextProvider>
</Router>
</MemoryRouter>
);

await act(async () => {
Expand Down
44 changes: 23 additions & 21 deletions ui/src/main/Routes/ProtectedRoute.test.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import React from "react";
import { render } from "@testing-library/react";
import { Routes, Route } from "react-router-dom";
import ProtectedRoute from "./ProtectedRoute";
import Login from "../../pages/Login/Login";
import { UserContext, UserState, initialUserState } from "../../contexts/UserContext/UserContext";
import { Router } from "react-router-dom";
import { createMemoryHistory } from "history";

const loggedUserState: UserState = {
...initialUserState,
loggedIn: true,
};
import { MemoryRouter } from "react-router-dom";

const dispatch = jest.fn();

Expand All @@ -17,32 +12,39 @@ beforeEach(() => {
});

test("renders protected route for unlogged user", () => {
const history = createMemoryHistory({ initialEntries: ["/test-route"] });

const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContext.Provider value={{ state: initialUserState, dispatch }}>
<ProtectedRoute path="/test-route">
<>Protected Text</>
</ProtectedRoute>
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<ProtectedRoute />}>
<Route index element={<>Protected Text</>} />
</Route>
</Routes>
</UserContext.Provider>
</Router>
</MemoryRouter>
);

expect(getByText("Please sign in")).toBeInTheDocument();
});

test("renders protected route for logged user", () => {
const history = createMemoryHistory({ initialEntries: ["/test-route"] });
const loggedUserState: UserState = {
...initialUserState,
loggedIn: true,
};

const { getByText } = render(
<Router history={history}>
<MemoryRouter initialEntries={[""]}>
<UserContext.Provider value={{ state: loggedUserState, dispatch }}>
<ProtectedRoute path="/test-route">
<>Protected Text</>
</ProtectedRoute>
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<ProtectedRoute />}>
<Route index element={<>Protected Text</>} />
</Route>
</Routes>
</UserContext.Provider>
</Router>
</MemoryRouter>
);

expect(getByText("Protected Text")).toBeInTheDocument();
Expand Down
14 changes: 6 additions & 8 deletions ui/src/main/Routes/ProtectedRoute.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import React from "react";
import { Route, RouteProps } from "react-router-dom";
import React, { useContext } from "react";
import { useLocation, Outlet, Navigate } from "react-router-dom";
import { UserContext } from "../../contexts/UserContext/UserContext";
import Login from "../../pages/Login/Login";

const ProtectedRoute: React.FC<RouteProps> = ({ children, ...props }) => {
const ProtectedRoute: React.FC = () => {
const {
state: { loggedIn },
} = React.useContext(UserContext);
} = useContext(UserContext);
const location = useLocation();

if (!loggedIn) return <Route {...props} component={Login} />;

return <Route {...props}>{children}</Route>;
return loggedIn ? <Outlet /> : <Navigate to="/login" state={{ from: location }} replace />;
};

export default ProtectedRoute;
Loading