Skip to content

Commit

Permalink
chore(tests): add provider form tests
Browse files Browse the repository at this point in the history
  • Loading branch information
huwshimi committed Dec 4, 2024
1 parent a2b87df commit 63a5691
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 18 deletions.
188 changes: 188 additions & 0 deletions ui/src/pages/providers/ProviderForm/ProviderForm.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { screen } from "@testing-library/dom";
import { faker } from "@faker-js/faker";
import userEvent from "@testing-library/user-event";
import { Formik } from "formik";
import MockAdapter from "axios-mock-adapter";

import { axiosInstance } from "api/axios";
import { renderComponent } from "test/utils";

import ProviderForm from "./ProviderForm";
import { ProviderFormTypes } from "./ProviderForm";
import { Label } from "./types";

const mock = new MockAdapter(axiosInstance);

const initialValues = {
id: "",
client_id: "",
client_secret: "",
auth_url: "",
issuer_url: "",
token_url: "",
subject_source: "userinfo",
microsoft_tenant: "",
provider: "",
mapper_url: "",
scope: "",
apple_team_id: "",
apple_private_key_id: "",
apple_private_key: "",
requested_claims: "",
} as const;

beforeEach(() => {
mock.reset();
});

test("submits field data", async () => {
const values = {
provider: "auth0",
id: faker.word.sample(),
client_id: faker.word.sample(),
client_secret: faker.word.sample(),
scope: faker.word.sample(),
requested_claims: faker.word.sample(),
mapper_url: faker.word.sample(),
};
const onSubmit = vi.fn();
renderComponent(
<Formik<ProviderFormTypes>
initialValues={initialValues}
onSubmit={onSubmit}
>
{(formik) => (
<>
<ProviderForm formik={formik} />
<button onClick={() => void formik.submitForm()}>Submit</button>
</>
)}
</Formik>,
);
await userEvent.selectOptions(
screen.getByRole("combobox", { name: Label.PROVIDER }),
values.provider,
);
await userEvent.type(
screen.getByRole("textbox", { name: Label.NAME }),
values.id,
);
await userEvent.type(
screen.getByRole("textbox", { name: Label.CLIENT_ID }),
values.client_id,
);
await userEvent.type(
screen.getByRole("textbox", { name: Label.CLIENT_SECRET }),
values.client_secret,
);
await userEvent.type(
screen.getByRole("textbox", { name: Label.SCOPES }),
values.scope,
);
await userEvent.type(
screen.getByRole("textbox", { name: Label.REQUESTED_CLAIMS }),
values.requested_claims,
);
await userEvent.type(
screen.getByRole("textbox", { name: Label.MAPPER }),
values.mapper_url,
);
await userEvent.click(screen.getByRole("button"));
expect(onSubmit.mock.calls[0][0]).toMatchObject(values);
});

test("displays fields for apple form", async () => {
renderComponent(
<Formik<ProviderFormTypes> initialValues={initialValues} onSubmit={vi.fn()}>
{(formik) => <ProviderForm formik={formik} />}
</Formik>,
);
await userEvent.selectOptions(
screen.getByRole("combobox", { name: Label.PROVIDER }),
"apple",
);
expect(
screen.queryByRole("textbox", { name: Label.CLIENT_SECRET }),
).not.toBeInTheDocument();
expect(
screen.getByRole("textbox", { name: Label.PRIVATE_KEY }),
).toBeInTheDocument();
expect(
screen.getByRole("textbox", { name: Label.DEVELOPER_TEAM_ID }),
).toBeInTheDocument();
expect(
screen.getByRole("textbox", { name: Label.PRIVATE_KEY_ID }),
).toBeInTheDocument();
});

test("displays fields for microsoft form", async () => {
renderComponent(
<Formik<ProviderFormTypes> initialValues={initialValues} onSubmit={vi.fn()}>
{(formik) => <ProviderForm formik={formik} />}
</Formik>,
);
await userEvent.selectOptions(
screen.getByRole("combobox", { name: Label.PROVIDER }),
"microsoft",
);
expect(
screen.getByRole("textbox", { name: Label.TENANT }),
).toBeInTheDocument();
expect(
screen.getByRole("radio", { name: Label.USERINFO }),
).toBeInTheDocument();
expect(screen.getByRole("radio", { name: Label.ME })).toBeInTheDocument();
});

