Skip to content

Commit

Permalink
add test for enabling auth
Browse files Browse the repository at this point in the history
  • Loading branch information
macfarlandian committed Oct 15, 2020
1 parent 22d75df commit 779d8c3
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 38 deletions.
77 changes: 74 additions & 3 deletions spotlight-client/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,84 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =============================================================================

import React from "react";
import { Auth0Provider, useAuth0 } from "@auth0/auth0-react";
import { render } from "@testing-library/react";
import React from "react";
import App from "./App";
import getAuthSettings from "./AuthProvider/getAuthSettings";
import isAuthEnabled from "./utils/isAuthEnabled";

test("does not explode", () => {
const { getByText } = render(<App />);
const { getByRole } = render(<App />);
// seems like a pretty safe bet this word will always be there somewhere!
const websiteName = getByText(/spotlight/i);
const websiteName = getByRole("heading", /spotlight/i);
expect(websiteName).toBeInTheDocument();
});

jest.mock("./AuthProvider/getAuthSettings");
const getAuthSettingsMock = getAuthSettings as jest.MockedFunction<
typeof getAuthSettings
>;

jest.mock("./utils/isAuthEnabled");
const isAuthEnabledMock = isAuthEnabled as jest.MockedFunction<
typeof isAuthEnabled
>;

// Although mocking the Auth0 library is not necessarily a great practice,
// it has a number of side effects (e.g. issuing XHRs, navigating to new URLs)
// that are challenging to handle or even simulate in this test environment,
// so this seemed like the better solution here
jest.mock("@auth0/auth0-react", () => {
return {
Auth0Provider: jest.fn(),
useAuth0: jest.fn(),
};
});

test("require auth", async () => {
// mock the environment configuration to enable auth
const MOCK_DOMAIN = "test.local";
const MOCK_CLIENT_ID = "abcdef";
getAuthSettingsMock.mockReturnValue({
domain: MOCK_DOMAIN,
clientId: MOCK_CLIENT_ID,
});
isAuthEnabledMock.mockReturnValue(true);

// mock the auth0 provider
const PROVIDER_TEST_ID = "Auth0Provider";
(Auth0Provider as jest.Mock).mockImplementation(({ children }) => {
// here we mock just enough to verify that the context provider is being included;
// we can use this as a proxy for the relationship between provider and hook.
return <div data-testid={PROVIDER_TEST_ID}>{children}</div>;
});

// mock the auth0 hook
const mockLoginWithRedirect = jest.fn();
(useAuth0 as jest.Mock).mockReturnValue({
// this isn't the full hook API, just what's relevant to this test
isAuthenticated: false,
loginWithRedirect: mockLoginWithRedirect,
});

// now we test
const { queryByRole, getByTestId } = render(<App />);

// verify that we have included an Auth0Provider
expect(getByTestId(PROVIDER_TEST_ID)).toBeInTheDocument();

// verify that we supplied that provider with
// the settings designated by our mock environment
expect((Auth0Provider as jest.Mock).mock.calls[0][0]).toEqual(
expect.objectContaining({ domain: MOCK_DOMAIN, clientId: MOCK_CLIENT_ID })
);

// verify that we have initiated an Auth0 login
expect(mockLoginWithRedirect.mock.calls.length).toBe(1);

// application contents should not have been rendered unauthed
expect(queryByRole("heading", /spotlight/i)).toBeNull();

jest.restoreAllMocks();
});
16 changes: 11 additions & 5 deletions spotlight-client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,20 @@
// =============================================================================

import React from "react";
import AuthProvider from "./AuthProvider";
import AuthWall from "./AuthWall";

const App: React.FC = () => {
return (
<div>
<header>
<h1>Spotlight</h1>
</header>
</div>
<AuthProvider>
<AuthWall>
<div>
<header>
<h1>Spotlight</h1>
</header>
</div>
</AuthWall>
</AuthProvider>
);
};

Expand Down
25 changes: 5 additions & 20 deletions spotlight-client/src/AuthProvider/AuthProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,20 @@
import { Auth0Provider } from "@auth0/auth0-react";
import React from "react";
import isAuthEnabled from "../utils/isAuthEnabled";

type Auth0Settings = {
domain: string;
clientId: string;
};

const SHOULD_PROVIDE_AUTH = isAuthEnabled();

let AUTH_SETTINGS: Auth0Settings;

// NOTE: there is no production auth requirement!
if (process.env.REACT_APP_AUTH_ENV === "development") {
AUTH_SETTINGS = {
domain: "recidiviz-spotlight-staging.us.auth0.com",
clientId: "ID9plpd8j4vaUin9rPTGxWlJoknSkDX1",
};
}
import getAuthSettings from "./getAuthSettings";

/**
* If auth is enabled for the current environment, wraps its children
* in an Auth0Provider to enable the Auth0 React context.
* If auth is disabled, renders its children unwrapped.
*/
const AuthProvider: React.FC = ({ children }) => {
if (SHOULD_PROVIDE_AUTH && AUTH_SETTINGS) {
const authSettings = getAuthSettings();
if (isAuthEnabled() && authSettings) {
return (
<Auth0Provider
domain={AUTH_SETTINGS.domain}
clientId={AUTH_SETTINGS.clientId}
domain={authSettings.domain}
clientId={authSettings.clientId}
redirectUri={window.location.href}
>
{children}
Expand Down
38 changes: 38 additions & 0 deletions spotlight-client/src/AuthProvider/getAuthSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Recidiviz - a data platform for criminal justice reform
// Copyright (C) 2020 Recidiviz, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =============================================================================

type Auth0Settings = {
domain: string;
clientId: string;
};

let AUTH_SETTINGS: Auth0Settings | undefined;

// NOTE: there is no production auth requirement!
if (process.env.REACT_APP_AUTH_ENV === "development") {
AUTH_SETTINGS = {
domain: "recidiviz-spotlight-staging.us.auth0.com",
clientId: "ID9plpd8j4vaUin9rPTGxWlJoknSkDX1",
};
}

/**
* Returns the auth settings configured for the current environment, if any.
*/
export default function getAuthSettings(): typeof AUTH_SETTINGS {
return AUTH_SETTINGS;
}
4 changes: 1 addition & 3 deletions spotlight-client/src/AuthWall/AuthWall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import { useAuth0 } from "@auth0/auth0-react";
import React from "react";
import isAuthEnabled from "../utils/isAuthEnabled";

const SHOULD_CHECK_AUTH = isAuthEnabled();

/**
* If auth is enabled in the current environment, wraps its children
* in the AuthWall to require authentication. If auth is disabled,
Expand All @@ -29,7 +27,7 @@ const SHOULD_CHECK_AUTH = isAuthEnabled();
const AuthWallContainer: React.FC = ({ children }) => {
// because AuthWall relies on hooks, we don't want to render it at all
// if auth is not enabled in this environment
if (SHOULD_CHECK_AUTH) {
if (isAuthEnabled()) {
return <AuthWall>{children}</AuthWall>;
}
return <>{children}</>;
Expand Down
8 changes: 1 addition & 7 deletions spotlight-client/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,10 @@ import "react-app-polyfill/stable";
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import AuthProvider from "./AuthProvider";
import AuthWall from "./AuthWall";

ReactDOM.render(
<React.StrictMode>
<AuthProvider>
<AuthWall>
<App />
</AuthWall>
</AuthProvider>
<App />
</React.StrictMode>,
document.getElementById("root")
);

0 comments on commit 779d8c3

Please sign in to comment.