@@ -97,11 +97,7 @@ describe('BaseNodeController (e2e) /api/base/:baseId/node', () => {
9797 } ) ;
9898
9999 afterEach ( async ( ) => {
100- try {
101- await deleteBaseNode ( baseId , testNodeId ) ;
102- } catch ( e ) {
103- // Node might already be deleted
104- }
100+ await deleteBaseNode ( baseId , testNodeId ) ;
105101 } ) ;
106102
107103 it ( 'should get single node successfully' , async ( ) => {
@@ -133,11 +129,7 @@ describe('BaseNodeController (e2e) /api/base/:baseId/node', () => {
133129 afterEach ( async ( ) => {
134130 // Cleanup created nodes
135131 for ( const nodeId of nodesToCleanup ) {
136- try {
137- await deleteBaseNode ( baseId , nodeId ) ;
138- } catch ( e ) {
139- // Ignore cleanup errors
140- }
132+ await deleteBaseNode ( baseId , nodeId ) ;
141133 }
142134 nodesToCleanup . length = 0 ;
143135 } ) ;
@@ -293,11 +285,7 @@ describe('BaseNodeController (e2e) /api/base/:baseId/node', () => {
293285 } ) ;
294286
295287 afterEach ( async ( ) => {
296- try {
297- await deleteBaseNode ( baseId , testNodeId ) ;
298- } catch ( e ) {
299- // Node might already be deleted
300- }
288+ await deleteBaseNode ( baseId , testNodeId ) ;
301289 } ) ;
302290
303291 it ( 'should update node name successfully' , async ( ) => {
@@ -400,11 +388,7 @@ describe('BaseNodeController (e2e) /api/base/:baseId/node', () => {
400388
401389 afterEach ( async ( ) => {
402390 for ( const nodeId of nodesToCleanup ) {
403- try {
404- await deleteBaseNode ( baseId , nodeId ) ;
405- } catch ( e ) {
406- // Ignore cleanup errors
407- }
391+ await deleteBaseNode ( baseId , nodeId ) ;
408392 }
409393 nodesToCleanup . length = 0 ;
410394 } ) ;
@@ -686,11 +670,7 @@ describe('BaseNodeController (e2e) /api/base/:baseId/node', () => {
686670
687671 afterEach ( async ( ) => {
688672 for ( const nodeId of nodesToCleanup ) {
689- try {
690- await deleteBaseNode ( baseId , nodeId ) ;
691- } catch ( e ) {
692- // Ignore cleanup errors
693- }
673+ await deleteBaseNode ( baseId , nodeId ) ;
694674 }
695675 nodesToCleanup . length = 0 ;
696676 } ) ;
@@ -760,11 +740,7 @@ describe('BaseNodeController (e2e) /api/base/:baseId/node', () => {
760740
761741 afterEach ( async ( ) => {
762742 for ( const nodeId of nodesToCleanup ) {
763- try {
764- await deleteBaseNode ( baseId , nodeId ) ;
765- } catch ( e ) {
766- // Ignore cleanup errors
767- }
743+ await deleteBaseNode ( baseId , nodeId ) ;
768744 }
769745 nodesToCleanup . length = 0 ;
770746 } ) ;
@@ -802,14 +778,12 @@ describe('BaseNodeController (e2e) /api/base/:baseId/node', () => {
802778 } ) ;
803779
804780 it ( 'should handle complex folder hierarchy' , async ( ) => {
805- // Create root folder
806781 const root = await createBaseNode ( baseId , {
807782 resourceType : BaseNodeResourceType . Folder ,
808783 name : 'Root' ,
809784 } ) ;
810785 nodesToCleanup . push ( root . data . id ) ;
811786
812- // Create level 1 children
813787 const child1 = await createBaseNode ( baseId , {
814788 resourceType : BaseNodeResourceType . Folder ,
815789 name : 'Child 1' ,
@@ -824,13 +798,14 @@ describe('BaseNodeController (e2e) /api/base/:baseId/node', () => {
824798 } ) ;
825799 nodesToCleanup . push ( child2 . data . id ) ;
826800
827- // Create level 2 children
828- const grandchild = await createBaseNode ( baseId , {
829- resourceType : BaseNodeResourceType . Folder ,
830- name : 'Grandchild' ,
801+ const child1Table = await createBaseNode ( baseId , {
802+ resourceType : BaseNodeResourceType . Table ,
803+ name : 'Child 1 Table' ,
831804 parentId : child1 . data . id ,
805+ fields : [ { name : 'Field1' , type : FieldType . SingleLineText } ] ,
806+ views : [ { name : 'Grid view' , type : ViewType . Grid } ] ,
832807 } ) ;
833- nodesToCleanup . push ( grandchild . data . id ) ;
808+ nodesToCleanup . push ( child1Table . data . id ) ;
834809
835810 // Verify structure
836811 const tree = await getBaseNodeTree ( baseId ) ;
@@ -908,6 +883,173 @@ describe('BaseNodeController (e2e) /api/base/:baseId/node', () => {
908883 } ) ;
909884 } ) ;
910885
886+ describe ( 'Folder depth limitation' , ( ) => {
887+ const nodesToCleanup : string [ ] = [ ] ;
888+
889+ afterEach ( async ( ) => {
890+ // Cleanup nodes in reverse order to handle hierarchy
891+ for ( const nodeId of [ ...nodesToCleanup ] . reverse ( ) ) {
892+ await deleteBaseNode ( baseId , nodeId ) ;
893+ }
894+ nodesToCleanup . length = 0 ;
895+ } ) ;
896+
897+ it ( 'should allow creating folders up to max depth (3 levels)' , async ( ) => {
898+ // Create level 1 folder
899+ const level1 = await createBaseNode ( baseId , {
900+ resourceType : BaseNodeResourceType . Folder ,
901+ name : 'Level 1 Folder' ,
902+ } ) ;
903+ nodesToCleanup . push ( level1 . data . id ) ;
904+ expect ( level1 . data . parentId ) . toBeNull ( ) ;
905+
906+ // Create level 2 folder
907+ const level2 = await createBaseNode ( baseId , {
908+ resourceType : BaseNodeResourceType . Folder ,
909+ name : 'Level 2 Folder' ,
910+ parentId : level1 . data . id ,
911+ } ) ;
912+ nodesToCleanup . push ( level2 . data . id ) ;
913+ expect ( level2 . data . parentId ) . toBe ( level1 . data . id ) ;
914+ } ) ;
915+
916+ it ( 'should fail when creating folder exceeding max depth (4th level)' , async ( ) => {
917+ // Create 3 levels of folders
918+ const level1 = await createBaseNode ( baseId , {
919+ resourceType : BaseNodeResourceType . Folder ,
920+ name : 'Depth Limit Level 1' ,
921+ } ) ;
922+ nodesToCleanup . push ( level1 . data . id ) ;
923+
924+ const level2 = await createBaseNode ( baseId , {
925+ resourceType : BaseNodeResourceType . Folder ,
926+ name : 'Depth Limit Level 2' ,
927+ parentId : level1 . data . id ,
928+ } ) ;
929+ nodesToCleanup . push ( level2 . data . id ) ;
930+
931+ // Try to create level 4 folder (should fail)
932+ const error = await getError ( ( ) =>
933+ createBaseNode ( baseId , {
934+ resourceType : BaseNodeResourceType . Folder ,
935+ name : 'Depth Limit Level 3' ,
936+ parentId : level2 . data . id ,
937+ } )
938+ ) ;
939+
940+ expect ( error ?. status ) . toBe ( 400 ) ;
941+ } ) ;
942+
943+ it ( 'should allow creating table in folder at max depth' , async ( ) => {
944+ // Create 2 levels of folders
945+ const level1 = await createBaseNode ( baseId , {
946+ resourceType : BaseNodeResourceType . Folder ,
947+ name : 'Table Depth Level 1' ,
948+ } ) ;
949+ nodesToCleanup . push ( level1 . data . id ) ;
950+
951+ const level2 = await createBaseNode ( baseId , {
952+ resourceType : BaseNodeResourceType . Folder ,
953+ name : 'Table Depth Level 2' ,
954+ parentId : level1 . data . id ,
955+ } ) ;
956+ nodesToCleanup . push ( level2 . data . id ) ;
957+
958+ // Create table in level 2 folder (should succeed - tables don't count as depth)
959+ const table = await createBaseNode ( baseId , {
960+ resourceType : BaseNodeResourceType . Table ,
961+ name : 'Table in Max Depth' ,
962+ parentId : level2 . data . id ,
963+ fields : [ { name : 'Field1' , type : FieldType . SingleLineText } ] ,
964+ views : [ { name : 'Grid view' , type : ViewType . Grid } ] ,
965+ } ) ;
966+ nodesToCleanup . push ( table . data . id ) ;
967+ expect ( table . data . parentId ) . toBe ( level2 . data . id ) ;
968+ } ) ;
969+
970+ it ( 'should fail when moving folder to exceed max depth using anchorId' , async ( ) => {
971+ // Create 3 levels of folders
972+ const level1 = await createBaseNode ( baseId , {
973+ resourceType : BaseNodeResourceType . Folder ,
974+ name : 'Move Depth Level 1' ,
975+ } ) ;
976+ nodesToCleanup . push ( level1 . data . id ) ;
977+
978+ const level2 = await createBaseNode ( baseId , {
979+ resourceType : BaseNodeResourceType . Folder ,
980+ name : 'Move Depth Level 2' ,
981+ parentId : level1 . data . id ,
982+ } ) ;
983+ nodesToCleanup . push ( level2 . data . id ) ;
984+
985+ const level3 = await createBaseNode ( baseId , {
986+ resourceType : BaseNodeResourceType . Table ,
987+ name : 'Table in Move Depth Level 3' ,
988+ parentId : level2 . data . id ,
989+ fields : [ { name : 'Field1' , type : FieldType . SingleLineText } ] ,
990+ views : [ { name : 'Grid view' , type : ViewType . Grid } ] ,
991+ } ) ;
992+ nodesToCleanup . push ( level3 . data . id ) ;
993+
994+ // Create a folder at root level to move
995+ const folderToMove = await createBaseNode ( baseId , {
996+ resourceType : BaseNodeResourceType . Folder ,
997+ name : 'Folder to Move' ,
998+ } ) ;
999+ nodesToCleanup . push ( folderToMove . data . id ) ;
1000+
1001+ // Try to move folder next to level2 (which would make it level 3 if it had the same parent)
1002+ // Using anchorId with position should check depth
1003+ const error = await getError ( ( ) =>
1004+ moveBaseNode ( baseId , folderToMove . data . id , {
1005+ anchorId : level3 . data . id ,
1006+ position : 'after' ,
1007+ } )
1008+ ) ;
1009+
1010+ expect ( error ?. status ) . toBe ( 400 ) ;
1011+ } ) ;
1012+
1013+ it ( 'should allow moving folder within valid depth using anchorId' , async ( ) => {
1014+ // Create 2 levels of folders
1015+ const level1 = await createBaseNode ( baseId , {
1016+ resourceType : BaseNodeResourceType . Folder ,
1017+ name : 'Valid Move Level 1' ,
1018+ } ) ;
1019+ nodesToCleanup . push ( level1 . data . id ) ;
1020+
1021+ const level2 = await createBaseNode ( baseId , {
1022+ resourceType : BaseNodeResourceType . Folder ,
1023+ name : 'Valid Move Level 2' ,
1024+ parentId : level1 . data . id ,
1025+ } ) ;
1026+ nodesToCleanup . push ( level2 . data . id ) ;
1027+
1028+ // Create a folder at root level
1029+ const folderToMove = await createBaseNode ( baseId , {
1030+ resourceType : BaseNodeResourceType . Folder ,
1031+ name : 'Folder to Move Valid' ,
1032+ } ) ;
1033+ nodesToCleanup . push ( folderToMove . data . id ) ;
1034+
1035+ // Move folder next to level2 (which makes it level 3 - still valid)
1036+ const response = await moveBaseNode ( baseId , folderToMove . data . id , {
1037+ anchorId : level2 . data . id ,
1038+ position : 'after' ,
1039+ } ) ;
1040+
1041+ expect ( response . data . id ) . toBe ( folderToMove . data . id ) ;
1042+ expect ( response . data . parentId ) . toBe ( level1 . data . id ) ;
1043+ } ) ;
1044+
1045+ it ( 'should return maxFolderDepth in tree response' , async ( ) => {
1046+ const response = await getBaseNodeTree ( baseId ) ;
1047+
1048+ expect ( response . data ) . toHaveProperty ( 'maxFolderDepth' ) ;
1049+ expect ( response . data . maxFolderDepth ) . toBe ( 2 ) ;
1050+ } ) ;
1051+ } ) ;
1052+
9111053 describe ( 'Permission tests' , ( ) => {
9121054 let permissionSpaceId : string ;
9131055 let permissionBaseId : string ;
@@ -1181,11 +1323,7 @@ describe('BaseNodeController (e2e) /api/base/:baseId/node', () => {
11811323
11821324 afterEach ( async ( ) => {
11831325 for ( const nodeId of creatorNodesToCleanup ) {
1184- try {
1185- await deleteBaseNode ( permissionBaseId , nodeId ) ;
1186- } catch ( e ) {
1187- // Ignore cleanup errors
1188- }
1326+ await deleteBaseNode ( permissionBaseId , nodeId ) ;
11891327 }
11901328 creatorNodesToCleanup . length = 0 ;
11911329 } ) ;
0 commit comments