Skip to content

Commit

Permalink
fix(filterable-select): ensure list does not reopen when user clicks …
Browse files Browse the repository at this point in the history
…option and openOnFocus prop set

Ensures that the `SelectList` does not reopen when a user selects and `Option` via clicking and the
`openOnFocus` prop is set.

fix #6462
  • Loading branch information
edleeks87 committed Dec 8, 2023
1 parent 560c4b5 commit 9913d7c
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,18 @@ context("Tests for FilterableSelect component", () => {
selectListWrapper().should("be.visible");
});

it("should not reopen list when openOnFocus set and user selects an option via click", () => {
CypressMountWithProviders(
<stories.FilterableSelectComponent openOnFocus />
);

commonDataElementInputPreview().focus();
selectInput().should("have.attr", "aria-expanded", "true");
selectListWrapper().should("be.visible");
selectOption(positionOfElement("first")).click();
selectListWrapper().should("not.be.visible");
});

it("should check list is open when input is clicked and openOnFocus is set", () => {
CypressMountWithProviders(
<stories.FilterableSelectComponent openOnFocus />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export const FilterableSelect = React.forwardRef(
label,
});
const focusTimer = useRef<null | ReturnType<typeof setTimeout>>(null);
const openOnFocusFlagBlock = useRef(false);

if (!deprecateInputRefWarnTriggered && inputRef) {
deprecateInputRefWarnTriggered = true;
Expand Down Expand Up @@ -478,12 +479,13 @@ export const FilterableSelect = React.forwardRef(
setActiveDescendantId(selectedOptionId);

if (selectionType !== "navigationKey") {
openOnFocusFlagBlock.current = !!openOnFocus;
setOpen(false);
textboxRef?.focus();
textboxRef?.select();
}
},
[textboxRef, triggerChange]
[textboxRef, triggerChange, openOnFocus]
);

const onSelectListClose = useCallback(() => {
Expand Down Expand Up @@ -521,6 +523,11 @@ export const FilterableSelect = React.forwardRef(
clearTimeout(focusTimer.current);
}

if (openOnFocusFlagBlock.current) {
openOnFocusFlagBlock.current = false;
return;
}

// we need to use a timeout here as there is a race condition when rendered in a modal
// whereby the select list isn't visible when the select is auto focused straight away
focusTimer.current = setTimeout(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,19 @@ describe("FilterableSelect", () => {

describe('when the "openOnFocus" prop is set', () => {
describe("and the Textbox Input is focused", () => {
it("the SelectList should be rendered", () => {
it("should render the SelectList", () => {
const wrapper = renderSelect({ openOnFocus: true });

act(() => {
wrapper.find("input").simulate("focus");
jest.runOnlyPendingTimers();
});
wrapper
.find(Option)
.forEach((option) => expect(option.getDOMNode()).toBeVisible());
});

it("should not reopen the SelectList when a user selects and Option by clicking", () => {
const wrapper = renderSelect({ openOnFocus: true });

act(() => {
Expand All @@ -1107,6 +1119,23 @@ describe("FilterableSelect", () => {
wrapper
.find(Option)
.forEach((option) => expect(option.getDOMNode()).toBeVisible());
act(() => {
wrapper.find(SelectList).prop("onSelect")({
value: "opt1",
text: "red",
selectionType: "click",
selectionConfirmed: true,
});
});
act(() => {
// need to programatically focus again here to hit coverage
wrapper.find("input").simulate("focus");
jest.runOnlyPendingTimers();
});
wrapper
.update()
.find(Option)
.forEach((option) => expect(option.getDOMNode()).not.toBeVisible());
});

describe.each(["readOnly", "disabled"])(
Expand Down

0 comments on commit 9913d7c

Please sign in to comment.