mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-08 06:25:45 +01:00
Split frontend code by routes (#1955)
Split large frontend components into own bundles. This way we decrease loading times and load the bundles right as they are used. We replace SystemJS with our own implementation to load the lazy modules right as there are required. Co-authored-by: Sebastian Sdorra <sebastian.sdorra@cloudogu.com>
This commit is contained in:
@@ -23,20 +23,20 @@
|
||||
*/
|
||||
|
||||
import { LegacyContext, useLegacyContext } from "./LegacyContext";
|
||||
import * as React from "react";
|
||||
import { FC } from "react";
|
||||
import { renderHook } from "@testing-library/react-hooks";
|
||||
import * as React from "react";
|
||||
import ApiProvider from "./ApiProvider";
|
||||
import { useQueryClient } from "react-query";
|
||||
|
||||
describe("ApiProvider tests", () => {
|
||||
const createWrapper = (context?: LegacyContext): FC => {
|
||||
const createWrapper = (context: LegacyContext): FC => {
|
||||
return ({ children }) => <ApiProvider {...context}>{children}</ApiProvider>;
|
||||
};
|
||||
|
||||
it("should register QueryClient", () => {
|
||||
const { result } = renderHook(() => useQueryClient(), {
|
||||
wrapper: createWrapper(),
|
||||
wrapper: createWrapper({ initialize: () => null })
|
||||
});
|
||||
expect(result.current).toBeDefined();
|
||||
});
|
||||
@@ -48,7 +48,7 @@ describe("ApiProvider tests", () => {
|
||||
};
|
||||
|
||||
const { result } = renderHook(() => useLegacyContext(), {
|
||||
wrapper: createWrapper({ onIndexFetched }),
|
||||
wrapper: createWrapper({ onIndexFetched, initialize: () => null })
|
||||
});
|
||||
|
||||
if (result.current?.onIndexFetched) {
|
||||
|
||||
@@ -31,9 +31,9 @@ import { reset } from "./reset";
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: false,
|
||||
},
|
||||
},
|
||||
retry: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
type Props = LegacyContext & {
|
||||
|
||||
@@ -24,12 +24,17 @@
|
||||
|
||||
import { IndexResources, Me } from "@scm-manager/ui-types";
|
||||
import React, { createContext, FC, useContext } from "react";
|
||||
import { QueryClient, useQueryClient } from "react-query";
|
||||
|
||||
export type LegacyContext = {
|
||||
export type BaseContext = {
|
||||
onIndexFetched?: (index: IndexResources) => void;
|
||||
onMeFetched?: (me: Me) => void;
|
||||
};
|
||||
|
||||
export type LegacyContext = BaseContext & {
|
||||
initialize: () => void;
|
||||
};
|
||||
|
||||
const Context = createContext<LegacyContext | undefined>(undefined);
|
||||
|
||||
export const useLegacyContext = () => {
|
||||
@@ -40,6 +45,31 @@ export const useLegacyContext = () => {
|
||||
return context;
|
||||
};
|
||||
|
||||
export const LegacyContextProvider: FC<LegacyContext> = ({ onIndexFetched, onMeFetched, children }) => (
|
||||
<Context.Provider value={{ onIndexFetched, onMeFetched }}>{children}</Context.Provider>
|
||||
);
|
||||
const createInitialContext = (queryClient: QueryClient, base: BaseContext): LegacyContext => {
|
||||
const ctx = {
|
||||
...base,
|
||||
initialize: () => {
|
||||
if (ctx.onIndexFetched) {
|
||||
const index: IndexResources | undefined = queryClient.getQueryData("index");
|
||||
if (index) {
|
||||
ctx.onIndexFetched(index);
|
||||
}
|
||||
}
|
||||
if (ctx.onMeFetched) {
|
||||
const me: Me | undefined = queryClient.getQueryData("me");
|
||||
if (me) {
|
||||
ctx.onMeFetched(me);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return ctx;
|
||||
};
|
||||
|
||||
export const LegacyContextProvider: FC<BaseContext> = ({ onIndexFetched, onMeFetched, children }) => {
|
||||
const queryClient = useQueryClient();
|
||||
const ctx = createInitialContext(queryClient, { onIndexFetched, onMeFetched });
|
||||
|
||||
return <Context.Provider value={ctx}>{children}</Context.Provider>;
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ describe("Test base api hooks", () => {
|
||||
describe("useIndex tests", () => {
|
||||
fetchMock.get("/api/v2/", {
|
||||
version: "x.y.z",
|
||||
_links: {},
|
||||
_links: {}
|
||||
});
|
||||
|
||||
it("should return index", async () => {
|
||||
@@ -48,9 +48,10 @@ describe("Test base api hooks", () => {
|
||||
it("should call onIndexFetched of LegacyContext", async () => {
|
||||
let index: IndexResources;
|
||||
const context: LegacyContext = {
|
||||
onIndexFetched: (fetchedIndex) => {
|
||||
onIndexFetched: fetchedIndex => {
|
||||
index = fetchedIndex;
|
||||
},
|
||||
initialize: () => null
|
||||
};
|
||||
const { result, waitFor } = renderHook(() => useIndex(), { wrapper: createWrapper(context) });
|
||||
await waitFor(() => {
|
||||
@@ -70,10 +71,10 @@ describe("Test base api hooks", () => {
|
||||
const queryClient = new QueryClient();
|
||||
queryClient.setQueryData("index", {
|
||||
version: "x.y.z",
|
||||
_links: {},
|
||||
_links: {}
|
||||
});
|
||||
const { result } = renderHook(() => useIndexLink("spaceships"), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
expect(result.current).toBeUndefined();
|
||||
});
|
||||
@@ -86,17 +87,17 @@ describe("Test base api hooks", () => {
|
||||
spaceships: [
|
||||
{
|
||||
name: "heartOfGold",
|
||||
href: "/spaceships/heartOfGold",
|
||||
href: "/spaceships/heartOfGold"
|
||||
},
|
||||
{
|
||||
name: "razorCrest",
|
||||
href: "/spaceships/razorCrest",
|
||||
},
|
||||
],
|
||||
},
|
||||
href: "/spaceships/razorCrest"
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
const { result } = renderHook(() => useIndexLink("spaceships"), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
expect(result.current).toBeUndefined();
|
||||
});
|
||||
@@ -107,12 +108,12 @@ describe("Test base api hooks", () => {
|
||||
version: "x.y.z",
|
||||
_links: {
|
||||
spaceships: {
|
||||
href: "/api/spaceships",
|
||||
},
|
||||
},
|
||||
href: "/api/spaceships"
|
||||
}
|
||||
}
|
||||
});
|
||||
const { result } = renderHook(() => useIndexLink("spaceships"), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
expect(result.current).toBe("/api/spaceships");
|
||||
});
|
||||
@@ -130,12 +131,12 @@ describe("Test base api hooks", () => {
|
||||
version: "x.y.z",
|
||||
_links: {
|
||||
spaceships: {
|
||||
href: "/api/spaceships",
|
||||
},
|
||||
},
|
||||
href: "/api/spaceships"
|
||||
}
|
||||
}
|
||||
});
|
||||
const { result } = renderHook(() => useIndexLinks(), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
expect((result.current!.spaceships as Link).href).toBe("/api/spaceships");
|
||||
});
|
||||
@@ -150,10 +151,10 @@ describe("Test base api hooks", () => {
|
||||
it("should return version", () => {
|
||||
const queryClient = new QueryClient();
|
||||
queryClient.setQueryData("index", {
|
||||
version: "x.y.z",
|
||||
version: "x.y.z"
|
||||
});
|
||||
const { result } = renderHook(() => useVersion(), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
expect(result.current).toBe("x.y.z");
|
||||
});
|
||||
@@ -164,10 +165,10 @@ describe("Test base api hooks", () => {
|
||||
const queryClient = new QueryClient();
|
||||
queryClient.setQueryData("index", {
|
||||
version: "x.y.z",
|
||||
_links: {},
|
||||
_links: {}
|
||||
});
|
||||
const { result } = renderHook(() => useRequiredIndexLink("spaceships"), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
expect(result.error).toBeDefined();
|
||||
});
|
||||
@@ -178,12 +179,12 @@ describe("Test base api hooks", () => {
|
||||
version: "x.y.z",
|
||||
_links: {
|
||||
spaceships: {
|
||||
href: "/api/spaceships",
|
||||
},
|
||||
},
|
||||
href: "/api/spaceships"
|
||||
}
|
||||
}
|
||||
});
|
||||
const { result } = renderHook(() => useRequiredIndexLink("spaceships"), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
expect(result.current).toBe("/api/spaceships");
|
||||
});
|
||||
@@ -196,19 +197,19 @@ describe("Test base api hooks", () => {
|
||||
version: "x.y.z",
|
||||
_links: {
|
||||
spaceships: {
|
||||
href: "/spaceships",
|
||||
},
|
||||
},
|
||||
href: "/spaceships"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const spaceship = {
|
||||
name: "heartOfGold",
|
||||
name: "heartOfGold"
|
||||
};
|
||||
|
||||
fetchMock.get("/api/v2/spaceships", spaceship);
|
||||
|
||||
const { result, waitFor } = renderHook(() => useIndexJsonResource<typeof spaceship>("spaceships"), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
@@ -223,11 +224,11 @@ describe("Test base api hooks", () => {
|
||||
const queryClient = new QueryClient();
|
||||
queryClient.setQueryData("index", {
|
||||
version: "x.y.z",
|
||||
_links: {},
|
||||
_links: {}
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => useIndexJsonResource<{}>("spaceships"), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
|
||||
expect(result.current.isLoading).toBe(false);
|
||||
|
||||
@@ -66,3 +66,5 @@ export * from "./compare";
|
||||
|
||||
export { default as ApiProvider } from "./ApiProvider";
|
||||
export * from "./ApiProvider";
|
||||
|
||||
export * from "./LegacyContext";
|
||||
|
||||
@@ -37,7 +37,7 @@ describe("Test login hooks", () => {
|
||||
name: "tricia",
|
||||
displayName: "Tricia",
|
||||
groups: [],
|
||||
_links: {},
|
||||
_links: {}
|
||||
};
|
||||
|
||||
describe("useMe tests", () => {
|
||||
@@ -45,7 +45,7 @@ describe("Test login hooks", () => {
|
||||
name: "tricia",
|
||||
displayName: "Tricia",
|
||||
groups: [],
|
||||
_links: {},
|
||||
_links: {}
|
||||
});
|
||||
|
||||
it("should return me", async () => {
|
||||
@@ -65,9 +65,10 @@ describe("Test login hooks", () => {
|
||||
|
||||
let me: Me;
|
||||
const context: LegacyContext = {
|
||||
onMeFetched: (fetchedMe) => {
|
||||
onMeFetched: fetchedMe => {
|
||||
me = fetchedMe;
|
||||
},
|
||||
initialize: () => null
|
||||
};
|
||||
|
||||
const { result, waitFor } = renderHook(() => useMe(), { wrapper: createWrapper(context, queryClient) });
|
||||
@@ -130,7 +131,7 @@ describe("Test login hooks", () => {
|
||||
name: "_anonymous",
|
||||
displayName: "Anonymous",
|
||||
groups: [],
|
||||
_links: {},
|
||||
_links: {}
|
||||
});
|
||||
const { result } = renderHook(() => useSubject(), { wrapper: createWrapper(undefined, queryClient) });
|
||||
|
||||
@@ -158,8 +159,8 @@ describe("Test login hooks", () => {
|
||||
cookie: true,
|
||||
grant_type: "password",
|
||||
username: "tricia",
|
||||
password: "hitchhikersSecret!",
|
||||
},
|
||||
password: "hitchhikersSecret!"
|
||||
}
|
||||
});
|
||||
|
||||
// required because we invalidate the whole cache and react-query refetches the index
|
||||
@@ -167,13 +168,13 @@ describe("Test login hooks", () => {
|
||||
version: "x.y.z",
|
||||
_links: {
|
||||
login: {
|
||||
href: "/second/login",
|
||||
},
|
||||
},
|
||||
href: "/second/login"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const { result, waitForNextUpdate } = renderHook(() => useLogin(), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
const { login } = result.current;
|
||||
expect(login).toBeDefined();
|
||||
@@ -194,7 +195,7 @@ describe("Test login hooks", () => {
|
||||
queryClient.setQueryData("me", tricia);
|
||||
|
||||
const { result } = renderHook(() => useLogin(), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
|
||||
expect(result.current.login).toBeUndefined();
|
||||
@@ -209,7 +210,7 @@ describe("Test login hooks", () => {
|
||||
fetchMock.deleteOnce("/api/v2/logout", {});
|
||||
|
||||
const { result, waitForNextUpdate } = renderHook(() => useLogout(), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
const { logout } = result.current;
|
||||
expect(logout).toBeDefined();
|
||||
@@ -229,7 +230,7 @@ describe("Test login hooks", () => {
|
||||
setEmptyIndex(queryClient);
|
||||
|
||||
const { result } = renderHook(() => useLogout(), {
|
||||
wrapper: createWrapper(undefined, queryClient),
|
||||
wrapper: createWrapper(undefined, queryClient)
|
||||
});
|
||||
|
||||
const { logout } = result.current;
|
||||
|
||||
Reference in New Issue
Block a user