Skip to content

Commit

Permalink
Merge pull request #1286 from syucream/fix/avoid-flicking-attrs
Browse files Browse the repository at this point in the history
Avoid flicking on attr condition field
  • Loading branch information
userlocalhost authored Oct 3, 2024
2 parents 04dcaf2 + 626dc2e commit 5ec567b
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 45 deletions.
22 changes: 21 additions & 1 deletion frontend/src/components/common/AutocompleteWithAllSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import {
FilterOptionsState,
} from "@mui/material";
import { AutocompleteProps } from "@mui/material/Autocomplete/Autocomplete";
import React, { HTMLAttributes, SyntheticEvent, useMemo, useRef } from "react";
import React, {
HTMLAttributes,
SyntheticEvent,
useEffect,
useMemo,
useRef,
} from "react";

type SelectorOption = "select-all" | "remove-all";

Expand Down Expand Up @@ -49,6 +55,7 @@ export const AutocompleteWithAllSelector = <
const {
options,
value,
disabled,
onChange,
}: AutocompleteProps<T | SelectorOption, true, DisableClearable, FreeSolo> =
autocompleteProps;
Expand All @@ -66,6 +73,19 @@ export const AutocompleteWithAllSelector = <
return createFilterOptions<T | SelectorOption>();
}, []);

useEffect(() => {
// reset on re-enable
if (!disabled) {
if (onChange != null) {
onChange({} as SyntheticEvent, [], "clear");
}
filterOptionResult.current = {
query: "",
results: options as Array<T | SelectorOption>,
};
}
}, [disabled]);

const handleChange = (
event: SyntheticEvent,
value: Array<
Expand Down
70 changes: 46 additions & 24 deletions frontend/src/pages/AdvancedSearchPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,17 @@ describe("AdvancedSearchPage", () => {
// This is a thip to close options of Entities that are shown above.
// make an event to press Escape key using fireEvent
// fireEvent.click(document.body); // this doesn't work :(
fireEvent.keyDown(elemInputEntity, { key: "Escape" });

if (elemInputEntityAttr.parentNode) {
fireEvent.click(elemInputEntityAttr.parentNode);
} else {
throw new Error("Parent node not found");
}
await act(async () => {
fireEvent.keyDown(elemInputEntity, { key: "Escape" });
});

await act(async () => {
if (elemInputEntityAttr.parentNode) {
fireEvent.click(elemInputEntityAttr.parentNode);
} else {
throw new Error("Parent node not found");
}
});

const options = screen.getAllByRole("option");

Expand All @@ -162,21 +166,27 @@ describe("AdvancedSearchPage", () => {

test("select 'Select All' in entity attr element", async () => {
const elemInputEntity = screen.getByPlaceholderText("モデルを選択");
fireEvent.change(elemInputEntity, { target: { value: "2" } });
await act(async () => {
fireEvent.change(elemInputEntity, { target: { value: "2" } });
});

const optionsEntity = screen.getAllByRole("option");
fireEvent.click(optionsEntity[0]);
fireEvent.keyDown(elemInputEntity, { key: "Escape" });
await act(async () => {
fireEvent.click(optionsEntity[0]);
fireEvent.keyDown(elemInputEntity, { key: "Escape" });
});

const elemInputEntityAttr = await screen.findByPlaceholderText(
"属性を選択"
);

if (elemInputEntityAttr.parentNode) {
fireEvent.click(elemInputEntityAttr.parentNode);
} else {
throw new Error("Parent node not found");
}
await act(async () => {
if (elemInputEntityAttr.parentNode) {
fireEvent.click(elemInputEntityAttr.parentNode);
} else {
throw new Error("Parent node not found");
}
});

const options = screen.getAllByRole("option");

Expand All @@ -185,7 +195,10 @@ describe("AdvancedSearchPage", () => {
expect(options[1]).toHaveTextContent("str");
expect(options[2]).toHaveTextContent("obj");

fireEvent.click(options[0]);
await act(async () => {
fireEvent.click(options[0]);
});

if (elemInputEntityAttr.parentNode instanceof HTMLElement) {
const selectedEntity = within(
elemInputEntityAttr.parentNode
Expand All @@ -211,7 +224,9 @@ describe("AdvancedSearchPage", () => {
"属性を選択"
);

fireEvent.change(elemInputEntityAttr, { target: { value: "str" } });
await act(async () => {
fireEvent.change(elemInputEntityAttr, { target: { value: "str" } });
});

const options = screen.getAllByRole("option");

Expand All @@ -232,7 +247,9 @@ describe("AdvancedSearchPage", () => {
"属性を選択"
);

fireEvent.change(elemInputEntityAttr, { target: { value: "hoge" } });
await act(async () => {
fireEvent.change(elemInputEntityAttr, { target: { value: "hoge" } });
});

const options = screen.getAllByRole("option");

Expand All @@ -245,24 +262,29 @@ describe("AdvancedSearchPage", () => {
fireEvent.change(elemInputEntity, { target: { value: "2" } });

const optionsEntity = screen.getAllByRole("option");
fireEvent.click(optionsEntity[0]);
fireEvent.keyDown(elemInputEntity, { key: "Escape" });
await act(async () => {
fireEvent.click(optionsEntity[0]);
fireEvent.keyDown(elemInputEntity, { key: "Escape" });
});

const elemInputEntityAttr = await screen.findByPlaceholderText(
"属性を選択"
);

fireEvent.change(elemInputEntityAttr, { target: { value: "str" } });
await act(async () => {
fireEvent.change(elemInputEntityAttr, { target: { value: "str" } });
});

const optionsEntityAttr = screen.getAllByRole("option");
fireEvent.click(optionsEntityAttr[0]);
fireEvent.keyDown(elemInputEntityAttr, { key: "Escape" });
await act(async () => {
fireEvent.click(optionsEntityAttr[0]);
fireEvent.keyDown(elemInputEntityAttr, { key: "Escape" });
});

const elemSubmitButton = screen.getByText("検索");
// check href attribute of the button
// URL decode the href string
const parameter = decodeURI(elemSubmitButton.getAttribute("href") ?? "");
console.log(parameter);
expect(parameter).toBe(
"/ui/advanced_search_result" +
"?entity=2" +
Expand Down
39 changes: 19 additions & 20 deletions frontend/src/pages/AdvancedSearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,26 +167,25 @@ export const AdvancedSearchPage: FC = () => {
<StyledFlexColumnBox>
<StyledTypography variant="h4">属性</StyledTypography>

{!attrs.loading && (
<AutocompleteWithAllSelector
selectAllLabel="すべて選択"
options={attrs.value ?? []}
value={selectedAttrs}
inputValue={attrName}
onChange={(_, value: Array<string>) => setSelectedAttrs(value)}
onInputChange={handleChangeInputAttrName}
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
placeholder="属性を選択"
/>
)}
multiple
disableCloseOnSelect
fullWidth
/>
)}
<AutocompleteWithAllSelector
selectAllLabel="すべて選択"
options={attrs.value ?? []}
value={selectedAttrs}
inputValue={attrName}
disabled={attrs.loading}
onChange={(_, value: Array<string>) => setSelectedAttrs(value)}
onInputChange={handleChangeInputAttrName}
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
placeholder="属性を選択"
/>
)}
multiple
disableCloseOnSelect
fullWidth
/>
<Box>
参照アイテムも含める
<Checkbox
Expand Down

0 comments on commit 5ec567b

Please sign in to comment.