@@ -299,4 +299,175 @@ describe('Profiler', () => {
299299 expect ( timeline [ 1 ] . duration ) . toBe ( 20 ) ;
300300 expect ( timeline [ 1 ] . componentCount ) . toBe ( 2 ) ;
301301 } ) ;
302+
303+ describe ( 'getExportData' , ( ) => {
304+ it ( 'returns null when no session exists' , ( ) => {
305+ expect ( profiler . getExportData ( tree ) ) . toBeNull ( ) ;
306+ } ) ;
307+
308+ it ( 'returns null when session has no commits' , ( ) => {
309+ profiler . start ( 'test' ) ;
310+ profiler . stop ( ) ;
311+ expect ( profiler . getExportData ( tree ) ) . toBeNull ( ) ;
312+ } ) ;
313+
314+ it ( 'exports version 5 format' , ( ) => {
315+ profiler . start ( 'test' ) ;
316+ profiler . processProfilingData ( {
317+ commitData : [
318+ {
319+ timestamp : 1000 ,
320+ duration : 15 ,
321+ fiberActualDurations : [ 1 , 10 , 2 , 3 , 3 , 2 ] ,
322+ fiberSelfDurations : [ 1 , 5 , 2 , 3 , 3 , 2 ] ,
323+ } ,
324+ ] ,
325+ } ) ;
326+ profiler . stop ( tree ) ;
327+
328+ const exported = profiler . getExportData ( tree ) ;
329+ expect ( exported ) . not . toBeNull ( ) ;
330+ expect ( exported ! . version ) . toBe ( 5 ) ;
331+ expect ( exported ! . dataForRoots ) . toHaveLength ( 1 ) ;
332+ } ) ;
333+
334+ it ( 'maps commits to CommitDataExport format' , ( ) => {
335+ profiler . start ( 'test' ) ;
336+ profiler . processProfilingData ( {
337+ commitData : [
338+ {
339+ timestamp : 1000 ,
340+ duration : 15 ,
341+ fiberActualDurations : [ 1 , 10 , 2 , 3 ] ,
342+ fiberSelfDurations : [ 1 , 5 , 2 , 3 ] ,
343+ changeDescriptions : [
344+ [ 1 , { props : [ 'theme' ] , isFirstMount : false } ] ,
345+ [ 2 , { isFirstMount : true } ] ,
346+ ] ,
347+ } ,
348+ ] ,
349+ } ) ;
350+ profiler . stop ( tree ) ;
351+
352+ const root = profiler . getExportData ( tree ) ! . dataForRoots [ 0 ] ;
353+ expect ( root . commitData ) . toHaveLength ( 1 ) ;
354+
355+ const commit = root . commitData [ 0 ] ;
356+ expect ( commit . timestamp ) . toBe ( 1000 ) ;
357+ expect ( commit . duration ) . toBe ( 15 ) ;
358+ expect ( commit . fiberActualDurations ) . toEqual ( expect . arrayContaining ( [ [ 1 , 10 ] , [ 2 , 3 ] ] ) ) ;
359+ expect ( commit . fiberSelfDurations ) . toEqual ( expect . arrayContaining ( [ [ 1 , 5 ] , [ 2 , 3 ] ] ) ) ;
360+ expect ( commit . effectDuration ) . toBeNull ( ) ;
361+ expect ( commit . passiveEffectDuration ) . toBeNull ( ) ;
362+ expect ( commit . priorityLevel ) . toBeNull ( ) ;
363+ expect ( commit . updaters ) . toBeNull ( ) ;
364+ } ) ;
365+
366+ it ( 'exports change descriptions with context:null field' , ( ) => {
367+ profiler . start ( 'test' ) ;
368+ profiler . processProfilingData ( {
369+ commitData : [
370+ {
371+ timestamp : 1000 ,
372+ duration : 5 ,
373+ fiberActualDurations : [ 1 , 5 ] ,
374+ fiberSelfDurations : [ 1 , 5 ] ,
375+ changeDescriptions : [
376+ [ 1 , { props : [ 'onClick' ] , state : [ 'count' ] , isFirstMount : false , didHooksChange : true } ] ,
377+ ] ,
378+ } ,
379+ ] ,
380+ } ) ;
381+ profiler . stop ( tree ) ;
382+
383+ const commit = profiler . getExportData ( tree ) ! . dataForRoots [ 0 ] . commitData [ 0 ] ;
384+ expect ( commit . changeDescriptions ) . toHaveLength ( 1 ) ;
385+ const [ id , desc ] = commit . changeDescriptions ! [ 0 ] ;
386+ expect ( id ) . toBe ( 1 ) ;
387+ expect ( desc . context ) . toBeNull ( ) ;
388+ expect ( desc . props ) . toEqual ( [ 'onClick' ] ) ;
389+ expect ( desc . state ) . toEqual ( [ 'count' ] ) ;
390+ expect ( desc . didHooksChange ) . toBe ( true ) ;
391+ expect ( desc . isFirstMount ) . toBe ( false ) ;
392+ } ) ;
393+
394+ it ( 'builds snapshots from component tree' , ( ) => {
395+ profiler . start ( 'test' ) ;
396+ profiler . processProfilingData ( {
397+ commitData : [
398+ {
399+ timestamp : 1000 ,
400+ duration : 5 ,
401+ fiberActualDurations : [ 1 , 5 ] ,
402+ fiberSelfDurations : [ 1 , 5 ] ,
403+ } ,
404+ ] ,
405+ } ) ;
406+ profiler . stop ( tree ) ;
407+
408+ const root = profiler . getExportData ( tree ) ! . dataForRoots [ 0 ] ;
409+ // Should have snapshots for all nodes in the tree
410+ expect ( root . snapshots . length ) . toBeGreaterThanOrEqual ( 3 ) ; // App, Header, Content
411+
412+ // Find the App snapshot
413+ const appSnapshot = root . snapshots . find ( ( [ id ] ) => id === 1 ) ;
414+ expect ( appSnapshot ) . toBeDefined ( ) ;
415+ const [ , appNode ] = appSnapshot ! ;
416+ expect ( appNode . displayName ) . toBe ( 'App' ) ;
417+ expect ( appNode . type ) . toBe ( 5 ) ; // ElementType for function
418+ expect ( appNode . children ) . toEqual ( expect . arrayContaining ( [ 2 , 3 ] ) ) ;
419+ expect ( appNode . compiledWithForget ) . toBe ( false ) ;
420+ expect ( appNode . hocDisplayNames ) . toBeNull ( ) ;
421+ } ) ;
422+
423+ it ( 'populates initialTreeBaseDurations from first commit' , ( ) => {
424+ profiler . start ( 'test' ) ;
425+ profiler . processProfilingData ( {
426+ commitData : [
427+ {
428+ timestamp : 1000 ,
429+ duration : 15 ,
430+ fiberActualDurations : [ 1 , 10 , 2 , 3 ] ,
431+ fiberSelfDurations : [ 1 , 5 , 2 , 3 ] ,
432+ } ,
433+ {
434+ timestamp : 2000 ,
435+ duration : 8 ,
436+ fiberActualDurations : [ 1 , 6 ] ,
437+ fiberSelfDurations : [ 1 , 4 ] ,
438+ } ,
439+ ] ,
440+ } ) ;
441+ profiler . stop ( tree ) ;
442+
443+ const root = profiler . getExportData ( tree ) ! . dataForRoots [ 0 ] ;
444+ // Should use first commit's self durations
445+ expect ( root . initialTreeBaseDurations ) . toEqual ( expect . arrayContaining ( [ [ 1 , 5 ] , [ 2 , 3 ] ] ) ) ;
446+ } ) ;
447+
448+ it ( 'produces JSON that can be serialized and parsed' , ( ) => {
449+ profiler . start ( 'test' ) ;
450+ profiler . processProfilingData ( {
451+ commitData : [
452+ {
453+ timestamp : 1000 ,
454+ duration : 15 ,
455+ fiberActualDurations : [ 1 , 10 , 2 , 3 , 3 , 2 ] ,
456+ fiberSelfDurations : [ 1 , 5 , 2 , 3 , 3 , 2 ] ,
457+ changeDescriptions : [
458+ [ 1 , { props : [ 'x' ] , isFirstMount : false } ] ,
459+ ] ,
460+ } ,
461+ ] ,
462+ } ) ;
463+ profiler . stop ( tree ) ;
464+
465+ const exported = profiler . getExportData ( tree ) ! ;
466+ const json = JSON . stringify ( exported ) ;
467+ const parsed = JSON . parse ( json ) ;
468+ expect ( parsed . version ) . toBe ( 5 ) ;
469+ expect ( parsed . dataForRoots ) . toHaveLength ( 1 ) ;
470+ expect ( parsed . dataForRoots [ 0 ] . commitData ) . toHaveLength ( 1 ) ;
471+ } ) ;
472+ } ) ;
302473} ) ;
0 commit comments