-
Notifications
You must be signed in to change notification settings - Fork 841
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
[EuiToolTip] Convert tests to RTL and export tooltip RTL helpers #6106
Conversation
Quick note: CI on this PR will fail until #6105 is merged (on the Enzyme regression test) |
@@ -40,6 +40,7 @@ export class EuiToolTipPopover extends Component<Props> { | |||
componentDidMount() { | |||
document.body.classList.add('euiBody-hasPortalContent'); | |||
window.addEventListener('resize', this.updateDimensions); | |||
this.updateDimensions(); |
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'm not 100% sure this is the best way to solve #6065 but it definitely is the quickest!
The issue here is that EuiToolTipPopover.updateDimensions
/EuiToolTip.positionToolTip
simply isn't getting called in tests.
I believe position styles are initially set/work in browser environments because of the EuiResizeObserver here:
eui/src/components/tool_tip/tool_tip.tsx
Lines 329 to 331 in f73360c
<EuiResizeObserver onResize={this.positionToolTip}> | |
{(resizeRef) => <div ref={resizeRef}>{content}</div>} | |
</EuiResizeObserver> |
But because this is jsdom, and jsdom doesn't support MutationObservers on the version we're on (v11), and presumably also does not support ResizeObservers, positionToolTip
never gets called and the visibility styles never get set.
Calling updateDimensions on mount should fix the issue and have minimal perf impact, but I could be wrong on that - 2nd opinions appreciated (cc @thompsongl).
If we absolutely had to we could attempt to either 1. polyfill window.ResizeObserver
or 2. mock EuiResizeObserver
, but one downside to those approaches is that consuming applications will have to import those mocks as opposed to simply getting a fix (this approach).
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.
We could use the IS_JEST_ENVIRONMENT
util and only run this during tests. Just confirmed locally that it'd work.
if (IS_JEST_ENVIRONMENT) this.updateDimensions();
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.
That's definitely an approach we can use - but I guess like, in a vacuum, doesn't it feel like positionTooltip
should be called on tooltip mount in any case? If you told me that it gets passed to a window resize listener and a resize observer, I wouldn't assume positionTooltip
gets called except on resize.
(Separately I also wonder if we should examine our EuiResizeObserver to make sure it isn't incorrectly calling the onResize
callback on mount when it shouldn't be)
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.
doesn't it feel like positionTooltip should be called on tooltip mount in any case? If you told me that it gets passed to a window resize listened and a resize observer, I wouldn't assume positionTooltip gets called except on resize. I do wonder if we should examine our EuiResizeObserver to make sure it isn't incorrectly calling the onResize callback on mount when it shouldn't be.
So ResizeObserver
does call the callback immediately upon instantiation, per spec: WICG/resize-observer#38 (comment)
https://codepen.io/thompsongl/pen/MWVVZjZ?editors=1111
At one point before browser support was there, EUI had it's own polyfill to mimic the callback-on-init behavior:
requestAnimationFrame(this.onResize); // Mimic ResizeObserver behavior of triggering a resize event on init |
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.
Not that it's intuitive at all, but calling the callback on mount explicitly would mean that the callback is called twice on mount in normal browsers situations.
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.
Ha 🙃 That spec is super unintuitive. Thanks for the source!
To be honest, I'm not a huge fan of our various usages of IS_JEST_ENVIRONMENT
and I'd rather move away from them than add another instance. I think jest.mock()
s are a safer way of handling test-only logic without adding unreachable branches to source/production code.
If we don't want the extra call on mount, I'd personally rather add a testenv
mock to EuiResizeObserver
that simply calls on the onResize
callback on mount. Thoughts?
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.
add a testenv mock to EuiResizeObserver that simply calls on the onResize callback on mount
Probably worth looking into. I wonder how/if that would impact consumers who are use the polyfill. Kibana doesn't use it as far as I know.
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.
Consumers who use the polyfill wouldn't be importing/automatically using our testenv
mock, so it shouldn't affect them 🤷
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.
Ah right!
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.
Alrighty, added a testenv mock: acb564c
Preview documentation changes for this PR: https://eui.elastic.co/pr_6106/ |
+ prefer runAllTimers over static timeout + restore real timers after
- keep single Enzyme test for legacy/portal regression catches
1f853ff
to
211dab8
Compare
Preview documentation changes for this PR: https://eui.elastic.co/pr_6106/ |
Preview documentation changes for this PR: https://eui.elastic.co/pr_6106/ |
// Re-export other exports | ||
export { hasResizeObserver, useResizeObserver } from './resize_observer'; |
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.
This won't work because resize_observer.testenv.tsx
completely replaces resize_observer.tsx
in the testenv
build.
For hasResizeObserver
you could probably copy-paste. For useResizeObserver
I'm not exactly sure. Maybe it's similar to EuiResizeObserver
and it just does an on mount useEffect
?
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.
ahhh gotcha gotcha, sorry, I totally brainfarted on how our test-env
export works. looking into this now
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.
ok this time for real 5f15f23
Preview documentation changes for this PR: https://eui.elastic.co/pr_6106/ |
fa75a72
to
5f15f23
Compare
Preview documentation changes for this PR: https://eui.elastic.co/pr_6106/ |
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.
Code here looks good but when I run tests in Kibana I get a bunch of errors like this:
Error: Uncaught [TypeError: Cannot read properties of undefined (reading '_context')]
I think it's unrelated and my local env is just borked but want to confirm that, say, src/plugins/discover
Jest tests all pass for you.
No failures with the following commands:
|
Summary
This PR:
waitForEuiToolTipVisible
andwaitForEuiToolTipHidden
test helpersChecklist