Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions packages/lib/src/search-bar/SearchBar.accessibility.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { render } from "@testing-library/react";
import DxcSearchBar from "./SearchBar";
import DxcSearchBarTrigger from "./SearchBarTrigger";
import { axe } from "../../test/accessibility/axe-helper";

describe("SearchBar component accessibility tests", () => {
it("Should not have basic accessibility issues", async () => {
const { container } = render(<DxcSearchBar />);
const results = await axe(container);
expect(results.violations).toHaveLength(0);
});

it("Should not have basic accessibility issues with placeholder", async () => {
const { container } = render(<DxcSearchBar placeholder="Search here..." />);
const results = await axe(container);
expect(results.violations).toHaveLength(0);
});

it("Should not have basic accessibility issues with disabled state", async () => {
const { container } = render(<DxcSearchBar disabled />);
const results = await axe(container);
expect(results.violations).toHaveLength(0);
});

it("Should not have basic accessibility issues with cancel button", async () => {
const { container } = render(<DxcSearchBar onCancel={() => {}} />);
const results = await axe(container);
expect(results.violations).toHaveLength(0);
});

it("Should not have basic accessibility issues with all props", async () => {
const { container } = render(
<DxcSearchBar
placeholder="Search items..."
onChange={() => {}}
onEnter={() => {}}
onBlur={() => {}}
onCancel={() => {}}
/>
);
const results = await axe(container);
expect(results.violations).toHaveLength(0);
});
});

describe("SearchBarTrigger component accessibility tests", () => {
it("Should not have basic accessibility issues", async () => {
const { container } = render(<DxcSearchBarTrigger />);
const results = await axe(container);
expect(results.violations).toHaveLength(0);
});

it("Should not have basic accessibility issues with onTriggerClick", async () => {
const { container } = render(<DxcSearchBarTrigger onTriggerClick={() => {}} />);
const results = await axe(container);
expect(results.violations).toHaveLength(0);
});
});
126 changes: 126 additions & 0 deletions packages/lib/src/search-bar/SearchBar.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { Meta, StoryObj } from "@storybook/react-vite";
import ExampleContainer from "../../.storybook/components/ExampleContainer";
import Title from "../../.storybook/components/Title";
import DxcSearchBarTrigger from "./SearchBarTrigger";
import { useState } from "react";
import DxcSearchBar from "./SearchBar";
import DxcFlex from "../flex/Flex";
import DxcContainer from "../container/Container";

export default {
title: "Searchbar",
component: DxcSearchBar,
} satisfies Meta<typeof DxcSearchBar>;

const SearchBarComponent = () => {
const [showSearch, setShowSearch] = useState(false);

return (
<DxcFlex alignItems="center">
{!showSearch ? (
<DxcSearchBarTrigger onTriggerClick={() => setShowSearch(!showSearch)} />
) : (
<DxcSearchBar
placeholder="Search..."
onBlur={(value) => {
console.log("onBlur", value);
}}
onChange={(value) => console.log("onChange", value)}
onEnter={(value) => {
console.log("onEnter", value);
setShowSearch(false);
}}
onCancel={() => setShowSearch(false)}
/>
)}
</DxcFlex>
);
};

const SearchBar = () => {
return (
<>
<Title title="Searchbar component" theme="light" level={2} />
<ExampleContainer>
<SearchBarComponent />
</ExampleContainer>

<Title title="States" theme="light" level={2} />
<ExampleContainer>
<Title title="Default" theme="light" level={4} />
<DxcSearchBar
placeholder="Search..."
onBlur={(value) => {
console.log("onBlur", value);
}}
onChange={(value) => console.log("onChange", value)}
onEnter={(value) => {
console.log("onEnter", value);
}}
/>
</ExampleContainer>
<ExampleContainer pseudoState="pseudo-hover">
<Title title="Hover" theme="light" level={4} />
<DxcSearchBar
placeholder="Search..."
onBlur={(value) => {
console.log("onBlur", value);
}}
onChange={(value) => console.log("onChange", value)}
onEnter={(value) => {
console.log("onEnter", value);
}}
/>
</ExampleContainer>
<ExampleContainer pseudoState="pseudo-focus-within">
<Title title="Focus" theme="light" level={4} />
<DxcSearchBar
placeholder="Search..."
onBlur={(value) => {
console.log("onBlur", value);
}}
onChange={(value) => console.log("onChange", value)}
onEnter={(value) => {
console.log("onEnter", value);
}}
/>
</ExampleContainer>
<ExampleContainer>
<Title title="Disabled" theme="light" level={4} />
<DxcSearchBar
placeholder="Search..."
onBlur={(value) => {
console.log("onBlur", value);
}}
onChange={(value) => console.log("onChange", value)}
onEnter={(value) => {
console.log("onEnter", value);
}}
disabled
/>
</ExampleContainer>

<Title title="Small Searchbar" theme="light" level={2} />
<ExampleContainer>
<DxcContainer width="220px">
<DxcSearchBar
placeholder="Search..."
onBlur={(value) => {
console.log("onBlur", value);
}}
onChange={(value) => console.log("onChange", value)}
onEnter={(value) => {
console.log("onEnter", value);
}}
/>
</DxcContainer>
</ExampleContainer>
</>
);
};

