mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
add debounced search on type to the search bar (#2703)
* debounced search on type * loading workspaces on page entry * fixing e2e test * removing boilerplate
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import { fireEvent, screen } from "@testing-library/react"
|
||||
import userEvent from "@testing-library/user-event"
|
||||
import { render } from "../../testHelpers/renderHelpers"
|
||||
import { SearchBarWithFilter } from "./SearchBarWithFilter"
|
||||
|
||||
// mock the debounce utility
|
||||
jest.mock("just-debounce-it", () =>
|
||||
jest.fn((fn) => {
|
||||
fn.cancel = jest.fn()
|
||||
return fn
|
||||
}),
|
||||
)
|
||||
|
||||
describe("SearchBarWithFilter", () => {
|
||||
it("calls the onFilter handler on keystroke", async () => {
|
||||
// When
|
||||
const onFilter = jest.fn()
|
||||
render(<SearchBarWithFilter onFilter={onFilter} />)
|
||||
|
||||
const searchInput = screen.getByRole("textbox")
|
||||
await userEvent.type(searchInput, "workspace") // 9 characters
|
||||
|
||||
// Then
|
||||
expect(onFilter).toBeCalledTimes(10) // 9 characters + 1 on component mount
|
||||
})
|
||||
|
||||
it("calls the onFilter handler on submit", async () => {
|
||||
// When
|
||||
const onFilter = jest.fn()
|
||||
render(<SearchBarWithFilter onFilter={onFilter} />)
|
||||
|
||||
const searchInput = screen.getByRole("textbox")
|
||||
await fireEvent.keyDown(searchInput, { key: "Enter", code: "Enter", charCode: 13 })
|
||||
|
||||
// Then
|
||||
expect(onFilter).toBeCalledTimes(1)
|
||||
})
|
||||
})
|
||||
@@ -7,7 +7,8 @@ import { makeStyles } from "@material-ui/core/styles"
|
||||
import TextField from "@material-ui/core/TextField"
|
||||
import SearchIcon from "@material-ui/icons/Search"
|
||||
import { FormikErrors, useFormik } from "formik"
|
||||
import { useState } from "react"
|
||||
import debounce from "just-debounce-it"
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
import { getValidationErrorMessage } from "../../api/errors"
|
||||
import { getFormHelpers } from "../../util/formUtils"
|
||||
import { CloseDropdown, OpenDropdown } from "../DropdownArrows/DropdownArrows"
|
||||
@@ -53,6 +54,23 @@ export const SearchBarWithFilter: React.FC<SearchBarWithFilterProps> = ({
|
||||
},
|
||||
})
|
||||
|
||||
// debounce query string entry by user
|
||||
// we want the dependency array empty here
|
||||
// as we don't need to redefine the function
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const debouncedOnFilter = useCallback(
|
||||
debounce((debouncedQueryString: string) => {
|
||||
onFilter(debouncedQueryString)
|
||||
}, 300),
|
||||
[],
|
||||
)
|
||||
|
||||
// update the query params while typing
|
||||
useEffect(() => {
|
||||
debouncedOnFilter(form.values.query)
|
||||
return () => debouncedOnFilter.cancel()
|
||||
}, [debouncedOnFilter, form.values.query])
|
||||
|
||||
const getFieldHelpers = getFormHelpers<FilterFormValues>(form)
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
|
||||
|
||||
@@ -12,6 +12,7 @@ const WorkspacesPage: FC = () => {
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const { workspaceRefs } = workspacesState.context
|
||||
|
||||
// On page load, populate the table with workspaces
|
||||
useEffect(() => {
|
||||
const filter = searchParams.get("filter")
|
||||
const query = filter ?? workspaceFilterQuery.me
|
||||
@@ -20,7 +21,8 @@ const WorkspacesPage: FC = () => {
|
||||
type: "GET_WORKSPACES",
|
||||
query,
|
||||
})
|
||||
}, [searchParams, send])
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -33,8 +35,11 @@ const WorkspacesPage: FC = () => {
|
||||
loading={workspacesState.hasTag("loading")}
|
||||
workspaceRefs={workspaceRefs}
|
||||
onFilter={(query) => {
|
||||
searchParams.set("filter", query)
|
||||
setSearchParams(searchParams)
|
||||
setSearchParams({ filter: query })
|
||||
send({
|
||||
type: "GET_WORKSPACES",
|
||||
query,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user