Chore: Convert SpanTreeOffset test to RTL (#56195)

* convert SpanTreeOffset tests to RTL (minus mouseenter/mouseleave tests)

* fix remaining tests
This commit is contained in:
Ashley Harrison 2022-11-03 09:31:09 +00:00 committed by GitHub
parent fc1b647474
commit b8303fd431
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 69 deletions

View File

@ -17,9 +17,6 @@ exports[`no enzyme tests`] = {
"packages/jaeger-ui-components/src/TraceTimelineViewer/ListView/index.test.js:1734982398": [ "packages/jaeger-ui-components/src/TraceTimelineViewer/ListView/index.test.js:1734982398": [
[14, 26, 13, "RegExp match", "2409514259"] [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": [ "packages/jaeger-ui-components/src/TraceTimelineViewer/TimelineHeaderRow/TimelineColumnResizer.test.js:989353473": [
[15, 17, 13, "RegExp match", "2409514259"] [15, 17, 13, "RegExp match", "2409514259"]
], ],

View File

@ -12,10 +12,9 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // 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 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'; import { createTheme } from '@grafana/data';
@ -31,7 +30,6 @@ describe('SpanTreeOffset', () => {
const rootSpanID = 'rootSpanID'; const rootSpanID = 'rootSpanID';
const specialRootID = 'root'; const specialRootID = 'root';
let props; let props;
let wrapper;
beforeEach(() => { beforeEach(() => {
// Mock implementation instead of Mock return value so that each call returns a new array (like normal) // 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, spanID: ownSpanID,
}, },
}; };
wrapper = shallow(<SpanTreeOffset {...props} />)
.dive()
.dive();
}); });
describe('.SpanTreeOffset--indentGuide', () => { 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([]); spanAncestorIdsSpy.mockReturnValue([]);
wrapper = shallow(<SpanTreeOffset {...props} />) render(<SpanTreeOffset {...props} />);
.dive() const indentGuide = screen.getByTestId('SpanTreeOffset--indentGuide');
.dive(); expect(indentGuide).toBeInTheDocument();
const indentGuides = wrapper.find('[data-testid="SpanTreeOffset--indentGuide"]'); expect(indentGuide).toHaveAttribute('data-ancestor-id', specialRootID);
expect(indentGuides.length).toBe(1);
expect(indentGuides.prop('data-ancestor-id')).toBe(specialRootID);
}); });
it('renders one .SpanTreeOffset--indentGuide per ancestor span, plus one for entire trace', () => { it('renders one SpanTreeOffset--indentGuide per ancestor span, plus one for entire trace', () => {
const indentGuides = wrapper.find('[data-testid="SpanTreeOffset--indentGuide"]'); render(<SpanTreeOffset {...props} />);
const indentGuides = screen.getAllByTestId('SpanTreeOffset--indentGuide');
expect(indentGuides.length).toBe(3); expect(indentGuides.length).toBe(3);
expect(indentGuides.at(0).prop('data-ancestor-id')).toBe(specialRootID); expect(indentGuides[0]).toHaveAttribute('data-ancestor-id', specialRootID);
expect(indentGuides.at(1).prop('data-ancestor-id')).toBe(rootSpanID); expect(indentGuides[1]).toHaveAttribute('data-ancestor-id', rootSpanID);
expect(indentGuides.at(2).prop('data-ancestor-id')).toBe(parentSpanID); expect(indentGuides[2]).toHaveAttribute('data-ancestor-id', parentSpanID);
}); });
it('adds .is-active to correct indentGuide', () => { it('adds .is-active to correct indentGuide', () => {
props.hoverIndentGuideIds = new Set([parentSpanID]); props.hoverIndentGuideIds = new Set([parentSpanID]);
wrapper = shallow(<SpanTreeOffset {...props} />) render(<SpanTreeOffset {...props} />);
.dive()
.dive();
const styles = getStyles(createTheme()); const styles = getStyles(createTheme());
const activeIndentGuide = wrapper.find(`.${styles.indentGuideActive}`); const activeIndentGuide = document.querySelector(`.${styles.indentGuideActive}`);
expect(activeIndentGuide.length).toBe(1); expect(activeIndentGuide).toBeInTheDocument();
expect(activeIndentGuide.prop('data-ancestor-id')).toBe(parentSpanID); expect(activeIndentGuide).toHaveAttribute('data-ancestor-id', parentSpanID);
}); });
it('calls props.addHoverIndentGuideId on mouse enter', () => { it('calls props.addHoverIndentGuideId on mouse enter', async () => {
wrapper.find({ 'data-ancestor-id': parentSpanID }).simulate('mouseenter', {}); render(<SpanTreeOffset {...props} />);
const span = document.querySelector(`[data-ancestor-id=${parentSpanID}]`);
await userEvent.hover(span);
expect(props.addHoverIndentGuideId).toHaveBeenCalledTimes(1); expect(props.addHoverIndentGuideId).toHaveBeenCalledTimes(1);
expect(props.addHoverIndentGuideId).toHaveBeenCalledWith(parentSpanID); expect(props.addHoverIndentGuideId).toHaveBeenCalledWith(parentSpanID);
}); });
it('does not call props.addHoverIndentGuideId on mouse enter if mouse came from a indentGuide with the same ancestorId', () => { it('calls props.removeHoverIndentGuideId on mouse leave', async () => {
const relatedTarget = document.createElement('span'); render(<SpanTreeOffset {...props} />);
relatedTarget.dataset.ancestorId = parentSpanID; const span = document.querySelector(`[data-ancestor-id=${parentSpanID}]`);
wrapper.find({ 'data-ancestor-id': parentSpanID }).simulate('mouseenter', { await userEvent.unhover(span);
relatedTarget,
});
expect(props.addHoverIndentGuideId).not.toHaveBeenCalled();
});
it('calls props.removeHoverIndentGuideId on mouse leave', () => {
wrapper.find({ 'data-ancestor-id': parentSpanID }).simulate('mouseleave', {});
expect(props.removeHoverIndentGuideId).toHaveBeenCalledTimes(1); expect(props.removeHoverIndentGuideId).toHaveBeenCalledTimes(1);
expect(props.removeHoverIndentGuideId).toHaveBeenCalledWith(parentSpanID); 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', () => { describe('icon', () => {
beforeEach(() => { 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', () => { it('does not render icon if props.span.hasChildren is false', () => {
wrapper.setProps({ span: { ...props.span, hasChildren: false } }); props.span.hasChildren = false;
expect(wrapper.find(IoChevronRight).length).toBe(0); render(<SpanTreeOffset {...props} />);
expect(wrapper.find(IoIosArrowDown).length).toBe(0); expect(screen.queryByTestId('icon-wrapper')).not.toBeInTheDocument();
}); });
it('does not render icon if props.span.hasChildren is true and showChildrenIcon is false', () => { it('does not render icon if props.span.hasChildren is true and showChildrenIcon is false', () => {
wrapper.setProps({ showChildrenIcon: false }); props.showChildrenIcon = false;
expect(wrapper.find(IoChevronRight).length).toBe(0); render(<SpanTreeOffset {...props} />);
expect(wrapper.find(IoIosArrowDown).length).toBe(0); expect(screen.queryByTestId('icon-wrapper')).not.toBeInTheDocument();
}); });
it('renders IoChevronRight if props.span.hasChildren is true and props.childrenVisible is false', () => { it('renders arrow-right if props.span.hasChildren is true and props.childrenVisible is false', () => {
expect(wrapper.find(IoChevronRight).length).toBe(1); render(<SpanTreeOffset {...props} />);
expect(wrapper.find(IoIosArrowDown).length).toBe(0); expect(screen.getByTestId('icon-arrow-right')).toBeInTheDocument();
}); });
it('renders IoIosArrowDown if props.span.hasChildren is true and props.childrenVisible is true', () => { it('renders arrow-down if props.span.hasChildren is true and props.childrenVisible is true', () => {
wrapper.setProps({ childrenVisible: true }); props.childrenVisible = true;
expect(wrapper.find(IoChevronRight).length).toBe(0); render(<SpanTreeOffset {...props} />);
expect(wrapper.find(IoIosArrowDown).length).toBe(1); expect(screen.getByTestId('icon-arrow-down')).toBeInTheDocument();
}); });
it('calls props.addHoverIndentGuideId on mouse enter', () => { it('calls props.addHoverIndentGuideId on mouse enter', async () => {
wrapper.find('[data-testid="icon-wrapper"]').simulate('mouseenter', {}); render(<SpanTreeOffset {...props} />);
const icon = screen.getByTestId('icon-wrapper');
await userEvent.hover(icon);
expect(props.addHoverIndentGuideId).toHaveBeenCalledTimes(1); expect(props.addHoverIndentGuideId).toHaveBeenCalledTimes(1);
expect(props.addHoverIndentGuideId).toHaveBeenCalledWith(ownSpanID); expect(props.addHoverIndentGuideId).toHaveBeenCalledWith(ownSpanID);
}); });
it('calls props.removeHoverIndentGuideId on mouse leave', () => { it('calls props.removeHoverIndentGuideId on mouse leave', async () => {
wrapper.find('[data-testid="icon-wrapper"]').simulate('mouseleave', {}); render(<SpanTreeOffset {...props} />);
const icon = screen.getByTestId('icon-wrapper');
await userEvent.unhover(icon);
expect(props.removeHoverIndentGuideId).toHaveBeenCalledTimes(1); expect(props.removeHoverIndentGuideId).toHaveBeenCalledTimes(1);
expect(props.removeHoverIndentGuideId).toHaveBeenCalledWith(ownSpanID); expect(props.removeHoverIndentGuideId).toHaveBeenCalledWith(ownSpanID);
}); });

View File

@ -138,7 +138,14 @@ export class UnthemedSpanTreeOffset extends React.PureComponent<TProps> {
const { childrenVisible, onClick, showChildrenIcon, span, theme } = this.props; const { childrenVisible, onClick, showChildrenIcon, span, theme } = this.props;
const { hasChildren, spanID } = span; const { hasChildren, spanID } = span;
const wrapperProps = hasChildren ? { onClick, role: 'switch', 'aria-checked': childrenVisible } : null; const wrapperProps = hasChildren ? { onClick, role: 'switch', 'aria-checked': childrenVisible } : null;
const icon = showChildrenIcon && hasChildren && (childrenVisible ? <IoIosArrowDown /> : <IoChevronRight />); const icon =
showChildrenIcon &&
hasChildren &&
(childrenVisible ? (
<IoIosArrowDown data-testid="icon-arrow-down" />
) : (
<IoChevronRight data-testid="icon-arrow-right" />
));
const styles = getStyles(theme); const styles = getStyles(theme);
return ( return (
<span className={cx(styles.SpanTreeOffset, { [styles.SpanTreeOffsetParent]: hasChildren })} {...wrapperProps}> <span className={cx(styles.SpanTreeOffset, { [styles.SpanTreeOffsetParent]: hasChildren })} {...wrapperProps}>