Skip to content

Commit

Permalink
feat(bulk-import): update preview form to use separate formik context (
Browse files Browse the repository at this point in the history
  • Loading branch information
debsmita1 authored Nov 7, 2024
1 parent ae43642 commit 06f1869
Show file tree
Hide file tree
Showing 12 changed files with 200 additions and 298 deletions.
5 changes: 5 additions & 0 deletions workspaces/bulk-import/.changeset/nervous-waves-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@red-hat-developer-hub/backstage-plugin-bulk-import': minor
---

update preview form to use separate formik context
3 changes: 2 additions & 1 deletion workspaces/bulk-import/plugins/bulk-import/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"react-use": "^17.2.4",
"yaml": "^2.0.0"
"yaml": "^2.0.0",
"yup": "^1.4.0"
},
"peerDependencies": {
"react": "16.13.1 || ^17.0.0 || ^18.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,83 +12,28 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ import React, { useState } from 'react';
*/
import React from 'react';

import { FormHelperText, TextField } from '@material-ui/core';

import { PullRequestPreview, PullRequestPreviewData } from '../../types';

interface KeyValueTextFieldProps {
repoId: string;
label: string;
name: string;
value: string;
onChange: (
event: React.FocusEvent<HTMLTextAreaElement | HTMLInputElement>,
) => void;
formErrors: PullRequestPreviewData;
setFormErrors: (pullRequest: PullRequestPreviewData) => void;
fieldError: string;
}

const validateKeyValuePairs = (value: string): string | null => {
const keyValuePairs = value.split(';').map(pair => pair.trim());
for (const pair of keyValuePairs) {
if (pair) {
const [key, val] = pair.split(':').map(part => part.trim());
if (!key || !val) {
return 'Each entry must have a key and a value separated by a colon.';
}
}
}
return null;
};

const KeyValueTextField: React.FC<KeyValueTextFieldProps> = ({
repoId,
const KeyValueTextField = ({
label,
name,
value,
onChange,
setFormErrors,
formErrors,
}) => {
const [error, setError] = useState<string | null>(null);
const fieldName = name.split('.').pop() ?? '';

const removeError = () => {
const err = { ...formErrors };
if (err[repoId]) {
delete err[repoId][fieldName as keyof PullRequestPreview];
}
setFormErrors(err);
};

const getUpdatedFormError = (
validationError: string,
): PullRequestPreviewData => {
return {
...formErrors,
[repoId]: {
...(formErrors?.[repoId] || {}),
[fieldName]: validationError,
},
};
};

const handleChange = (
event: React.FocusEvent<HTMLTextAreaElement | HTMLInputElement, Element>,
) => {
const validationError = validateKeyValuePairs(event.target.value);
if (validationError) {
setError(validationError);
setFormErrors(getUpdatedFormError(validationError));
} else {
setError(null);
removeError();
}
onChange(event);
};

fieldError,
}: KeyValueTextFieldProps) => {
return (
<div>
<TextField
Expand All @@ -100,9 +45,9 @@ const KeyValueTextField: React.FC<KeyValueTextFieldProps> = ({
fullWidth
name={name}
value={value}
onChange={handleChange}
error={!!error}
helperText={error}
onChange={onChange}
error={!!fieldError}
helperText={fieldError}
/>
<FormHelperText style={{ marginLeft: '0.8rem' }}>
Use semicolon to separate {label.toLocaleLowerCase('en-US')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export const PreviewFileSidebar = ({
[id]: {
error: {
message: [
`The entity YAML in your pull request is invalid (empty file or missing apiVersion, kind, or metadata.name). A new YAML has been generated below.`,
'The entity YAML in your pull request is invalid (empty file or missing apiVersion, kind, or metadata.name). A new YAML has been generated below.',
],
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export const PreviewFileSidebarDrawerContent = ({
isSubmitting ||
(!!formErrors &&
Object.values(formErrors).length > 0 &&
Object.values(formErrors).every(
Object.values(formErrors).some(
fe => !!fe && Object.values(fe).length > 0,
))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ export const PreviewPullRequest = ({
}) => {
const { status } = useFormikContext<AddRepositoriesFormValues>();

const [entityOwner, setEntityOwner] = React.useState<string>('');

const error = status?.errors?.[repoId];
const info = status?.infos?.[repoId];
if (
Expand Down Expand Up @@ -114,8 +112,6 @@ export const PreviewPullRequest = ({
</Box>
)}
<PreviewPullRequestForm
entityOwner={entityOwner}
setEntityOwner={setEntityOwner}
repoId={repoId}
repoUrl={repoUrl}
pullRequest={pullRequest}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ import React, { useState } from 'react';
*/
import React from 'react';

import { configApiRef } from '@backstage/core-plugin-api';
import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react';
import { MockConfigApi, TestApiProvider } from '@backstage/test-utils';

import { fireEvent, render } from '@testing-library/react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { useFormikContext } from 'formik';

import { bulkImportApiRef } from '../../api/BulkImportBackendClient';
Expand All @@ -28,11 +29,6 @@ import { ApprovalTool, ImportJobStatus } from '../../types';
import { getPRTemplate } from '../../utils/repository-utils';
import { PreviewPullRequestForm } from './PreviewPullRequestForm';

jest.mock('react', () => ({
...jest.requireActual('react'),
useState: jest.fn(),
}));

jest.mock('@material-ui/core', () => ({
...jest.requireActual('@material-ui/core'),
makeStyles: () => () => {
Expand Down Expand Up @@ -64,12 +60,6 @@ class MockBulkImportApi {
}
}

const setState = jest.fn();

beforeEach(() => {
(useState as jest.Mock).mockImplementation(initial => [initial, setState]);
});

const mockBulkImportApi = new MockBulkImportApi();

const mockCatalogApi: Partial<CatalogApi> = {
Expand Down Expand Up @@ -110,8 +100,6 @@ describe('Preview Pull Request Form', () => {
<PreviewPullRequestForm
repoId="org/dessert/cupcake"
repoUrl="https://github.com/org/dessert/cupcake"
entityOwner="user:default/guest"
setEntityOwner={jest.fn()}
pullRequest={{
cupcake: getPRTemplate(
'org/dessert/cupcake',
Expand Down Expand Up @@ -165,8 +153,6 @@ describe('Preview Pull Request Form', () => {
<PreviewPullRequestForm
repoId="org/dessert/cupcake"
repoUrl="https://github.com/org/dessert/cupcake"
entityOwner="user:default/guest"
setEntityOwner={jest.fn()}
pullRequest={{
'org/dessert/cupcake': getPRTemplate(
'org/dessert/cupcake',
Expand Down Expand Up @@ -222,8 +208,6 @@ describe('Preview Pull Request Form', () => {
<PreviewPullRequestForm
repoId="org/dessert/cupcake"
repoUrl="https://github.com/org/dessert/cupcake"
entityOwner="user:default/guest"
setEntityOwner={jest.fn()}
pullRequest={{
'org/dessert/cupcake': getPRTemplate(
'org/dessert/cupcake',
Expand All @@ -244,18 +228,18 @@ describe('Preview Pull Request Form', () => {
/Add Backstage catalog entity descriptor files/,
);
fireEvent.change(prTitle, { target: { value: '' } });
expect(setFormErrors).toHaveBeenCalledWith({
'org/dessert/cupcake': {
prTitle: 'Pull request title is missing',
},
await waitFor(() => {
expect(
screen.queryByText('Pull request title is required'),
).toBeInTheDocument();
});

const componentName = getByPlaceholderText(/Component Name/);
fireEvent.change(componentName, { target: { value: '' } });
expect(setFormErrors).toHaveBeenCalledWith({
'org/dessert/cupcake': {
componentName: 'Component name is missing',
},
await waitFor(() => {
expect(
screen.queryByText('Component name is required'),
).toBeInTheDocument();
});
});
});
Loading

0 comments on commit 06f1869

Please sign in to comment.