UNPKG

@zendesk/react-measure-timing-hooks

Version:

react hooks for measuring time to interactive and time to render of components

335 lines 15.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const vitest_1 = require("vitest"); const convertToRum_1 = require("./convertToRum"); const recordingComputeUtils_1 = require("./recordingComputeUtils"); const createMockFactory_1 = require("./testUtility/createMockFactory"); const baseDefinitionFixture = { name: 'test-trace', relationSchemaName: 'global', relationSchema: { global: {} }, requiredSpans: [() => true], computedSpanDefinitions: {}, computedValueDefinitions: {}, variants: { origin: { timeout: 45_000 }, }, }; (0, vitest_1.describe)('recordingComputeUtils', () => { (0, vitest_1.describe)('error status propagation', () => { (0, vitest_1.it)('should mark trace as error if any non-suppressed span has error status', () => { const recording = (0, recordingComputeUtils_1.createTraceRecording)({ definition: baseDefinitionFixture, recordedItems: new Set([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { status: 'error', name: 'error-span', }), (0, createMockFactory_1.createMockSpanAndAnnotation)(200, { status: 'ok', name: 'ok-span' }), ]), input: { id: 'test', startTime: (0, createMockFactory_1.createTimestamp)(0), relatedTo: {}, variant: 'origin', }, recordedItemsByLabel: {}, }, { transitionFromState: 'active' }); (0, vitest_1.expect)(recording.status).toBe('error'); (0, vitest_1.expect)(recording.additionalDurations.startTillInteractive).toBeNull(); (0, vitest_1.expect)(recording.additionalDurations.completeTillInteractive).toBeNull(); (0, vitest_1.expect)(recording.additionalDurations.startTillRequirementsMet).toBeNull(); }); (0, vitest_1.it)('should not mark trace as error if all error spans are suppressed', () => { const recording = (0, recordingComputeUtils_1.createTraceRecording)({ definition: { ...baseDefinitionFixture, suppressErrorStatusPropagationOnSpans: [ ({ span }) => span.name === 'suppressed-error-span', ], }, recordedItems: new Set([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { status: 'error', name: 'suppressed-error-span', }), (0, createMockFactory_1.createMockSpanAndAnnotation)(200, { status: 'ok', name: 'ok-span' }), ]), input: { id: 'test', startTime: (0, createMockFactory_1.createTimestamp)(0), relatedTo: {}, variant: 'origin', }, recordedItemsByLabel: {}, }, { transitionFromState: 'active' }); (0, vitest_1.expect)(recording.status).toBe('ok'); (0, vitest_1.expect)(recording.additionalDurations.startTillInteractive).toBeNull(); }); (0, vitest_1.it)('should mark trace as error if any error span is not suppressed', () => { const recording = (0, recordingComputeUtils_1.createTraceRecording)({ definition: { ...baseDefinitionFixture, suppressErrorStatusPropagationOnSpans: [ ({ span }) => span.name === 'suppressed-error-span', ], }, recordedItems: new Set([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { status: 'error', name: 'suppressed-error-span', }), (0, createMockFactory_1.createMockSpanAndAnnotation)(200, { status: 'error', name: 'non-suppressed-error-span', }), (0, createMockFactory_1.createMockSpanAndAnnotation)(300, { status: 'ok', name: 'ok-span' }), ]), input: { id: 'test', startTime: (0, createMockFactory_1.createTimestamp)(0), relatedTo: {}, variant: 'origin', }, recordedItemsByLabel: {}, }, { transitionFromState: 'active' }); (0, vitest_1.expect)(recording.status).toBe('error'); (0, vitest_1.expect)(recording.additionalDurations.startTillInteractive).toBeNull(); }); (0, vitest_1.it)('should prioritize interrupted status over error status', () => { const recording = (0, recordingComputeUtils_1.createTraceRecording)({ definition: baseDefinitionFixture, recordedItems: new Set([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { status: 'error', name: 'error-span', }), ]), input: { id: 'test', startTime: (0, createMockFactory_1.createTimestamp)(0), relatedTo: {}, variant: 'origin', }, recordedItemsByLabel: {}, }, { transitionFromState: 'active', interruptionReason: 'timeout', }); (0, vitest_1.expect)(recording.status).toBe('interrupted'); (0, vitest_1.expect)(recording.additionalDurations.startTillInteractive).toBeNull(); }); }); (0, vitest_1.describe)('getComputedSpans', () => { const baseDefinition = { ...baseDefinitionFixture, computedSpanDefinitions: { 'test-computed-span': { startSpan: ({ span }) => span.name === 'start-span', endSpan: ({ span }) => span.name === 'end-span', }, }, }; (0, vitest_1.it)('should compute duration and startOffset correctly', () => { const result = (0, recordingComputeUtils_1.getComputedSpans)({ definition: baseDefinition, recordedItems: new Set([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'start-span', duration: 50, }), (0, createMockFactory_1.createMockSpanAndAnnotation)(200, { name: 'end-span', duration: 50, }), ]), input: { id: 'test', startTime: (0, createMockFactory_1.createTimestamp)(0), relatedTo: {}, variant: 'origin', }, recordedItemsByLabel: {}, }); (0, vitest_1.expect)(result['test-computed-span']).toEqual({ duration: 150, // (200 + 50) - 100 startOffset: 100, }); }); (0, vitest_1.it)('should handle operation-start and operation-end special matchers', () => { const definition = { ...baseDefinition, computedSpanDefinitions: { 'operation-span': { startSpan: 'operation-start', endSpan: 'operation-end', }, }, }; const markedCompleteSpan = (0, createMockFactory_1.createMockSpanAndAnnotation)(200, { name: 'end-span', }); markedCompleteSpan.annotation.markedComplete = true; const result = (0, recordingComputeUtils_1.getComputedSpans)({ definition, recordedItems: new Set([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'start-span' }), markedCompleteSpan, ]), input: { id: 'test', startTime: (0, createMockFactory_1.createTimestamp)(0), // eslint-disable-next-line @typescript-eslint/consistent-type-assertions relatedTo: {}, variant: 'origin', }, recordedItemsByLabel: {}, }); (0, vitest_1.expect)(result['operation-span']).toBeDefined(); }); }); (0, vitest_1.describe)('getComputedValues', () => { const baseDefinition = { ...baseDefinitionFixture, computedValueDefinitions: { 'error-count': { matches: [({ span }) => span.status === 'error'], computeValueFromMatches: (matches) => matches.length, }, }, }; (0, vitest_1.it)('should compute values based on matching spans', () => { const result = (0, recordingComputeUtils_1.getComputedValues)({ definition: baseDefinition, recordedItems: new Set([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { status: 'error' }), (0, createMockFactory_1.createMockSpanAndAnnotation)(200, { status: 'error' }), (0, createMockFactory_1.createMockSpanAndAnnotation)(300, { status: 'ok' }), ]), input: { id: 'test', startTime: (0, createMockFactory_1.createTimestamp)(0), // eslint-disable-next-line @typescript-eslint/consistent-type-assertions relatedTo: {}, variant: 'origin', }, recordedItemsByLabel: {}, }); (0, vitest_1.expect)(result['error-count']).toBe(2); }); (0, vitest_1.it)('should handle multiple matches in computeValueFromMatches', () => { const definition = { ...baseDefinition, computedValueDefinitions: { 'status-counts': { matches: [ ({ span }) => span.status === 'error', ({ span }) => span.status === 'ok', ], computeValueFromMatches: (errors, oks) => errors.length + oks.length, }, }, }; const result = (0, recordingComputeUtils_1.getComputedValues)({ definition, recordedItems: new Set([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { status: 'error' }), (0, createMockFactory_1.createMockSpanAndAnnotation)(200, { status: 'ok' }), (0, createMockFactory_1.createMockSpanAndAnnotation)(300, { status: 'error' }), ]), input: { id: 'test', startTime: (0, createMockFactory_1.createTimestamp)(0), // eslint-disable-next-line @typescript-eslint/consistent-type-assertions relatedTo: {}, variant: 'origin', }, recordedItemsByLabel: {}, }); (0, vitest_1.expect)(result['status-counts']).toEqual(3); }); }); (0, vitest_1.describe)('getSpanSummaryAttributes', () => { (0, vitest_1.it)('should merge attributes from spans with the same name', () => { const result = (0, convertToRum_1.getSpanSummaryAttributes)([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'test-span', attributes: { first: true }, }), (0, createMockFactory_1.createMockSpanAndAnnotation)(200, { name: 'test-span', attributes: { second: true }, }), ]); (0, vitest_1.expect)(result['test-span']).toEqual({ first: true, second: true, }); }); }); (0, vitest_1.describe)('computedRenderBeaconSpans', () => { (0, vitest_1.it)('should compute render beacon metrics correctly', () => { const recording = (0, recordingComputeUtils_1.createTraceRecording)({ definition: baseDefinitionFixture, recordedItems: new Set([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { name: 'test-component', type: 'component-render', relatedTo: {}, duration: 50, isIdle: true, renderCount: 1, renderedOutput: 'loading', }), (0, createMockFactory_1.createMockSpanAndAnnotation)(200, { name: 'test-component', type: 'component-render', relatedTo: {}, duration: 50, isIdle: true, renderCount: 2, renderedOutput: 'content', }, { occurrence: 2 }), ]), input: { id: 'test', startTime: (0, createMockFactory_1.createTimestamp)(0), relatedTo: {}, variant: 'origin', }, recordedItemsByLabel: {}, }, { transitionFromState: 'active' }); (0, vitest_1.expect)(recording.computedRenderBeaconSpans['test-component']).toEqual({ startOffset: 100, firstRenderTillContent: 150, firstRenderTillLoading: 50, firstRenderTillData: 100, renderCount: 2, sumOfRenderDurations: 100, }); }); }); (0, vitest_1.describe)('variant property', () => { (0, vitest_1.it)('should include the variant in the recording', () => { const recording = (0, recordingComputeUtils_1.createTraceRecording)({ definition: baseDefinitionFixture, recordedItems: new Set([ (0, createMockFactory_1.createMockSpanAndAnnotation)(100, { status: 'ok', name: 'test-span', }), ]), input: { id: 'test', startTime: (0, createMockFactory_1.createTimestamp)(0), relatedTo: {}, variant: 'origin', }, recordedItemsByLabel: {}, }, { transitionFromState: 'active' }); // Verify the variant is included in the recording (0, vitest_1.expect)(recording.variant).toBe('origin'); }); }); }); //# sourceMappingURL=recordingComputeUtils.test.js.map