Merge pull request #26781 from stephenglass/secret-widget-perf

perf: improve performance of scaffolder secret widget
This commit is contained in:
Ben Lambert
2024-12-17 08:25:32 +01:00
committed by GitHub
3 changed files with 38 additions and 10 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-react': patch
---
Improve performance of typing into scaffolder secret widget
@@ -17,7 +17,8 @@
import { WidgetProps } from '@rjsf/utils';
import { useTemplateSecrets } from '@backstage/plugin-scaffolder-react';
import TextField from '@material-ui/core/TextField';
import React from 'react';
import React, { useMemo, useState } from 'react';
import debounce from 'lodash/debounce';
/**
* Secret Widget for overriding the default password input widget
@@ -38,16 +39,31 @@ export const SecretWidget = (
disabled,
} = props;
const [localValue, setLocalValue] = useState(secrets[name] ?? '');
// Memoize the debounced function so it persists across re-renders
const debouncedSetSecrets = useMemo(
() =>
debounce((value: string) => {
setSecrets({ [name]: value });
}, 300),
[setSecrets, name],
);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value;
setLocalValue(newValue);
onChange(Array(newValue.length).fill('*').join(''));
debouncedSetSecrets(newValue);
};
return (
<TextField
id={title}
label={title}
aria-describedby={title}
onChange={e => {
onChange(Array(e.target.value.length).fill('*').join(''));
setSecrets({ [name]: e.target.value });
}}
value={secrets[name] ?? ''}
onChange={handleChange}
value={localValue}
type="password"
autoComplete="off"
required={required}
@@ -22,7 +22,7 @@ import { SecretInput } from './SecretInput';
import { renderInTestApp } from '@backstage/test-utils';
import { Form } from '@backstage/plugin-scaffolder-react/alpha';
import validator from '@rjsf/validator-ajv8';
import { fireEvent, act } from '@testing-library/react';
import { fireEvent, act, waitFor } from '@testing-library/react';
describe('<SecretInput />', () => {
const SecretsComponent = () => {
@@ -63,8 +63,15 @@ describe('<SecretInput />', () => {
fireEvent.change(secretInput, { target: { value: mockSecret } });
});
const { secrets } = JSON.parse(getByTestId('current-secrets').textContent!);
expect(secrets.myKey).toBe(mockSecret);
// Wait for the debounced update to occur
await waitFor(
() => {
const { secrets } = JSON.parse(
getByTestId('current-secrets').textContent!,
);
expect(secrets.myKey).toBe(mockSecret);
},
{ timeout: 500 },
);
});
});