test("generic form displays auto discovery fields", async () => {
renderComponent(
<Formik<ProviderFormTypes> initialValues={initialValues} onSubmit={vi.fn()}>
{(formik) => <ProviderForm formik={formik} />}
</Formik>,
);
await userEvent.selectOptions(
screen.getByRole("combobox", { name: Label.PROVIDER }),
"generic",
);
await userEvent.click(screen.getByRole("radio", { name: Label.YES }));
expect(
screen.getByRole("textbox", { name: Label.OIDC_SERVER_URL }),
).toBeInTheDocument();
expect(
screen.queryByRole("textbox", { name: Label.AUTH_URL }),
).not.toBeInTheDocument();
expect(
screen.queryByRole("textbox", { name: Label.TOKEN_URL }),
).not.toBeInTheDocument();
});

test("generic form displays non auto discovery fields", async () => {
renderComponent(
<Formik<ProviderFormTypes> initialValues={initialValues} onSubmit={vi.fn()}>
{(formik) => <ProviderForm formik={formik} />}
</Formik>,
);
await userEvent.selectOptions(
screen.getByRole("combobox", { name: Label.PROVIDER }),
"generic",
);
await userEvent.click(screen.getByRole("radio", { name: Label.NO }));
expect(
screen.queryByRole("textbox", { name: Label.OIDC_SERVER_URL }),
).not.toBeInTheDocument();
expect(
screen.getByRole("textbox", { name: Label.AUTH_URL }),
).toBeInTheDocument();
expect(
screen.getByRole("textbox", { name: Label.TOKEN_URL }),
).toBeInTheDocument();
});

test("disables the mapper URL field when editing", async () => {

Check failure on line 181 in ui/src/pages/providers/ProviderForm/ProviderForm.test.tsx

View workflow job for this annotation

GitHub Actions / Lint (20.x)

Async arrow function has no 'await' expression
renderComponent(
<Formik<ProviderFormTypes> initialValues={initialValues} onSubmit={vi.fn()}>
{(formik) => <ProviderForm isEdit formik={formik} />}
</Formik>,
);
expect(screen.getByRole("textbox", { name: Label.MAPPER })).toBeDisabled();
});
37 changes: 19 additions & 18 deletions ui/src/pages/providers/ProviderForm/ProviderForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FC, useState } from "react";
import { Form, Input, Select, Textarea } from "@canonical/react-components";
import { FormikProps } from "formik";
import { Label } from "./types";

