diff --git a/ui/src/pages/providers/ProviderForm/ProviderForm.test.tsx b/ui/src/pages/providers/ProviderForm/ProviderForm.test.tsx new file mode 100644 index 000000000..ca46b2f07 --- /dev/null +++ b/ui/src/pages/providers/ProviderForm/ProviderForm.test.tsx @@ -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( + + initialValues={initialValues} + onSubmit={onSubmit} + > + {(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( + initialValues={initialValues} onSubmit={vi.fn()}> + {(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( + initialValues={initialValues} onSubmit={vi.fn()}> + {(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( + initialValues={initialValues} onSubmit={vi.fn()}> + {(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( + initialValues={initialValues} onSubmit={vi.fn()}> + {(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", () => { + renderComponent( + initialValues={initialValues} onSubmit={vi.fn()}> + {(formik) => } + , + ); + expect(screen.getByRole("textbox", { name: Label.MAPPER })).toBeDisabled(); +}); diff --git a/ui/src/pages/providers/ProviderForm/ProviderForm.tsx b/ui/src/pages/providers/ProviderForm/ProviderForm.tsx index 6bbf1e04a..66f200303 100644 --- a/ui/src/pages/providers/ProviderForm/ProviderForm.tsx +++ b/ui/src/pages/providers/ProviderForm/ProviderForm.tsx @@ -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 = [ { @@ -120,14 +121,14 @@ const ProviderForm: FC = ({ formik, isEdit = false }) => { {...formik.getFieldProps("provider")} id="provider" options={providerOptions} - label="Provider" + label={Label.PROVIDER} error={formik.touched.provider ? formik.errors.provider : null} /> @@ -135,7 +136,7 @@ const ProviderForm: FC = ({ formik, isEdit = false }) => { {...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} /> @@ -144,7 +145,7 @@ const ProviderForm: FC = ({ 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 } @@ -159,7 +160,7 @@ const ProviderForm: FC = ({ 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{" "} @@ -178,7 +179,7 @@ const ProviderForm: FC = ({ formik, isEdit = false }) => { @@ -188,7 +189,7 @@ const ProviderForm: FC = ({ formik, isEdit = false }) => { The id field of https://graph.microsoft.com/v1.0/me @@ -208,7 +209,7 @@ const ProviderForm: FC = ({ formik, isEdit = false }) => {