Skip to content

Commit

Permalink
FI-3598: Add title to auth inputs and consolidate input modes (#591)
Browse files Browse the repository at this point in the history
* add card to auth input mode

* move auth files to auth folder

* consolidate auth and access
  • Loading branch information
AlyssaWang authored Jan 17, 2025
1 parent 4620ff3 commit 78f4f7e
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 188 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FC } from 'react';
import { InputOption, TestInput } from '~/models/testSuiteModels';
import InputCombobox from './InputCombobox';
import InputCombobox from '~/components/InputsModal/InputCombobox';

export interface InputAccessProps {
input: TestInput;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,28 @@ import { Card, CardContent, InputLabel, List, ListItem } from '@mui/material';
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { Auth, TestInput } from '~/models/testSuiteModels';
import { AuthType, getAccessFields } from '~/components/InputsModal/AuthSettings';
import {
AuthType,
getAccessFields,
getAuthFields,
} from '~/components/InputsModal/Auth/AuthSettings';
import AuthTypeSelector from '~/components/InputsModal/Auth/AuthTypeSelector';
import FieldLabel from '~/components/InputsModal/FieldLabel';
import InputFields from '~/components/InputsModal/InputFields';
import useStyles from './styles';
import AuthTypeSelector from './AuthTypeSelector';
import useStyles from '../styles';

export interface InputAccessProps {
export interface InputAuthProps {
mode: 'access' | 'auth';
input: TestInput;
index: number;
inputsMap: Map<string, unknown>;
setInputsMap: (map: Map<string, unknown>, edited?: boolean) => void;
}

const InputAccess: FC<InputAccessProps> = ({ input, index, inputsMap, setInputsMap }) => {
const InputAuth: FC<InputAuthProps> = ({ mode, input, index, inputsMap, setInputsMap }) => {
const { classes } = useStyles();
const [accessValues, setAccessValues] = React.useState<Map<string, unknown>>(new Map());
const [accessValuesPopulated, setAccessValuesPopulated] = React.useState<boolean>(false);
const [authValues, setAuthValues] = React.useState<Map<string, unknown>>(new Map());
const [authValuesPopulated, setAuthValuesPopulated] = React.useState<boolean>(false);

// Default auth type settings
const authComponent = input.options?.components?.find(
Expand All @@ -35,16 +40,21 @@ const InputAccess: FC<InputAccessProps> = ({ input, index, inputsMap, setInputsM
(authComponent?.default || firstListOption || 'public') as string,
);

const [accessFields, setAccessFields] = React.useState<TestInput[]>(
getAccessFields(authType as AuthType, accessValues, input.options?.components || []),
);
// Set fields depending on mode
let fields: TestInput[] = [];
if (mode === 'access') {
fields = getAccessFields(authType as AuthType, authValues, input.options?.components || []);
} else if (mode === 'auth') {
fields = getAuthFields(authType as AuthType, authValues, input.options?.components || []);
}
const [authFields, setAuthFields] = React.useState<TestInput[]>(fields);

useEffect(() => {
// Set defaults on radio buttons
// This is necessary because radio buttons with no preset defaults will still cause
// missing input errors
setAccessFields(
accessFields.map((field) => {
setAuthFields(
authFields.map((field) => {
if (
field.type === 'radio' &&
!field.default &&
Expand All @@ -59,38 +69,47 @@ const InputAccess: FC<InputAccessProps> = ({ input, index, inputsMap, setInputsM

const combinedStartingValues = getStartingValues();

// Populate accessValues on mount
accessValues.set('auth_type', authType);
accessFields.forEach((field: TestInput) => {
accessValues.set(field.name, combinedStartingValues[field.name as keyof Auth] || '');
// Populate authValues on mount
authValues.set('auth_type', authType);
authFields.forEach((field: TestInput) => {
authValues.set(field.name, combinedStartingValues[field.name as keyof Auth] || '');
});
setAccessValuesPopulated(true);
setAuthValuesPopulated(true);

// Trigger change on mount for default values
const accessValuesCopy = new Map(accessValues);
setAccessValues(accessValuesCopy);
const authValuesCopy = new Map(authValues);
setAuthValues(authValuesCopy);
}, []);

useEffect(() => {
// Recalculate hidden fields
setAccessFields(
getAccessFields(authType as AuthType, accessValues, input.options?.components || []),
);
if (mode === 'access') {
setAuthFields(
getAccessFields(authType as AuthType, authValues, input.options?.components || []),
);
} else if (mode === 'auth') {
setAuthFields(
getAuthFields(authType as AuthType, authValues, input.options?.components || []),
);
}

// Update inputsMap while maintaining hidden values
if (accessValuesPopulated) {
const combinedStartingValues = getStartingValues();
const accessValuesObject = Object.fromEntries(accessValues) as Auth;
const combinedValues = { ...combinedStartingValues, ...accessValuesObject };
const stringifiedAccessValues = JSON.stringify(combinedValues);
inputsMap.set(input.name, stringifiedAccessValues);
if (authValuesPopulated) {
let stringifiedValues = JSON.stringify(Object.fromEntries(authValues));
if (mode === 'access') {
const combinedStartingValues = getStartingValues();
const accessValuesObject = Object.fromEntries(authValues) as Auth;
const combinedValues = { ...combinedStartingValues, ...accessValuesObject };
stringifiedValues = JSON.stringify(combinedValues);
}
inputsMap.set(input.name, stringifiedValues);
setInputsMap(new Map(inputsMap));
}
}, [accessValues]);
}, [authValues]);

const getStartingValues = () => {
// Pre-populate values from AuthFields, input, and inputsMap in order of precedence
const fieldDefaultValues = accessFields.reduce(
const fieldDefaultValues = authFields.reduce(
(acc, field) => ({ ...acc, [field.name]: field.default }),
{},
) as Auth;
Expand All @@ -101,6 +120,7 @@ const InputAccess: FC<InputAccessProps> = ({ input, index, inputsMap, setInputsM
const inputsMapValues = inputsMap.get(input.name)
? (JSON.parse(inputsMap.get(input.name) as string) as Auth)
: {};

return {
...fieldDefaultValues,
...inputDefaultValues,
Expand All @@ -111,7 +131,7 @@ const InputAccess: FC<InputAccessProps> = ({ input, index, inputsMap, setInputsM

const updateAuthType = (map: Map<string, unknown>) => {
setAuthType(map.get('auth_type') as string);
setAccessValues(map);
setAuthValues(map);
};

return (
Expand All @@ -134,20 +154,16 @@ const InputAccess: FC<InputAccessProps> = ({ input, index, inputsMap, setInputsM
<AuthTypeSelector
input={input}
index={index}
inputsMap={accessValues}
inputsMap={authValues}
setInputsMap={updateAuthType}
key={`input-${index}`}
/>
</List>
<InputFields
inputs={accessFields}
inputsMap={accessValues}
setInputsMap={setAccessValues}
/>
<InputFields inputs={authFields} inputsMap={authValues} setInputsMap={setAuthValues} />
</CardContent>
</Card>
</ListItem>
);
};

export default InputAccess;
export default InputAuth;
136 changes: 0 additions & 136 deletions client/src/components/InputsModal/InputAuth.tsx

This file was deleted.

13 changes: 7 additions & 6 deletions client/src/components/InputsModal/InputFields.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import React, { FC } from 'react';
import { List } from '@mui/material';
import { TestInput } from '~/models/testSuiteModels';
import InputOAuthCredentials from '~/components/InputsModal/InputOAuthCredentials';
import InputAuth from '~/components/InputsModal/Auth/InputAuth';
import InputCheckboxGroup from '~/components/InputsModal/InputCheckboxGroup';
import InputCombobox from '~/components/InputsModal/InputCombobox';
import InputOAuthCredentials from '~/components/InputsModal/InputOAuthCredentials';
import InputRadioGroup from '~/components/InputsModal/InputRadioGroup';
import InputTextField from '~/components/InputsModal/InputTextField';
import InputAuth from '~/components/InputsModal/InputAuth';
import InputSingleCheckbox from '~/components/InputsModal/InputSingleCheckbox';
import InputCombobox from '~/components/InputsModal/InputCombobox';
import InputAccess from '~/components/InputsModal/InputAccess';
import InputTextField from '~/components/InputsModal/InputTextField';

export interface InputFieldsProps {
inputs: TestInput[];
Expand All @@ -26,6 +25,7 @@ const InputFields: FC<InputFieldsProps> = ({ inputs, inputsMap, setInputsMap })
if (input.options?.mode === 'auth') {
return (
<InputAuth
mode="auth"
input={input}
index={index}
inputsMap={inputsMap}
Expand All @@ -35,7 +35,8 @@ const InputFields: FC<InputFieldsProps> = ({ inputs, inputsMap, setInputsMap })
);
}
return (
<InputAccess
<InputAuth
mode="access"
input={input}
index={index}
inputsMap={inputsMap}
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/InputsModal/InputHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import YAML from 'js-yaml';
import { enqueueSnackbar } from 'notistack';
import { Auth, OAuthCredentials, TestInput } from '~/models/testSuiteModels';
import { AuthType, getAuthFields, getAccessFields } from './AuthSettings';
import { AuthType, getAuthFields, getAccessFields } from './Auth/AuthSettings';

export const getMissingRequiredInput = (inputs: TestInput[], inputsMap: Map<string, unknown>) => {
return inputs.some((input: TestInput) => {
Expand Down
13 changes: 7 additions & 6 deletions client/src/components/InputsModal/__tests__/Inputs.test.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import { SnackbarProvider } from 'notistack';
import { TestInput } from '~/models/testSuiteModels';
import ThemeProvider from '~/components/ThemeProvider';
import InputAuth from '~/components/InputsModal/Auth/InputAuth';
import InputCheckboxGroup from '~/components/InputsModal/InputCheckboxGroup';
import InputOAuthCredentials from '~/components/InputsModal/InputOAuthCredentials';
import InputRadioGroup from '~/components/InputsModal/InputRadioGroup';
import InputTextField from '~/components/InputsModal/InputTextField';
import InputOAuthCredentials from '~/components/InputsModal/InputOAuthCredentials';
import InputAuth from '~/components/InputsModal/InputAuth';
import InputAccess from '~/components/InputsModal/InputAccess';
import { describe, expect, it } from 'vitest';
import ThemeProvider from '~/components/ThemeProvider';

describe('Input Components', () => {
it('renders InputCheckboxGroup', () => {
Expand Down Expand Up @@ -176,6 +175,7 @@ describe('Input Components', () => {
<ThemeProvider>
<SnackbarProvider>
<InputAuth
mode="auth"
input={authInput}
index={0}
inputsMap={new Map<string, string>()}
Expand Down Expand Up @@ -208,7 +208,8 @@ describe('Input Components', () => {
render(
<ThemeProvider>
<SnackbarProvider>
<InputAccess
<InputAuth
mode="access"
input={accessInput}
index={0}
inputsMap={new Map<string, string>()}
Expand Down

0 comments on commit 78f4f7e

Please sign in to comment.