Skip to content
Permalink
Browse files
fix(form): Maintain Floating Label for Invalid Numbers
Browsers will try to prevent invalid characters from being entered into
an `<input type="number" />`, but they are unable to prevent numbers
like: `"--00"`, `"0-0"`, or `"123-"`. When these types of numbers are
entered, the input actually reports the value as the empty string
instead of the current text value which caused the floating label to
cover the input when blurred.
  • Loading branch information
mlaursen committed Nov 22, 2020
1 parent 23d92dd commit 2443f9a
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 2 deletions.
@@ -1,5 +1,5 @@
import React from "react";
import { render } from "@testing-library/react";
import { fireEvent, render } from "@testing-library/react";

import { TextField } from "../TextField";

@@ -19,4 +19,93 @@ describe("TextField", () => {
expect(container).toMatchSnapshot();
expect(document.getElementById("field")).toHaveAttribute("disabled");
});

it("should correctly call the onChange event", () => {
const onChange = jest.fn();
const { getByRole } = render(
<TextField id="field" label="Label" onChange={onChange} />
);
const field = getByRole("textbox");
expect(onChange).not.toBeCalled();

fireEvent.change(field, { target: { value: "2" } });
expect(onChange).toBeCalledTimes(1);
});

it("should add the inactive floating label state when a number text field is blurred while containing an invalid value", () => {
const { getByRole, getByText } = render(
<TextField id="text-field" label="Label" type="number" defaultValue="" />
);

const field = getByRole("spinbutton") as HTMLInputElement;
const label = getByText("Label");
expect(field).toHaveAttribute("value", "");
expect(label.className).not.toContain("rmd-floating-label--active");
expect(label.className).not.toContain("rmd-floating-label--inactive");

fireEvent.focus(field);
expect(label.className).toContain("rmd-floating-label--active");
expect(label.className).not.toContain("rmd-floating-label--inactive");

fireEvent.change(field, { target: { value: "123" } });
expect(label.className).toContain("rmd-floating-label--active");
expect(label.className).not.toContain("rmd-floating-label--inactive");

// TODO: Look into writing real browser tests since this isn't implemented in JSDOM
Object.defineProperty(field.validity, "badInput", {
writable: true,
value: true,
});
expect(field.validity.badInput).toBe(true);
fireEvent.change(field, {
target: { value: "123-" },
});
expect(field.validity.badInput).toBe(true);
expect(label.className).toContain("rmd-floating-label--active");
expect(label.className).not.toContain("rmd-floating-label--inactive");

fireEvent.blur(field);
expect(label.className).toContain("rmd-floating-label--active");
expect(label.className).toContain("rmd-floating-label--inactive");
});

it("should not add the inactive floating label state when a non-number type has a badInput validity", () => {
const { getByRole, getByText } = render(
<TextField id="text-field" label="Label" type="url" defaultValue="" />
);

const field = getByRole("textbox") as HTMLInputElement;
const label = getByText("Label");
expect(field).toHaveAttribute("value", "");
expect(label.className).not.toContain("rmd-floating-label--active");
expect(label.className).not.toContain("rmd-floating-label--inactive");

fireEvent.focus(field);
expect(label.className).toContain("rmd-floating-label--active");
expect(label.className).not.toContain("rmd-floating-label--inactive");

// TODO: Look into writing real browser tests since this isn't implemented in JSDOM
Object.defineProperty(field.validity, "badInput", {
writable: true,
value: true,
});
fireEvent.change(field, { target: { value: "123" } });
expect(field.validity.badInput).toBe(true);
expect(label.className).toContain("rmd-floating-label--active");
expect(label.className).not.toContain("rmd-floating-label--inactive");

fireEvent.blur(field);
expect(field.validity.badInput).toBe(true);
expect(label.className).toContain("rmd-floating-label--active");
expect(label.className).toContain("rmd-floating-label--inactive");

fireEvent.focus(field);
expect(label.className).toContain("rmd-floating-label--active");
expect(label.className).not.toContain("rmd-floating-label--inactive");

fireEvent.change(field, { target: { value: "" } });
fireEvent.blur(field);
expect(label.className).not.toContain("rmd-floating-label--active");
expect(label.className).not.toContain("rmd-floating-label--inactive");
});
});
@@ -43,7 +43,10 @@ export function useValuedState<T extends TextElement>({

if (event.currentTarget.value.length > 0) {
enable();
} else {
} else if (
event.currentTarget.getAttribute("type") !== "number" ||
!event.currentTarget.validity.badInput
) {
disable();
}
},

0 comments on commit 2443f9a

Please sign in to comment.