Skip to content

Commit 40d3434

Browse files
authored
chore: Refactor InputGroup tests (#7455)
1 parent e707b5f commit 40d3434

File tree

1 file changed

+73
-71
lines changed

1 file changed

+73
-71
lines changed

packages/core/test/controls/inputGroupTests.tsx

Lines changed: 73 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -14,103 +14,105 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { assert } from "chai";
18-
import { mount } from "enzyme";
17+
import { render, screen } from "@testing-library/react";
18+
import userEvent from "@testing-library/user-event";
19+
import { expect } from "chai";
1920
import * as React from "react";
2021
import { spy } from "sinon";
2122

22-
import { Classes, Icon, InputGroup } from "../../src";
23+
import { Classes, InputGroup } from "../../src";
2324

2425
describe("<InputGroup>", () => {
25-
it("renders left icon before input", () => {
26-
const input = mount(<InputGroup leftIcon="star" />).children();
27-
assert.isTrue(input.childAt(0).is(Icon));
28-
assert.isTrue(input.childAt(1).hasClass(Classes.INPUT));
26+
it("should render left icon before input", () => {
27+
render(<InputGroup leftIcon="star" />);
28+
const input = screen.getByRole<HTMLInputElement>("textbox");
29+
const inputGroup = input.parentElement;
30+
31+
expect(inputGroup).to.exist;
32+
expect([...inputGroup!.classList]).to.include(Classes.INPUT_GROUP);
33+
expect([...inputGroup!.children[0].classList]).to.include(Classes.ICON);
34+
expect(inputGroup!.children[1]).to.equal(input);
2935
});
3036

31-
it("supports custom props", () => {
32-
const input = mount(<InputGroup leftIcon="star" style={{ background: "yellow" }} tabIndex={4} />);
33-
const inputElement = input.find("input").getDOMNode<HTMLElement>();
34-
assert.equal(inputElement.style.background, "yellow");
35-
assert.equal(inputElement.tabIndex, 4);
37+
it("should support custom props", () => {
38+
render(<InputGroup style={{ background: "yellow" }} tabIndex={4} />);
39+
const input = screen.getByRole<HTMLInputElement>("textbox");
40+
41+
expect(input.style.background).to.equal("yellow");
42+
expect(input.tabIndex).to.equal(4);
43+
});
44+
45+
it(`should render right element inside .${Classes.INPUT_ACTION}`, () => {
46+
render(<InputGroup rightElement={<div data-testid="right-element" />} />);
47+
48+
expect(screen.getByTestId("right-element")).to.exist;
49+
const action = screen.getByTestId("right-element").parentElement;
50+
expect(action).to.exist;
51+
expect([...action!.classList]).to.include(Classes.INPUT_ACTION);
3652
});
3753

38-
it(`renders right element inside .${Classes.INPUT_ACTION} after input`, () => {
39-
const action = mount(<InputGroup rightElement={<address />} />)
40-
.children()
41-
.childAt(1);
42-
assert.isTrue(action.hasClass(Classes.INPUT_ACTION));
43-
assert.lengthOf(action.find("address"), 1);
54+
it("should support onChange callback", () => {
55+
const onChange = spy();
56+
render(<InputGroup onChange={onChange} />);
57+
const input = screen.getByRole<HTMLInputElement>("textbox");
58+
59+
userEvent.type(input, "x");
60+
61+
expect(input.value).to.equal("x");
62+
expect(onChange.calledOnce).to.be.true;
63+
64+
const event = onChange.getCall(0).args[0] as React.ChangeEvent<HTMLInputElement>;
65+
expect(event.target.value).to.equal("x");
4466
});
4567

46-
it("works like a text input", () => {
47-
const changeSpy = spy();
48-
const input = mount(<InputGroup value="value" onChange={changeSpy} />).find("input");
49-
assert.strictEqual(input.prop("type"), "text");
50-
assert.strictEqual(input.prop("value"), "value");
68+
it("should support the onValueChange callback", () => {
69+
const onValueChange = spy();
70+
render(<InputGroup onValueChange={onValueChange} />);
71+
const input = screen.getByRole<HTMLInputElement>("textbox");
72+
73+
userEvent.type(input, "x");
5174

52-
input.simulate("change");
53-
assert.isTrue(changeSpy.calledOnce, "onChange not called");
75+
expect(input.value).to.equal("x");
76+
expect(onValueChange.calledOnce).to.be.true;
77+
expect(onValueChange.getCall(0).args[0]).to.equal("x");
78+
expect(onValueChange.getCall(0).args[1].value).to.equal("x");
5479
});
5580

56-
it("supports custom type attribute", () => {
57-
const group = mount(<InputGroup type="email" />);
58-
assert.strictEqual(group.find("input").prop("type"), "email");
81+
it("should support custom type attribute", () => {
82+
render(<InputGroup type="email" />);
83+
const input = screen.getByRole<HTMLInputElement>("textbox");
5984

60-
group.setProps({ type: "password" });
61-
assert.strictEqual(group.find("input").prop("type"), "password");
85+
expect(input.type).to.equal("email");
6286
});
6387

64-
it("supports inputRef", () => {
65-
let input: HTMLInputElement | null = null;
66-
mount(<InputGroup inputRef={ref => (input = ref)} />);
67-
assert.instanceOf(input, HTMLInputElement);
88+
it("should support inputRef", () => {
89+
const inputRef = React.createRef<HTMLInputElement>();
90+
render(<InputGroup inputRef={inputRef} />);
91+
92+
expect(inputRef.current).to.be.instanceOf(HTMLInputElement);
6893
});
6994

7095
// this test was added to validate a regression introduced by AsyncControllableInput,
7196
// see https://github.com/palantir/blueprint/issues/4375
72-
it("accepts controlled update truncating the input value", () => {
73-
class TestComponent extends React.PureComponent<
74-
{ initialValue: string; transformInput: (value: string) => string },
75-
{ value: string }
76-
> {
77-
public state = { value: this.props.initialValue };
78-
79-
public render() {
80-
return <InputGroup type="text" value={this.state.value} onChange={this.handleChange} />;
81-
}
82-
83-
private handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
84-
this.setState({
85-
value: this.props.transformInput(e.target.value),
86-
});
97+
it("should accept controlled update truncating input value", () => {
98+
function TestComponent(props: { initialValue: string; transformInput: (value: string) => string }) {
99+
const { initialValue, transformInput } = props;
100+
const [value, setValue] = React.useState(initialValue);
101+
102+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
103+
setValue(transformInput(event.target.value));
87104
};
105+
106+
return <InputGroup type="text" value={value} onChange={handleChange} />;
88107
}
89108

90-
const wrapper = mount(
91-
<TestComponent initialValue="abc" transformInput={(value: string) => value.substring(0, 3)} />,
92-
);
109+
render(<TestComponent initialValue="abc" transformInput={(value: string) => value.substring(0, 3)} />);
110+
const input = screen.getByRole<HTMLInputElement>("textbox");
93111

94-
let input = wrapper.find("input");
95-
assert.strictEqual(input.prop("value"), "abc");
112+
expect(input.value).to.equal("abc");
96113

97-
input.simulate("change", { target: { value: "abcd" } });
98-
input = wrapper.find("input");
99-
// value should not change because our change handler prevents it from being longer than characters
100-
assert.strictEqual(input.prop("value"), "abc");
101-
});
114+
userEvent.type(input, "d");
102115

103-
it("supports the onValueChange callback", () => {
104-
const initialValue = "value";
105-
const newValue = "new-value";
106-
const handleValueChange = spy();
107-
const inputGroup = mount(<InputGroup value={initialValue} onValueChange={handleValueChange} />);
108-
assert.strictEqual(inputGroup.find("input").prop("value"), initialValue);
109-
110-
inputGroup
111-
.find("input")
112-
.simulate("change", { currentTarget: { value: newValue }, target: { value: newValue } });
113-
assert.isTrue(handleValueChange.calledOnce, "onValueChange not called");
114-
assert.isTrue(handleValueChange.calledWithMatch(newValue), `onValueChange not called with '${newValue}'`);
116+
expect(input.value).to.equal("abc");
115117
});
116118
});

0 commit comments

Comments
 (0)