type Story = StoryObj<typeof DxcSearchBar>;

export const Chromatic: Story = {
render: SearchBar,
};
99 changes: 99 additions & 0 deletions packages/lib/src/search-bar/SearchBar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { render, fireEvent } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import DxcSearchBar from "./SearchBar";
import DxcSearchBarTrigger from "./SearchBarTrigger";

describe("SearchBarTrigger component tests", () => {
test("Renders correctly", () => {
const { getByRole } = render(<DxcSearchBarTrigger />);

const button = getByRole("button");
expect(button).toBeTruthy();
});

test("Calls onTriggerClick when button is clicked", () => {
const onTriggerClick = jest.fn();
const { getByRole } = render(<DxcSearchBarTrigger onTriggerClick={onTriggerClick} />);

const button = getByRole("button");
userEvent.click(button);

expect(onTriggerClick).toHaveBeenCalledTimes(1);
});
});

describe("SearchBar component tests", () => {
test("Renders correctly", () => {
const { getByPlaceholderText } = render(<DxcSearchBar placeholder="Search..." />);

const text = getByPlaceholderText("Search...");
expect(text).toBeTruthy();
});

test("Calls onChange when typing", () => {
const onChange = jest.fn();
const { getByRole } = render(<DxcSearchBar onChange={onChange} />);

const input = getByRole("textbox") as HTMLInputElement;
userEvent.type(input, "hello");

expect(onChange).toHaveBeenCalled();
expect(onChange).toHaveBeenLastCalledWith("hello");
});

test("Calls onEnter with value when pressing Enter", () => {
const onEnter = jest.fn();
const { getByRole } = render(<DxcSearchBar onEnter={onEnter} />);

const input = getByRole("textbox") as HTMLInputElement;
userEvent.type(input, "search text");
fireEvent.keyDown(input, { key: "Enter" });

expect(onEnter).toHaveBeenCalledTimes(1);
expect(onEnter).toHaveBeenCalledWith("search text");
});

test("Clears value when clicking clear icon", () => {
const { getByRole } = render(<DxcSearchBar />);

const input = getByRole("textbox") as HTMLInputElement;
userEvent.type(input, "abc");

const clearButton = getByRole("button");
expect(clearButton).toBeTruthy();

userEvent.click(clearButton);
expect(input.value).toBe("");
});

test("Clears value when pressing Escape", () => {
const { getByRole } = render(<DxcSearchBar />);

const input = getByRole("textbox") as HTMLInputElement;
userEvent.type(input, "xyz");
fireEvent.keyDown(input, { key: "Escape" });

expect(input.value).toBe("");
});

test("Calls onBlur with current value when blurred", () => {
const onBlur = jest.fn();
const { getByRole } = render(<DxcSearchBar onBlur={onBlur} />);

const input = getByRole("textbox") as HTMLInputElement;
userEvent.type(input, "blur me");
fireEvent.blur(input);

expect(onBlur).toHaveBeenCalledWith("blur me");
});

test("Calls onCancel when Cancel button is clicked", () => {
const onCancel = jest.fn();
const { getByRole } = render(<DxcSearchBar onCancel={onCancel} />);

const cancelButton = getByRole("button", { name: /Cancel/i });
userEvent.click(cancelButton);

expect(onCancel).toHaveBeenCalledTimes(1);
});
});
Loading