diff --git a/app/client/packages/design-system/widgets-old/package.json b/app/client/packages/design-system/widgets-old/package.json index 90d7c6dbf8a4..5ec161524594 100644 --- a/app/client/packages/design-system/widgets-old/package.json +++ b/app/client/packages/design-system/widgets-old/package.json @@ -7,11 +7,16 @@ "license": "Apache-2.0", "scripts": { "lint": "yarn g:lint", - "prettier": "yarn g:prettier" + "prettier": "yarn g:prettier", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage" }, "devDependencies": { "@svgr/webpack": "5.5.0", + "@testing-library/jest-dom": "^6.5.0", "@types/emoji-mart": "3.0.4", + "@types/jest": "^29.5.13", "@types/loadable__component": "^5.13.4", "@types/react-form": "^4.0.2", "@types/react-table": "*", @@ -20,9 +25,12 @@ "eslint-config-react": "^1.1.7", "eslint-plugin-storybook": "^0.6.8", "identity-obj-proxy": "3.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", "playwright": "^1.25.1", "postcss": "^8.4.31", "postcss-import": "^14.1.0", + "ts-jest": "^29.2.5", "tsconfig-paths-webpack-plugin": "^3.5.2" }, "peerDependencies": { diff --git a/app/client/packages/design-system/widgets-old/src/SearchComponent/index.test.tsx b/app/client/packages/design-system/widgets-old/src/SearchComponent/index.test.tsx new file mode 100644 index 000000000000..139fd5c99e04 --- /dev/null +++ b/app/client/packages/design-system/widgets-old/src/SearchComponent/index.test.tsx @@ -0,0 +1,66 @@ +import React from "react"; +import { render, fireEvent, screen } from "@testing-library/react"; +import SearchComponent from "../SearchComponent"; +import "@testing-library/jest-dom"; + +jest.mock("lodash", () => ({ + debounce: (fn: any) => fn, +})); + +jest.mock("../utils/icon-loadables", () => ({ + importSvg: jest.fn().mockReturnValue(() => ), +})); + +describe("SearchComponent", () => { + const onSearchMock = jest.fn(); + + const renderComponent = (props = {}) => { + return render( + , + ); + }; + + it("1.should clear the search value and trigger onSearch with an empty value when the cross icon is clicked anh have focused", () => { + const { getByPlaceholderText, getByTestId } = renderComponent({ + enableClientSideSearch: true, + value: "test", + }); + const inputElement = screen.getByPlaceholderText( + "Search...", + ) as HTMLInputElement; + const clearButton = screen.getByTestId("cross-icon"); + + fireEvent.click(clearButton); + + expect(inputElement).toHaveFocus(); + expect(inputElement.value).toBe(""); + expect(onSearchMock).toHaveBeenCalledWith(""); + }); + + it("2.should reset localValue when component receives a new value prop", () => { + const { getByPlaceholderText, rerender } = renderComponent({ + value: "initial", + }); + + const inputElement = screen.getByPlaceholderText( + "Search...", + ) as HTMLInputElement; + + expect(inputElement.value).toBe("initial"); + + rerender( + , + ); + + expect(inputElement.value).toBe("updated"); + }); +}); diff --git a/app/client/packages/design-system/widgets-old/src/SearchComponent/index.tsx b/app/client/packages/design-system/widgets-old/src/SearchComponent/index.tsx index ab51942ff46b..3aa6543b6236 100644 --- a/app/client/packages/design-system/widgets-old/src/SearchComponent/index.tsx +++ b/app/client/packages/design-system/widgets-old/src/SearchComponent/index.tsx @@ -86,6 +86,7 @@ class SearchComponent extends React.Component< SearchProps, { localValue: string } > { + private inputRef = React.createRef(); onDebouncedSearch = debounce(this.props.onSearch, 400); constructor(props: SearchProps) { super(props); @@ -113,6 +114,10 @@ class SearchComponent extends React.Component< clearSearch = () => { this.setState({ localValue: "" }); this.onDebouncedSearch(""); + + if (this.inputRef.current) { + this.inputRef.current.focus(); + } }; render() { @@ -121,6 +126,7 @@ class SearchComponent extends React.Component< filter ? ( -