Fix the broken deeplink of support form
Summary: I just noticed that the deeplink of the support form didn't select the right group. It got broken after the recent design change of the support form. This diff fixes that issue. I have also added unit tests. Reviewed By: passy Differential Revision: D21817153 fbshipit-source-id: 06298b3b60cfc1bd77bea6c1f902b983474808dc
This commit is contained in:
committed by
Facebook GitHub Bot
parent
3c97c1d3bc
commit
965a36ee52
@@ -71,6 +71,7 @@ function RowComponent(props: {
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<RowComponentContainer
|
<RowComponentContainer
|
||||||
|
data-testid={'row-component'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.onClick(props.elem.id);
|
props.onClick(props.elem.id);
|
||||||
}}>
|
}}>
|
||||||
@@ -85,15 +86,11 @@ function RowComponent(props: {
|
|||||||
|
|
||||||
export default function (props: Props) {
|
export default function (props: Props) {
|
||||||
const {list, handleNoResults, onSelect, selectedElementID} = props;
|
const {list, handleNoResults, onSelect, selectedElementID} = props;
|
||||||
const initialElement = list.find((e) => {
|
|
||||||
return e.id === selectedElementID;
|
|
||||||
});
|
|
||||||
const [filteredElements, setFilteredElements] = useState<Array<Element>>([]);
|
const [filteredElements, setFilteredElements] = useState<Array<Element>>([]);
|
||||||
const [searchedValue, setSearchedValue] = useState<string>(
|
const [searchedValue, setSearchedValue] = useState<string>('');
|
||||||
initialElement ? initialElement.label : '',
|
|
||||||
);
|
|
||||||
const [selectedElement, setSelectedElement] = useState<Element | undefined>(
|
const [selectedElement, setSelectedElement] = useState<Element | undefined>(
|
||||||
initialElement,
|
undefined,
|
||||||
);
|
);
|
||||||
const [focussed, setFocus] = useState<boolean>(false);
|
const [focussed, setFocus] = useState<boolean>(false);
|
||||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -129,6 +126,16 @@ export default function (props: Props) {
|
|||||||
[setFocus],
|
[setFocus],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Set the searched value and selectedElement when the selectedElementID changes.
|
||||||
|
useEffect(() => {
|
||||||
|
const initialElement = list.find((e) => e.id === selectedElementID);
|
||||||
|
if (initialElement) {
|
||||||
|
setSearchedValue(initialElement.label);
|
||||||
|
}
|
||||||
|
setSelectedElement(initialElement);
|
||||||
|
setFocus(false);
|
||||||
|
}, [selectedElementID, list]);
|
||||||
|
|
||||||
// Effect to filter items
|
// Effect to filter items
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (searchedValue.length > 0) {
|
if (searchedValue.length > 0) {
|
||||||
@@ -195,6 +202,7 @@ export default function (props: Props) {
|
|||||||
onFocus={onFocusCallBack}
|
onFocus={onFocusCallBack}
|
||||||
value={searchedValue}
|
value={searchedValue}
|
||||||
isValidInput={false}
|
isValidInput={false}
|
||||||
|
data-testid={'search-input'}
|
||||||
/>
|
/>
|
||||||
</SearchBox>
|
</SearchBox>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -203,14 +211,14 @@ export default function (props: Props) {
|
|||||||
<ListViewContainer scrollable={true}>
|
<ListViewContainer scrollable={true}>
|
||||||
{filteredElements.map((e, idx) => {
|
{filteredElements.map((e, idx) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<FlexColumn key={idx}>
|
||||||
<RowComponent
|
<RowComponent
|
||||||
elem={e}
|
elem={e}
|
||||||
onClick={onSelectCallBack}
|
onClick={onSelectCallBack}
|
||||||
selected={selectedElement && e.id == selectedElement.id}
|
selected={selectedElement && e.id == selectedElement.id}
|
||||||
/>
|
/>
|
||||||
{idx < filteredElements.length - 1 && <Separator />}
|
{idx < filteredElements.length - 1 && <Separator />}
|
||||||
</>
|
</FlexColumn>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ListViewContainer>
|
</ListViewContainer>
|
||||||
|
|||||||
173
desktop/app/src/chrome/__tests__/DropDownSearchView.node.tsx
Normal file
173
desktop/app/src/chrome/__tests__/DropDownSearchView.node.tsx
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import {render, fireEvent} from '@testing-library/react';
|
||||||
|
import DropDownSearchView from '../DropDownSearchView';
|
||||||
|
import {act} from 'react-dom/test-utils';
|
||||||
|
|
||||||
|
test('Test selected element id is shown as the selected one.', async () => {
|
||||||
|
const res = render(
|
||||||
|
<DropDownSearchView
|
||||||
|
list={[{id: 'id1', label: 'label1'}]}
|
||||||
|
onSelect={jest.fn()}
|
||||||
|
handleNoResults={jest.fn()}
|
||||||
|
selectedElementID={'id1'}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
const searchInput = (await res.findByTestId(
|
||||||
|
'search-input',
|
||||||
|
)) as HTMLInputElement;
|
||||||
|
expect(searchInput).toBeTruthy();
|
||||||
|
expect(searchInput.value).toEqual('label1');
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
searchInput.dispatchEvent(new FocusEvent('focus', {bubbles: true}));
|
||||||
|
});
|
||||||
|
expect(await res.queryByText('label1')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test the change of the selectedElementID changes the the selected element in the UI.', async () => {
|
||||||
|
const res = render(
|
||||||
|
<DropDownSearchView
|
||||||
|
list={[
|
||||||
|
{id: 'id1', label: 'label1'},
|
||||||
|
{id: 'id2', label: 'label2'},
|
||||||
|
]}
|
||||||
|
onSelect={jest.fn()}
|
||||||
|
handleNoResults={jest.fn()}
|
||||||
|
selectedElementID={'id1'}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
const searchInput = (await res.findByTestId(
|
||||||
|
'search-input',
|
||||||
|
)) as HTMLInputElement;
|
||||||
|
expect(searchInput).toBeTruthy();
|
||||||
|
expect(searchInput.value).toEqual('label1');
|
||||||
|
|
||||||
|
res.rerender(
|
||||||
|
<DropDownSearchView
|
||||||
|
list={[
|
||||||
|
{id: 'id1', label: 'label1'},
|
||||||
|
{id: 'id2', label: 'label2'},
|
||||||
|
]}
|
||||||
|
onSelect={jest.fn()}
|
||||||
|
handleNoResults={jest.fn()}
|
||||||
|
selectedElementID={'id2'}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
const searchInputRerendered = (await res.findByTestId(
|
||||||
|
'search-input',
|
||||||
|
)) as HTMLInputElement;
|
||||||
|
expect(searchInputRerendered).toBeTruthy();
|
||||||
|
expect(searchInputRerendered.value).toEqual('label2');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test the entire flow and click on the available options.', async () => {
|
||||||
|
const onSelect = jest.fn();
|
||||||
|
const res = render(
|
||||||
|
<DropDownSearchView
|
||||||
|
list={[
|
||||||
|
{id: 'id1', label: 'label1'},
|
||||||
|
{id: 'id2', label: 'label2'},
|
||||||
|
{id: 'id3', label: 'label3'},
|
||||||
|
{id: 'id4', label: 'label4'},
|
||||||
|
]}
|
||||||
|
onSelect={onSelect}
|
||||||
|
handleNoResults={jest.fn()}
|
||||||
|
selectedElementID={'id1'}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
const searchInput = (await res.findByTestId(
|
||||||
|
'search-input',
|
||||||
|
)) as HTMLInputElement;
|
||||||
|
expect(searchInput).toBeTruthy();
|
||||||
|
expect(searchInput.value).toEqual('label1');
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
searchInput.dispatchEvent(new FocusEvent('focus', {bubbles: true}));
|
||||||
|
});
|
||||||
|
// Right now just the filtered elements will show up
|
||||||
|
expect(await res.queryByText('label1')).toBeTruthy();
|
||||||
|
expect(await res.queryByText('label2')).toBeFalsy();
|
||||||
|
expect(await res.queryByText('label3')).toBeFalsy();
|
||||||
|
expect(await res.queryByText('label4')).toBeFalsy();
|
||||||
|
act(() => {
|
||||||
|
fireEvent.change(searchInput, {target: {value: ''}});
|
||||||
|
});
|
||||||
|
// Once the input field is cleared all the available options will show up.
|
||||||
|
expect(await res.queryByText('label1')).toBeTruthy();
|
||||||
|
expect(await res.queryByText('label2')).toBeTruthy();
|
||||||
|
expect(await res.queryByText('label3')).toBeTruthy();
|
||||||
|
const text4 = await res.queryByText('label4');
|
||||||
|
|
||||||
|
expect(text4).toBeTruthy();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
text4?.parentElement?.dispatchEvent(
|
||||||
|
new MouseEvent('click', {bubbles: true}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(searchInput.value).toEqual('label4');
|
||||||
|
expect(onSelect).toBeCalledTimes(1);
|
||||||
|
// After onSelect the expanded menu gets closed.
|
||||||
|
expect(await res.queryByText('label1')).toBeFalsy();
|
||||||
|
expect(await res.queryByText('label2')).toBeFalsy();
|
||||||
|
expect(await res.queryByText('label3')).toBeFalsy();
|
||||||
|
expect(await res.queryByText('label4')).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test the validation error.', async () => {
|
||||||
|
const handleNoResults = jest.fn();
|
||||||
|
const res = render(
|
||||||
|
<DropDownSearchView
|
||||||
|
list={[
|
||||||
|
{id: 'id1', label: 'label1 group'},
|
||||||
|
{id: 'id2', label: 'label2 group'},
|
||||||
|
{id: 'id3', label: 'label3 support'},
|
||||||
|
{id: 'id4', label: 'label4 support'},
|
||||||
|
]}
|
||||||
|
handleNoResults={handleNoResults}
|
||||||
|
selectedElementID={undefined}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
const searchInput = (await res.findByTestId(
|
||||||
|
'search-input',
|
||||||
|
)) as HTMLInputElement;
|
||||||
|
expect(searchInput).toBeTruthy();
|
||||||
|
expect(searchInput.value).toEqual('');
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
searchInput.dispatchEvent(new FocusEvent('focus', {bubbles: true}));
|
||||||
|
});
|
||||||
|
// Right now just the filtered elements will show up
|
||||||
|
expect(await res.queryByText('label1 group')).toBeTruthy();
|
||||||
|
expect(await res.queryByText('label2 group')).toBeTruthy();
|
||||||
|
expect(await res.queryByText('label3 support')).toBeTruthy();
|
||||||
|
expect(await res.queryByText('label4 support')).toBeTruthy();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.change(searchInput, {target: {value: 'support'}});
|
||||||
|
});
|
||||||
|
// Only the items which satisfy the search query should be shown
|
||||||
|
expect(await res.queryByText('label3 support')).toBeTruthy();
|
||||||
|
expect(await res.queryByText('label4 support')).toBeTruthy();
|
||||||
|
expect(await res.queryByText('label1 group')).toBeFalsy();
|
||||||
|
expect(await res.queryByText('label2 group')).toBeFalsy();
|
||||||
|
act(() => {
|
||||||
|
fireEvent.change(searchInput, {target: {value: 'gibberish'}});
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(handleNoResults).toBeCalled();
|
||||||
|
expect(await res.queryByText('label3 support')).toBeFalsy();
|
||||||
|
expect(await res.queryByText('label4 support')).toBeFalsy();
|
||||||
|
expect(await res.queryByText('label1 group')).toBeFalsy();
|
||||||
|
expect(await res.queryByText('label2 group')).toBeFalsy();
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user