-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create a resuable combo box component to choose and search a particul…
…ar skill (#93) * feat: implement the combo box for common and for endorsements page, correct the test to add combo box in the endorsements page * feat:add the combo box and the mock values alogn with the unit andintegration test cases for this * fix:re-arrange the types values * fix:the typescript error of the value type and the null value in the tests * fix:prettier issue * fix:remove theunused var * fix:remove the unused var and fix the indentation * fix:prettier check * fix:prettier indentation error and lint error
- Loading branch information
Showing
14 changed files
with
1,419 additions
and
717 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export const ComboboxMockData = [ | ||
{ | ||
id: 1, | ||
name: "React", | ||
}, | ||
{ | ||
id: 2, | ||
name: "Go", | ||
}, | ||
{ | ||
id: 3, | ||
name: "Vanilla JS", | ||
}, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import React from "react"; | ||
import { render, fireEvent, screen, waitFor } from "@testing-library/react"; | ||
import { ComboboxMockData } from "../../../../__mocks__/combobox"; | ||
import ComboboxDropdown from "@/components/Combobox"; | ||
|
||
describe("Combobox Component", () => { | ||
it("should render with placeholder and dropdown closed", () => { | ||
render(<ComboboxDropdown options={ComboboxMockData} placeholder="placeholder" />); | ||
|
||
const input = screen.getByRole("combobox"); | ||
expect(input).toHaveAttribute("placeholder", "placeholder"); | ||
|
||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is not visible | ||
}); | ||
|
||
it("should open dropdown on button click and display the options", async () => { | ||
render(<ComboboxDropdown options={ComboboxMockData} placeholder="placeholder" />); | ||
|
||
const button = screen.getByRole("button"); | ||
|
||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is initially closed | ||
|
||
fireEvent.click(button); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for dropdown animation | ||
|
||
await screen.findByRole("listbox"); | ||
|
||
expect(screen.getByText("React")).toBeInTheDocument(); | ||
expect(screen.getByText("Go")).toBeInTheDocument(); | ||
expect(screen.getByText("Vanilla JS")).toBeInTheDocument(); | ||
}); | ||
|
||
it("Select a value from the combobox list", async () => { | ||
const onChangeMock = jest.fn(); | ||
render(<ComboboxDropdown options={ComboboxMockData} placeholder="placeholder" onChange={onChangeMock} />); | ||
const button = screen.getByRole("button"); | ||
|
||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is initially closed | ||
|
||
fireEvent.click(button); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for dropdown animation | ||
|
||
await screen.findByRole("listbox"); | ||
|
||
expect(screen.getByText("React")).toBeInTheDocument(); | ||
expect(screen.getByText("Go")).toBeInTheDocument(); | ||
expect(screen.getByText("Vanilla JS")).toBeInTheDocument(); | ||
|
||
fireEvent.click(screen.getByText("React")); | ||
expect(onChangeMock).toHaveBeenCalledWith({ id: 1, name: "React" }); | ||
}); | ||
|
||
it("filters the options based on input value", async () => { | ||
render(<ComboboxDropdown onChange={() => {}} placeholder="placeholder" options={ComboboxMockData} />); | ||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); | ||
const button = screen.getByRole("button"); | ||
fireEvent.click(button); | ||
await screen.findByRole("listbox"); | ||
|
||
const input = screen.getByPlaceholderText("placeholder"); | ||
fireEvent.change(input, { target: { value: "React", id: 1 } }); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByText("React")).toBeInTheDocument(); | ||
}); | ||
|
||
screen.debug(); | ||
}); | ||
|
||
it("Display No Results option when no options are present", async () => { | ||
render(<ComboboxDropdown options={ComboboxMockData} placeholder="placeholder" />); | ||
const input = screen.getByRole("combobox"); | ||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is initially closed | ||
|
||
fireEvent.change(input, { target: { value: "NonexistentSkill" } }); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for dropdown animation | ||
|
||
await screen.findByRole("listbox"); | ||
|
||
await screen.findByText("No Results"); | ||
|
||
expect(screen.getByText("No Results")).toBeInTheDocument(); | ||
}); | ||
|
||
it("Close the combo box when clicked outside", async () => { | ||
render( | ||
<div> | ||
<ComboboxDropdown onChange={() => {}} placeholder="placeholder" options={ComboboxMockData} /> | ||
<div data-testid="outside-element">Outside Element</div> | ||
</div> | ||
); | ||
|
||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); | ||
const button = screen.getByRole("button"); | ||
fireEvent.click(button); | ||
|
||
// Ensure the dropdown is open | ||
await screen.findByRole("listbox"); | ||
expect(screen.getByRole("listbox")).toBeInTheDocument(); | ||
|
||
const outsideElement = screen.getByTestId("outside-element"); | ||
fireEvent.mouseDown(outsideElement); | ||
fireEvent.mouseUp(outsideElement); | ||
fireEvent.click(outsideElement); | ||
|
||
// Wait for the dropdown to close | ||
await waitFor(() => { | ||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); | ||
}); | ||
}); | ||
}); |
123 changes: 123 additions & 0 deletions
123
__tests__/Unit/Componets/SkillComboBox/SkillComboBox.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import React from "react"; | ||
import { render, fireEvent, screen, waitFor } from "@testing-library/react"; | ||
import SkillCombobox from "@/components/SkillComboBox"; | ||
import { skillMockData } from "../../../../__mocks__/endorsements"; | ||
|
||
describe("SkillCombobox Component", () => { | ||
it("should render with placeholder and dropdown closed", () => { | ||
render(<SkillCombobox options={skillMockData} placeholder="select skill" />); | ||
|
||
const input = screen.getByRole("combobox"); | ||
expect(input).toHaveAttribute("placeholder", "select skill"); | ||
|
||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is not visible | ||
}); | ||
|
||
it("should open dropdown on button click and display the options", async () => { | ||
render(<SkillCombobox options={skillMockData} placeholder="select skill" />); | ||
|
||
const button = screen.getByRole("button"); | ||
|
||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is initially closed | ||
|
||
fireEvent.click(button); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for dropdown animation | ||
|
||
await screen.findByRole("listbox"); | ||
|
||
expect(screen.getByText("React")).toBeInTheDocument(); | ||
expect(screen.getByText("Go")).toBeInTheDocument(); | ||
expect(screen.getByText("Vanilla JS")).toBeInTheDocument(); | ||
}); | ||
|
||
it("Select a value from the combobox list", async () => { | ||
const onChangeMock = jest.fn(); | ||
render(<SkillCombobox options={skillMockData} placeholder="select skill" onChange={onChangeMock} />); | ||
const button = screen.getByRole("button"); | ||
|
||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is initially closed | ||
|
||
fireEvent.click(button); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for dropdown animation | ||
|
||
await screen.findByRole("listbox"); | ||
|
||
expect(screen.getByText("React")).toBeInTheDocument(); | ||
expect(screen.getByText("Go")).toBeInTheDocument(); | ||
expect(screen.getByText("Vanilla JS")).toBeInTheDocument(); | ||
|
||
fireEvent.click(screen.getByText("React")); | ||
expect(onChangeMock).toHaveBeenCalledWith({ id: 1, skill: "React" }); | ||
}); | ||
|
||
it("filters the options based on input value", async () => { | ||
render(<SkillCombobox onChange={() => {}} placeholder="select skill" options={skillMockData} />); | ||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); | ||
const button = screen.getByRole("button"); | ||
fireEvent.click(button); | ||
await screen.findByRole("listbox"); | ||
|
||
const input = screen.getByPlaceholderText("select skill"); | ||
fireEvent.change(input, { target: { value: "React", id: 1 } }); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByText("React")).toBeInTheDocument(); | ||
}); | ||
|
||
screen.debug(); | ||
}); | ||
|
||
it("Display Add new Skill option when no options are present and add new skill click perform action", async () => { | ||
const handleAddSkill = jest.fn(); | ||
|
||
render(<SkillCombobox options={skillMockData} placeholder="select skill" handleAddSkill={handleAddSkill} />); | ||
const input = screen.getByRole("combobox"); | ||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is initially closed | ||
|
||
fireEvent.change(input, { target: { value: "NonexistentSkill" } }); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for dropdown animation | ||
|
||
await screen.findByRole("listbox"); | ||
|
||
await screen.findByText("Add New Skill"); | ||
|
||
await fireEvent.click(screen.getByText("Add New Skill")); | ||
|
||
expect(handleAddSkill).toHaveBeenCalled(); | ||
}); | ||
|
||
it("Close the combo box when clicked outside", async () => { | ||
render( | ||
<div> | ||
<SkillCombobox | ||
onChange={() => {}} | ||
placeholder="select skill" | ||
options={skillMockData} | ||
handleAddSkill={() => {}} | ||
/> | ||
<div data-testid="outside-element">Outside Element</div> | ||
</div> | ||
); | ||
|
||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); | ||
const button = screen.getByRole("button"); | ||
fireEvent.click(button); | ||
|
||
// Ensure the dropdown is open | ||
await screen.findByRole("listbox"); | ||
expect(screen.getByRole("listbox")).toBeInTheDocument(); | ||
|
||
const outsideElement = screen.getByTestId("outside-element"); | ||
fireEvent.mouseDown(outsideElement); | ||
fireEvent.mouseUp(outsideElement); | ||
fireEvent.click(outsideElement); | ||
|
||
// Wait for the dropdown to close | ||
await waitFor(() => { | ||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import React from "react"; | ||
import { render, fireEvent, screen, waitFor } from "@testing-library/react"; | ||
import { ComboboxMockData } from "../../../__mocks__/combobox"; | ||
import ComboboxDropdown from "@/components/Combobox"; | ||
|
||
global.ResizeObserver = class { | ||
observe() {} | ||
unobserve() {} | ||
disconnect() {} | ||
}; | ||
|
||
describe("Combobox Component", () => { | ||
it("Should display combobox with placeholder and Down arrow icon", async () => { | ||
render(<ComboboxDropdown options={ComboboxMockData} placeholder="placeholder" />); | ||
|
||
expect(screen.getByRole("combobox")).toBeInTheDocument(); | ||
expect(screen.getByPlaceholderText("placeholder")).toBeInTheDocument(); | ||
expect(screen.getByAltText("expand")).toBeInTheDocument(); | ||
}); | ||
|
||
it("should open dropdown on button click and display the options", async () => { | ||
render(<ComboboxDropdown options={ComboboxMockData} placeholder="placeholder" />); | ||
|
||
const button = screen.getByRole("button"); | ||
|
||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is initially closed | ||
|
||
fireEvent.click(button); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for dropdown animation | ||
|
||
await screen.findByRole("listbox"); | ||
|
||
expect(screen.getByText("React")).toBeInTheDocument(); | ||
expect(screen.getByText("Go")).toBeInTheDocument(); | ||
expect(screen.getByText("Vanilla JS")).toBeInTheDocument(); | ||
}); | ||
|
||
it("Select a value from the combobox list", async () => { | ||
const onChangeMock = jest.fn(); | ||
render(<ComboboxDropdown options={ComboboxMockData} placeholder="placeholder" onChange={onChangeMock} />); | ||
const button = screen.getByRole("button"); | ||
|
||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is initially closed | ||
|
||
fireEvent.click(button); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for dropdown animation | ||
|
||
await screen.findByRole("listbox"); | ||
|
||
expect(screen.getByText("React")).toBeInTheDocument(); | ||
expect(screen.getByText("Go")).toBeInTheDocument(); | ||
expect(screen.getByText("Vanilla JS")).toBeInTheDocument(); | ||
|
||
fireEvent.click(screen.getByText("React")); | ||
expect(onChangeMock).toHaveBeenCalledWith({ id: 1, name: "React" }); | ||
}); | ||
|
||
it("filters the options based on input value", async () => { | ||
render(<ComboboxDropdown onChange={() => {}} placeholder="placeholder" options={ComboboxMockData} />); | ||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); | ||
const button = screen.getByRole("button"); | ||
fireEvent.click(button); | ||
await screen.findByRole("listbox"); | ||
|
||
const input = screen.getByPlaceholderText("placeholder"); | ||
fireEvent.change(input, { target: { value: "React", id: 1 } }); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByText("React")).toBeInTheDocument(); | ||
}); | ||
|
||
screen.debug(); | ||
}); | ||
|
||
it("Display No Results option when no options are present", async () => { | ||
render(<ComboboxDropdown options={ComboboxMockData} placeholder="placeholder" />); | ||
const input = screen.getByRole("combobox"); | ||
expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); // Check listbox is initially closed | ||
|
||
fireEvent.change(input, { target: { value: "NonexistentSkill" } }); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for dropdown animation | ||
|
||
await screen.findByRole("listbox"); | ||
|
||
await screen.findByText("No Results"); | ||
}); | ||
}); |
Oops, something went wrong.