@@ -189,6 +189,73 @@ describe('DevTools - AtomViewer', () => {
189189 expect ( container ) . toMatchSnapshot ( ) ;
190190 } ) ;
191191 } ) ;
192+
193+ describe ( 'auto unmount' , ( ) => {
194+ it ( 'should unselect the atom when an atom is unsubscribed' , async ( ) => {
195+ const BasicAtoms = ( ) => {
196+ const countAtom = useMemo ( ( ) => atom ( 0 ) , [ ] ) ;
197+ countAtom . debugLabel = 'countAtom' ;
198+ const doubleCountAtom = useMemo (
199+ ( ) => atom ( ( get ) => get ( countAtom ) * 2 ) ,
200+ [ countAtom ] ,
201+ ) ;
202+ doubleCountAtom . debugLabel = 'doubleCountAtom' ;
203+ useAtomValue ( doubleCountAtom ) ;
204+
205+ return < div data-testid = "basic-atoms" > </ div > ;
206+ } ;
207+
208+ const ToggleAbleAtomWithDevTools = ( ) => {
209+ const [ shouldShow , setShouldShow ] = React . useState ( true ) ;
210+
211+ const handleOntoggle = React . useCallback ( ( ) => {
212+ setShouldShow ( ( s ) => ! s ) ;
213+ } , [ setShouldShow ] ) ;
214+
215+ return (
216+ < >
217+ { shouldShow ? < BasicAtoms /> : null }
218+ < button onClick = { handleOntoggle } > Toggle</ button >
219+ </ >
220+ ) ;
221+ } ;
222+
223+ const TestComponent = ( ) => {
224+ return (
225+ < >
226+ < DevTools isInitialOpen = { true } />
227+ < ToggleAbleAtomWithDevTools />
228+ </ >
229+ ) ;
230+ } ;
231+
232+ customRender ( < TestComponent /> ) ;
233+ await act ( async ( ) => {
234+ await userEvent . click ( screen . getByText ( 'doubleCountAtom' ) ) ;
235+ } ) ;
236+ expect (
237+ screen . getByTestId ( 'display-detail-item-value-doubleCountAtom' ) ,
238+ ) . toBeInTheDocument ( ) ;
239+
240+ await act ( async ( ) => {
241+ await userEvent . click ( screen . getByText ( 'Toggle' ) ) ;
242+ } ) ;
243+
244+ expect ( screen . queryByText ( 'Atom Details' ) ) . not . toBeInTheDocument ( ) ;
245+ expect (
246+ screen . queryByText ( 'display-detail-item-value-doubleCountAtom' ) ,
247+ ) . not . toBeInTheDocument ( ) ;
248+ expect (
249+ screen . getByTestId ( 'atom-list-no-atoms-found-message' ) ,
250+ ) . toHaveTextContent ( 'No Atoms found!' ) ;
251+ expect ( screen . getByLabelText ( 'Search' ) ) . toBeInTheDocument ( ) ;
252+ expect (
253+ screen . getByText (
254+ 'Select an atom from the left panel to view the details' ,
255+ ) ,
256+ ) . toBeInTheDocument ( ) ;
257+ } ) ;
258+ } ) ;
192259 } ) ;
193260
194261 describe ( 'Atom details' , ( ) => {
@@ -310,99 +377,5 @@ describe('DevTools - AtomViewer', () => {
310377 ) ;
311378 } ) ;
312379 } ) ;
313-
314- describe ( 'Deep nested values' , ( ) => {
315- it ( 'should display atom details with deeply parsed value when an atom is selected' , async ( ) => {
316- const NestedAtomsWithDevTools = ( ) => {
317- // Create atoms inside the component so that they are recreated for each test
318- const countAtom = useMemo ( ( ) => atom ( 0 ) , [ ] ) ;
319- countAtom . debugLabel = 'countAtom' ;
320-
321- const doubleNestedAtom = useMemo (
322- ( ) => atom ( atom ( ( get ) => get ( countAtom ) * 2 + 1 ) ) ,
323- [ countAtom ] ,
324- ) ;
325-
326- useAtomValue ( countAtom ) ;
327- useAtomValue ( doubleNestedAtom ) ;
328- return (
329- < DevTools
330- isInitialOpen = { true }
331- options = { { atomValueParser : 'deep-nested' } }
332- />
333- ) ;
334- } ;
335-
336- const { container } = customRender ( < NestedAtomsWithDevTools /> ) ;
337-
338- await act ( async ( ) => {
339- await userEvent . click ( screen . getByText ( '<unlabeled-atom>' ) ) ;
340- } ) ;
341-
342- expect ( screen . getByText ( 'Atom Details' ) ) . toBeInTheDocument ( ) ;
343- expect ( screen . getByText ( 'Meta' ) ) . toBeInTheDocument ( ) ;
344- expect ( screen . getByText ( 'Debug Label' ) ) . toBeInTheDocument ( ) ;
345- expect (
346- screen . getByTestId ( 'display-detail-item-value-<unlabeled-atom>' ) ,
347- ) . toHaveTextContent ( '<unlabeled-atom>' ) ;
348- expect ( screen . getByText ( 'Value type' ) ) . toBeInTheDocument ( ) ;
349- expect (
350- screen . getByTestId ( 'display-detail-item-value-atom' ) ,
351- ) . toHaveTextContent ( 'atom' ) ;
352-
353- expect ( screen . getByText ( 'Parsed value' ) ) . toBeInTheDocument ( ) ;
354- expect ( screen . getByTestId ( 'atom-parsed-value' ) ) . toHaveTextContent ( '1' ) ;
355-
356- expect ( screen . getByText ( 'Dependents' ) ) . toBeInTheDocument ( ) ;
357- // There are no dependents for this atom yet because those dependents are not yet mounted
358- expect ( screen . getByText ( 'No dependents' ) ) . toBeInTheDocument ( ) ;
359- await waitFor ( ( ) => expect ( container ) . toMatchSnapshot ( ) ) ;
360- } ) ;
361-
362- describe ( 'Supports most primitive value types' , ( ) => {
363- const AtomRenderer = ( { atom } : { atom : AnyAtom } ) => {
364- useAtomValue ( atom ) ;
365- return (
366- < DevTools
367- isInitialOpen = { true }
368- options = { {
369- atomValueParser : 'deep-nested' ,
370- } }
371- />
372- ) ;
373- } ;
374-
375- it . each `
376- type | value | expected
377- ${ 'string' } | ${ 'some-string' } | ${ 'some-string' }
378- ${ 'number' } | ${ 123 } | ${ 123 }
379- ${ 'boolean' } | ${ true } | ${ true }
380- ${ 'boolean' } | ${ false } | ${ false }
381- ${ 'null' } | ${ null } | ${ 'null' }
382- ${ 'undefined' } | ${ undefined } | ${ 'undefined' }
383- ${ 'bigint' } | ${ BigInt ( 123 ) } | ${ '123' }
384- ${ 'symbol' } | ${ Symbol ( 'some-symbol' ) } | ${ 'Symbol(some-symbol)' }
385- ${ 'function' } | ${ ( ) => ( ) => 'hello' } | ${ "()=>'hello'" }
386- ${ 'object' } | ${ { foo : 'bar' } } | ${ '{ "foo": "bar"}' }
387- ${ 'array' } | ${ [ 1 , 2 , 3 ] } | ${ '[ 1, 2, 3]' }
388- ` (
389- 'should parse "$type" value correctly' ,
390- async ( { value, expected } ) => {
391- const valueAtom = atom ( value ) ;
392- valueAtom . debugLabel = 'valueAtom' ;
393-
394- customRender ( < AtomRenderer atom = { valueAtom } /> ) ;
395-
396- await act ( async ( ) => {
397- await userEvent . click ( screen . getByText ( 'valueAtom' ) ) ;
398- } ) ;
399-
400- expect ( screen . getByTestId ( 'atom-parsed-value' ) ) . toHaveTextContent (
401- expected ,
402- ) ;
403- } ,
404- ) ;
405- } ) ;
406- } ) ;
407380 } ) ;
408381} ) ;
0 commit comments