@@ -6,6 +6,7 @@ import { framePromise } from '@jupyterlab/testing';
66import { NotebookPanel } from '@jupyterlab/notebook' ;
77import { INotebookModel } from '@jupyterlab/notebook' ;
88import { Widget } from '@lumino/widgets' ;
9+ import { Message } from '@lumino/messaging' ;
910import { simulate } from 'simulate-event' ;
1011
1112describe ( 'NotebookPicker' , ( ) => {
@@ -125,7 +126,6 @@ describe('NotebookPicker', () => {
125126
126127 document . body . innerHTML = '' ;
127128 const widget = new NotebookPicker ( errorPanel ) ;
128- // Override onAfterAttach to avoid errors from this.parent being null
129129 ( widget as any ) . onAfterAttach = jest . fn ( ) ;
130130 Widget . attach ( widget , document . body ) ;
131131 await framePromise ( ) ;
@@ -139,4 +139,62 @@ describe('NotebookPicker', () => {
139139
140140 consoleErrorSpy . mockRestore ( ) ;
141141 } ) ;
142+
143+ it ( 'should handle null model in handleChange' , async ( ) => {
144+ const nullModelPanel = {
145+ context : {
146+ ready : Promise . resolve ( ) ,
147+ model : {
148+ getMetadata : jest . fn ( ) . mockReturnValue ( {
149+ notebooks : {
150+ nb1 : { id : 'nb1' , name : 'nb1' , cells : [ ] }
151+ } ,
152+ notebook_names : [ 'nb1' ]
153+ } )
154+ }
155+ } ,
156+ model : null
157+ } as any ;
158+
159+ document . body . innerHTML = '' ;
160+ const widget = new NotebookPicker ( nullModelPanel ) ;
161+ ( widget as any ) . onAfterAttach = jest . fn ( ) ;
162+ Widget . attach ( widget , document . body ) ;
163+ await framePromise ( ) ;
164+
165+ const select = document . querySelector ( 'select' ) as HTMLSelectElement ;
166+ simulate ( select , 'change' , { target : { value : 'nb1' } } ) ;
167+ await framePromise ( ) ;
168+ } ) ;
169+
170+ it ( 'should handle invalid metadata in handleChange' , async ( ) => {
171+ const consoleErrorSpy = jest
172+ . spyOn ( console , 'error' )
173+ . mockImplementation ( ( ) => { } ) ;
174+ const getMetadata = panel . context . model . getMetadata as jest . Mock ;
175+ getMetadata . mockReturnValue ( { invalid : 'metadata' } ) ;
176+
177+ const select = document . querySelector ( 'select' ) as HTMLSelectElement ;
178+ simulate ( select , 'change' , { target : { value : 'nb1' } } ) ;
179+ await framePromise ( ) ;
180+
181+ expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
182+ 'Invalid deepnote metadata:' ,
183+ expect . anything ( )
184+ ) ;
185+ expect ( model . fromJSON ) . not . toHaveBeenCalled ( ) ;
186+
187+ consoleErrorSpy . mockRestore ( ) ;
188+ } ) ;
189+
190+ it ( 'should handle onAfterAttach without parent' , async ( ) => {
191+ document . body . innerHTML = '' ;
192+ const widget = new NotebookPicker ( panel ) ;
193+ Widget . attach ( widget , document . body ) ;
194+ await framePromise ( ) ;
195+
196+ const onAfterAttachMethod = ( widget as any ) . onAfterAttach . bind ( widget ) ;
197+ onAfterAttachMethod ( { } as Message ) ;
198+ await new Promise ( resolve => requestAnimationFrame ( resolve ) ) ;
199+ } ) ;
142200} ) ;
0 commit comments