@@ -33,6 +33,8 @@ import com.cosmotech.api.rbac.ROLE_EDITOR
3333import com.cosmotech.api.rbac.ROLE_NONE
3434import com.cosmotech.api.rbac.ROLE_VIEWER
3535import com.cosmotech.dataset.domain.DatasetAccessControl
36+ import com.cosmotech.dataset.domain.DatasetCreateRequest
37+ import com.cosmotech.dataset.domain.DatasetPart
3638import com.cosmotech.dataset.domain.DatasetPartCreateRequest
3739import com.cosmotech.dataset.domain.DatasetPartTypeEnum
3840import com.cosmotech.dataset.domain.DatasetPartUpdateRequest
@@ -44,6 +46,7 @@ import com.cosmotech.solution.domain.RunTemplateResourceSizing
4446import java.io.InputStream
4547import kotlin.test.Ignore
4648import org.apache.commons.io.IOUtils
49+ import org.hamcrest.Matchers.empty
4750import org.hamcrest.Matchers.greaterThan
4851import org.json.JSONArray
4952import org.json.JSONObject
@@ -160,6 +163,91 @@ class DatasetControllerTests : ControllerTestBase() {
160163 .andDo(document(" organizations/{organization_id}/workspaces/{workspace_id}/datasets/POST" ))
161164 }
162165
166+ @Test
167+ @WithMockOauth2User
168+ fun create_dataset_with_no_files_parameter () {
169+ val datasetCreateRequest =
170+ MockMultipartFile (
171+ " datasetCreateRequest" ,
172+ null ,
173+ MediaType .APPLICATION_JSON_VALUE ,
174+ JSONObject (
175+ DatasetCreateRequest (
176+ name = DATASET_NAME ,
177+ description = DATASET_DESCRIPTION ,
178+ tags = mutableListOf (" tag1" , " tag2" ),
179+ runnerId = " r-12345678910" ))
180+ .toString()
181+ .byteInputStream())
182+
183+ mvc.perform(
184+ multipart(" /organizations/$organizationId /workspaces/$workspaceId /datasets" )
185+ .file(datasetCreateRequest)
186+ .accept(MediaType .APPLICATION_JSON )
187+ .with (csrf()))
188+ .andExpect(status().is2xxSuccessful)
189+ .andExpect(jsonPath(" $.name" ).value(DATASET_NAME ))
190+ .andExpect(jsonPath(" $.description" ).value(DATASET_DESCRIPTION ))
191+ .andExpect(jsonPath(" $.organizationId" ).value(organizationId))
192+ .andExpect(jsonPath(" $.workspaceId" ).value(workspaceId))
193+ .andExpect(jsonPath(" $.parts" , empty<DatasetPart >()))
194+ .andExpect(jsonPath(" $.createInfo.userId" ).value(PLATFORM_ADMIN_EMAIL ))
195+ .andExpect(jsonPath(" $.createInfo.runnerId" ).value(" r-12345678910" ))
196+ .andExpect(jsonPath(" $.createInfo.timestamp" ).isNumber)
197+ .andExpect(jsonPath(" $.createInfo.timestamp" ).value(greaterThan(0 .toLong())))
198+ .andExpect(jsonPath(" $.updateInfo.userId" ).value(PLATFORM_ADMIN_EMAIL ))
199+ .andExpect(jsonPath(" $.updateInfo.timestamp" ).isNumber)
200+ .andExpect(jsonPath(" $.updateInfo.timestamp" ).value(greaterThan(0 .toLong())))
201+ .andExpect(jsonPath(" $.tags" ).value(mutableListOf (" tag1" , " tag2" )))
202+ .andExpect(jsonPath(" $.security.default" ).value(ROLE_NONE ))
203+ .andExpect(jsonPath(" $.security.accessControlList[0].role" ).value(ROLE_ADMIN ))
204+ .andExpect(jsonPath(" $.security.accessControlList[0].id" ).value(PLATFORM_ADMIN_EMAIL ))
205+ .andDo(MockMvcResultHandlers .print ())
206+ }
207+
208+ @Test
209+ @WithMockOauth2User
210+ fun create_dataset_with_no_files_parameter_empty_parts () {
211+ val datasetCreateRequest =
212+ MockMultipartFile (
213+ " datasetCreateRequest" ,
214+ null ,
215+ MediaType .APPLICATION_JSON_VALUE ,
216+ JSONObject (
217+ DatasetCreateRequest (
218+ name = DATASET_NAME ,
219+ description = DATASET_DESCRIPTION ,
220+ tags = mutableListOf (" tag1" , " tag2" ),
221+ parts = mutableListOf (),
222+ runnerId = " r-12345678910" ))
223+ .toString()
224+ .byteInputStream())
225+
226+ mvc.perform(
227+ multipart(" /organizations/$organizationId /workspaces/$workspaceId /datasets" )
228+ .file(datasetCreateRequest)
229+ .accept(MediaType .APPLICATION_JSON )
230+ .with (csrf()))
231+ .andExpect(status().is2xxSuccessful)
232+ .andExpect(jsonPath(" $.name" ).value(DATASET_NAME ))
233+ .andExpect(jsonPath(" $.description" ).value(DATASET_DESCRIPTION ))
234+ .andExpect(jsonPath(" $.organizationId" ).value(organizationId))
235+ .andExpect(jsonPath(" $.workspaceId" ).value(workspaceId))
236+ .andExpect(jsonPath(" $.parts" , empty<DatasetPart >()))
237+ .andExpect(jsonPath(" $.createInfo.userId" ).value(PLATFORM_ADMIN_EMAIL ))
238+ .andExpect(jsonPath(" $.createInfo.runnerId" ).value(" r-12345678910" ))
239+ .andExpect(jsonPath(" $.createInfo.timestamp" ).isNumber)
240+ .andExpect(jsonPath(" $.createInfo.timestamp" ).value(greaterThan(0 .toLong())))
241+ .andExpect(jsonPath(" $.updateInfo.userId" ).value(PLATFORM_ADMIN_EMAIL ))
242+ .andExpect(jsonPath(" $.updateInfo.timestamp" ).isNumber)
243+ .andExpect(jsonPath(" $.updateInfo.timestamp" ).value(greaterThan(0 .toLong())))
244+ .andExpect(jsonPath(" $.tags" ).value(mutableListOf (" tag1" , " tag2" )))
245+ .andExpect(jsonPath(" $.security.default" ).value(ROLE_NONE ))
246+ .andExpect(jsonPath(" $.security.accessControlList[0].role" ).value(ROLE_ADMIN ))
247+ .andExpect(jsonPath(" $.security.accessControlList[0].id" ).value(PLATFORM_ADMIN_EMAIL ))
248+ .andDo(MockMvcResultHandlers .print ())
249+ }
250+
163251 @Test
164252 @WithMockOauth2User
165253 fun download_dataset_part () {
@@ -901,6 +989,169 @@ class DatasetControllerTests : ControllerTestBase() {
901989 " organizations/{organization_id}/workspaces/{workspace_id}/datasets/{dataset_id}/PATCH" ))
902990 }
903991
992+ @Test
993+ @WithMockOauth2User
994+ fun update_dataset_with_no_files_parameter () {
995+ val datasetId =
996+ createDatasetAndReturnId(
997+ mvc,
998+ organizationId,
999+ workspaceId,
1000+ constructDatasetCreateRequest(
1001+ security =
1002+ DatasetSecurity (
1003+ default = ROLE_NONE ,
1004+ accessControlList =
1005+ mutableListOf (
1006+ DatasetAccessControl (id = PLATFORM_ADMIN_EMAIL , role = ROLE_ADMIN ),
1007+ DatasetAccessControl (
1008+ id = ORGANIZATION_USER_EMAIL , role = ROLE_EDITOR )))))
1009+
1010+ val newName = " this_a_new_name_for_dataset"
1011+ val newDescription = " this_a_new_description_for_dataset"
1012+ val newTags = mutableListOf (" tag1_updated" , " tag2_updated" )
1013+
1014+ val datasetUpdateRequest =
1015+ DatasetUpdateRequest (
1016+ name = newName,
1017+ description = newDescription,
1018+ tags = newTags,
1019+ security =
1020+ DatasetSecurity (
1021+ default = ROLE_NONE ,
1022+ accessControlList =
1023+ mutableListOf (
1024+ DatasetAccessControl (id = PLATFORM_ADMIN_EMAIL , role = ROLE_ADMIN ),
1025+ DatasetAccessControl (
1026+ id = ORGANIZATION_USER_EMAIL , role = ROLE_VIEWER ))))
1027+
1028+ val datasetUpdateRequestMultipartFile =
1029+ MockMultipartFile (
1030+ " datasetUpdateRequest" ,
1031+ null ,
1032+ MediaType .APPLICATION_JSON_VALUE ,
1033+ JSONObject (datasetUpdateRequest).toString().byteInputStream())
1034+ mvc.perform(
1035+ multipart(" /organizations/$organizationId /workspaces/$workspaceId /datasets/$datasetId " )
1036+ .file(datasetUpdateRequestMultipartFile)
1037+ .accept(MediaType .APPLICATION_JSON )
1038+ .with (csrf())
1039+ // By default, behind multipart, the HTTP verb used is POST
1040+ // We can override the HTTP verb as following
1041+ // https://stackoverflow.com/questions/38571716/how-to-put-multipart-form-data-using-spring-mockmvc
1042+ .with { request ->
1043+ request.method = " PATCH"
1044+ request
1045+ })
1046+ .andExpect(status().is2xxSuccessful)
1047+ .andExpect(jsonPath(" $.name" ).value(newName))
1048+ .andExpect(jsonPath(" $.description" ).value(newDescription))
1049+ .andExpect(jsonPath(" $.organizationId" ).value(organizationId))
1050+ .andExpect(jsonPath(" $.workspaceId" ).value(workspaceId))
1051+ .andExpect(jsonPath(" $.createInfo.userId" ).value(PLATFORM_ADMIN_EMAIL ))
1052+ .andExpect(jsonPath(" $.createInfo.timestamp" ).isNumber)
1053+ .andExpect(jsonPath(" $.createInfo.timestamp" ).value(greaterThan(0 .toLong())))
1054+ .andExpect(jsonPath(" $.updateInfo.userId" ).value(PLATFORM_ADMIN_EMAIL ))
1055+ .andExpect(jsonPath(" $.updateInfo.timestamp" ).isNumber)
1056+ .andExpect(jsonPath(" $.updateInfo.timestamp" ).value(greaterThan(0 .toLong())))
1057+ .andExpect(jsonPath(" $.parts[0].name" ).value(DATASET_PART_NAME ))
1058+ .andExpect(jsonPath(" $.parts[0].description" ).value(DATASET_PART_DESCRIPTION ))
1059+ .andExpect(jsonPath(" $.parts[0].organizationId" ).value(organizationId))
1060+ .andExpect(jsonPath(" $.parts[0].workspaceId" ).value(workspaceId))
1061+ .andExpect(jsonPath(" $.parts[0].sourceName" ).value(TEST_FILE_NAME ))
1062+ .andExpect(jsonPath(" $.parts[0].tags" ).value(mutableListOf (" tag_part1" , " tag_part2" )))
1063+ .andExpect(jsonPath(" $.parts[0].type" ).value(DatasetPartTypeEnum .File .value))
1064+ .andExpect(jsonPath(" $.parts[0].createInfo.userId" ).value(PLATFORM_ADMIN_EMAIL ))
1065+ .andExpect(jsonPath(" $.parts[0].createInfo.timestamp" ).isNumber)
1066+ .andExpect(jsonPath(" $.parts[0].createInfo.timestamp" ).value(greaterThan(0 .toLong())))
1067+ .andExpect(jsonPath(" $.parts[0].updateInfo.userId" ).value(PLATFORM_ADMIN_EMAIL ))
1068+ .andExpect(jsonPath(" $.parts[0].updateInfo.timestamp" ).isNumber)
1069+ .andExpect(jsonPath(" $.parts[0].updateInfo.timestamp" ).value(greaterThan(0 .toLong())))
1070+ .andExpect(jsonPath(" $.tags" ).value(newTags))
1071+ .andExpect(jsonPath(" $.security.default" ).value(ROLE_NONE ))
1072+ .andExpect(jsonPath(" $.security.accessControlList[0].role" ).value(ROLE_ADMIN ))
1073+ .andExpect(jsonPath(" $.security.accessControlList[0].id" ).value(PLATFORM_ADMIN_EMAIL ))
1074+ .andExpect(jsonPath(" $.security.accessControlList[1].role" ).value(ROLE_VIEWER ))
1075+ .andExpect(jsonPath(" $.security.accessControlList[1].id" ).value(ORGANIZATION_USER_EMAIL ))
1076+ .andDo(MockMvcResultHandlers .print ())
1077+ }
1078+
1079+ @Test
1080+ @WithMockOauth2User
1081+ fun update_dataset_with_no_files_parameter_empty_parts () {
1082+ val datasetId =
1083+ createDatasetAndReturnId(
1084+ mvc,
1085+ organizationId,
1086+ workspaceId,
1087+ constructDatasetCreateRequest(
1088+ security =
1089+ DatasetSecurity (
1090+ default = ROLE_NONE ,
1091+ accessControlList =
1092+ mutableListOf (
1093+ DatasetAccessControl (id = PLATFORM_ADMIN_EMAIL , role = ROLE_ADMIN ),
1094+ DatasetAccessControl (
1095+ id = ORGANIZATION_USER_EMAIL , role = ROLE_EDITOR )))))
1096+
1097+ val newName = " this_a_new_name_for_dataset"
1098+ val newDescription = " this_a_new_description_for_dataset"
1099+ val newTags = mutableListOf (" tag1_updated" , " tag2_updated" )
1100+
1101+ val datasetUpdateRequest =
1102+ DatasetUpdateRequest (
1103+ name = newName,
1104+ description = newDescription,
1105+ tags = newTags,
1106+ parts = mutableListOf (),
1107+ security =
1108+ DatasetSecurity (
1109+ default = ROLE_NONE ,
1110+ accessControlList =
1111+ mutableListOf (
1112+ DatasetAccessControl (id = PLATFORM_ADMIN_EMAIL , role = ROLE_ADMIN ),
1113+ DatasetAccessControl (
1114+ id = ORGANIZATION_USER_EMAIL , role = ROLE_VIEWER ))))
1115+
1116+ val datasetUpdateRequestMultipartFile =
1117+ MockMultipartFile (
1118+ " datasetUpdateRequest" ,
1119+ null ,
1120+ MediaType .APPLICATION_JSON_VALUE ,
1121+ JSONObject (datasetUpdateRequest).toString().byteInputStream())
1122+ mvc.perform(
1123+ multipart(" /organizations/$organizationId /workspaces/$workspaceId /datasets/$datasetId " )
1124+ .file(datasetUpdateRequestMultipartFile)
1125+ .accept(MediaType .APPLICATION_JSON )
1126+ .with (csrf())
1127+ // By default, behind multipart, the HTTP verb used is POST
1128+ // We can override the HTTP verb as following
1129+ // https://stackoverflow.com/questions/38571716/how-to-put-multipart-form-data-using-spring-mockmvc
1130+ .with { request ->
1131+ request.method = " PATCH"
1132+ request
1133+ })
1134+ .andExpect(status().is2xxSuccessful)
1135+ .andExpect(jsonPath(" $.name" ).value(newName))
1136+ .andExpect(jsonPath(" $.description" ).value(newDescription))
1137+ .andExpect(jsonPath(" $.organizationId" ).value(organizationId))
1138+ .andExpect(jsonPath(" $.workspaceId" ).value(workspaceId))
1139+ .andExpect(jsonPath(" $.parts" , empty<DatasetPart >()))
1140+ .andExpect(jsonPath(" $.createInfo.userId" ).value(PLATFORM_ADMIN_EMAIL ))
1141+ .andExpect(jsonPath(" $.createInfo.timestamp" ).isNumber)
1142+ .andExpect(jsonPath(" $.createInfo.timestamp" ).value(greaterThan(0 .toLong())))
1143+ .andExpect(jsonPath(" $.updateInfo.userId" ).value(PLATFORM_ADMIN_EMAIL ))
1144+ .andExpect(jsonPath(" $.updateInfo.timestamp" ).isNumber)
1145+ .andExpect(jsonPath(" $.updateInfo.timestamp" ).value(greaterThan(0 .toLong())))
1146+ .andExpect(jsonPath(" $.tags" ).value(newTags))
1147+ .andExpect(jsonPath(" $.security.default" ).value(ROLE_NONE ))
1148+ .andExpect(jsonPath(" $.security.accessControlList[0].role" ).value(ROLE_ADMIN ))
1149+ .andExpect(jsonPath(" $.security.accessControlList[0].id" ).value(PLATFORM_ADMIN_EMAIL ))
1150+ .andExpect(jsonPath(" $.security.accessControlList[1].role" ).value(ROLE_VIEWER ))
1151+ .andExpect(jsonPath(" $.security.accessControlList[1].id" ).value(ORGANIZATION_USER_EMAIL ))
1152+ .andDo(MockMvcResultHandlers .print ())
1153+ }
1154+
9041155 @Test
9051156 @WithMockOauth2User
9061157 fun update_dataset_access_control () {
0 commit comments