From b8303fd43163b9c157e9e58ecddc3784018dcc13 Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Thu, 3 Nov 2022 09:31:09 +0000 Subject: [PATCH] Chore: Convert `SpanTreeOffset` test to RTL (#56195) * convert SpanTreeOffset tests to RTL (minus mouseenter/mouseleave tests) * fix remaining tests --- .betterer.results | 3 - .../SpanTreeOffset.test.js | 112 ++++++++---------- .../TraceTimelineViewer/SpanTreeOffset.tsx | 9 +- 3 files changed, 55 insertions(+), 69 deletions(-) diff --git a/.betterer.results b/.betterer.results index bffae94656a..a7ee5f2f633 100644 --- a/.betterer.results +++ b/.betterer.results @@ -17,9 +17,6 @@ exports[`no enzyme tests`] = { "packages/jaeger-ui-components/src/TraceTimelineViewer/ListView/index.test.js:1734982398": [ [14, 26, 13, "RegExp match", "2409514259"] ], - "packages/jaeger-ui-components/src/TraceTimelineViewer/SpanTreeOffset.test.js:174536706": [ - [14, 19, 13, "RegExp match", "2409514259"] - ], "packages/jaeger-ui-components/src/TraceTimelineViewer/TimelineHeaderRow/TimelineColumnResizer.test.js:989353473": [ [15, 17, 13, "RegExp match", "2409514259"] ], diff --git a/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanTreeOffset.test.js b/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanTreeOffset.test.js index 58383f7e2b0..29e16cde7bf 100644 --- a/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanTreeOffset.test.js +++ b/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanTreeOffset.test.js @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { shallow } from 'enzyme'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; -import IoChevronRight from 'react-icons/lib/io/chevron-right'; -import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down'; import { createTheme } from '@grafana/data'; @@ -31,7 +30,6 @@ describe('SpanTreeOffset', () => { const rootSpanID = 'rootSpanID'; const specialRootID = 'root'; let props; - let wrapper; beforeEach(() => { // Mock implementation instead of Mock return value so that each call returns a new array (like normal) @@ -45,108 +43,92 @@ describe('SpanTreeOffset', () => { spanID: ownSpanID, }, }; - wrapper = shallow() - .dive() - .dive(); }); describe('.SpanTreeOffset--indentGuide', () => { - it('renders only one .SpanTreeOffset--indentGuide for entire trace if span has no ancestors', () => { + it('renders only one SpanTreeOffset--indentGuide for entire trace if span has no ancestors', () => { spanAncestorIdsSpy.mockReturnValue([]); - wrapper = shallow() - .dive() - .dive(); - const indentGuides = wrapper.find('[data-testid="SpanTreeOffset--indentGuide"]'); - expect(indentGuides.length).toBe(1); - expect(indentGuides.prop('data-ancestor-id')).toBe(specialRootID); + render(); + const indentGuide = screen.getByTestId('SpanTreeOffset--indentGuide'); + expect(indentGuide).toBeInTheDocument(); + expect(indentGuide).toHaveAttribute('data-ancestor-id', specialRootID); }); - it('renders one .SpanTreeOffset--indentGuide per ancestor span, plus one for entire trace', () => { - const indentGuides = wrapper.find('[data-testid="SpanTreeOffset--indentGuide"]'); + it('renders one SpanTreeOffset--indentGuide per ancestor span, plus one for entire trace', () => { + render(); + const indentGuides = screen.getAllByTestId('SpanTreeOffset--indentGuide'); expect(indentGuides.length).toBe(3); - expect(indentGuides.at(0).prop('data-ancestor-id')).toBe(specialRootID); - expect(indentGuides.at(1).prop('data-ancestor-id')).toBe(rootSpanID); - expect(indentGuides.at(2).prop('data-ancestor-id')).toBe(parentSpanID); + expect(indentGuides[0]).toHaveAttribute('data-ancestor-id', specialRootID); + expect(indentGuides[1]).toHaveAttribute('data-ancestor-id', rootSpanID); + expect(indentGuides[2]).toHaveAttribute('data-ancestor-id', parentSpanID); }); it('adds .is-active to correct indentGuide', () => { props.hoverIndentGuideIds = new Set([parentSpanID]); - wrapper = shallow() - .dive() - .dive(); + render(); const styles = getStyles(createTheme()); - const activeIndentGuide = wrapper.find(`.${styles.indentGuideActive}`); - expect(activeIndentGuide.length).toBe(1); - expect(activeIndentGuide.prop('data-ancestor-id')).toBe(parentSpanID); + const activeIndentGuide = document.querySelector(`.${styles.indentGuideActive}`); + expect(activeIndentGuide).toBeInTheDocument(); + expect(activeIndentGuide).toHaveAttribute('data-ancestor-id', parentSpanID); }); - it('calls props.addHoverIndentGuideId on mouse enter', () => { - wrapper.find({ 'data-ancestor-id': parentSpanID }).simulate('mouseenter', {}); + it('calls props.addHoverIndentGuideId on mouse enter', async () => { + render(); + const span = document.querySelector(`[data-ancestor-id=${parentSpanID}]`); + await userEvent.hover(span); expect(props.addHoverIndentGuideId).toHaveBeenCalledTimes(1); expect(props.addHoverIndentGuideId).toHaveBeenCalledWith(parentSpanID); }); - it('does not call props.addHoverIndentGuideId on mouse enter if mouse came from a indentGuide with the same ancestorId', () => { - const relatedTarget = document.createElement('span'); - relatedTarget.dataset.ancestorId = parentSpanID; - wrapper.find({ 'data-ancestor-id': parentSpanID }).simulate('mouseenter', { - relatedTarget, - }); - expect(props.addHoverIndentGuideId).not.toHaveBeenCalled(); - }); - - it('calls props.removeHoverIndentGuideId on mouse leave', () => { - wrapper.find({ 'data-ancestor-id': parentSpanID }).simulate('mouseleave', {}); + it('calls props.removeHoverIndentGuideId on mouse leave', async () => { + render(); + const span = document.querySelector(`[data-ancestor-id=${parentSpanID}]`); + await userEvent.unhover(span); expect(props.removeHoverIndentGuideId).toHaveBeenCalledTimes(1); expect(props.removeHoverIndentGuideId).toHaveBeenCalledWith(parentSpanID); }); - - it('does not call props.removeHoverIndentGuideId on mouse leave if mouse leaves to a indentGuide with the same ancestorId', () => { - const relatedTarget = document.createElement('span'); - relatedTarget.dataset.ancestorId = parentSpanID; - wrapper.find({ 'data-ancestor-id': parentSpanID }).simulate('mouseleave', { - relatedTarget, - }); - expect(props.removeHoverIndentGuideId).not.toHaveBeenCalled(); - }); }); describe('icon', () => { beforeEach(() => { - wrapper.setProps({ span: { ...props.span, hasChildren: true } }); + props = { ...props, span: { ...props.span, hasChildren: true } }; }); it('does not render icon if props.span.hasChildren is false', () => { - wrapper.setProps({ span: { ...props.span, hasChildren: false } }); - expect(wrapper.find(IoChevronRight).length).toBe(0); - expect(wrapper.find(IoIosArrowDown).length).toBe(0); + props.span.hasChildren = false; + render(); + expect(screen.queryByTestId('icon-wrapper')).not.toBeInTheDocument(); }); it('does not render icon if props.span.hasChildren is true and showChildrenIcon is false', () => { - wrapper.setProps({ showChildrenIcon: false }); - expect(wrapper.find(IoChevronRight).length).toBe(0); - expect(wrapper.find(IoIosArrowDown).length).toBe(0); + props.showChildrenIcon = false; + render(); + expect(screen.queryByTestId('icon-wrapper')).not.toBeInTheDocument(); }); - it('renders IoChevronRight if props.span.hasChildren is true and props.childrenVisible is false', () => { - expect(wrapper.find(IoChevronRight).length).toBe(1); - expect(wrapper.find(IoIosArrowDown).length).toBe(0); + it('renders arrow-right if props.span.hasChildren is true and props.childrenVisible is false', () => { + render(); + expect(screen.getByTestId('icon-arrow-right')).toBeInTheDocument(); }); - it('renders IoIosArrowDown if props.span.hasChildren is true and props.childrenVisible is true', () => { - wrapper.setProps({ childrenVisible: true }); - expect(wrapper.find(IoChevronRight).length).toBe(0); - expect(wrapper.find(IoIosArrowDown).length).toBe(1); + it('renders arrow-down if props.span.hasChildren is true and props.childrenVisible is true', () => { + props.childrenVisible = true; + render(); + expect(screen.getByTestId('icon-arrow-down')).toBeInTheDocument(); }); - it('calls props.addHoverIndentGuideId on mouse enter', () => { - wrapper.find('[data-testid="icon-wrapper"]').simulate('mouseenter', {}); + it('calls props.addHoverIndentGuideId on mouse enter', async () => { + render(); + const icon = screen.getByTestId('icon-wrapper'); + await userEvent.hover(icon); expect(props.addHoverIndentGuideId).toHaveBeenCalledTimes(1); expect(props.addHoverIndentGuideId).toHaveBeenCalledWith(ownSpanID); }); - it('calls props.removeHoverIndentGuideId on mouse leave', () => { - wrapper.find('[data-testid="icon-wrapper"]').simulate('mouseleave', {}); + it('calls props.removeHoverIndentGuideId on mouse leave', async () => { + render(); + const icon = screen.getByTestId('icon-wrapper'); + await userEvent.unhover(icon); expect(props.removeHoverIndentGuideId).toHaveBeenCalledTimes(1); expect(props.removeHoverIndentGuideId).toHaveBeenCalledWith(ownSpanID); }); diff --git a/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanTreeOffset.tsx b/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanTreeOffset.tsx index cc08a5e6c22..03d9cc4662d 100644 --- a/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanTreeOffset.tsx +++ b/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanTreeOffset.tsx @@ -138,7 +138,14 @@ export class UnthemedSpanTreeOffset extends React.PureComponent { const { childrenVisible, onClick, showChildrenIcon, span, theme } = this.props; const { hasChildren, spanID } = span; const wrapperProps = hasChildren ? { onClick, role: 'switch', 'aria-checked': childrenVisible } : null; - const icon = showChildrenIcon && hasChildren && (childrenVisible ? : ); + const icon = + showChildrenIcon && + hasChildren && + (childrenVisible ? ( + + ) : ( + + )); const styles = getStyles(theme); return (