@@ -79,4 +79,44 @@ describe('ProfilerStore', () => {
7979 store . profilerStore . profilingData = fauxProfilingData ;
8080 expect ( store . profilerStore . profilingData ) . toBe ( fauxProfilingData ) ;
8181 } ) ;
82+
83+ // This test covers current broken behavior (arguably) with the synthetic event system.
84+ it ( 'should filter empty commits' , ( ) => {
85+ const inputRef = React . createRef ( ) ;
86+ const ControlledInput = ( ) => {
87+ const [ name , setName ] = React . useState ( 'foo' ) ;
88+ const handleChange = event => setName ( event . target . value ) ;
89+ return < input ref = { inputRef } value = { name } onChange = { handleChange } /> ;
90+ } ;
91+
92+ const container = document . createElement ( 'div' ) ;
93+
94+ // This element has to be in the <body> for the event system to work.
95+ document . body . appendChild ( container ) ;
96+
97+ // It's important that this test uses legacy sync mode.
98+ // The root API does not trigger this particular failing case.
99+ ReactDOM . render ( < ControlledInput /> , container ) ;
100+
101+ utils . act ( ( ) => store . profilerStore . startProfiling ( ) ) ;
102+
103+ // Sets a value in a way that React doesn't see,
104+ // so that a subsequent "change" event will trigger the event handler.
105+ const setUntrackedValue = Object . getOwnPropertyDescriptor (
106+ HTMLInputElement . prototype ,
107+ 'value' ,
108+ ) . set ;
109+
110+ const target = inputRef . current ;
111+ setUntrackedValue . call ( target , 'bar' ) ;
112+ target . dispatchEvent ( new Event ( 'input' , { bubbles : true , cancelable : true } ) ) ;
113+ expect ( target . value ) . toBe ( 'bar' ) ;
114+
115+ utils . act ( ( ) => store . profilerStore . stopProfiling ( ) ) ;
116+
117+ // Only one commit should have been recorded (in response to the "change" event).
118+ const root = store . roots [ 0 ] ;
119+ const data = store . profilerStore . getDataForRoot ( root ) ;
120+ expect ( data . commitData ) . toHaveLength ( 1 ) ;
121+ } ) ;
82122} ) ;
0 commit comments