Skip to content

Commit

Permalink
Adding Precision text box in set-type directive and modifying directi…
Browse files Browse the repository at this point in the history
…ve format to include precision and

adding corresponding test cases

Signed-off-by: minurajeeve <[email protected]>
  • Loading branch information
minurajeeve committed Nov 21, 2023
1 parent f004df9 commit 494b9ca
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ const ROUNDING_PREFIX = `${PREFIX}.roundingOptions`;
const ID_PREFIX = 'DataPrep-Directives-ChangeDataType-decimal';

const SCALE_INPUT_ID = `${ID_PREFIX}-scaleInputId`;
const PRECISION_INPUT_ID = `${ID_PREFIX}-precisionInputId`;
const ROUNDING_INPUT_ID = `${ID_PREFIX}-roundingInputId`;
const ROUNDING_LABEL_ID = `${ID_PREFIX}-roundingLableId`;
const ROUNDING_LABEL_ID = `${ID_PREFIX}-roundingLabelId`;

interface IRoundingMode {
value: string;
Expand Down Expand Up @@ -114,24 +115,36 @@ const useStyles = makeStyles((theme) => ({

export const DecimalOptions = ({ onApply, onCancel }: ISubmenuProps): JSX.Element => {
const [scale, setScale] = useState<string>('');
const [precision, setPrecision] = useState<string>('');
const [rounding, setRounding] = useState<string>('');

const classes = useStyles();
const isRoundingDisabled = scale === '';
const isRoundingDisabled = scale === '' && precision === '';

function handleScaleChange(event) {
const val = event.target.value;
setScale(val);
}

function handlePrecisionChange(event) {
const val = event.target.value;
setPrecision(val);
}

function handleRoundingChange(event) {
const val = event.target.value;
setRounding(val);
}

function applyDirective() {
const option = 'decimal';
const extraArgs = scale !== '' ? `${scale} '${rounding || 'HALF_EVEN'}'` : '';
let extraArgs = scale !== '' ? `${scale}` : '';
if (scale !== '' || precision !== '') {
extraArgs = `${extraArgs} '${rounding || 'HALF_EVEN'}'`;
}
if (precision !== '') {
extraArgs = `${extraArgs} prop:{precision=${precision}}`;
}
return onApply(option, extraArgs);
}

Expand Down Expand Up @@ -168,6 +181,37 @@ export const DecimalOptions = ({ onApply, onCancel }: ISubmenuProps): JSX.Elemen
/>
<FormHelperText>{T.translate(`${PREFIX}.scaleHelperText`)}</FormHelperText>
</FormControl>
<FormControl variant="outlined">
<InputLabel htmlFor={PRECISION_INPUT_ID}>
{T.translate(`${PREFIX}.precisionLabel`)}
</InputLabel>
<OutlinedInput
fullWidth
labelWidth={72}
id={PRECISION_INPUT_ID}
type="number"
value={precision}
onChange={handlePrecisionChange}
endAdornment={
<InputAdornment position="end">
<Tooltip
arrow
enterDelay={500}
title={T.translate(`${PREFIX}.precisionTooltip`).toString()}
classes={{ tooltip: classes.customTooltip, arrow: classes.customTooltipArrow }}
>
<IconButton
aria-label={T.translate(`${PREFIX}.precisionHelpButton`).toString()}
edge="end"
>
<HelpIcon />
</IconButton>
</Tooltip>
</InputAdornment>
}
/>
<FormHelperText>{T.translate(`${PREFIX}.precisionHelperText`)}</FormHelperText>
</FormControl>
<Tooltip
arrow
placement="top"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const ROUNDING_OPTIONS = [

describe('DecimalOptions component', () => {
const SCALE_LABEL = T.translate(`${PREFIX}.scaleLabel`).toString();
const PRECISION_LABEL = T.translate(`${PREFIX}.precisionLabel`).toString();
const ROUNDING_LABEL = T.translate(`${PREFIX}.roundingLabel`).toString();
const FLOOR = T.translate(`${PREFIX}.roundingOptions.FLOOR.label`).toString();
const APPLY = T.translate(`${PREFIX}.applyButton`).toString();
Expand All @@ -51,21 +52,26 @@ describe('DecimalOptions component', () => {
submenu = render(<DecimalOptions onApply={onApply} onCancel={onCancel} />);
});

it('should render a number input for scale and a select dropdown for rounding mode', () => {
it('should render a number input for scale, precision and a select dropdown for rounding mode', () => {
const scaleInput = submenu.getByLabelText(SCALE_LABEL);
const precisionInput = submenu.getByLabelText(PRECISION_LABEL);
const roundingInput = submenu.getByLabelText(ROUNDING_LABEL);

expect(scaleInput).toBeVisible();
expect(scaleInput).toBeEnabled();
expect(scaleInput).toHaveAttribute('type', 'number');

expect(precisionInput).toBeVisible();
expect(precisionInput).toBeEnabled();
expect(precisionInput).toHaveAttribute('type', 'number');

// Rounding mode select dropdown should be disabled initially as no scale
// has been specified yet.
expect(roundingInput).toBeVisible();
expect(roundingInput).toHaveClass('Mui-disabled');
});

it('should enable the rounding mode input only when scale is specified', () => {
it('should enable the rounding mode input when scale is specified', () => {
const scaleInput = submenu.getByLabelText(SCALE_LABEL);
const roundingInput = submenu.getByLabelText(ROUNDING_LABEL);

Expand All @@ -78,7 +84,7 @@ describe('DecimalOptions component', () => {
const options = within(listbox).getAllByRole('option');
const optionValues = options.map((li) => li.getAttribute('data-value'));

// The roundig modes select menu should have the 8 rounding modes
// The rounding modes select menu should have the 8 rounding modes
// in any order
expect(optionValues).toHaveLength(8);
ROUNDING_OPTIONS.forEach((opt) => expect(optionValues).toContain(opt));
Expand All @@ -87,22 +93,46 @@ describe('DecimalOptions component', () => {
expect(roundingInput).toHaveClass('Mui-disabled');
});

it('should enable the rounding mode input when precision is specified', () => {
const precisionInput = submenu.getByLabelText(PRECISION_LABEL);
const roundingInput = submenu.getByLabelText(ROUNDING_LABEL);

expect(roundingInput).toHaveClass('Mui-disabled');
fireEvent.change(precisionInput, { target: { value: '8' } });
expect(roundingInput).not.toHaveClass('Mui-disabled');

fireEvent.mouseDown(roundingInput);
const listbox = within(screen.getByRole('presentation')).getByRole('listbox');
const options = within(listbox).getAllByRole('option');
const optionValues = options.map((li) => li.getAttribute('data-value'));

// The rounding modes select menu should have the 8 rounding modes
// in any order
expect(optionValues).toHaveLength(8);
ROUNDING_OPTIONS.forEach((opt) => expect(optionValues).toContain(opt));

fireEvent.change(precisionInput, { target: { value: '' } });
expect(roundingInput).toHaveClass('Mui-disabled');
});

it('should pass correct args to the directive on apply', () => {
const scaleInput = submenu.getByLabelText(SCALE_LABEL);
const precisionInput = submenu.getByLabelText(PRECISION_LABEL);
const roundingInput = submenu.getByLabelText(ROUNDING_LABEL);

fireEvent.change(scaleInput, { target: { value: '4' } });
fireEvent.change(precisionInput, { target: { value: '8' } });
fireEvent.mouseDown(roundingInput);
fireEvent.click(submenu.getByText(FLOOR));
fireEvent.click(submenu.getByText(APPLY));

expect(onApply.mock.calls).toHaveLength(1);
expect(onApply.mock.calls[0]).toHaveLength(2);
expect(onApply.mock.calls[0][0]).toBe('decimal');
expect(onApply.mock.calls[0][1]).toBe("4 'FLOOR'");
expect(onApply.mock.calls[0][1]).toBe("4 'FLOOR' prop:{precision=8}");
});

it('should default rouding mode to HALF_EVEN if scale is specified and rounding mode is not specified', () => {
it('should default rounding mode to HALF_EVEN if scale is specified and rounding mode is not specified', () => {
const scaleInput = submenu.getByLabelText(SCALE_LABEL);
fireEvent.change(scaleInput, { target: { value: '2' } });
fireEvent.click(submenu.getByText(APPLY));
Expand All @@ -113,7 +143,18 @@ describe('DecimalOptions component', () => {
expect(onApply.mock.calls[0][1]).toBe("2 'HALF_EVEN'");
});

it('should not add any extra args if scale is not specified', () => {
it('should default rounding mode to HALF_EVEN if precision is specified and rounding mode is not specified', () => {
const precisionInput = submenu.getByLabelText(PRECISION_LABEL);
fireEvent.change(precisionInput, { target: { value: '8' } });
fireEvent.click(submenu.getByText(APPLY));

expect(onApply.mock.calls).toHaveLength(1);
expect(onApply.mock.calls[0]).toHaveLength(2);
expect(onApply.mock.calls[0][0]).toBe('decimal');
expect(onApply.mock.calls[0][1]).toBe(" 'HALF_EVEN' prop:{precision=8}");
});

it('should not add any extra args if scale and precision are not specified', () => {
fireEvent.click(submenu.getByText(APPLY));
expect(onApply.mock.calls).toHaveLength(1);
expect(onApply.mock.calls[0]).toHaveLength(2);
Expand Down
4 changes: 4 additions & 0 deletions app/cdap/text/text-en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,10 @@ features:
decimalConfig:
applyButton: APPLY
cancelButton: CANCEL
precisionLabel: Precision
precisionHelpButton: Tooltip for precision input
precisionHelperText: Define precision here
precisionTooltip: Specifies the precision of the decimal.
scaleLabel: Scale
scaleHelpButton: Tooltip for scale input
scaleHelperText: Define scale here
Expand Down

0 comments on commit 494b9ca

Please sign in to comment.