View Javadoc
1   package de.dlr.shepard.integrationtests;
2   
3   import static io.restassured.RestAssured.given;
4   import static org.assertj.core.api.Assertions.assertThat;
5   import static org.junit.jupiter.api.Assertions.assertEquals;
6   import static org.junit.jupiter.api.Assertions.assertNotEquals;
7   
8   import de.dlr.shepard.ErrorResponse;
9   import de.dlr.shepard.common.configuration.feature.toggles.VersioningFeatureToggle;
10  import de.dlr.shepard.common.util.Constants;
11  import de.dlr.shepard.context.collection.endpoints.DataObjectAttributes;
12  import de.dlr.shepard.context.collection.io.CollectionIO;
13  import de.dlr.shepard.context.collection.io.DataObjectIO;
14  import de.dlr.shepard.context.collection.services.DataObjectIOBuilder;
15  import de.dlr.shepard.context.version.io.VersionIO;
16  import io.quarkus.test.junit.QuarkusIntegrationTest;
17  import java.util.HashSet;
18  import java.util.Map;
19  import java.util.UUID;
20  import org.junit.jupiter.api.BeforeAll;
21  import org.junit.jupiter.api.MethodOrderer;
22  import org.junit.jupiter.api.Order;
23  import org.junit.jupiter.api.Test;
24  import org.junit.jupiter.api.TestMethodOrder;
25  
26  @QuarkusIntegrationTest
27  @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
28  public class DataObjectIT extends BaseTestCaseIT {
29  
30    private static CollectionIO collection;
31    private static CollectionIO collectionForOrderByTest;
32    private static CollectionIO versionizedCollection;
33  
34    private static String dataObjectsURL;
35    private static String orderByDataObjectsURL;
36    private static String versioningURL;
37    private static String versionizedCollectionURL;
38    private static DataObjectIO dataObject;
39    private static DataObjectIO child;
40    private static DataObjectIO successor;
41    private static DataObjectIO successorAndChild;
42    private static DataObjectIO aDataObject;
43    private static DataObjectIO bDataObject;
44    private static DataObjectIO cDataObject;
45    private static DataObjectIO dDataObject;
46    private static DataObjectIO eDataObject;
47    private static DataObjectIO fDataObject;
48    private static DataObjectIO firstVersionizedDataobject;
49    private static DataObjectIO secondVersionizedDataObject;
50    private static DataObjectIO thirdVersionizedDataObject;
51    private static UUID HEADVersionUID;
52    private static UUID firstVersionUID;
53  
54    @BeforeAll
55    public static void setUp() {
56      collection = createCollection("DataObjectTestCollection");
57      collectionForOrderByTest = createCollection("OrderByTestCollection");
58      versionizedCollection = createCollection("collection for versioning");
59  
60      dataObjectsURL = "/%s/%d/%s".formatted(Constants.COLLECTIONS, collection.getId(), Constants.DATA_OBJECTS);
61      orderByDataObjectsURL = "/%s/%d/%s".formatted(
62          Constants.COLLECTIONS,
63          collectionForOrderByTest.getId(),
64          Constants.DATA_OBJECTS
65        );
66      versioningURL = "/%s/%d/%s".formatted(Constants.COLLECTIONS, versionizedCollection.getId(), Constants.DATA_OBJECTS);
67      versionizedCollectionURL = "/%s/%d".formatted(Constants.COLLECTIONS, versionizedCollection.getId());
68  
69      var aInput = new DataObjectIO();
70      aInput.setName("a");
71      aDataObject = given()
72        .spec(requestSpecOfDefaultUser)
73        .body(aInput)
74        .when()
75        .post(orderByDataObjectsURL)
76        .then()
77        .statusCode(201)
78        .extract()
79        .as(DataObjectIO.class);
80      var bInput = new DataObjectIO();
81      bInput.setName("b");
82      bDataObject = given()
83        .spec(requestSpecOfDefaultUser)
84        .body(bInput)
85        .when()
86        .post(orderByDataObjectsURL)
87        .then()
88        .statusCode(201)
89        .extract()
90        .as(DataObjectIO.class);
91      var cInput = new DataObjectIO();
92      cInput.setName("c");
93      cDataObject = given()
94        .spec(requestSpecOfDefaultUser)
95        .body(cInput)
96        .when()
97        .post(orderByDataObjectsURL)
98        .then()
99        .statusCode(201)
100       .extract()
101       .as(DataObjectIO.class);
102     var dInput = new DataObjectIO();
103     dInput.setName("d");
104     dDataObject = given()
105       .spec(requestSpecOfDefaultUser)
106       .body(dInput)
107       .when()
108       .post(orderByDataObjectsURL)
109       .then()
110       .statusCode(201)
111       .extract()
112       .as(DataObjectIO.class);
113     var eInput = new DataObjectIO();
114     eInput.setName("e");
115     eDataObject = given()
116       .spec(requestSpecOfDefaultUser)
117       .body(eInput)
118       .when()
119       .post(orderByDataObjectsURL)
120       .then()
121       .statusCode(201)
122       .extract()
123       .as(DataObjectIO.class);
124     var fInput = new DataObjectIO();
125     fInput.setName("f");
126     fDataObject = given()
127       .spec(requestSpecOfDefaultUser)
128       .body(fInput)
129       .when()
130       .post(orderByDataObjectsURL)
131       .then()
132       .statusCode(201)
133       .extract()
134       .as(DataObjectIO.class);
135     DataObjectIO firstVersionizedDataObjectInput = new DataObjectIO();
136     firstVersionizedDataObjectInput.setName("first versionized DataObject");
137     firstVersionizedDataobject = given()
138       .spec(requestSpecOfDefaultUser)
139       .body(firstVersionizedDataObjectInput)
140       .when()
141       .post(versioningURL)
142       .then()
143       .statusCode(201)
144       .extract()
145       .as(DataObjectIO.class);
146     DataObjectIO secondVersionizedDataObjectInput = new DataObjectIO();
147     secondVersionizedDataObjectInput.setName("second versionized DataObject");
148     secondVersionizedDataObjectInput.setParentId(firstVersionizedDataobject.getId());
149     secondVersionizedDataObject = given()
150       .spec(requestSpecOfDefaultUser)
151       .body(secondVersionizedDataObjectInput)
152       .when()
153       .post(versioningURL)
154       .then()
155       .statusCode(201)
156       .extract()
157       .as(DataObjectIO.class);
158     DataObjectIO thirdVersionizedDataObjectInput = new DataObjectIO();
159     thirdVersionizedDataObjectInput.setName("third versionized DataoObject");
160     long[] thirdVersionizedDataObjectPredecessorIds = { secondVersionizedDataObject.getId() };
161     thirdVersionizedDataObjectInput.setPredecessorIds(thirdVersionizedDataObjectPredecessorIds);
162     thirdVersionizedDataObject = given()
163       .spec(requestSpecOfDefaultUser)
164       .body(thirdVersionizedDataObjectInput)
165       .when()
166       .post(versioningURL)
167       .then()
168       .statusCode(201)
169       .extract()
170       .as(DataObjectIO.class);
171   }
172 
173   @Test
174   @Order(1)
175   public void postDataObjectTest_Successful() {
176     var attributes = Map.of(
177       "a",
178       "1",
179       "b",
180       "2",
181       "key.abc",
182       "value",
183       "key|abc",
184       "value",
185       "key..abc",
186       "value",
187       "key/\\abc",
188       "value",
189       "key\"abc",
190       "value"
191     );
192     var payload = new DataObjectIO();
193     payload.setName("DataObjectDummy");
194     payload.setDescription("My Description");
195     payload.setAttributes(attributes);
196 
197     DataObjectIO actual = given()
198       .spec(requestSpecOfDefaultUser)
199       .body(payload)
200       .when()
201       .post(dataObjectsURL)
202       .then()
203       .statusCode(201)
204       .extract()
205       .as(DataObjectIO.class);
206     dataObject = actual;
207 
208     assertThat(actual.getId()).isNotNull();
209     assertThat(actual.getAttributes()).isEqualTo(attributes);
210     assertThat(actual.getDescription()).isEqualTo("My Description");
211     assertThat(actual.getCreatedAt()).isNotNull();
212     assertThat(actual.getCreatedBy()).isEqualTo(nameOfDefaultUser);
213     assertThat(actual.getIncomingIds()).isEmpty();
214     assertThat(actual.getReferenceIds()).isEmpty();
215     assertThat(actual.getChildrenIds()).isEmpty();
216     assertThat(actual.getPredecessorIds()).isEmpty();
217     assertThat(actual.getSuccessorIds()).isEmpty();
218     assertThat(actual.getParentId()).isNull();
219     assertThat(actual.getName()).isEqualTo("DataObjectDummy");
220     assertThat(actual.getCollectionId()).isEqualTo(collection.getId());
221     assertThat(actual.getUpdatedAt()).isNull();
222     assertThat(actual.getUpdatedBy()).isNull();
223   }
224 
225   @Test
226   @Order(2)
227   public void postDataObjectTest_ValidationError() {
228     // use attribute key that contains parsing delimiter ('||') and therefore is invalid
229     var attributes = Map.of("key||abc", "value");
230     var payload = new DataObjectIO();
231     payload.setName("DataObjectDummy");
232     payload.setDescription("My Description");
233     payload.setAttributes(attributes);
234 
235     given().spec(requestSpecOfDefaultUser).body(payload).when().post(dataObjectsURL).then().statusCode(400);
236   }
237 
238   @Test
239   @Order(3)
240   public void postDataObjectTest_ParentId() {
241     var payload = new DataObjectIO();
242     payload.setName("ChildDummy");
243     payload.setParentId(dataObject.getId());
244 
245     DataObjectIO actual = given()
246       .spec(requestSpecOfDefaultUser)
247       .body(payload)
248       .when()
249       .post(dataObjectsURL)
250       .then()
251       .statusCode(201)
252       .extract()
253       .as(DataObjectIO.class);
254     child = actual;
255 
256     assertThat(actual.getId()).isNotNull();
257     assertThat(actual.getChildrenIds()).isEmpty();
258     assertThat(actual.getPredecessorIds()).isEmpty();
259     assertThat(actual.getSuccessorIds()).isEmpty();
260     assertThat(actual.getParentId()).isEqualTo(dataObject.getId());
261     assertThat(actual.getCollectionId()).isEqualTo(collection.getId());
262 
263     DataObjectIO parent = given()
264       .spec(requestSpecOfDefaultUser)
265       .when()
266       .get(dataObjectsURL + "/" + dataObject.getId())
267       .then()
268       .statusCode(200)
269       .extract()
270       .as(DataObjectIO.class);
271     assertThat(parent).usingRecursiveComparison().ignoringFields("childrenIds").isEqualTo(dataObject);
272     assertThat(parent.getChildrenIds()).containsExactlyInAnyOrder(child.getId());
273     dataObject = parent;
274   }
275 
276   @Test
277   @Order(4)
278   public void postDataObjectTest_PredecessorId() {
279     var payload = new DataObjectIO();
280     payload.setName("SuccessorDummy");
281     payload.setPredecessorIds(new long[] { dataObject.getId() });
282 
283     DataObjectIO actual = given()
284       .spec(requestSpecOfDefaultUser)
285       .body(payload)
286       .when()
287       .post(dataObjectsURL)
288       .then()
289       .statusCode(201)
290       .extract()
291       .as(DataObjectIO.class);
292     successor = actual;
293 
294     assertThat(actual.getId()).isNotNull();
295     assertThat(actual.getChildrenIds()).isEmpty();
296     assertThat(actual.getPredecessorIds()).containsExactlyInAnyOrder(dataObject.getId());
297     assertThat(actual.getSuccessorIds()).isEmpty();
298     assertThat(actual.getParentId()).isNull();
299     assertThat(actual.getCollectionId()).isEqualTo(collection.getId());
300 
301     DataObjectIO predecessor = given()
302       .spec(requestSpecOfDefaultUser)
303       .when()
304       .get(dataObjectsURL + "/" + dataObject.getId())
305       .then()
306       .statusCode(200)
307       .extract()
308       .as(DataObjectIO.class);
309     assertThat(predecessor).usingRecursiveComparison().ignoringFields("successorIds").isEqualTo(dataObject);
310     assertThat(predecessor.getSuccessorIds()).containsExactlyInAnyOrder(successor.getId());
311     dataObject = predecessor;
312   }
313 
314   @Test
315   @Order(5)
316   public void postDataObjectTest_PredecessorIdAndParentId() {
317     var payload = new DataObjectIO();
318     payload.setName("ChildAndSuccessorDummy");
319     payload.setParentId(dataObject.getId());
320     payload.setPredecessorIds(new long[] { child.getId() });
321 
322     DataObjectIO actual = given()
323       .spec(requestSpecOfDefaultUser)
324       .body(payload)
325       .when()
326       .post(dataObjectsURL)
327       .then()
328       .statusCode(201)
329       .extract()
330       .as(DataObjectIO.class);
331     successorAndChild = actual;
332 
333     assertThat(actual.getId()).isNotNull();
334     assertThat(actual.getChildrenIds()).isEmpty();
335     assertThat(actual.getPredecessorIds()).containsExactlyInAnyOrder(child.getId());
336     assertThat(actual.getSuccessorIds()).isEmpty();
337     assertThat(actual.getParentId()).isEqualTo(dataObject.getId());
338     assertThat(actual.getCollectionId()).isEqualTo(collection.getId());
339 
340     DataObjectIO parent = given()
341       .spec(requestSpecOfDefaultUser)
342       .when()
343       .get(dataObjectsURL + "/" + dataObject.getId())
344       .then()
345       .statusCode(200)
346       .extract()
347       .as(DataObjectIO.class);
348     assertThat(parent).usingRecursiveComparison().ignoringFields("childrenIds").isEqualTo(dataObject);
349     assertThat(parent.getChildrenIds()).containsExactlyInAnyOrder(child.getId(), successorAndChild.getId());
350     dataObject = parent;
351 
352     DataObjectIO predecessor = given()
353       .spec(requestSpecOfDefaultUser)
354       .when()
355       .get(dataObjectsURL + "/" + child.getId())
356       .then()
357       .statusCode(200)
358       .extract()
359       .as(DataObjectIO.class);
360     assertThat(predecessor).usingRecursiveComparison().ignoringFields("successorIds").isEqualTo(child);
361     assertThat(predecessor.getSuccessorIds()).containsExactlyInAnyOrder(successorAndChild.getId());
362     child = predecessor;
363   }
364 
365   @Test
366   @Order(6)
367   public void getDataObjectTest_Successful() {
368     DataObjectIO actual = given()
369       .spec(requestSpecOfDefaultUser)
370       .when()
371       .get(dataObjectsURL + "/" + dataObject.getId())
372       .then()
373       .statusCode(200)
374       .extract()
375       .as(DataObjectIO.class);
376 
377     assertThat(actual).isEqualTo(dataObject);
378   }
379 
380   @Test
381   @Order(7)
382   public void getDataObjectTest_ByName() {
383     DataObjectIO[] response = given()
384       .spec(requestSpecOfDefaultUser)
385       .queryParam("name", dataObject.getName())
386       .when()
387       .get(dataObjectsURL)
388       .then()
389       .statusCode(200)
390       .extract()
391       .as(DataObjectIO[].class);
392 
393     assertThat(response)
394       .usingRecursiveFieldByFieldElementComparatorIgnoringFields("childrenIds", "successorIds", "predecessorIds")
395       .containsExactlyInAnyOrder(dataObject);
396   }
397 
398   @Test
399   @Order(8)
400   public void getDataObjectsTest_Successful() {
401     DataObjectIO[] response = given()
402       .spec(requestSpecOfDefaultUser)
403       .when()
404       .get(dataObjectsURL)
405       .then()
406       .statusCode(200)
407       .extract()
408       .as(DataObjectIO[].class);
409 
410     assertThat(response)
411       .usingRecursiveFieldByFieldElementComparatorIgnoringFields("childrenIds", "successorIds", "predecessorIds")
412       .containsExactlyInAnyOrder(dataObject, child, successor, successorAndChild);
413   }
414 
415   @Test
416   @Order(9)
417   public void getDataObjectsTest_ByParent() {
418     DataObjectIO[] response = given()
419       .spec(requestSpecOfDefaultUser)
420       .queryParam("parentId", dataObject.getId())
421       .when()
422       .get(dataObjectsURL)
423       .then()
424       .statusCode(200)
425       .extract()
426       .as(DataObjectIO[].class);
427 
428     assertThat(response)
429       .usingRecursiveFieldByFieldElementComparatorIgnoringFields("childrenIds", "successorIds", "predecessorIds")
430       .containsExactlyInAnyOrder(child, successorAndChild);
431   }
432 
433   @Test
434   @Order(10)
435   public void getDataObjectsTest_WithoutParent() {
436     DataObjectIO[] response = given()
437       .spec(requestSpecOfDefaultUser)
438       .queryParam("parentId", -1)
439       .when()
440       .get(dataObjectsURL)
441       .then()
442       .statusCode(200)
443       .extract()
444       .as(DataObjectIO[].class);
445 
446     assertThat(response)
447       .usingRecursiveFieldByFieldElementComparatorIgnoringFields("childrenIds", "successorIds", "predecessorIds")
448       .containsExactlyInAnyOrder(dataObject, successor);
449   }
450 
451   @Test
452   @Order(11)
453   public void getDataObjectsTest_ByPredecessor() {
454     DataObjectIO[] response = given()
455       .spec(requestSpecOfDefaultUser)
456       .queryParam("predecessorId", dataObject.getId())
457       .when()
458       .get(dataObjectsURL)
459       .then()
460       .statusCode(200)
461       .extract()
462       .as(DataObjectIO[].class);
463 
464     assertThat(response)
465       .usingRecursiveFieldByFieldElementComparatorIgnoringFields("childrenIds", "successorIds", "predecessorIds")
466       .containsExactlyInAnyOrder(successor);
467   }
468 
469   @Test
470   @Order(12)
471   public void getDataObjectsTest_WithoutPredecessor() {
472     DataObjectIO[] response = given()
473       .spec(requestSpecOfDefaultUser)
474       .queryParam("predecessorId", -1)
475       .when()
476       .get(dataObjectsURL)
477       .then()
478       .statusCode(200)
479       .extract()
480       .as(DataObjectIO[].class);
481 
482     assertThat(response)
483       .usingRecursiveFieldByFieldElementComparatorIgnoringFields("childrenIds", "successorIds", "predecessorIds")
484       .containsExactlyInAnyOrder(dataObject, child);
485   }
486 
487   @Test
488   @Order(13)
489   public void getDataObjectsTest_BySuccessor() {
490     DataObjectIO[] response = given()
491       .spec(requestSpecOfDefaultUser)
492       .queryParam("successorId", successor.getId())
493       .when()
494       .get(dataObjectsURL)
495       .then()
496       .statusCode(200)
497       .extract()
498       .as(DataObjectIO[].class);
499 
500     assertThat(response)
501       .usingRecursiveFieldByFieldElementComparatorIgnoringFields("childrenIds", "successorIds", "predecessorIds")
502       .containsExactlyInAnyOrder(dataObject);
503   }
504 
505   @Test
506   @Order(14)
507   public void getDataObjectsTest_WithoutSuccessor() {
508     DataObjectIO[] response = given()
509       .spec(requestSpecOfDefaultUser)
510       .queryParam("successorId", -1)
511       .when()
512       .get(dataObjectsURL)
513       .then()
514       .statusCode(200)
515       .extract()
516       .as(DataObjectIO[].class);
517 
518     assertThat(response)
519       .usingRecursiveFieldByFieldElementComparatorIgnoringFields("childrenIds", "successorIds", "predecessorIds")
520       .containsExactlyInAnyOrder(successor, successorAndChild);
521   }
522 
523   @Test
524   @Order(14)
525   public void getDataObjectsTest_negativeId_BadRequest() {
526     given().spec(requestSpecOfDefaultUser).when().get(dataObjectsURL + "/-1").then().statusCode(400);
527   }
528 
529   @Test
530   @Order(14)
531   public void getDataObjectsTest_wrongVersionUUIDFormat_BadRequest() {
532     // correct UUID: 00000000-0000-0000-0000-000000000000
533     // false UUID:   000000-0000-0000-0000-000000000000
534     given()
535       .spec(requestSpecOfDefaultUser)
536       .queryParam("versionUId", "000000-0000-0000-0000-000000000000")
537       .when()
538       .get(dataObjectsURL)
539       .then()
540       .statusCode(400);
541   }
542 
543   @Test
544   @Order(15)
545   public void putDataObjectTest_Successful() {
546     dataObject.setName("DataObjectSuccessorChanged");
547 
548     DataObjectIO actual = given()
549       .spec(requestSpecOfDefaultUser)
550       .body(dataObject)
551       .when()
552       .put(dataObjectsURL + "/" + dataObject.getId())
553       .then()
554       .statusCode(200)
555       .extract()
556       .as(DataObjectIO.class);
557 
558     assertThat(actual.getUpdatedAt()).isNotNull();
559     assertThat(actual.getUpdatedBy()).isEqualTo(nameOfDefaultUser);
560     assertThat(actual)
561       .usingRecursiveComparison()
562       .ignoringFields("updatedBy", "updatedAt", "childrenIds")
563       .isEqualTo(dataObject);
564     HashSet<Long> childrenActual = new HashSet<Long>();
565     for (int i = 0; i < actual.getChildrenIds().length; i++) childrenActual.add(actual.getChildrenIds()[i]);
566     HashSet<Long> childrenDataObject = new HashSet<Long>();
567     for (int i = 0; i < dataObject.getChildrenIds().length; i++) childrenDataObject.add(dataObject.getChildrenIds()[i]);
568     assertEquals(childrenActual, childrenDataObject);
569     dataObject = actual;
570   }
571 
572   @Test
573   @Order(16)
574   public void putDataObjectTest_newParent() {
575     successorAndChild.setName("DataObjectChildChanged");
576     successorAndChild.setParentId(successor.getId());
577 
578     DataObjectIO actual = given()
579       .spec(requestSpecOfDefaultUser)
580       .body(successorAndChild)
581       .when()
582       .put(dataObjectsURL + "/" + successorAndChild.getId())
583       .then()
584       .statusCode(200)
585       .extract()
586       .as(DataObjectIO.class);
587 
588     assertThat(actual).usingRecursiveComparison().ignoringFields("updatedBy", "updatedAt").isEqualTo(successorAndChild);
589     successorAndChild = actual;
590 
591     DataObjectIO oldParent = given()
592       .spec(requestSpecOfDefaultUser)
593       .when()
594       .get(dataObjectsURL + "/" + dataObject.getId())
595       .then()
596       .statusCode(200)
597       .extract()
598       .as(DataObjectIO.class);
599     assertThat(oldParent).usingRecursiveComparison().ignoringFields("childrenIds").isEqualTo(dataObject);
600     assertThat(oldParent.getChildrenIds()).doesNotContain(successorAndChild.getId());
601     dataObject = oldParent;
602 
603     successor.setChildrenIds(new long[] { actual.getId() });
604     DataObjectIO newParent = given()
605       .spec(requestSpecOfDefaultUser)
606       .when()
607       .get(dataObjectsURL + "/" + successor.getId())
608       .then()
609       .statusCode(200)
610       .extract()
611       .as(DataObjectIO.class);
612     assertThat(newParent).isEqualTo(successor);
613   }
614 
615   @Test
616   @Order(17)
617   public void putDataObjectTest_newPredecessor() {
618     child.setName("DataObjectSuccessorChanged");
619     child.setPredecessorIds(new long[] { dataObject.getId() });
620     DataObjectIO actual = given()
621       .spec(requestSpecOfDefaultUser)
622       .body(child)
623       .when()
624       .put(dataObjectsURL + "/" + child.getId())
625       .then()
626       .statusCode(200)
627       .extract()
628       .as(DataObjectIO.class);
629 
630     assertThat(actual).usingRecursiveComparison().ignoringFields("updatedBy", "updatedAt").isEqualTo(child);
631     child = actual;
632 
633     DataObjectIO newPredecessor = given()
634       .spec(requestSpecOfDefaultUser)
635       .when()
636       .get(dataObjectsURL + "/" + dataObject.getId())
637       .then()
638       .statusCode(200)
639       .extract()
640       .as(DataObjectIO.class);
641     assertThat(newPredecessor)
642       .usingRecursiveComparison()
643       .ignoringFields("successorIds", "childrenIds")
644       .isEqualTo(dataObject);
645     assertThat(newPredecessor.getChildrenIds()).containsExactlyInAnyOrder(dataObject.getChildrenIds());
646     assertThat(newPredecessor.getSuccessorIds()).containsExactlyInAnyOrder(successor.getId(), child.getId());
647     dataObject = newPredecessor;
648   }
649 
650   @Test
651   @Order(18)
652   public void deleteDataObjectTest_Successful() {
653     given()
654       .spec(requestSpecOfDefaultUser)
655       .when()
656       .delete(dataObjectsURL + "/" + dataObject.getId())
657       .then()
658       .statusCode(204);
659     given()
660       .spec(requestSpecOfDefaultUser)
661       .when()
662       .delete(dataObjectsURL + "/" + dataObject.getId())
663       .then()
664       .statusCode(404);
665     given().spec(requestSpecOfDefaultUser).when().get(dataObjectsURL + "/" + dataObject.getId()).then().statusCode(404);
666   }
667 
668   @Test
669   @Order(19)
670   public void getOrderByName() {
671     DataObjectIO[] response = given()
672       .spec(requestSpecOfDefaultUser)
673       .queryParam("orderBy", DataObjectAttributes.name)
674       .when()
675       .get(orderByDataObjectsURL)
676       .then()
677       .statusCode(200)
678       .extract()
679       .as(DataObjectIO[].class);
680     assertThat(response).containsExactly(aDataObject, bDataObject, cDataObject, dDataObject, eDataObject, fDataObject);
681   }
682 
683   @Test
684   @Order(20)
685   public void getOrderByNameDesc() {
686     DataObjectIO[] response = given()
687       .spec(requestSpecOfDefaultUser)
688       .queryParam("orderBy", DataObjectAttributes.name)
689       .queryParam("orderDesc", true)
690       .when()
691       .get(orderByDataObjectsURL)
692       .then()
693       .statusCode(200)
694       .extract()
695       .as(DataObjectIO[].class);
696     assertThat(response).containsExactly(fDataObject, eDataObject, dDataObject, cDataObject, bDataObject, aDataObject);
697   }
698 
699   @Test
700   @Order(21)
701   public void getOrderByCreatedAt() {
702     DataObjectIO[] response = given()
703       .spec(requestSpecOfDefaultUser)
704       .queryParam("orderBy", DataObjectAttributes.createdAt)
705       .queryParam("orderDesc", false)
706       .when()
707       .get(orderByDataObjectsURL)
708       .then()
709       .statusCode(200)
710       .extract()
711       .as(DataObjectIO[].class);
712     assertThat(response).containsExactly(aDataObject, bDataObject, cDataObject, dDataObject, eDataObject, fDataObject);
713   }
714 
715   @Test
716   @Order(22)
717   public void getOrderByCreatedFirstPage() {
718     DataObjectIO[] response = given()
719       .spec(requestSpecOfDefaultUser)
720       .queryParam("orderBy", DataObjectAttributes.createdAt)
721       .queryParam("orderDesc", false)
722       .queryParam("page", 0)
723       .queryParam("size", 3)
724       .when()
725       .get(orderByDataObjectsURL)
726       .then()
727       .statusCode(200)
728       .extract()
729       .as(DataObjectIO[].class);
730     assertThat(response).containsExactly(aDataObject, bDataObject, cDataObject);
731   }
732 
733   @Test
734   @Order(23)
735   public void getOrderByCreatedSecondPage() {
736     DataObjectIO[] response = given()
737       .spec(requestSpecOfDefaultUser)
738       .queryParam("orderBy", DataObjectAttributes.createdAt)
739       .queryParam("orderDesc", false)
740       .queryParam("page", 1)
741       .queryParam("size", 3)
742       .when()
743       .get(orderByDataObjectsURL)
744       .then()
745       .statusCode(200)
746       .extract()
747       .as(DataObjectIO[].class);
748     assertThat(response).containsExactly(dDataObject, eDataObject, fDataObject);
749   }
750 
751   @Test
752   @Order(24)
753   public void getOrderByCreatedDescSecondPage() {
754     DataObjectIO[] response = given()
755       .spec(requestSpecOfDefaultUser)
756       .queryParam("orderBy", DataObjectAttributes.createdAt)
757       .queryParam("orderDesc", true)
758       .queryParam("page", 1)
759       .queryParam("size", 3)
760       .when()
761       .get(orderByDataObjectsURL)
762       .then()
763       .statusCode(200)
764       .extract()
765       .as(DataObjectIO[].class);
766     assertThat(response).containsExactly(cDataObject, bDataObject, aDataObject);
767   }
768 
769   @Test
770   @Order(25)
771   public void getOrderByCreatedDescFirstPage() {
772     DataObjectIO[] response = given()
773       .spec(requestSpecOfDefaultUser)
774       .queryParam("orderBy", DataObjectAttributes.createdAt)
775       .queryParam("orderDesc", true)
776       .queryParam("page", 0)
777       .queryParam("size", 3)
778       .when()
779       .get(orderByDataObjectsURL)
780       .then()
781       .statusCode(200)
782       .extract()
783       .as(DataObjectIO[].class);
784     assertThat(response).containsExactly(fDataObject, eDataObject, dDataObject);
785   }
786 
787   @Test
788   @Order(25)
789   public void getHEADVersion() {
790     if (VersioningFeatureToggle.isEnabled()) {
791       VersionIO[] HEADVersion = given()
792         .spec(requestSpecOfDefaultUser)
793         .when()
794         .get(versionizedCollectionURL + "/versions")
795         .then()
796         .statusCode(200)
797         .extract()
798         .as(VersionIO[].class);
799       assertEquals(HEADVersion.length, 1);
800       HEADVersionUID = HEADVersion[0].getUid();
801     }
802   }
803 
804   @Test
805   @Order(26)
806   public void createFirstVersion() {
807     if (VersioningFeatureToggle.isEnabled()) {
808       VersionIO firstVersionInput = new VersionIO();
809       firstVersionInput.setName("first version");
810       firstVersionInput.setDescription("first version");
811       VersionIO firstVersion = given()
812         .spec(requestSpecOfDefaultUser)
813         .body(firstVersionInput)
814         .when()
815         .post(versionizedCollectionURL + "/versions")
816         .then()
817         .statusCode(201)
818         .extract()
819         .as(VersionIO.class);
820       assertEquals(firstVersionInput.getName(), firstVersion.getName());
821       assertEquals(firstVersionInput.getDescription(), firstVersion.getDescription());
822       firstVersionUID = firstVersion.getUid();
823     }
824   }
825 
826   @Test
827   @Order(27)
828   public void putFirstVersionizedDataObject() {
829     if (VersioningFeatureToggle.isEnabled()) {
830       String newName = "first versionized DataObject with new name";
831       firstVersionizedDataobject.setName(newName);
832       DataObjectIO actual = given()
833         .spec(requestSpecOfDefaultUser)
834         .body(firstVersionizedDataobject)
835         .when()
836         .put(versioningURL + "/" + firstVersionizedDataobject.getId())
837         .then()
838         .statusCode(200)
839         .extract()
840         .as(DataObjectIO.class);
841       assertEquals(newName, actual.getName());
842     }
843   }
844 
845   @Test
846   @Order(28)
847   public void differentFirstVersionizedDataObjects() {
848     if (VersioningFeatureToggle.isEnabled()) {
849       DataObjectIO firstDataObjectFirstVersion = given()
850         .spec(requestSpecOfDefaultUser)
851         .queryParam("versionUid", firstVersionUID.toString())
852         .when()
853         .get(versioningURL + "/" + firstVersionizedDataobject.getId())
854         .then()
855         .statusCode(200)
856         .extract()
857         .as(DataObjectIO.class);
858       DataObjectIO firstDataObjectExpliciteHEADVersion = given()
859         .spec(requestSpecOfDefaultUser)
860         .queryParam("versionUid", HEADVersionUID.toString())
861         .when()
862         .get(versioningURL + "/" + firstVersionizedDataobject.getId())
863         .then()
864         .statusCode(200)
865         .extract()
866         .as(DataObjectIO.class);
867       DataObjectIO firstDataObjectImpliciteHEADVersion = given()
868         .spec(requestSpecOfDefaultUser)
869         .when()
870         .get(versioningURL + "/" + firstVersionizedDataobject.getId())
871         .then()
872         .statusCode(200)
873         .extract()
874         .as(DataObjectIO.class);
875       assertEquals(firstDataObjectExpliciteHEADVersion.getName(), firstDataObjectImpliciteHEADVersion.getName());
876       assertNotEquals(firstDataObjectExpliciteHEADVersion.getName(), firstDataObjectFirstVersion.getName());
877     }
878   }
879 
880   @Test
881   @Order(29)
882   public void predecessorsInFirstVersion() {
883     if (VersioningFeatureToggle.isEnabled()) {
884       DataObjectIO thirdDataObjectFirstVersion = given()
885         .spec(requestSpecOfDefaultUser)
886         .queryParam("versionUid", firstVersionUID.toString())
887         .when()
888         .get(versioningURL + "/" + thirdVersionizedDataObject.getId())
889         .then()
890         .statusCode(200)
891         .extract()
892         .as(DataObjectIO.class);
893       assertEquals(1, thirdDataObjectFirstVersion.getPredecessorIds().length);
894       long actualPredecessorId = thirdDataObjectFirstVersion.getPredecessorIds()[0];
895       long expectedPredecessorId = secondVersionizedDataObject.getId();
896       assertEquals(actualPredecessorId, expectedPredecessorId);
897     }
898   }
899 
900   @Test
901   @Order(30)
902   public void parentInFirstVersion() {
903     if (VersioningFeatureToggle.isEnabled()) {
904       DataObjectIO secondDataObjectFirstVersion = given()
905         .spec(requestSpecOfDefaultUser)
906         .queryParam("versionUid", firstVersionUID.toString())
907         .when()
908         .get(versioningURL + "/" + secondVersionizedDataObject.getId())
909         .then()
910         .statusCode(200)
911         .extract()
912         .as(DataObjectIO.class);
913       long actualParentId = secondDataObjectFirstVersion.getParentId();
914       long expectedParentId = firstVersionizedDataobject.getId();
915       assertEquals(actualParentId, expectedParentId);
916     }
917   }
918 
919   @Test
920   @Order(31)
921   public void deleteFirstVersionizedDataObject() {
922     if (VersioningFeatureToggle.isEnabled()) {
923       given()
924         .spec(requestSpecOfDefaultUser)
925         .when()
926         .delete(versioningURL + "/" + firstVersionizedDataobject.getId())
927         .then()
928         .statusCode(204);
929       DataObjectIO[] response = given()
930         .spec(requestSpecOfDefaultUser)
931         .when()
932         .get(versioningURL)
933         .then()
934         .statusCode(200)
935         .extract()
936         .as(DataObjectIO[].class);
937       if (VersioningFeatureToggle.isEnabled()) assertEquals(2, response.length);
938       else assertEquals(5, response.length);
939     }
940   }
941 
942   @Test
943   @Order(32)
944   public void getDataObjectsOfFirstVersion() {
945     if (VersioningFeatureToggle.isEnabled()) {
946       DataObjectIO[] response = given()
947         .spec(requestSpecOfDefaultUser)
948         .queryParam("versionUid", firstVersionUID)
949         .when()
950         .get(versioningURL)
951         .then()
952         .statusCode(200)
953         .extract()
954         .as(DataObjectIO[].class);
955       assertEquals(3, response.length);
956     }
957   }
958 
959   @Test
960   public void getDataObject_wrongId_notFound() {
961     ErrorResponse response = given()
962       .spec(requestSpecOfDefaultUser)
963       .when()
964       .get(dataObjectsURL + "/99999")
965       .then()
966       .statusCode(404)
967       .extract()
968       .as(ErrorResponse.class);
969     assertThat(response.getMessage()).startsWith("ID ERROR - DataObject");
970   }
971 
972   @Test
973   public void getDataObject_doesNotExistNegativeId_badRequest() {
974     var actual = given()
975       .spec(requestSpecOfDefaultUser)
976       .when()
977       .get(dataObjectsURL + "/-1")
978       .then()
979       .statusCode(400)
980       .extract();
981     assertThat(actual.body().asString()).isEqualTo(
982       "{\"title\":\"Constraint Violation\",\"status\":400,\"violations\":[{\"field\":\"getDataObject.dataObjectId\",\"message\":\"must be greater than or equal to 0\"}]}"
983     );
984   }
985 
986   @Test
987   public void getDataObject_privateCollection_forbidden() {
988     // This is a test implementation for the Bug described in #475
989     CollectionIO privateCollection = createCollection("private collection", otherUser);
990     DataObjectIO privateDataObject = createDataObject("private data object", privateCollection.getId(), otherUser);
991 
992     ErrorResponse response = given()
993       .spec(requestSpecOfDefaultUser)
994       .when()
995       .get(
996         "/%s/%d/%s/%d".formatted(
997             Constants.COLLECTIONS,
998             privateCollection.getId(),
999             Constants.DATA_OBJECTS,
1000             privateDataObject.getId()
1001           )
1002       )
1003       .then()
1004       .statusCode(403)
1005       .extract()
1006       .as(ErrorResponse.class);
1007     assertThat(response.getMessage()).isEqualTo("The requested action is forbidden by the permission policies");
1008   }
1009 
1010   @Test
1011   public void getDataObject_wrongCollection_notFound() {
1012     CollectionIO thisCollection = createCollection("private collection");
1013     DataObjectIO thisDataObject = createDataObject("private data object", thisCollection.getId());
1014     CollectionIO otherCollection = createCollection("private collection");
1015 
1016     ErrorResponse response = given()
1017       .spec(requestSpecOfDefaultUser)
1018       .when()
1019       .get(
1020         "/%s/%d/%s/%d".formatted(
1021             Constants.COLLECTIONS,
1022             otherCollection.getId(),
1023             Constants.DATA_OBJECTS,
1024             thisDataObject.getId()
1025           )
1026       )
1027       .then()
1028       .statusCode(404)
1029       .extract()
1030       .as(ErrorResponse.class);
1031     assertThat(response.getMessage()).isEqualTo("ID ERROR - There is no association between collection and dataObject");
1032   }
1033 
1034   @Test
1035   public void putDataObjectTest_RemoveParentAndPredecessor() {
1036     DataObjectIO parent = new DataObjectIO();
1037     parent.setName("10001 Parent");
1038     parent = given()
1039       .spec(requestSpecOfDefaultUser)
1040       .body(parent)
1041       .when()
1042       .post(dataObjectsURL)
1043       .then()
1044       .statusCode(201)
1045       .extract()
1046       .as(DataObjectIO.class);
1047 
1048     DataObjectIO predecessor = new DataObjectIO();
1049     predecessor.setName("10001 predecessor");
1050     predecessor = given()
1051       .spec(requestSpecOfDefaultUser)
1052       .body(predecessor)
1053       .when()
1054       .post(dataObjectsURL)
1055       .then()
1056       .statusCode(201)
1057       .extract()
1058       .as(DataObjectIO.class);
1059 
1060     DataObjectIO dataObject = new DataObjectIO();
1061     dataObject.setName("ChildAndSuccessorDummy");
1062     dataObject.setParentId(parent.getId());
1063     dataObject.setPredecessorIds(new long[] { predecessor.getId() });
1064 
1065     dataObject = given()
1066       .spec(requestSpecOfDefaultUser)
1067       .body(dataObject)
1068       .when()
1069       .post(dataObjectsURL)
1070       .then()
1071       .statusCode(201)
1072       .extract()
1073       .as(DataObjectIO.class);
1074 
1075     dataObject.setPredecessorIds(new long[] {});
1076 
1077     dataObject = given()
1078       .spec(requestSpecOfDefaultUser)
1079       .body(dataObject)
1080       .when()
1081       .put(dataObjectsURL + "/" + dataObject.getId())
1082       .then()
1083       .statusCode(200)
1084       .extract()
1085       .as(DataObjectIO.class);
1086 
1087     dataObject = given()
1088       .spec(requestSpecOfDefaultUser)
1089       .when()
1090       .get(dataObjectsURL + "/" + dataObject.getId())
1091       .then()
1092       .statusCode(200)
1093       .extract()
1094       .as(DataObjectIO.class);
1095 
1096     assertThat(dataObject.getPredecessorIds()).isEmpty();
1097 
1098     dataObject.setParentId(null);
1099     dataObject = given()
1100       .spec(requestSpecOfDefaultUser)
1101       .body(dataObject)
1102       .when()
1103       .put(dataObjectsURL + "/" + dataObject.getId())
1104       .then()
1105       .statusCode(200)
1106       .extract()
1107       .as(DataObjectIO.class);
1108 
1109     dataObject = given()
1110       .spec(requestSpecOfDefaultUser)
1111       .when()
1112       .get(dataObjectsURL + "/" + dataObject.getId())
1113       .then()
1114       .statusCode(200)
1115       .extract()
1116       .as(DataObjectIO.class);
1117 
1118     assertThat(dataObject.getParentId()).isEqualTo(null);
1119   }
1120 
1121   @Test
1122   public void updateDataObject_deleteParentWhenPredecessorIsPresent_successfullyDeleteParent() {
1123     // Arrange
1124     var dataObjectAsParentAndPredecessorCreationPayload = new DataObjectIO();
1125     dataObjectAsParentAndPredecessorCreationPayload.setName("dataObjectWithParentAndPredecessor");
1126 
1127     DataObjectIO dataObjectAsParentAndPredecessor = given()
1128       .spec(requestSpecOfDefaultUser)
1129       .body(dataObjectAsParentAndPredecessorCreationPayload)
1130       .when()
1131       .post(dataObjectsURL)
1132       .then()
1133       .statusCode(201)
1134       .extract()
1135       .as(DataObjectIO.class);
1136 
1137     var dataObjectWithParentAndPredecessorCreationPayload = new DataObjectIO();
1138     dataObjectWithParentAndPredecessorCreationPayload.setName("dataObjectWithParentAndPredecessor");
1139     dataObjectWithParentAndPredecessorCreationPayload.setParentId(dataObjectAsParentAndPredecessor.getId());
1140     dataObjectWithParentAndPredecessorCreationPayload.setPredecessorIds(
1141       new long[] { dataObjectAsParentAndPredecessor.getId() }
1142     );
1143 
1144     DataObjectIO dataObjectWithParentAndPredecessor = given()
1145       .spec(requestSpecOfDefaultUser)
1146       .body(dataObjectWithParentAndPredecessorCreationPayload)
1147       .when()
1148       .post(dataObjectsURL)
1149       .then()
1150       .statusCode(201)
1151       .extract()
1152       .as(DataObjectIO.class);
1153 
1154     // Act
1155     dataObjectWithParentAndPredecessor.setParentId(null);
1156 
1157     given()
1158       .spec(requestSpecOfDefaultUser)
1159       .body(dataObjectWithParentAndPredecessor)
1160       .when()
1161       .put(dataObjectsURL + "/" + dataObjectWithParentAndPredecessor.getId())
1162       .then()
1163       .statusCode(200)
1164       .extract()
1165       .as(DataObjectIO.class);
1166 
1167     // Assert
1168     DataObjectIO updatedParent = given()
1169       .spec(requestSpecOfDefaultUser)
1170       .when()
1171       .get(dataObjectsURL + "/" + dataObjectWithParentAndPredecessor.getId())
1172       .then()
1173       .statusCode(200)
1174       .extract()
1175       .as(DataObjectIO.class);
1176 
1177     assertEquals(null, updatedParent.getParentId());
1178   }
1179 
1180   @Test
1181   public void updateDataObject_deleteAttribute_successfullyDeleteAttribute() {
1182     // Arrange
1183     DataObjectIO dataObjectIO = new DataObjectIOBuilder().setAttributes(Map.of("name", "my data object")).build();
1184     DataObjectIO dataObject = given()
1185       .spec(requestSpecOfDefaultUser)
1186       .body(dataObjectIO)
1187       .when()
1188       .post(dataObjectsURL)
1189       .then()
1190       .statusCode(201)
1191       .extract()
1192       .as(DataObjectIO.class);
1193 
1194     // Act
1195     dataObjectIO.setAttributes(Map.of());
1196     given()
1197       .spec(requestSpecOfDefaultUser)
1198       .body(dataObjectIO)
1199       .when()
1200       .put(dataObjectsURL + "/" + dataObject.getId())
1201       .then()
1202       .statusCode(200)
1203       .extract()
1204       .as(DataObjectIO.class);
1205 
1206     // Assert
1207     DataObjectIO updatedDataObject = given()
1208       .spec(requestSpecOfDefaultUser)
1209       .when()
1210       .get(dataObjectsURL + "/" + dataObject.getId())
1211       .then()
1212       .statusCode(200)
1213       .extract()
1214       .as(DataObjectIO.class);
1215     assertEquals(Map.of(), updatedDataObject.getAttributes());
1216   }
1217 
1218   @Test
1219   public void createDataObjectWithSuccessors() {
1220     // Arrange
1221     var dataObjectWithSuccessors = new DataObjectIO();
1222     dataObjectWithSuccessors.setName("dows");
1223     long[] successorIds = { 0L };
1224     dataObjectWithSuccessors.setSuccessorIds(successorIds);
1225     //Act
1226     ErrorResponse res = given()
1227       .spec(requestSpecOfDefaultUser)
1228       .body(dataObjectWithSuccessors)
1229       .when()
1230       .post(orderByDataObjectsURL)
1231       .then()
1232       .statusCode(400)
1233       .extract()
1234       .as(ErrorResponse.class);
1235     //Assert
1236     assertEquals("InvalidBodyException", res.getException());
1237   }
1238 
1239   @Test
1240   public void updateDataObjectWithIncorrectSuccessors() {
1241     // Arrange
1242     var do1IO = new DataObjectIO();
1243     do1IO.setName("do1");
1244     DataObjectIO do1 = given()
1245       .spec(requestSpecOfDefaultUser)
1246       .body(do1IO)
1247       .when()
1248       .post(orderByDataObjectsURL)
1249       .then()
1250       .statusCode(201)
1251       .extract()
1252       .as(DataObjectIO.class);
1253     var do2IO = new DataObjectIO();
1254     do2IO.setName("do2");
1255     long[] predecessors = { do1.getId() };
1256     do2IO.setPredecessorIds(predecessors);
1257     DataObjectIO do2 = given()
1258       .spec(requestSpecOfDefaultUser)
1259       .body(do2IO)
1260       .when()
1261       .post(orderByDataObjectsURL)
1262       .then()
1263       .statusCode(201)
1264       .extract()
1265       .as(DataObjectIO.class);
1266     //Act
1267     var do1New = new DataObjectIO();
1268     do1New.setName("do1New");
1269     long[] successors = { do2.getId() + 1 };
1270     do1New.setSuccessorIds(successors);
1271     System.out.println("PUTURL: " + dataObjectsURL + "/" + do1.getId());
1272     ErrorResponse res = given()
1273       .spec(requestSpecOfDefaultUser)
1274       .body(do1New)
1275       .when()
1276       .put(orderByDataObjectsURL + "/" + do1.getId())
1277       .then()
1278       .statusCode(400)
1279       .extract()
1280       .as(ErrorResponse.class);
1281     //Assert
1282     assertEquals("InvalidBodyException", res.getException());
1283   }
1284 
1285   @Test
1286   public void updateDataObjectWithCorrectSuccessors() {
1287     // Arrange
1288     var do1IO = new DataObjectIO();
1289     do1IO.setName("do1");
1290     DataObjectIO do1 = given()
1291       .spec(requestSpecOfDefaultUser)
1292       .body(do1IO)
1293       .when()
1294       .post(orderByDataObjectsURL)
1295       .then()
1296       .statusCode(201)
1297       .extract()
1298       .as(DataObjectIO.class);
1299     var do2IO = new DataObjectIO();
1300     do2IO.setName("do2");
1301     long[] predecessors = { do1.getId() };
1302     do2IO.setPredecessorIds(predecessors);
1303     DataObjectIO do2 = given()
1304       .spec(requestSpecOfDefaultUser)
1305       .body(do2IO)
1306       .when()
1307       .post(orderByDataObjectsURL)
1308       .then()
1309       .statusCode(201)
1310       .extract()
1311       .as(DataObjectIO.class);
1312     //Act
1313     var do1New = new DataObjectIO();
1314     do1New.setName("do1New");
1315     long[] successors = { do2.getId() };
1316     do1New.setSuccessorIds(successors);
1317     System.out.println("PUTURL: " + dataObjectsURL + "/" + do1.getId());
1318     DataObjectIO res = given()
1319       .spec(requestSpecOfDefaultUser)
1320       .body(do1New)
1321       .when()
1322       .put(orderByDataObjectsURL + "/" + do1.getId())
1323       .then()
1324       .statusCode(200)
1325       .extract()
1326       .as(DataObjectIO.class);
1327     //Assert
1328     assertEquals(do1New.getName(), res.getName());
1329   }
1330 }