Skip to content

Commit

Permalink
Merge branch 'master' into feature/group-invite-link
Browse files Browse the repository at this point in the history
  • Loading branch information
Repumba authored May 29, 2023
2 parents 7bde325 + c52a1d6 commit 6adbe5d
Show file tree
Hide file tree
Showing 140 changed files with 1,975 additions and 819 deletions.
17 changes: 17 additions & 0 deletions mwdb/web/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
module.exports = {
preset: "ts-jest",
testEnvironment: "jsdom",
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
},
transform: {
"^.+\\.(js|jsx|ts|tsx)$": "ts-jest",
},
testMatch: [
"<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
"<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}",
],
moduleFileExtensions: ["js", "jsx", "ts", "tsx"],
moduleNameMapper: {
"^@mwdb-web/commons/(.*)$": "<rootDir>/src/commons/$1",
"^@mwdb-web/plugins$": "<rootDir>/src/mocks/plugins.ts",
},
resetMocks: true,
};
553 changes: 553 additions & 0 deletions mwdb/web/package-lock.json

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion mwdb/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"test": "jest"
"test": "jest",
"lint": "tsc --watch"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.1.1",
Expand Down Expand Up @@ -47,15 +48,23 @@
"@babel/preset-env": "^7.21.4",
"@babel/preset-react": "^7.18.6",
"@testing-library/react": "^14.0.0",
"@types/identicon.js": "^2.3.1",
"@types/jest": "^29.5.1",
"@types/react": "^18.0.26",
"@types/react-copy-to-clipboard": "^5.0.4",
"@types/react-dom": "^18.0.9",
"@types/react-js-pagination": "^3.0.4",
"@types/react-modal": "^3.16.0",
"@types/sha1": "^1.1.3",
"@vitejs/plugin-react": "^3.0.0",
"babel-jest": "^29.5.0",
"dpdm": "^3.9.0",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"prettier": "^2.4.1",
"react-test-renderer": "^18.2.0",
"ts-jest": "^29.1.0",
"ts-node": "^10.9.1",
"vite": "^4.0.0",
"vite-plugin-checker": "^0.5.6"
},
Expand Down
3 changes: 2 additions & 1 deletion mwdb/web/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ import UserCapabilities from "./components/Settings/Views/UserCapabilities";
import UserAPIKeys from "./components/Settings/Views/UserAPIKeys";
import { AttributeEditTemplate } from "./components/Settings/Views/AttributeEditTemplate";

import { Capability } from "./commons/auth";
import { ConfigContext } from "./commons/config";
import { fromPlugins, Extendable } from "./commons/plugins";
import { ErrorBoundary, RequiresAuth, RequiresCapability } from "./commons/ui";

import { Capability } from "@mwdb-web/types/types";

