Skip to content

Commit

Permalink
Merge pull request #6142 from Sage/FE-5892_Decimal-emptyValue-borked
Browse files Browse the repository at this point in the history
fix(decimal): ensure empty value is formatted correctly - FE-5892
  • Loading branch information
DipperTheDan committed Jun 29, 2023
2 parents 42281ce + 284cabc commit d009d39
Show file tree
Hide file tree
Showing 3 changed files with 307 additions and 21 deletions.
86 changes: 86 additions & 0 deletions cypress/components/decimal/decimal.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,92 @@ context("Tests for Decimal component", () => {
});
});

describe("allowEmptyValue", () => {
it.each([
[0, "en", "0", "0"],
[1, "en", "0.0", "0.0"],
[2, "en", "0.00", "0.00"],
[0, "es-ES", "0", "0"],
[1, "es-ES", "0.0", "0,0"],
[2, "es-ES", "0.00", "0,00"],
[0, "fr", "0", "0"],
[1, "fr", "0.0", "0,0"],
[2, "fr", "0.00", "0,00"],
[0, "pt-PT", "0", "0"],
[1, "pt-PT", "0.0", "0,0"],
[2, "pt-PT", "0.00", "0,00"],
] as [DecimalProps["precision"], string, string, string][])(
"should format an empty value correctly when precision is %s, locale is %s and allowEmptyValue is false",
(precisionValue, localeValue, rawValue, expectedValue) => {
const callback: DecimalProps["onBlur"] = cy.stub().as("onBlur");

CypressMountWithProviders(
<Decimal
precision={precisionValue}
locale={localeValue}
allowEmptyValue={false}
onBlur={callback}
/>
);

commonDataElementInputPreview().type("100");
commonDataElementInputPreview()
.clear()
.blur({ force: true })
.then(() => {
cy.get("@onBlur").should(
"have.been.calledWith",
eventOutput(expectedValue, rawValue)
);
});
expect(
commonDataElementInputPreview().should("have.value", expectedValue)
);
}
);

it.each([
[0, "en"],
[1, "en"],
[2, "en"],
[0, "es-ES"],
[1, "es-ES"],
[2, "es-ES"],
[0, "fr"],
[1, "fr"],
[2, "fr"],
[0, "pt-PT"],
[1, "pt-PT"],
[2, "pt-PT"],
] as [DecimalProps["precision"], string][])(
"should format an empty value correctly when precision is %s, locale is %s and allowEmptyValue is true",
(precisionValue, localeValue) => {
const callback: DecimalProps["onBlur"] = cy.stub().as("onBlur");

CypressMountWithProviders(
<Decimal
precision={precisionValue}
locale={localeValue}
allowEmptyValue
onBlur={callback}
/>
);

commonDataElementInputPreview().type("100");
commonDataElementInputPreview()
.clear()
.blur({ force: true })
.then(() => {
cy.get("@onBlur").should(
"have.been.calledWith",
eventOutput("", "")
);
});
expect(commonDataElementInputPreview().should("have.value", ""));
}
);
});

describe("check events for Decimal component", () => {
const inputValue = "123";
const iterable = [
Expand Down
44 changes: 23 additions & 21 deletions src/components/decimal/decimal.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,27 +105,6 @@ export const Decimal = React.forwardRef(
);
}

const emptyValue = allowEmptyValue ? "" : "0.00";

const getSafeValueProp = useCallback(
(initialValue) => {
// We're intentionally preventing the use of number values to help prevent any unintentional rounding issues
invariant(
typeof initialValue === "string",
"Decimal `value` prop must be a string"
);

if (initialValue && !allowEmptyValue) {
invariant(
initialValue !== "",
"Decimal `value` must not be an empty string. Please use `allowEmptyValue` or `0.00`"
);
}
return initialValue;
},
[allowEmptyValue]
);

const getSeparator = useCallback(
(separatorType) => {
const numberWithGroupAndDecimalSeparator = 10000.1;
Expand Down Expand Up @@ -179,6 +158,29 @@ export const Decimal = React.forwardRef(
[getSeparator, isNaN, l, locale, precision]
);

const emptyValue = allowEmptyValue
? ""
: formatValue((0).toFixed(precision));

const getSafeValueProp = useCallback(
(initialValue) => {
// We're intentionally preventing the use of number values to help prevent any unintentional rounding issues
invariant(
typeof initialValue === "string",
"Decimal `value` prop must be a string"
);

if (initialValue && !allowEmptyValue) {
invariant(
initialValue !== "",
"Decimal `value` must not be an empty string. Please use `allowEmptyValue` or specify a non-empty initialValue"
);
}
return initialValue;
},
[allowEmptyValue]
);

/**
* Determine if the precision value has changed from the previous ref value for precision
*/
Expand Down
198 changes: 198 additions & 0 deletions src/components/decimal/decimal.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,46 @@ describe("Decimal", () => {
})
);
});

it("formats a value correctly when precision is 0 and allowEmptyValue is false", () => {
const onBlur = jest.fn();
render({
precision: 0,
value: "",
onBlur,
onChange: (e: CustomEvent) => {
setProps({ value: e.target.value.rawValue });
},
allowEmptyValue: false,
...esProps,
});

setProps({ value: "" });
blur();
expect(value()).toBe("0");
expect(hiddenValue()).toBe("0");
expect(onBlur).toHaveBeenCalled();
});

it("formats a value correctly when precision is 1 and allowEmptyValue is false", () => {
const onBlur = jest.fn();
render({
precision: 1,
value: "0",
onBlur,
onChange: (e: CustomEvent) => {
setProps({ value: e.target.value.rawValue });
},
allowEmptyValue: false,
...esProps,
});

setProps({ value: "" });
blur();
expect(value()).toBe("0,0");
expect(hiddenValue()).toBe("0.0");
expect(onBlur).toHaveBeenCalled();
});
});

