@@ -197,6 +197,50 @@ describe('theme-change chart redraw', () => {
197197 expect ( updates . length ) . toBeGreaterThan ( 0 ) ;
198198 } ) ;
199199
200+ it ( 'prefers addEventListener when the MediaQueryList supports both listener APIs' , ( ) => {
201+ installThemeRadios ( 'system' ) ;
202+ const bound = [ ] ;
203+ window . matchMedia = ( ) => ( {
204+ matches : false ,
205+ addEventListener ( type , listener ) { bound . push ( [ 'modern' , type , listener ] ) ; } ,
206+ addListener ( listener ) { bound . push ( [ 'legacy' , listener ] ) ; }
207+ } ) ;
208+ document . documentElement . removeAttribute ( 'data-rf-theme-redraw-bound' ) ;
209+ bindThemeChartRedraw ( ) ;
210+
211+ expect ( bound ) . toHaveLength ( 1 ) ;
212+ expect ( bound [ 0 ] [ 0 ] ) . toBe ( 'modern' ) ;
213+ expect ( bound [ 0 ] [ 1 ] ) . toBe ( 'change' ) ;
214+ expect ( bound [ 0 ] [ 2 ] ) . toBeTypeOf ( 'function' ) ;
215+ } ) ;
216+
217+ it ( 'falls back to addListener when the MediaQueryList lacks addEventListener' , ( ) => {
218+ installThemeRadios ( 'system' ) ;
219+ let legacyListener = null ;
220+ window . matchMedia = ( ) => ( {
221+ matches : false ,
222+ addListener ( listener ) { legacyListener = listener ; }
223+ } ) ;
224+ document . documentElement . removeAttribute ( 'data-rf-theme-redraw-bound' ) ;
225+ bindThemeChartRedraw ( ) ;
226+ expect ( legacyListener ) . not . toBeNull ( ) ;
227+
228+ // The legacy subscription must drive the same redraw callback.
229+ const updates = [ ] ;
230+ window . Chart = function ( ) { return { update : ( ) => updates . push ( 'redraw' ) } ; } ;
231+ initBubbleChart ( document . getElementById ( 'chart_GOD' ) , 'God Classes' , { bubbles : [ ] } ) ;
232+ expect ( updates . length ) . toBe ( 0 ) ;
233+ legacyListener ( ) ;
234+ expect ( updates . length ) . toBeGreaterThan ( 0 ) ;
235+ } ) ;
236+
237+ it ( 'keeps working when the MediaQueryList exposes neither listener API' , ( ) => {
238+ installThemeRadios ( 'system' ) ;
239+ window . matchMedia = ( ) => ( { matches : false } ) ;
240+ document . documentElement . removeAttribute ( 'data-rf-theme-redraw-bound' ) ;
241+ expect ( ( ) => bindThemeChartRedraw ( ) ) . not . toThrow ( ) ;
242+ } ) ;
243+
200244 it ( 'redraws live charts when a theme radio changes' , ( ) => {
201245 installThemeRadios ( 'system' ) ;
202246 bindThemeChartRedraw ( ) ; // no-op: already bound above (and possibly earlier files)
0 commit comments