11import { fireEvent , render } from '@testing-library/react'
22import { describe , expect , it } from 'vitest'
33import Json from './Json.js'
4+ import { isPrimitive , shouldObjectCollapse } from './helpers.js'
45
56describe ( 'Json Component' , ( ) => {
67 it ( 'renders primitive types correctly' , ( ) => {
@@ -19,39 +20,134 @@ describe('Json Component', () => {
1920 expect ( getByText ( '"bar"' ) ) . toBeDefined ( )
2021 } )
2122
23+ it . for ( [
24+ [ 'foo' , 'bar' ] ,
25+ [ ] ,
26+ [ 1 , 2 , 3 ] ,
27+ [ 1 , 'foo' , null ] ,
28+ Array . from ( { length : 101 } , ( _ , i ) => i ) ,
29+ ] ) ( 'collapses any array' , ( array ) => {
30+ const { queryByText } = render ( < Json json = { array } /> )
31+ expect ( queryByText ( '▶' ) ) . toBeDefined ( )
32+ expect ( queryByText ( '▼' ) ) . toBeNull ( )
33+ } )
34+
35+ it . for ( [
36+ [ 'foo' , 'bar' ] ,
37+ [ ] ,
38+ [ 1 , 2 , 3 ] ,
39+ [ 1 , 'foo' , null , undefined ] ,
40+ ] ) ( 'shows short arrays of primitive items, without trailing comment about length' , ( array ) => {
41+ const { queryByText } = render ( < Json json = { array } /> )
42+ expect ( queryByText ( '...' ) ) . toBeNull ( )
43+ expect ( queryByText ( 'length' ) ) . toBeNull ( )
44+ } )
45+
46+ it . for ( [
47+ [ 1 , 'foo' , [ 1 , 2 , 3 ] ] ,
48+ Array . from ( { length : 101 } , ( _ , i ) => i ) ,
49+ ] ) ( 'hides long arrays, and non-primitive items, with trailing comment about length' , ( array ) => {
50+ const { queryByText } = render ( < Json json = { array } /> )
51+ expect ( queryByText ( '...' ) ) . toBeDefined ( )
52+ expect ( queryByText ( 'length' ) ) . toBeDefined ( )
53+ } )
54+
2255 it ( 'renders an object' , ( ) => {
2356 const { getByText } = render ( < Json json = { { key : 'value' } } /> )
2457 expect ( getByText ( 'key:' ) ) . toBeDefined ( )
2558 expect ( getByText ( '"value"' ) ) . toBeDefined ( )
2659 } )
2760
2861 it ( 'renders nested objects' , ( ) => {
29- const { getByText } = render ( < Json json = { { obj : { arr : [ 314 , null ] } } } /> )
62+ const { getByText } = render ( < Json json = { { obj : { arr : [ 314 , '42' ] } } } /> )
3063 expect ( getByText ( 'obj:' ) ) . toBeDefined ( )
3164 expect ( getByText ( 'arr:' ) ) . toBeDefined ( )
3265 expect ( getByText ( '314' ) ) . toBeDefined ( )
33- expect ( getByText ( 'null' ) ) . toBeDefined ( )
66+ expect ( getByText ( '"42"' ) ) . toBeDefined ( )
67+ } )
68+
69+ it . for ( [
70+ { obj : [ 314 , null ] } ,
71+ { obj : { nested : true } } ,
72+ ] ) ( 'expands short objects with non-primitive values' , ( obj ) => {
73+ const { queryByText } = render ( < Json json = { obj } /> )
74+ expect ( queryByText ( '▼' ) ) . toBeDefined ( )
75+ } )
76+
77+ it . for ( [
78+ { obj : [ 314 , null ] } ,
79+ { obj : { nested : true } } ,
80+ ] ) ( 'hides the content and append number of entries when objects with non-primitive values are collapsed' , ( obj ) => {
81+ const { getByText, queryByText } = render ( < Json json = { obj } /> )
82+ fireEvent . click ( getByText ( '▼' ) )
83+ expect ( queryByText ( '...' ) ) . toBeDefined ( )
84+ expect ( queryByText ( 'entries' ) ) . toBeDefined ( )
85+ } )
86+
87+ it . for ( [
88+ { } ,
89+ { a : 1 , b : 2 } ,
90+ { a : 1 , b : true , c : null , d : undefined } ,
91+ Object . fromEntries ( Array . from ( { length : 101 } , ( _ , i ) => [ `key${ i } ` , { nested : true } ] ) ) ,
92+ ] ) ( 'collapses long objects, or objects with only primitive values (included empty object)' , ( obj ) => {
93+ const { queryByText } = render ( < Json json = { obj } /> )
94+ expect ( queryByText ( '▶' ) ) . toBeDefined ( )
95+ expect ( queryByText ( '▼' ) ) . toBeNull ( )
96+ } )
97+
98+ it . for ( [
99+ Object . fromEntries ( Array . from ( { length : 101 } , ( _ , i ) => [ `key${ i } ` , { nested : true } ] ) ) ,
100+ ] ) ( 'hides the content and append number of entries when objects has many entries' , ( obj ) => {
101+ const { queryByText } = render ( < Json json = { obj } /> )
102+ expect ( queryByText ( '...' ) ) . toBeDefined ( )
103+ expect ( queryByText ( 'entries' ) ) . toBeDefined ( )
34104 } )
35105
36106 it ( 'toggles array collapse state' , ( ) => {
37- const { getByText, queryByText } = render ( < Json json = { [ 'foo' , 'bar' ] } /> )
38- expect ( getByText ( '"foo"' ) ) . toBeDefined ( )
39- expect ( getByText ( '"bar"' ) ) . toBeDefined ( )
107+ const longArray = Array . from ( { length : 101 } , ( _ , i ) => i )
108+ const { getByText, queryByText } = render ( < Json json = { longArray } /> )
109+ expect ( getByText ( '...' ) ) . toBeDefined ( )
110+ fireEvent . click ( getByText ( '▶' ) )
111+ expect ( queryByText ( '...' ) ) . toBeNull ( )
40112 fireEvent . click ( getByText ( '▼' ) )
41- expect ( queryByText ( '0: 1' ) ) . toBeNull ( )
42- fireEvent . click ( getByText ( '[...]' ) )
43- expect ( getByText ( '"foo"' ) ) . toBeDefined ( )
44- expect ( getByText ( '"bar"' ) ) . toBeDefined ( )
113+ expect ( getByText ( '...' ) ) . toBeDefined ( )
45114 } )
46115
47116 it ( 'toggles object collapse state' , ( ) => {
48- const { getByText, queryByText } = render ( < Json json = { { key : 'value' } } /> )
49- expect ( getByText ( 'key:' ) ) . toBeDefined ( )
50- expect ( getByText ( '"value"' ) ) . toBeDefined ( )
117+ const longObject = Object . fromEntries ( Array . from ( { length : 101 } , ( _ , i ) => [ `key${ i } ` , { nested : true } ] ) )
118+ const { getByText, queryByText } = render ( < Json json = { longObject } /> )
119+ expect ( getByText ( '...' ) ) . toBeDefined ( )
120+ fireEvent . click ( getByText ( '▶' ) )
121+ expect ( queryByText ( '...' ) ) . toBeNull ( )
51122 fireEvent . click ( getByText ( '▼' ) )
52- expect ( queryByText ( 'key: "value"' ) ) . toBeNull ( )
53- fireEvent . click ( getByText ( '{...}' ) )
54- expect ( getByText ( 'key:' ) ) . toBeDefined ( )
55- expect ( getByText ( '"value"' ) ) . toBeDefined ( )
123+ expect ( getByText ( '...' ) ) . toBeDefined ( )
124+ } )
125+ } )
126+
127+ describe ( 'isPrimitive' , ( ) => {
128+ it ( 'returns true only for primitive types' , ( ) => {
129+ expect ( isPrimitive ( 'test' ) ) . toBe ( true )
130+ expect ( isPrimitive ( 42 ) ) . toBe ( true )
131+ expect ( isPrimitive ( true ) ) . toBe ( true )
132+ expect ( isPrimitive ( 1n ) ) . toBe ( true )
133+ expect ( isPrimitive ( null ) ) . toBe ( true )
134+ expect ( isPrimitive ( undefined ) ) . toBe ( true )
135+ expect ( isPrimitive ( { } ) ) . toBe ( false )
136+ expect ( isPrimitive ( [ ] ) ) . toBe ( false )
137+ } )
138+ } )
139+
140+ describe ( 'shouldObjectCollapse' , ( ) => {
141+ it ( 'returns true for objects with all primitive values' , ( ) => {
142+ expect ( shouldObjectCollapse ( { a : 1 , b : 'test' } ) ) . toBe ( true )
143+ } )
144+
145+ it ( 'returns false for objects with non-primitive values' , ( ) => {
146+ expect ( shouldObjectCollapse ( { a : 1 , b : { } } ) ) . toBe ( false )
147+ } )
148+
149+ it ( 'returns true for large objects' , ( ) => {
150+ const largeObject = Object . fromEntries ( Array . from ( { length : 101 } , ( _ , i ) => [ `key${ i } ` , i ] ) )
151+ expect ( shouldObjectCollapse ( largeObject ) ) . toBe ( true )
56152 } )
57153} )
0 commit comments