describe("pt", () => {
Expand Down Expand Up @@ -772,6 +812,46 @@ describe("Decimal", () => {
expect(value()).toBe("10\xa0000\xa0000,00");
expect(hiddenValue()).toBe("10000000.00");
});

it("formats a value correctly when precision is 0 and allowEmptyValue is false", () => {
const onBlur = jest.fn();
render({
precision: 0,
value: "0.00",
onBlur,
onChange: (e: CustomEvent) => {
setProps({ value: e.target.value.rawValue });
},
allowEmptyValue: false,
...ptProps,
});

setProps({ value: "" });
blur();
expect(value()).toBe("0");
expect(hiddenValue()).toBe("0");
expect(onBlur).toHaveBeenCalled();
});

it("formats a value correctly when precision is 1 and allowEmptyValue is false", () => {
const onBlur = jest.fn();
render({
precision: 1,
value: "0",
onBlur,
onChange: (e: CustomEvent) => {
setProps({ value: e.target.value.rawValue });
},
allowEmptyValue: false,
...ptProps,
});

setProps({ value: "" });
blur();
expect(value()).toBe("0,0");
expect(hiddenValue()).toBe("0.0");
expect(onBlur).toHaveBeenCalled();
});
});

describe("fr", () => {
Expand All @@ -798,6 +878,46 @@ describe("Decimal", () => {
);
}
);

it("formats a value correctly when precision is 0 and allowEmptyValue is false", () => {
const onBlur = jest.fn();
render({
precision: 0,
value: "0.00",
onBlur,
onChange: (e: CustomEvent) => {
setProps({ value: e.target.value.rawValue });
},
allowEmptyValue: false,
...frProps,
});

setProps({ value: "" });
blur();
expect(value()).toBe("0");
expect(hiddenValue()).toBe("0");
expect(onBlur).toHaveBeenCalled();
});

it("formats a value correctly when precision is 1 and allowEmptyValue is false", () => {
const onBlur = jest.fn();
render({
precision: 1,
value: "0",
onBlur,
onChange: (e: CustomEvent) => {
setProps({ value: e.target.value.rawValue });
},
allowEmptyValue: false,
...frProps,
});

setProps({ value: "" });
blur();
expect(value()).toBe("0,0");
expect(hiddenValue()).toBe("0.0");
expect(onBlur).toHaveBeenCalled();
});
});

describe("it", () => {
Expand Down Expand Up @@ -846,6 +966,46 @@ describe("Decimal", () => {
expect(hiddenValue()).toBe("-1234.56");
});

it("formats a value correctly when precision is 0 and allowEmptyValue is false", () => {
const onBlur = jest.fn();
render({
precision: 0,
value: "0.00",
onBlur,
onChange: (e: CustomEvent) => {
setProps({ value: e.target.value.rawValue });
},
allowEmptyValue: false,
...itProps,
});

setProps({ value: "" });
blur();
expect(value()).toBe("0");
expect(hiddenValue()).toBe("0");
expect(onBlur).toHaveBeenCalled();
});

it("formats a value correctly when precision is 1 and allowEmptyValue is false", () => {
const onBlur = jest.fn();
render({
precision: 1,
value: "0",
onBlur,
onChange: (e: CustomEvent) => {
setProps({ value: e.target.value.rawValue });
},
allowEmptyValue: false,
...itProps,
});

setProps({ value: "" });
blur();
expect(value()).toBe("0,0");
expect(hiddenValue()).toBe("0.0");
expect(onBlur).toHaveBeenCalled();
});

describe("precision", () => {
it("fires a console error when precision is changed once component is loaded.", () => {
const consoleSpy = jest
Expand Down Expand Up @@ -1183,6 +1343,44 @@ describe("Decimal", () => {
expect(hiddenValue()).toBe("-");
});

it("formats a value correctly when precision is 0 and allowEmptyValue is false", () => {
const onBlur = jest.fn();
render({
precision: 0,
value: "",
onBlur,
onChange: (e: CustomEvent) => {
setProps({ value: e.target.value.rawValue });
},
allowEmptyValue: false,
});

setProps({ value: "" });
blur();
expect(value()).toBe("0");
expect(hiddenValue()).toBe("0");
expect(onBlur).toHaveBeenCalled();
});

it("formats a value correctly when precision is 1 and allowEmptyValue is false", () => {
const onBlur = jest.fn();
render({
precision: 1,
value: "",
onBlur,
onChange: (e: CustomEvent) => {
setProps({ value: e.target.value.rawValue });
},
allowEmptyValue: false,
});

setProps({ value: "" });
blur();
expect(value()).toBe("0.0");
expect(hiddenValue()).toBe("0.0");
expect(onBlur).toHaveBeenCalled();
});

it("typing a negative value does not revert to the default value (allowEmptyValue)", () => {
render({ value: "", allowEmptyValue: true });
setProps({ value: "-" });
Expand Down

0 comments on commit d009d39

Please sign in to comment.