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 ? (
-