Skip to content

Commit

Permalink
Generalize withContext function to accept any Application props
Browse files Browse the repository at this point in the history
  • Loading branch information
jpellizzari committed Nov 17, 2021
1 parent 953367a commit ae231a3
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 43 deletions.
10 changes: 7 additions & 3 deletions ui/components/__tests__/CommitsTable.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as React from "react";
import { unmountComponentAtNode } from "react-dom";
import { act } from "react-dom/test-utils";
import { ListCommitsResponse } from "../../lib/api/applications/applications.pb";
import { withContext, withTheme } from "../../lib/test-utils";
import { createMockClient, withContext, withTheme } from "../../lib/test-utils";
import CommitsTable from "../CommitsTable";

describe("CommitsTable", () => {
Expand Down Expand Up @@ -39,7 +39,9 @@ describe("CommitsTable", () => {
await act(async () => {
const { container: div } = render(
withTheme(
withContext(<CommitsTable app={app} authSuccess={true} />, "/", ovr)
withContext(<CommitsTable app={app} authSuccess={true} />, "/", {
applicationsClient: createMockClient(ovr),
})
),
container
);
Expand All @@ -63,7 +65,9 @@ describe("CommitsTable", () => {
await act(async () => {
render(
withTheme(
withContext(<CommitsTable app={app} authSuccess={true} />, "/", ovr)
withContext(<CommitsTable app={app} authSuccess={true} />, "/", {
applicationsClient: createMockClient(ovr),
})
),
container
);
Expand Down
7 changes: 4 additions & 3 deletions ui/components/__tests__/GithubDeviceAuthModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { unmountComponentAtNode } from "react-dom";
import { act } from "react-dom/test-utils";
import {
ApplicationOverrides,
createMockClient,
withContext,
withTheme,
} from "../../lib/test-utils";
Expand Down Expand Up @@ -45,7 +46,7 @@ describe("GithubDeviceAuthModal", () => {
onSuccess={() => null}
/>,
"/",
ovr
{ applicationsClient: createMockClient(ovr) }
)
),
container
Expand Down Expand Up @@ -73,7 +74,7 @@ describe("GithubDeviceAuthModal", () => {
onSuccess={() => null}
/>,
"/",
ovr
{ applicationsClient: createMockClient(ovr) }
)
),
container
Expand All @@ -100,7 +101,7 @@ describe("GithubDeviceAuthModal", () => {
onSuccess={() => null}
/>,
"/",
ovr
{ applicationsClient: createMockClient(ovr) }
)
),
container
Expand Down
15 changes: 11 additions & 4 deletions ui/contexts/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import _ from "lodash";
import * as React from "react";
import { Applications } from "../lib/api/applications/applications.pb";
import { GitProviderName } from "../lib/types";
import { getProviderToken, storeProviderToken } from "../lib/utils";
import {
getProviderToken,
notifySuccess,
storeProviderToken,
} from "../lib/utils";

type AppState = {
error: null | { fatal: boolean; message: string; detail?: string };
Expand All @@ -26,17 +30,19 @@ export type AppContextType = {
linkResolver: LinkResolver;
getProviderToken: typeof getProviderToken;
storeProviderToken: typeof storeProviderToken;
notifySuccess: typeof notifySuccess;
};

export const AppContext = React.createContext<AppContextType>(
null as AppContextType
);

export interface Props {
applicationsClient: typeof Applications;
export interface AppProps {
applicationsClient?: typeof Applications;
linkResolver?: LinkResolver;
children?: any;
renderFooter?: boolean;
notifySuccess?: typeof notifySuccess;
}

// Due to the way the grpc-gateway typescript client is generated,
Expand Down Expand Up @@ -67,7 +73,7 @@ function wrapClient<T>(client: any, tokenGetter: () => string): T {
export default function AppContextProvider({
applicationsClient,
...props
}: Props) {
}: AppProps) {
const [appState, setAppState] = React.useState({
error: null,
});
Expand Down Expand Up @@ -97,6 +103,7 @@ export default function AppContextProvider({
linkResolver: props.linkResolver || defaultLinkResolver,
getProviderToken,
storeProviderToken,
notifySuccess: props.notifySuccess || notifySuccess,
settings: {
renderFooter: props.renderFooter,
},
Expand Down
14 changes: 11 additions & 3 deletions ui/hooks/__tests__/applications.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { render, screen } from "@testing-library/react";
import _ from "lodash";
import * as React from "react";
import { Application } from "../../lib/api/applications/applications.pb";
import { withContext } from "../../lib/test-utils";
import { createMockClient, withContext } from "../../lib/test-utils";
import useApplications from "../applications";

describe("useApplications", () => {
Expand Down Expand Up @@ -42,7 +42,11 @@ describe("useApplications", () => {
);
};

render(withContext(TestComponent, `/`, mockResponses));
render(
withContext(TestComponent, `/`, {
applicationsClient: createMockClient(mockResponses),
})
);

expect((await screen.findByTestId(name)).textContent).toEqual(name);
});
Expand All @@ -63,7 +67,11 @@ describe("useApplications", () => {
return <p data-testid="url">{app.url}</p>;
};

render(withContext(TestComponent, `/`, mockResponses));
render(
withContext(TestComponent, `/`, {
applicationsClient: createMockClient(mockResponses),
})
);

expect((await screen.findByTestId("url")).textContent).toEqual(url);
});
Expand Down
14 changes: 11 additions & 3 deletions ui/hooks/__tests__/auth.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { render, screen } from "@testing-library/react";
import * as React from "react";
import { withContext } from "../../lib/test-utils";
import { createMockClient, withContext } from "../../lib/test-utils";
import useAuth from "../auth";

describe("useAuth", () => {
Expand Down Expand Up @@ -33,7 +33,11 @@ describe("useAuth", () => {

return <div data-testid={id}>{userCode}</div>;
};
render(withContext(TestComponent, `/`, ovr));
render(
withContext(TestComponent, `/`, {
applicationsClient: createMockClient(ovr),
})
);
expect((await screen.findByTestId(id)).textContent).toEqual(userCode);
});
it("returns the github device auth status", async () => {
Expand All @@ -60,7 +64,11 @@ describe("useAuth", () => {

return <div data-testid={id}>{accessToken}</div>;
};
render(withContext(TestComponent, `/`, ovr));
render(
withContext(TestComponent, `/`, {
applicationsClient: createMockClient(ovr),
})
);
expect((await screen.findByTestId(id)).textContent).toEqual(accessToken);
});
});
25 changes: 12 additions & 13 deletions ui/lib/test-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import _ from "lodash";
import * as React from "react";
import { Router } from "react-router-dom";
import { ThemeProvider } from "styled-components";
import AppContextProvider from "../contexts/AppContext";
import AppContextProvider, { AppProps } from "../contexts/AppContext";
import {
Applications,
GetApplicationRequest,
Expand All @@ -25,6 +25,7 @@ import {
SyncApplicationResponse,
} from "./api/applications/applications.pb";
import theme, { muiTheme } from "./theme";
import { RequestError } from "./types";

export type ApplicationOverrides = {
ListApplications?: (req: ListApplicationsRequest) => ListApplicationsResponse;
Expand All @@ -45,13 +46,18 @@ export type ApplicationOverrides = {

// Don't make the user wire up all the promise stuff to be interface-compliant
export const createMockClient = (
ovr: ApplicationOverrides
ovr: ApplicationOverrides,
error?: RequestError
): typeof Applications => {
const promisified = _.reduce(
ovr,
(result, handlerFn, method) => {
result[method] = (req) =>
new Promise((accept) => accept(handlerFn(req) as any));
result[method] = (req) => {
if (error) {
return new Promise((_, reject) => reject(error));
}
return new Promise((accept) => accept(handlerFn(req) as any));
};

return result;
},
Expand All @@ -69,21 +75,14 @@ export function withTheme(element) {
);
}

export function withContext(
TestComponent,
url: string,
appOverrides?: ApplicationOverrides
) {
export function withContext(TestComponent, url: string, ctxProps: AppProps) {
const history = createMemoryHistory();
history.push(url);

const isElement = React.isValidElement(TestComponent);
return (
<Router history={history}>
<AppContextProvider
renderFooter
applicationsClient={createMockClient(appOverrides) as any}
>
<AppContextProvider renderFooter {...ctxProps}>
{isElement ? TestComponent : <TestComponent />}
</AppContextProvider>
</Router>
Expand Down
14 changes: 8 additions & 6 deletions ui/pages/ApplicationDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ import {
} from "../lib/api/applications/applications.pb";
import { getChildren } from "../lib/graph";
import { PageRoute } from "../lib/types";
import { notifySuccess } from "../lib/utils";

type Props = {
className?: string;
name: string;
};

function ApplicationDetail({ className, name }: Props) {
const { applicationsClient, linkResolver } = React.useContext(AppContext);
const { applicationsClient, linkResolver, notifySuccess } =
React.useContext(AppContext);
const [authSuccess, setAuthSuccess] = React.useState(false);
const [githubAuthModalOpen, setGithubAuthModalOpen] = React.useState(false);
const [removeAppModalOpen, setRemoveAppModalOpen] = React.useState(false);
Expand Down Expand Up @@ -76,7 +76,9 @@ function ApplicationDetail({ className, name }: Props) {
}, [removeRes]);

React.useEffect(() => {
if (syncRes) notifySuccess("App Sync Successful");
if (syncRes) {
notifySuccess("App Sync Successful");
}
}, [syncRes]);

if (error) {
Expand Down Expand Up @@ -133,11 +135,11 @@ function ApplicationDetail({ className, name }: Props) {
</Flex>
}
>
{syncError || error ? (
{syncError ? (
<Alert
severity="error"
title="Error fetching Application"
message={error.message}
title="Error syncing Application"
message={syncError.message}
/>
) : (
authSuccess && (
Expand Down

0 comments on commit ae231a3

Please sign in to comment.