Skip to content

Commit

Permalink
WIP refactor trace detail, tests working again
Browse files Browse the repository at this point in the history
  • Loading branch information
tiffon committed Aug 20, 2017
1 parent 93a6fb7 commit b8945ab
Show file tree
Hide file tree
Showing 10 changed files with 348 additions and 545 deletions.
3 changes: 1 addition & 2 deletions src/components/TracePage/TimelineScrubber.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import PropTypes from 'prop-types';
import React from 'react';

import tracePropTypes from '../../propTypes/trace';
import { getTraceTimestamp, getTraceDuration } from '../../selectors/trace';
import { getPercentageOfInterval } from '../../utils/date';

Expand Down Expand Up @@ -79,7 +78,7 @@ export default function TimelineScrubber({

TimelineScrubber.propTypes = {
onMouseDown: PropTypes.func,
trace: tracePropTypes.isRequired,
trace: PropTypes.object,
timestamp: PropTypes.number.isRequired,
handleTopOffset: PropTypes.number,
handleWidth: PropTypes.number,
Expand Down
84 changes: 41 additions & 43 deletions src/components/TracePage/TimelineScrubber.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,53 +27,51 @@ import traceGenerator from '../../../src/demo/trace-generators';

import { getTraceTimestamp, getTraceDuration } from '../../../src/selectors/trace';

const generatedTrace = traceGenerator.trace({ numberOfSpans: 45 });
describe('<TimelineScrubber>', () => {
const generatedTrace = traceGenerator.trace({ numberOfSpans: 45 });
const defaultProps = {
onMouseDown: sinon.spy(),
trace: generatedTrace,
timestamp: getTraceTimestamp(generatedTrace),
};

const defaultProps = {
onMouseDown: sinon.spy(),
trace: generatedTrace,
timestamp: getTraceTimestamp(generatedTrace),
};
let wrapper;

it('<TimelineScrubber /> should contain the proper svg components', () => {
const wrapper = shallow(<TimelineScrubber {...defaultProps} />);
beforeEach(() => {
wrapper = shallow(<TimelineScrubber {...defaultProps} />);
});

expect(
wrapper.matchesElement(
<g className="timeline-scrubber">
<line className="timeline-scrubber__line" />
<rect className="timeline-scrubber__handle" />
<circle className="timeline-scrubber__handle--grip" />
<circle className="timeline-scrubber__handle--grip" />
<circle className="timeline-scrubber__handle--grip" />
</g>
)
).toBeTruthy();
});

it('<TimelineScrubber /> should calculate the correct x% for a timestamp', () => {
const timestamp = getTraceDuration(generatedTrace) * 0.5 + getTraceTimestamp(generatedTrace);

const wrapper = shallow(<TimelineScrubber {...defaultProps} timestamp={timestamp} />);
const line = wrapper.find('line').first();
const rect = wrapper.find('rect').first();

expect(line.prop('x1')).toBe('50%');
expect(line.prop('x2')).toBe('50%');
expect(rect.prop('x')).toBe('50%');
});

it('<TimelineScrubber /> should support onMouseDown', () => {
const wrapper = shallow(<TimelineScrubber {...defaultProps} />);
const event = {};
it('contains the proper svg components', () => {
expect(
wrapper.matchesElement(
<g className="timeline-scrubber">
<line className="timeline-scrubber__line" />
<rect className="timeline-scrubber__handle" />
<circle className="timeline-scrubber__handle--grip" />
<circle className="timeline-scrubber__handle--grip" />
<circle className="timeline-scrubber__handle--grip" />
</g>
)
).toBeTruthy();
});

wrapper.find('g').prop('onMouseDown')(event);

expect(defaultProps.onMouseDown.calledWith(event)).toBeTruthy();
});
it('calculates the correct x% for a timestamp', () => {
const timestamp = getTraceDuration(generatedTrace) * 0.5 + getTraceTimestamp(generatedTrace);
wrapper = shallow(<TimelineScrubber {...defaultProps} timestamp={timestamp} />);
const line = wrapper.find('line').first();
const rect = wrapper.find('rect').first();
expect(line.prop('x1')).toBe('50%');
expect(line.prop('x2')).toBe('50%');
expect(rect.prop('x')).toBe('50%');
});

it('<TimelineScrubber /> should not fail if onMouseDown is not provided', () => {
const wrapper = shallow(<TimelineScrubber {...defaultProps} />);
it('supports onMouseDown', () => {
const event = {};
wrapper.find('g').prop('onMouseDown')(event);
expect(defaultProps.onMouseDown.calledWith(event)).toBeTruthy();
});

expect(() => wrapper.find('g').prop('onMouseDown')()).not.toThrow();
it("doesn't fail if onMouseDown is not provided", () => {
expect(() => wrapper.find('g').prop('onMouseDown')()).not.toThrow();
});
});
102 changes: 53 additions & 49 deletions src/components/TracePage/TracePageHeader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,65 +20,69 @@

import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import { shallow, mount } from 'enzyme';

import TracePageHeader, { HEADER_ITEMS } from './TracePageHeader';
import traceGenerator from '../../demo/trace-generators';
import { getTraceName } from '../../selectors/trace';

const defaultProps = {
trace: traceGenerator.trace({ numberOfSpans: 50 }),
};

const defaultOptions = {
context: {
textFilter: '',
updateTextFilter: () => {},
},
};

it('<TracePageHeader /> should render a <header />', () => {
const wrapper = shallow(<TracePageHeader {...defaultProps} />, defaultOptions);

expect(wrapper.find('header').length).toBe(1);
});

it('<TracePageHeader /> should render an empty <div /> if no trace present', () => {
const wrapper = shallow(<TracePageHeader {...defaultProps} trace={null} />, defaultOptions);

expect(wrapper.matchesElement(<div />)).toBeTruthy();
});

it('<TracePageHeader /> should render the trace title', () => {
const wrapper = shallow(<TracePageHeader {...defaultProps} />, defaultOptions);
const h2 = wrapper.find('h2').first();

expect(h2.contains(getTraceName(defaultProps.trace))).toBeTruthy();
});
describe('<TracePageHeader>', () => {
const defaultProps = {
traceID: 'some-trace-id',
name: 'some-trace-name',

// maxDepth: PropTypes.number, // eslint-disable-line react/no-unused-prop-types
// numServices: PropTypes.number, // eslint-disable-line react/no-unused-prop-types
// numSpans: PropTypes.number, // eslint-disable-line react/no-unused-prop-types
// durationMs: PropTypes.number, // eslint-disable-line react/no-unused-prop-types
// timestampMs: PropTypes.number, // eslint-disable-line react/no-unused-prop-types
// slimView: PropTypes.bool,
// onSlimViewClicked: PropTypes.func,
};

const defaultOptions = {
context: {
textFilter: '',
updateTextFilter: () => {},
},
};

it('<TracePageHeader /> should render the header items', () => {
const wrapper = shallow(<TracePageHeader {...defaultProps} />, defaultOptions);
let wrapper;

wrapper.find('.horizontal .item').forEach((item, idx) => {
expect(item.contains(HEADER_ITEMS[idx].title)).toBeTruthy();
expect(item.contains(HEADER_ITEMS[idx].renderer(defaultProps.trace))).toBeTruthy();
beforeEach(() => {
wrapper = shallow(<TracePageHeader {...defaultProps} />, defaultOptions);
});
});

it('<TracePageHeader /> should call the context filter method onChange of the input', () => {
const updateTextFilter = sinon.spy();
it('renders a <header />', () => {
expect(wrapper.find('header').length).toBe(1);
});

const wrapper = shallow(<TracePageHeader {...defaultProps} />, {
...defaultOptions,
context: {
...defaultOptions.context,
updateTextFilter,
},
it('renders an empty <div> if no traceID is present', () => {
wrapper = mount(<TracePageHeader {...defaultProps} traceID={null} />, defaultOptions);
expect(wrapper.children().length).toBe(0);
});

const event = { target: { value: 'my new value' } };
it('renders the trace title', () => {
const h2 = wrapper.find('h2').first();
expect(h2.contains(defaultProps.name)).toBeTruthy();
});

wrapper.find('#trace-page__text-filter').first().prop('onChange')(event);
it('renders the header items', () => {
wrapper.find('.horizontal .item').forEach((item, i) => {
expect(item.contains(HEADER_ITEMS[i].title)).toBeTruthy();
expect(item.contains(HEADER_ITEMS[i].renderer(defaultProps.trace))).toBeTruthy();
});
});

expect(updateTextFilter.calledWith('my new value')).toBeTruthy();
it('calls the context updateTextFilter() function for onChange of the input', () => {
const updateTextFilter = sinon.spy();
wrapper = shallow(<TracePageHeader {...defaultProps} />, {
...defaultOptions,
context: {
...defaultOptions.context,
updateTextFilter,
},
});
const event = { target: { value: 'my new value' } };
wrapper.find('#trace-page__text-filter').first().prop('onChange')(event);
expect(updateTextFilter.calledWith('my new value')).toBeTruthy();
});
});
4 changes: 1 addition & 3 deletions src/components/TracePage/TraceSpanGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,18 @@ import { window } from 'global';

import SpanGraph from './SpanGraph';
import SpanGraphTickHeader from './SpanGraph/SpanGraphTickHeader';
import tracePropTypes from '../../propTypes/trace';
import TimelineScrubber from './TimelineScrubber';

import { getTraceId, getTraceTimestamp, getTraceEndTimestamp, getTraceDuration } from '../../selectors/trace';
import { getPercentageOfInterval } from '../../utils/date';

const TIMELINE_TICK_INTERVAL = 4;
const TIMELINE_TICK_WIDTH = 2;

export default class TraceSpanGraph extends Component {
static get propTypes() {
return {
xformedTrace: PropTypes.object,
trace: tracePropTypes,
trace: PropTypes.object,
height: PropTypes.number.isRequired,
};
}
Expand Down
Loading

0 comments on commit b8945ab

Please sign in to comment.