diff --git a/src/components/TracePage/TraceTimelineViewer/utils.test.js b/src/components/TracePage/TraceTimelineViewer/utils.test.js index 5160f7ead9..227a6eacde 100644 --- a/src/components/TracePage/TraceTimelineViewer/utils.test.js +++ b/src/components/TracePage/TraceTimelineViewer/utils.test.js @@ -18,10 +18,95 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import { spanContainsErredSpan } from './utils'; +import { + calculateSpanPosition, + calculateTimeAtPositon, + convertTimeRangeToPercent, + ensureWithinRange, + hasTagKey, + isClientSpan, + isErrorSpan, + isServerSpan, + spanContainsErredSpan, +} from './utils'; import traceGenerator from '../../../demo/trace-generators'; -it('spanContainsErredSpan(...) is true only when a descendant has an error tag', () => { +it('calculateSpanPosition() maps a sub-range to percents with a zoom applied', () => { + const args = { + traceStartTime: 100, + traceEndTime: 200, + xStart: 0, + xEnd: 50, + }; + + args.spanStart = 100; + args.spanEnd = 200; + expect(calculateSpanPosition(args)).toEqual({ xStart: 0, xEnd: 200 }); + + args.spanStart = 100; + args.spanEnd = 150; + expect(calculateSpanPosition(args)).toEqual({ xStart: 0, xEnd: 100 }); + + args.spanStart = 150; + args.spanEnd = 200; + expect(calculateSpanPosition(args)).toEqual({ xStart: 100, xEnd: 200 }); +}); + +it('calculateTimeAtPositon() converts a percent to a value in [0, duration]', () => { + const traceDuration = 1000; + expect(calculateTimeAtPositon({ position: 0, traceDuration })).toBe(0); + expect(calculateTimeAtPositon({ position: 100, traceDuration })).toBe( + traceDuration + ); + expect(calculateTimeAtPositon({ position: 50, traceDuration })).toBe( + 0.5 * traceDuration + ); +}); + +it('convertTimeRangeToPercent() converts a sub-range to percent start and end values', () => { + const traceRange = [100, 200]; + expect(convertTimeRangeToPercent([100, 200], traceRange)).toEqual([0, 100]); + expect(convertTimeRangeToPercent([199, 200], traceRange)).toEqual([99, 100]); + expect(convertTimeRangeToPercent([100, 101], traceRange)).toEqual([0, 1]); + expect(convertTimeRangeToPercent([100, 150], traceRange)).toEqual([0, 50]); + expect(convertTimeRangeToPercent([0, 250], traceRange)).toEqual([-100, 150]); +}); + +it('ensureWithinRange() clamps numeric values', () => { + const min = 10; + const max = 20; + expect(ensureWithinRange([min, max], -1)).toBe(10); + expect(ensureWithinRange([min, max], 0)).toBe(10); + expect(ensureWithinRange([min, max], 15)).toBe(15); + expect(ensureWithinRange([min, max], 25)).toBe(20); + expect(isNaN(ensureWithinRange([min, max], NaN))).toBe(true); +}); + +it('hasTagKey() returns true iff the key/value pair is found', () => { + const tags = traceGenerator.tags(); + tags.push({ key: 'span.kind', value: 'server' }); + expect(hasTagKey([], 'span.kind', 'client')).toBe(false); + expect(hasTagKey(tags, 'span.kind', 'client')).toBe(false); + expect(hasTagKey(tags, 'span.kind', 'server')).toBe(true); +}); + +const spanTypeTestCases = [ + { fn: isClientSpan, name: 'isClientSpan', key: 'span.kind', value: 'client' }, + { fn: isServerSpan, name: 'isServerSpan', key: 'span.kind', value: 'server' }, + { fn: isErrorSpan, name: 'isErrorSpan', key: 'error', value: true }, +]; + +spanTypeTestCases.forEach(testCase => { + const msg = `${testCase.name}() is true only when a ${testCase.key}=${testCase.value} tag is present`; + it(msg, () => { + const span = { tags: traceGenerator.tags() }; + expect(testCase.fn(span)).toBe(false); + span.tags.push(testCase); + expect(testCase.fn(span)).toBe(true); + }); +}); + +it('spanContainsErredSpan() is true only when a descendant has an error tag', () => { const errorTag = { key: 'error', type: 'bool', value: true }; const getTags = withError => withError ? traceGenerator.tags().concat(errorTag) : traceGenerator.tags(); diff --git a/src/components/TracePage/index.js b/src/components/TracePage/index.js index 7277abf4ab..a276bc717e 100644 --- a/src/components/TracePage/index.js +++ b/src/components/TracePage/index.js @@ -120,6 +120,9 @@ export default class TracePage extends Component { toggleSlimView(slimView) { this.setState({ slimView }); + // fix issue #12 - TraceView header expander not working correctly + // TODO: evaluate alternatives to react-sticky + setTimeout(() => this.forceUpdate(), 0); } ensureTraceFetched() {