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 (