fast icon indicating copy to clipboard operation
fast copied to clipboard

fix: number-field accepts arbitrary "e" characters

Open radium-v opened this issue 3 years ago • 7 comments

🐛 Bug Report

The <fast-number-field> element allows for the e character to be entered.

💻 Repro or Code Sample

  1. Go to https://explore.fast.design/components/fast-number-field
  2. Click the number field
  3. type e
  4. 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 e into number fields
  • Only allow e when 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

radium-v avatar Aug 01 '22 18:08 radium-v

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'.

rizwan3d avatar Nov 19 '23 07:11 rizwan3d

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; where b is a base number (integer or floating), followed by an E or e character (which serves as separator or exponent indicator) and N, 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:

  1. Check for the presence of e or E
  2. Confirm that everything before the e is a floating or integer (^[+-]?[0-9]*(?:\.[0-9]+)?)
  3. 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.

radium-v avatar Nov 27 '23 05:11 radium-v

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.

rizwan3d avatar Nov 27 '23 07:11 rizwan3d

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.

radium-v avatar Nov 27 '23 07:11 radium-v

Thanks for explanation issue resolved.

https://stackblitz.com/edit/proof-of-work-for-exponential-notation

rizwan3d avatar Nov 27 '23 09:11 rizwan3d

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

rizwan3d avatar Nov 27 '23 09:11 rizwan3d

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.

radium-v avatar Nov 27 '23 20:11 radium-v