function NavigateFor404() {
/**
* Fallback route for unknown routes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { GenericOrJSX } from "@mwdb-web/types/types";
import { capitalize, intersperse, mapObjectType } from "../../commons/helpers";

describe("capitalize", () => {
test("should return empty string when param is not typeof string", () => {
const string = {};
const expected = "";
const result = capitalize(string);
const result = capitalize(string as string);
expect(result).toEqual(expected);
});

Expand All @@ -25,20 +26,32 @@ describe("capitalize", () => {

describe("intersperse", () => {
test("should return an empty array when passed an empty array", () => {
const expected = [];
const expected: GenericOrJSX<string>[] = [];
const result = intersperse([], "-");
expect(result).toEqual(expected);
});

it("should intersperse a single item in an array", () => {
const expected = [1, "-", 2, "-", 3];
const result = intersperse([1, 2, 3], "-");
const expected = ["1", "-", "2", "-", "3"];
const result = intersperse(["1", "2", "3"], "-");
expect(result).toEqual(expected);
});

it("should intersperse multiple items in an array", () => {
const expected = [1, "-", ".", 2, "-", ".", 3];
const result = intersperse([1, 2, 3], ["-", "."]);
const expected = ["1", "-", ".", "2", "-", ".", "3"];
const result = intersperse(["1", "2", "3"], ["-", "."]);
expect(expected).toEqual(result);
});

it("should intersperse a single JSX item in an array", () => {
const expected = [1, <br />, 2, <br />, 3];
const result = intersperse([1, 2, 3], <br />);
expect(expected).toEqual(result);
});

it("should intersperse a multiple JSX items in an array", () => {
const expected = [1, <br />, <div />, 2, <br />, <div />, 3];
const result = intersperse([1, 2, 3], [<br />, <div />]);
expect(expected).toEqual(result);
});
});
Expand Down
45 changes: 45 additions & 0 deletions mwdb/web/src/__tests__/hooks/useCheckCapabilities.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { renderHook } from "@testing-library/react";
import { useCheckCapabilities } from "@mwdb-web/commons/hooks";
import { AuthContextValues, Capability } from "@mwdb-web/types/types";
import { AuthContext } from "@mwdb-web/commons/auth";
import { AuthProviderProps } from "@mwdb-web/types/props";

describe("useCheckCapabilities", () => {
const authContextValue = {
user: {
capabilities: [
Capability.accessAllObjects,
Capability.accessAllObjects,
Capability.addingTags,
],
},
} as AuthContextValues;

const wrapperWithInitValues =
(initValues: AuthContextValues) => (props: AuthProviderProps) =>
(
<AuthContext.Provider value={initValues}>
{props.children}
</AuthContext.Provider>
);

it("should return true if user has the capability", () => {
const wrapper = wrapperWithInitValues(authContextValue);
const { result } = renderHook(() => useCheckCapabilities(), {
wrapper,
});
const { userHasCapabilities } = result.current;

expect(userHasCapabilities(Capability.accessAllObjects)).toBe(true);
});

it("should return false if user doesn't have the capability", () => {
const wrapper = wrapperWithInitValues(authContextValue);
const { result } = renderHook(() => useCheckCapabilities(), {
wrapper,
});
const { userHasCapabilities } = result.current;

expect(userHasCapabilities(Capability.removingKarton)).toBe(false);
});
});
19 changes: 19 additions & 0 deletions mwdb/web/src/__tests__/hooks/useComponentState.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";
import { renderHook, act } from "@testing-library/react";
import { useComponentState } from "@mwdb-web/commons/hooks";

describe("useComponentState", () => {
test("should initialize with React.Fragment as the default component", () => {
const { result } = renderHook(() => useComponentState());
expect(result.current.Component).toBe(React.Fragment);
});

test("should update the component when setComponent is called", () => {
const { result } = renderHook(() => useComponentState());
const newComponent = () => <div>New Component</div>;
act(() => {
result.current.setComponent(newComponent);
});
expect(result.current.Component).toBe(newComponent);
});
});
37 changes: 37 additions & 0 deletions mwdb/web/src/__tests__/hooks/useNavRedirect.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useNavRedirect } from "@mwdb-web/commons/hooks";
import { renderHook, act } from "@testing-library/react";

const navigateMock = jest.fn();
const locationMock = { state: { prevLocation: "/" } };

jest.mock("react-router-dom", () => ({
useNavigate: () => navigateMock,
useLocation: () => locationMock,
}));

describe("useNavRedirect", () => {
beforeEach(() => {
navigateMock.mockClear();
});

afterEach(() => {
jest.clearAllMocks();
});

test("should call navigate with the provided URL", () => {
const { result } = renderHook(() => useNavRedirect());
const url = "/redirect";
act(() => {
result.current.redirectTo(url);
});
expect(navigateMock).toHaveBeenCalledWith(url);
});

test("should call navigate with the previous location", () => {
const { result } = renderHook(() => useNavRedirect());
act(() => {
result.current.goBackToPrevLocation();
});
expect(navigateMock).toHaveBeenCalledWith("/");
});
});
110 changes: 110 additions & 0 deletions mwdb/web/src/__tests__/hooks/useViewAlert.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { useViewAlert } from "@mwdb-web/commons/hooks";
import {
RedirectToAlertProps,
SetAlertProps,
} from "@mwdb-web/commons/hooks/useViewAlert";
import { renderHook } from "@testing-library/react";
import { useNavigate, useLocation } from "react-router-dom";
import { toast } from "react-toastify";

jest.mock("react-router-dom", () => ({
...(jest.requireActual("react-router-dom") as any),
useNavigate: jest.fn(),
useLocation: jest.fn(),
}));

jest.mock("react-toastify", () => ({
toast: jest.fn(),
}));

const mockNavigate = jest.fn();
const mockLocation = {
pathname: "/",
search: "",
state: {},
};

describe("useViewAlert", () => {
beforeEach(() => {
jest.clearAllMocks();
(useNavigate as jest.Mock).mockReturnValue(mockNavigate);
(useLocation as jest.Mock).mockReturnValue(mockLocation);
});

test("should set alert and navigate with state", () => {
const { result } = renderHook(() => useViewAlert());

const setAlertProps: SetAlertProps = {
success: "Success message",
state: { additionalState: true },
};

result.current.setAlert(setAlertProps);

expect(toast).toHaveBeenCalledWith("Success message", {
type: "success",
});

expect(mockNavigate).toHaveBeenCalledWith(
{ pathname: "/", search: "" },
{ replace: true, state: { additionalState: true } }
);
});

test("should set error alert and navigate without state", () => {
const { result } = renderHook(() => useViewAlert());

const setAlertProps = {
error: {
response: {
data: {
message: "Error message",
},
},
},
} as SetAlertProps;

result.current.setAlert(setAlertProps);

expect(toast).toHaveBeenCalledWith("Error message", { type: "error" });

expect(mockNavigate).toHaveBeenCalledWith(
{ pathname: "/", search: "" },
{ replace: true, state: {} }
);
});

test("should set error as a string alert", () => {
const { result } = renderHook(() => useViewAlert());

const setAlertProps: SetAlertProps = {
error: "String Error Message",
};

result.current.setAlert(setAlertProps);

expect(toast).toHaveBeenCalledWith("String Error Message", {
type: "error",
});
});

test("should redirect with alert and state", () => {
const { result } = renderHook(() => useViewAlert());

const redirectToAlertProps: RedirectToAlertProps = {
warning: "Warning message",
target: "/target",
state: { additionalState: true },
};

result.current.redirectToAlert(redirectToAlertProps);

expect(toast).toHaveBeenCalledWith("Warning message", {
type: "warning",
});

expect(mockNavigate).toHaveBeenCalledWith("/target", {
state: { additionalState: true },
});
});
});
Original file line number Diff line number Diff line change
@@ -1,34 +1,7 @@
import { afterPluginsLoaded, fromPlugins } from "../plugins";
import { Capability } from "@mwdb-web/types/types";

export const Capability = {
manageUsers: "manage_users",
shareQueriedObjects: "share_queried_objects",
accessAllObjects: "access_all_objects",
sharingWithAll: "sharing_with_all",
accessUploaderInfo: "access_uploader_info",
addingTags: "adding_tags",
removingTags: "removing_tags",
addingComments: "adding_comments",
removingComments: "removing_comments",
addingParents: "adding_parents",
removingParents: "removing_parents",
readingAllAttributes: "reading_all_attributes",
addingAllAttributes: "adding_all_attributes",
removingAttributes: "removing_attributes",
addingFiles: "adding_files",
addingConfigs: "adding_configs",
addingBlobs: "adding_blobs",
unlimitedRequests: "unlimited_requests",
removingObjects: "removing_objects",
manageProfile: "manage_profile",
personalize: "personalize",
kartonAssign: "karton_assign",
kartonReanalyze: "karton_reanalyze",
removingKarton: "karton_unassign",
modify3rdPartySharing: "modify_3rd_party_sharing",
};

export let capabilitiesList = {
export let capabilitiesList: Record<Capability, string> = {
[Capability.manageUsers]:
"Managing users and groups (system administration)",
[Capability.shareQueriedObjects]: "Query for all objects in system",
Expand Down
3 changes: 0 additions & 3 deletions mwdb/web/src/commons/auth/context.jsx

This file was deleted.

6 changes: 6 additions & 0 deletions mwdb/web/src/commons/auth/context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AuthContextValues } from "@mwdb-web/types/types";
import React from "react";

export const AuthContext = React.createContext<AuthContextValues>(
{} as AuthContextValues
);
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { AuthContext } from "./context";
export { AuthProvider, localStorageAuthKey } from "./provider";
export { Capability, capabilitiesList } from "./capabilities";
export { capabilitiesList } from "./capabilities";
Loading

0 comments on commit 6adbe5d

Please sign in to comment.