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