const providerOptions = [
{
Expand Down Expand Up @@ -120,22 +121,22 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
{...formik.getFieldProps("provider")}
id="provider"
options={providerOptions}
label="Provider"
label={Label.PROVIDER}
error={formik.touched.provider ? formik.errors.provider : null}
/>
<Input
{...formik.getFieldProps("id")}
id="id"
type="text"
label="Name"
label={Label.NAME}
error={formik.touched.id ? formik.errors.id : null}
disabled={isEdit}
/>
<Input
{...formik.getFieldProps("client_id")}
id="client_id"
type="text"
label="Client ID"
label={Label.CLIENT_ID}
error={formik.touched.client_id ? formik.errors.client_id : null}
disabled={isEdit}
/>
Expand All @@ -144,7 +145,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
{...formik.getFieldProps("client_secret")}
id="client_secret"
type="text"
label="Client secret"
label={Label.CLIENT_SECRET}
error={
formik.touched.client_secret ? formik.errors.client_secret : null
}
Expand All @@ -159,7 +160,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
{...formik.getFieldProps("microsoft_tenant")}
id="microsoft_tenant"
type="text"
label="Tenant"
label={Label.TENANT}
help={
<>
The Azure AD Tenant to use for authentication. Can either be{" "}
Expand All @@ -178,7 +179,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
<Input
name="subject_source"
type="radio"
label="Userinfo"
label={Label.USERINFO}
help="The subject identifier is taken from sub field of userifo standard endpoint response"
checked={formik.values.subject_source === "userinfo"}
onChange={() =>
Expand All @@ -188,7 +189,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
<Input
name="subject_source"
type="radio"
label="Me"
label={Label.ME}
help={
<>
The <code>id</code> field of https://graph.microsoft.com/v1.0/me
Expand All @@ -208,7 +209,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
<Textarea
{...formik.getFieldProps("apple_private_key")}
id="apple_private_key"
label="Private Key"
label={Label.PRIVATE_KEY}
error={
formik.touched.apple_private_key
? formik.errors.apple_private_key
Expand All @@ -219,7 +220,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
{...formik.getFieldProps("apple_team_id")}
id="apple_team_id"
type="text"
label="Developer Team ID"
label={Label.DEVELOPER_TEAM_ID}
help={
<>
The Apple Developer Team ID can be found at{" "}
Expand All @@ -240,7 +241,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
{...formik.getFieldProps("apple_private_key_id")}
id="apple_private_key_id"
type="text"
label="Private Key ID"
label={Label.PRIVATE_KEY_ID}
error={
formik.touched.apple_private_key_id
? formik.errors.apple_private_key_id
Expand Down Expand Up @@ -269,7 +270,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
<Input
type="radio"
id="discovery_on"
label="Yes"
label={Label.YES}
name="oidc_discovery"
checked={hasAutoDiscovery}
onChange={() => setAutoDiscovery(true)}
Expand All @@ -280,7 +281,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
{...formik.getFieldProps("issuer_url")}
id="issuer_url"
type="text"
label="OIDC server URL"
label={Label.OIDC_SERVER_URL}
error={
formik.touched.issuer_url ? formik.errors.issuer_url : null
}
Expand All @@ -290,7 +291,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
<Input
type="radio"
id="discovery_off"
label="No"
label={Label.NO}
name="oidc_discovery"
checked={!hasAutoDiscovery}
onChange={() => setAutoDiscovery(false)}
Expand All @@ -301,15 +302,15 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
{...formik.getFieldProps("auth_url")}
id="auth_url"
type="text"
label="Auth URL"
label={Label.AUTH_URL}
help="I.e. https://example.org/oauth2/auth"
error={formik.touched.auth_url ? formik.errors.auth_url : null}
/>
<Input
{...formik.getFieldProps("token_url")}
id="token_url"
type="text"
label="Token URL"
label={Label.TOKEN_URL}
help="I.e. https://example.org/oauth2/token"
error={
formik.touched.token_url ? formik.errors.token_url : null
Expand All @@ -326,7 +327,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
{...formik.getFieldProps("scope")}
id="scope"
type="text"
label="Scopes"
label={Label.SCOPES}
help={
<>
Comma seperated list of optional requested permissions. Common
Expand All @@ -341,7 +342,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
{...formik.getFieldProps("requested_claims")}
id="requested_claims"
type="text"
label="Requested claims"
label={Label.REQUESTED_CLAIMS}
error={
formik.touched.requested_claims
? formik.errors.requested_claims
Expand All @@ -352,7 +353,7 @@ const ProviderForm: FC<Props> = ({ formik, isEdit = false }) => {
{...formik.getFieldProps("mapper_url")}
id="mapper_url"
type="text"
label="Mapper"
label={Label.MAPPER}
help="Mapper specifies the JSONNet code snippet which uses the OpenID Connect Provider's data to hydrate the identity's data. Supported file types are .jsonnet"
error={formik.touched.mapper_url ? formik.errors.mapper_url : null}
disabled={isEdit}
Expand Down
20 changes: 20 additions & 0 deletions ui/src/pages/providers/ProviderForm/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export enum Label {
AUTH_URL = "Auth URL",
CLIENT_ID = "Client ID",
CLIENT_SECRET = "Client secret",
DEVELOPER_TEAM_ID = "Developer Team ID",
MAPPER = "Mapper",
ME = "Me",
NAME = "Name",
NO = "No",
OIDC_SERVER_URL = "OIDC server URL",
PRIVATE_KEY = "Private Key",
PRIVATE_KEY_ID = "Private Key ID",
PROVIDER = "Provider",
REQUESTED_CLAIMS = "Requested claims",
SCOPES = "Scopes",
TENANT = "Tenant",
TOKEN_URL = "Token URL",
USERINFO = "Userinfo",
YES = "Yes",
}

0 comments on commit 63a5691

Please sign in to comment.