fast
fast copied to clipboard
fix: number-field accepts arbitrary "e" characters
🐛 Bug Report
The <fast-number-field> element allows for the e character to be entered.
💻 Repro or Code Sample
- Go to https://explore.fast.design/components/fast-number-field
- Click the number field
- type
e - Type more
e
🤔 Expected Behavior
Should the e character be allowed in the number field for exponent notation?
😯 Current Behavior
Values like eeeeeeeee are permitted.
💁 Possible Solution
- Completely eliminate the ability to type
einto number fields - Only allow
ewhen used in exponent notation (ex.123e2,123e+12)
🔦 Context
This bug was discovered while converting number field tests to Playwright. This is the new test which fails to remove the e character from the input string:
test("should not allow non-number entry", async ({ page }) => {
const value = "11abcdefg";
const expectedValue = "11";
await page.goto(fixtureURL("number-field--number-field"));
const element = page.locator("fast-number-field");
const control = element.locator(".control");
await element.type(value);
await expect(element).toHaveJSProperty("value", expectedValue);
await expect(control).toHaveValue(expectedValue);
});
Error: expect(received).toHaveValue(expected)
Expected string: "11"
Received string: "11e"
🌍 Your Environment
- OS & Device: Windows 11, Ubuntu via WSL2, PC
- Playwright 1.24
There's no way to check for a valid exponential input unless we have a complete input. To address this, we might want to consider adding a new function or property, let's call it numValue, that specifically verifies the presence of numbers on both sides of the 'e'.
I think there's more to this than just supporting e, since there's a specific structure to exponential notation:
The decimal exponential literal is specified by the following format:
beN; wherebis a base number (integer or floating), followed by anEorecharacter (which serves as separator or exponent indicator) andN, which is exponent or power number – a signed integer.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#exponential
It would probably work best if we check in stages:
- Check for the presence of
eorE - Confirm that everything before the
eis a floating or integer (^[+-]?[0-9]*(?:\.[0-9]+)?) - Confirm that everything after the e is a signed integer (
[+-]?[0-9]?$)
This is tightly coupled to #6713 and #6714. Since we're not actually working with numbers, we may need to use a library like MikeMcl/big.js to resolve all of these together.
I think If the input contains the letter 'e' and is a normal number, mask the input field as (RealNumber)E(Integer).
if 'e' in input or 'E' in input:
if not isMasked:
maskInputForExponentialNo()
validateMaskedInput()
else:
input = re.sub(r'[^0-9\-+.]', '', input)
Optional: For masking, consider using "ₓ(U+2093)⏨(U+23E8)" instead of 'e' in the input field for normal numbers.
If the input contains the letter 'e' and is a normal number
Users press keys sequentially. In non-programmatic cases, this will inevitably lead to partial values like 1.234e or 4.56e- when the user hasn't finished typing their desired value. This would be valid input for the number field until either field validation occurs or the value is changed via the up/down arrow keys or arrow buttons.
For masking, consider using "ₓ(U+2093)⏨(U+23E8)" instead of 'e' in the input field for normal numbers.
This would be out of scope for the FAST NumberField as it would be unexpected behavior.
Thanks for explanation issue resolved.
https://stackblitz.com/edit/proof-of-work-for-exponential-notation
MikeMcl/big.js cannot work here.
Reason:
| Attempt | Output | Expected |
|---|---|---|
| 1.23.4567 | 1.234567 | |
| 123.4567 | 123.4567 | 123.4567 |
| 123 | 123 | 123 |
| 0.123123 | 0.123123 | 0.123123 |
| 123456.7e | 123456.7 | |
| e-3 | 0e-3 | |
| 123456.7e3e3 | 123456.7e33 |
My mention of big.js was a general suggestion for how we approach all of these number-field issues. I'll create a separate issue for that discussion.