@@ -4,8 +4,10 @@ import {
44 createPluginTestHelpers ,
55 screen ,
66 waitFor ,
7+ render ,
8+ userEvent ,
79} from '@mongodb-js/testing-library-compass' ;
8- import DiagramEditor from './diagram-editor' ;
10+ import DiagramEditor , { getFieldsFromSchema } from './diagram-editor' ;
911import type { DataModelingStore } from '../../test/setup-store' ;
1012import type {
1113 Edit ,
@@ -229,3 +231,182 @@ describe('DiagramEditor', function () {
229231 } ) ;
230232 } ) ;
231233} ) ;
234+
235+ describe ( 'getFieldsFromSchema' , function ( ) {
236+ const validateMixedType = async (
237+ type : React . ReactNode ,
238+ expectedTooltip : RegExp
239+ ) => {
240+ render ( < > { type } </ > ) ;
241+ const mixed = screen . getByText ( '(mixed)' ) ;
242+ expect ( mixed ) . to . be . visible ;
243+ expect ( screen . queryByText ( expectedTooltip ) ) . to . not . exist ;
244+ userEvent . hover ( mixed ) ;
245+ await waitFor ( ( ) => {
246+ expect ( screen . getByText ( expectedTooltip ) ) . to . be . visible ;
247+ } ) ;
248+ } ;
249+
250+ describe ( 'flat schema' , function ( ) {
251+ it ( 'return empty array for empty schema' , function ( ) {
252+ const result = getFieldsFromSchema ( { } ) ;
253+ expect ( result ) . to . deep . equal ( [ ] ) ;
254+ } ) ;
255+
256+ it ( 'returns fields for a simple schema' , function ( ) {
257+ const result = getFieldsFromSchema ( {
258+ bsonType : 'object' ,
259+ properties : {
260+ name : { bsonType : 'string' } ,
261+ age : { bsonType : 'int' } ,
262+ } ,
263+ } ) ;
264+ expect ( result ) . to . deep . equal ( [
265+ { name : 'name' , type : 'string' , depth : 0 , glyphs : [ ] } ,
266+ { name : 'age' , type : 'int' , depth : 0 , glyphs : [ ] } ,
267+ ] ) ;
268+ } ) ;
269+
270+ it ( 'returns mixed fields with tooltip on hover' , async function ( ) {
271+ const result = getFieldsFromSchema ( {
272+ bsonType : 'object' ,
273+ properties : {
274+ age : { bsonType : [ 'int' , 'string' ] } ,
275+ } ,
276+ } ) ;
277+ expect ( result [ 0 ] ) . to . deep . include ( { name : 'age' , depth : 0 , glyphs : [ ] } ) ;
278+ await validateMixedType ( result [ 0 ] . type , / i n t , s t r i n g / ) ;
279+ } ) ;
280+ } ) ;
281+
282+ describe ( 'nested schema' , function ( ) {
283+ it ( 'returns fields for a nested schema' , function ( ) {
284+ const result = getFieldsFromSchema ( {
285+ bsonType : 'object' ,
286+ properties : {
287+ person : {
288+ bsonType : 'object' ,
289+ properties : {
290+ name : { bsonType : 'string' } ,
291+ address : {
292+ bsonType : 'object' ,
293+ properties : {
294+ street : { bsonType : 'string' } ,
295+ city : { bsonType : 'string' } ,
296+ } ,
297+ } ,
298+ } ,
299+ } ,
300+ } ,
301+ } ) ;
302+ expect ( result ) . to . deep . equal ( [
303+ { name : 'person' , type : 'object' , depth : 0 , glyphs : [ ] } ,
304+ { name : 'name' , type : 'string' , depth : 1 , glyphs : [ ] } ,
305+ { name : 'address' , type : 'object' , depth : 1 , glyphs : [ ] } ,
306+ { name : 'street' , type : 'string' , depth : 2 , glyphs : [ ] } ,
307+ { name : 'city' , type : 'string' , depth : 2 , glyphs : [ ] } ,
308+ ] ) ;
309+ } ) ;
310+
311+ it ( 'returns [] for array' , function ( ) {
312+ const result = getFieldsFromSchema ( {
313+ bsonType : 'object' ,
314+ properties : {
315+ tags : {
316+ bsonType : 'array' ,
317+ items : { bsonType : 'string' } ,
318+ } ,
319+ } ,
320+ } ) ;
321+ expect ( result ) . to . deep . equal ( [
322+ { name : 'tags' , type : '[]' , depth : 0 , glyphs : [ ] } ,
323+ ] ) ;
324+ } ) ;
325+
326+ it ( 'returns fields for an array of objects' , function ( ) {
327+ const result = getFieldsFromSchema ( {
328+ bsonType : 'object' ,
329+ properties : {
330+ todos : {
331+ bsonType : 'array' ,
332+ items : {
333+ bsonType : 'object' ,
334+ properties : {
335+ title : { bsonType : 'string' } ,
336+ completed : { bsonType : 'boolean' } ,
337+ } ,
338+ } ,
339+ } ,
340+ } ,
341+ } ) ;
342+ expect ( result ) . to . deep . equal ( [
343+ { name : 'todos' , type : '[]' , depth : 0 , glyphs : [ ] } ,
344+ { name : 'title' , type : 'string' , depth : 1 , glyphs : [ ] } ,
345+ { name : 'completed' , type : 'boolean' , depth : 1 , glyphs : [ ] } ,
346+ ] ) ;
347+ } ) ;
348+
349+ it ( 'returns fields for a mixed schema with objects' , async function ( ) {
350+ const result = getFieldsFromSchema ( {
351+ bsonType : 'object' ,
352+ properties : {
353+ name : {
354+ anyOf : [
355+ { bsonType : 'string' } ,
356+ {
357+ bsonType : 'object' ,
358+ properties : {
359+ first : { bsonType : 'string' } ,
360+ last : { bsonType : 'string' } ,
361+ } ,
362+ } ,
363+ ] ,
364+ } ,
365+ } ,
366+ } ) ;
367+ expect ( result ) . to . have . lengthOf ( 3 ) ;
368+ expect ( result [ 0 ] ) . to . deep . include ( { name : 'name' , depth : 0 , glyphs : [ ] } ) ;
369+ await validateMixedType ( result [ 0 ] . type , / s t r i n g , o b j e c t / ) ;
370+ expect ( result [ 1 ] ) . to . deep . equal ( {
371+ name : 'first' ,
372+ type : 'string' ,
373+ depth : 1 ,
374+ glyphs : [ ] ,
375+ } ) ;
376+ expect ( result [ 2 ] ) . to . deep . equal ( {
377+ name : 'last' ,
378+ type : 'string' ,
379+ depth : 1 ,
380+ glyphs : [ ] ,
381+ } ) ;
382+ } ) ;
383+
384+ it ( 'returns fields for an array of mixed (including objects)' , function ( ) {
385+ const result = getFieldsFromSchema ( {
386+ bsonType : 'object' ,
387+ properties : {
388+ todos : {
389+ bsonType : 'array' ,
390+ items : {
391+ anyOf : [
392+ {
393+ bsonType : 'object' ,
394+ properties : {
395+ title : { bsonType : 'string' } ,
396+ completed : { bsonType : 'boolean' } ,
397+ } ,
398+ } ,
399+ { bsonType : 'string' } ,
400+ ] ,
401+ } ,
402+ } ,
403+ } ,
404+ } ) ;
405+ expect ( result ) . to . deep . equal ( [
406+ { name : 'todos' , type : '[]' , depth : 0 , glyphs : [ ] } ,
407+ { name : 'title' , type : 'string' , depth : 1 , glyphs : [ ] } ,
408+ { name : 'completed' , type : 'boolean' , depth : 1 , glyphs : [ ] } ,
409+ ] ) ;
410+ } ) ;
411+ } ) ;
412+ } ) ;
0 commit comments