New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: fix selectPicker when search is controlled and exit Dropdown wit… #2411
Conversation
…hout resetting external search
@myNameIsDu is attempting to deploy a commit to the rsuite Team on Vercel. A member of the Team first needs to authorize it. |
This pull request is being automatically deployed with Vercel (learn more). rsuite-nextjs – ./docs🔍 Inspect: https://vercel.com/rsuite/rsuite-nextjs/B3pvCDUNtue8MQm1XW5UQnihDdrK rsuite-v4 – ./docs🔍 Inspect: https://vercel.com/rsuite/rsuite-v4/CPUtsZ5qGpDXvcMSbcoSRFJgKcF7 [Deployment for b3793f9 canceled] |
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit d7653ee:
|
Codecov Report
@@ Coverage Diff @@
## main #2411 +/- ##
==========================================
+ Coverage 85.54% 85.59% +0.04%
==========================================
Files 274 275 +1
Lines 8648 8655 +7
Branches 2428 2433 +5
==========================================
+ Hits 7398 7408 +10
+ Misses 660 658 -2
+ Partials 590 589 -1
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
src/SelectPicker/SelectPicker.tsx
Outdated
@@ -288,6 +288,7 @@ const SelectPicker = React.forwardRef( | |||
const handleExited = useCallback(() => { | |||
setSearchKeyword(''); | |||
setActive(false); | |||
onSearch?.(''); | |||
onClose?.(); | |||
}, [onClose, setSearchKeyword]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
React Hook useCallback has a missing dependency: 'onSearch'. Either include it or remove the dependency array
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah,I added it.
afterEach(() => { | ||
cleanup(); | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cleanup()
is unnecessary here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah,I removed it
it('SearchWord should be reset when controlled and triggered off', done => { | ||
let searchRef = ''; | ||
let onClose = null; | ||
const promise = new Promise(resolve => { | ||
onClose = resolve; | ||
}); | ||
const Wrapper = () => { | ||
const [search, setSearch] = useState(searchRef); | ||
const containerRef = useRef(); | ||
searchRef = search; | ||
const handleSearch = value => { | ||
setSearch(value); | ||
}; | ||
const handleClose = () => { | ||
onClose(); | ||
}; | ||
const container = () => containerRef.current; | ||
return ( | ||
<div ref={containerRef}> | ||
<button id="exit">exit</button> | ||
<SelectPicker | ||
container={container} | ||
search={search} | ||
defaultOpen | ||
onClose={handleClose} | ||
onSearch={handleSearch} | ||
data={data} | ||
/> | ||
</div> | ||
); | ||
}; | ||
Wrapper.displayName = 'WrapperSelectPicker'; | ||
const { container } = render(<Wrapper />); | ||
|
||
const exit = container?.querySelector('#exit'); | ||
const input = container.querySelector('.rs-picker-search-bar-input'); | ||
|
||
// change search | ||
fireEvent.change(input, { target: { value: 'a' } }); | ||
assert.equal(searchRef, 'a'); | ||
|
||
// close select | ||
fireEvent.mouseDown(exit, { bubbles: true }); | ||
|
||
promise.then(() => { | ||
assert.equal(searchRef, ''); | ||
done(); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please refer to existing test scripts and see how to use sinon.spy()
to validate a callback has been called with correct arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I modified it, but I think this test code does not reflect its operation scenario, How do you think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean the way this is written should not be suitable for such a description, should is "shoule call onSearch when closed", or other
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean the way this is written should not be suitable for such a description, should is "shoule call onSearch when closed", or other
The description was not quite suitable in the first place. "Should call onSearch with '' when closed" is exactly what should be tested here. The goal of unit tests is to make sure the APIs we provide (onSearch
) work as expected (called with '' when closed), rather than to cover how users are using our APIs (e.g. updating a state when onSearch is called).
bfd9b2d
to
61cd20f
Compare
await waitForElementToBeRemoved(document.querySelector('.rs-picker-search-bar-input')); | ||
|
||
assert.isTrue(handleSearch.calledOnce); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid mentioning implementation detail in test cases. Simply use waitFor
from @testing-library/react
for async assertions.
Arguments of onSearch call should also be asserted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah
const Wrapper = () => { | ||
return ( | ||
<> | ||
<button id="exit">exit</button> | ||
<SelectPicker container={container} defaultOpen onSearch={handleSearch} data={data} /> | ||
</> | ||
); | ||
}; | ||
Wrapper.displayName = 'WrapperSelectPicker'; | ||
let { container } = render(<Wrapper />); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary wrapping. Simply render
the fragment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah
}; | ||
Wrapper.displayName = 'WrapperSelectPicker'; | ||
let { container } = render(<Wrapper />); | ||
const exit = container.querySelector('#exit'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use getElementById
when possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The container doesn't have the getElementById method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
document
should be available in test scripts.
8d48674
to
064deca
Compare
064deca
to
b4e78d7
Compare
b4e78d7
to
b3793f9
Compare
await waitFor(() => assert.isTrue(handleClose.calledOnce)); | ||
|
||
assert.isTrue(handleSearch.calledOnce); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicated assertions. You could wrap multiple assertions within waitFor
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great writing style
fix selectPicker when search is controlled and exit Dropdown without resetting external search