From d6404b9142d51b74a5e29fdb8aedbe6d1e1133e2 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 14 Aug 2025 16:55:47 -0400 Subject: [PATCH 01/13] #11387 update command to allow for leaving input levels alone --- .../impl/AbstractWriteDataverseCommand.java | 8 ++- .../iq/dataverse/api/DataversesIT.java | 53 ++++++++++++++++--- .../edu/harvard/iq/dataverse/api/UtilIT.java | 20 +++++++ 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractWriteDataverseCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractWriteDataverseCommand.java index 8227572da3b..e4fd5373c7d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractWriteDataverseCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractWriteDataverseCommand.java @@ -105,10 +105,14 @@ private void processInputLevels(CommandContext ctxt) { ctxt.fieldTypeInputLevels().deleteDataverseFieldTypeInputLevelFor(dataverse); } else { dataverse.addInputLevelsMetadataBlocksIfNotPresent(inputLevels); - ctxt.fieldTypeInputLevels().deleteDataverseFieldTypeInputLevelFor(dataverse); + //if levels not empty either create or update (handled by save - update when id not null create if null) inputLevels.forEach(inputLevel -> { + DataverseFieldTypeInputLevel ftil = ctxt.fieldTypeInputLevels().findByDataverseIdDatasetFieldTypeId(dataverse.getId(), inputLevel.getDatasetFieldType().getId()); + if(ftil != null){ + inputLevel.setId(ftil.getId()); + } inputLevel.setDataverse(dataverse); - ctxt.fieldTypeInputLevels().create(inputLevel); + ctxt.fieldTypeInputLevels().save(inputLevel); }); } } diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java index 3e1a160c9f2..50f171de352 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java @@ -1255,6 +1255,45 @@ public void testUpdateInputLevels() { updateDataverseInputLevelsResponse.then().assertThat() .body("message", equalTo("Error while updating dataverse input levels: Input level list cannot be null or empty")) .statusCode(INTERNAL_SERVER_ERROR.getStatusCode()); + + //Add new types and see that previously changed ones remain as before... #11387 + testInputLevelNames = new String[]{"subtitle", "relatedMaterial"}; + + testRequiredInputLevels = new boolean[] {false, false}; + testIncludedInputLevels = new boolean[] {true, true}; + boolean [] testDisplayOnCreate = new boolean[] {true, true}; + updateDataverseInputLevelsResponse = UtilIT.updateDataverseInputLevels(dataverseAlias, testInputLevelNames, testRequiredInputLevels, testIncludedInputLevels, testDisplayOnCreate, apiToken); + actualInputLevelName = updateDataverseInputLevelsResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); + int subtitleInputLevelIndex = actualInputLevelName.equals("subtitle") ? 0 : 1; + updateDataverseInputLevelsResponse.prettyPrint(); + + updateDataverseInputLevelsResponse.then().assertThat() + .body(String.format("data.inputLevels[%d].include", subtitleInputLevelIndex), equalTo(true)) + .body(String.format("data.inputLevels[%d].required", subtitleInputLevelIndex), equalTo(false)) + .body(String.format("data.inputLevels[%d].displayOnCreate", subtitleInputLevelIndex), equalTo(true)) + .body(String.format("data.inputLevels[%d].include", 1 - subtitleInputLevelIndex), equalTo(true)) + .body(String.format("data.inputLevels[%d].required", 1 - subtitleInputLevelIndex), equalTo(false)) + .body(String.format("data.inputLevels[%d].displayOnCreate", 1 - subtitleInputLevelIndex), equalTo(true)) + .statusCode(OK.getStatusCode()); + actualFieldTypeName1 = updateDataverseInputLevelsResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); + actualFieldTypeName2 = updateDataverseInputLevelsResponse.then().extract().path("data.inputLevels[1].datasetFieldTypeName"); + assertNotEquals(actualFieldTypeName1, actualFieldTypeName2); + assertThat(testInputLevelNames, hasItemInArray(actualFieldTypeName1)); + assertThat(testInputLevelNames, hasItemInArray(actualFieldTypeName2)); + + + testInputLevelNames = new String[]{"subtitle", "otherReferences"}; + testRequiredInputLevels = new boolean[] {false, false}; + testIncludedInputLevels = new boolean[] {true, true}; + testDisplayOnCreate = new boolean[] {false, true}; + + updateDataverseInputLevelsResponse = UtilIT.updateDataverseInputLevels(dataverseAlias, testInputLevelNames, testRequiredInputLevels, testIncludedInputLevels, testDisplayOnCreate, apiToken); + updateDataverseInputLevelsResponse.prettyPrint(); + + updateDataverseInputLevelsResponse.then().assertThat() + .statusCode(OK.getStatusCode()); + + } @Test @@ -2274,14 +2313,16 @@ public void testUpdateInputLevelDisplayOnCreateOverride() { .body("data[0].displayName", equalTo("Citation Metadata")) .body("data.size()", equalTo(expectedOnlyDisplayedOnCreateNumberOfMetadataBlocks)) .body("data[0].fields.author.childFields.size()", is(4)); - + updateResponse = UtilIT.updateDataverseInputLevelDisplayOnCreate( - dataverseAlias, "subtitle", false, apiToken); + dataverseAlias, "subtitle", false, apiToken); + String actualInputLevelName = updateResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); + int subtitleIndex = actualInputLevelName.equals("subtitle") ? 0 : 1; updateResponse.then().assertThat() - .statusCode(OK.getStatusCode()) - .body("data.inputLevels[0].displayOnCreate", equalTo(false)) - .body("data.inputLevels[0].datasetFieldTypeName", equalTo("subtitle")); - + .body(String.format("data.inputLevels[%d].displayOnCreate", subtitleIndex), equalTo(false)) + .body(String.format("data.inputLevels[%d].datasetFieldTypeName", subtitleIndex), equalTo("subtitle")) + .statusCode(OK.getStatusCode()); + } @Test diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index 24f2adbb3ed..8c858a17ec9 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -4578,6 +4578,18 @@ public static Response updateDataverseInputLevels(String dataverseAlias, String[ .contentType(ContentType.JSON) .put("/api/dataverses/" + dataverseAlias + "/inputLevels"); } + + public static Response updateDataverseInputLevels(String dataverseAlias, String[] inputLevelNames, boolean[] requiredInputLevels, boolean[] includedInputLevels, boolean[] displayOnCreate, String apiToken) { + JsonArrayBuilder inputLevelsArrayBuilder = Json.createArrayBuilder(); + for (int i = 0; i < inputLevelNames.length; i++) { + inputLevelsArrayBuilder.add(createInputLevelObject(inputLevelNames[i], requiredInputLevels[i], includedInputLevels[i], displayOnCreate[i])); + } + return given() + .header(API_TOKEN_HTTP_HEADER, apiToken) + .body(inputLevelsArrayBuilder.build().toString()) + .contentType(ContentType.JSON) + .put("/api/dataverses/" + dataverseAlias + "/inputLevels"); + } private static JsonObjectBuilder createInputLevelObject(String name, boolean required, boolean include) { return Json.createObjectBuilder() @@ -4585,6 +4597,14 @@ private static JsonObjectBuilder createInputLevelObject(String name, boolean req .add("required", required) .add("include", include); } + + private static JsonObjectBuilder createInputLevelObject(String name, boolean required, boolean include, boolean displayOnCreate) { + return Json.createObjectBuilder() + .add("datasetFieldTypeName", name) + .add("required", required) + .add("include", include) + .add("displayOnCreate", displayOnCreate); + } public static Response getOpenAPI(String accept, String format) { Response response = given() From 2788a6d7e5d2959fef406c1dee47dc16081a7ab1 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Fri, 15 Aug 2025 10:42:46 -0400 Subject: [PATCH 02/13] #11387 update test; cleanup --- .../edu/harvard/iq/dataverse/api/DataversesIT.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java index 50f171de352..b07c3e4ffa0 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java @@ -1289,10 +1289,21 @@ public void testUpdateInputLevels() { updateDataverseInputLevelsResponse = UtilIT.updateDataverseInputLevels(dataverseAlias, testInputLevelNames, testRequiredInputLevels, testIncludedInputLevels, testDisplayOnCreate, apiToken); updateDataverseInputLevelsResponse.prettyPrint(); + + actualInputLevelName = updateDataverseInputLevelsResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); + subtitleInputLevelIndex = actualInputLevelName.equals("subtitle") ? 0 : 1; + //make sure subtitle got changed to false updateDataverseInputLevelsResponse.then().assertThat() + .body(String.format("data.inputLevels[%d].displayOnCreate", subtitleInputLevelIndex), equalTo(false)) .statusCode(OK.getStatusCode()); + //make superuser for cleanup + String username = UtilIT.getUsernameFromResponse(createUserResponse); + UtilIT.setSuperuserStatus(username, Boolean.TRUE); + Response deleteDataverse1Response = UtilIT.deleteDataverse(dataverseAlias, apiToken); + deleteDataverse1Response.prettyPrint(); + assertEquals(200, deleteDataverse1Response.getStatusCode()); } From 08dfd98b0bbc4165068bf077c952865db526770d Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Fri, 15 Aug 2025 11:31:23 -0400 Subject: [PATCH 03/13] #11387 fix test --- .../engine/command/impl/CreateDataverseCommandTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommandTest.java b/src/test/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommandTest.java index 73880b78e7b..2d2fd943d4d 100644 --- a/src/test/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommandTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/engine/command/impl/CreateDataverseCommandTest.java @@ -307,7 +307,7 @@ public void testCustomOptions() throws CommandException { i++; } - assertTrue( dftilsDeleted ); + // assertTrue( dftilsDeleted ); we no longer delete when adding new input levels to preserve previously created for ( DataverseFieldTypeInputLevel dftil : createdDftils ) { assertEquals( result, dftil.getDataverse() ); } From 949b61758c7712cc91ab998c9f427e303b810bd9 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Fri, 15 Aug 2025 15:43:07 -0400 Subject: [PATCH 04/13] #11387 source format --- src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java index b07c3e4ffa0..36901548f2d 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java @@ -2324,9 +2324,8 @@ public void testUpdateInputLevelDisplayOnCreateOverride() { .body("data[0].displayName", equalTo("Citation Metadata")) .body("data.size()", equalTo(expectedOnlyDisplayedOnCreateNumberOfMetadataBlocks)) .body("data[0].fields.author.childFields.size()", is(4)); - - updateResponse = UtilIT.updateDataverseInputLevelDisplayOnCreate( - dataverseAlias, "subtitle", false, apiToken); + + updateResponse = UtilIT.updateDataverseInputLevelDisplayOnCreate(dataverseAlias, "subtitle", false, apiToken); String actualInputLevelName = updateResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); int subtitleIndex = actualInputLevelName.equals("subtitle") ? 0 : 1; updateResponse.then().assertThat() From 2644fc73dbeeb7abf8acebb601781403f4e7eb9c Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 19 Aug 2025 15:38:02 -0400 Subject: [PATCH 05/13] #11387 get actual index for test --- .../java/edu/harvard/iq/dataverse/api/DataversesIT.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java index 36901548f2d..e851134a8c7 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java @@ -2306,12 +2306,15 @@ public void testUpdateInputLevelDisplayOnCreateOverride() { .body("data.inputLevels[0].displayOnCreate", equalTo(true)) .body("data.inputLevels[0].datasetFieldTypeName", equalTo("notesText")); + String actualInputLevelName = updateResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); + int subtitleInputLevelIndex = actualInputLevelName.equals("subtitle") ? 0 : 1; + updateResponse = UtilIT.updateDataverseInputLevelDisplayOnCreate( dataverseAlias, "subtitle", true, apiToken); updateResponse.then().assertThat() .statusCode(OK.getStatusCode()) - .body("data.inputLevels[0].displayOnCreate", equalTo(true)) - .body("data.inputLevels[0].datasetFieldTypeName", equalTo("subtitle")); + .body(String.format("data.inputLevels[%d].displayOnCreate", subtitleInputLevelIndex), equalTo(true)) + .body(String.format("data.inputLevels[%d].datasetFieldTypeName", subtitleInputLevelIndex), equalTo("subtitle")); listMetadataBlocksResponse = UtilIT.listMetadataBlocks(dataverseAlias, true, true, apiToken); listMetadataBlocksResponse.prettyPrint(); @@ -2326,7 +2329,7 @@ public void testUpdateInputLevelDisplayOnCreateOverride() { .body("data[0].fields.author.childFields.size()", is(4)); updateResponse = UtilIT.updateDataverseInputLevelDisplayOnCreate(dataverseAlias, "subtitle", false, apiToken); - String actualInputLevelName = updateResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); + actualInputLevelName = updateResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); int subtitleIndex = actualInputLevelName.equals("subtitle") ? 0 : 1; updateResponse.then().assertThat() .body(String.format("data.inputLevels[%d].displayOnCreate", subtitleIndex), equalTo(false)) From a9f7f078b76bd2681b4fcb79ac6f62fed8984b26 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 19 Aug 2025 17:04:16 -0400 Subject: [PATCH 06/13] #11387 fix get index for test --- .../java/edu/harvard/iq/dataverse/api/DataversesIT.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java index e851134a8c7..17256d3317b 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java @@ -2306,11 +2306,13 @@ public void testUpdateInputLevelDisplayOnCreateOverride() { .body("data.inputLevels[0].displayOnCreate", equalTo(true)) .body("data.inputLevels[0].datasetFieldTypeName", equalTo("notesText")); - String actualInputLevelName = updateResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); - int subtitleInputLevelIndex = actualInputLevelName.equals("subtitle") ? 0 : 1; - + updateResponse = UtilIT.updateDataverseInputLevelDisplayOnCreate( dataverseAlias, "subtitle", true, apiToken); + + String actualInputLevelName = updateResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); + int subtitleInputLevelIndex = actualInputLevelName.equals("subtitle") ? 0 : 1; + updateResponse.prettyPrint(); updateResponse.then().assertThat() .statusCode(OK.getStatusCode()) .body(String.format("data.inputLevels[%d].displayOnCreate", subtitleInputLevelIndex), equalTo(true)) From 04f6534e4da7a3ff373fe9e72fb1aba371fbf97c Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 20 Aug 2025 11:20:58 -0400 Subject: [PATCH 07/13] #11387 guard against differing json array in test --- .../iq/dataverse/api/DataversesIT.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java index 17256d3317b..e650cd11f6f 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java @@ -1261,19 +1261,31 @@ public void testUpdateInputLevels() { testRequiredInputLevels = new boolean[] {false, false}; testIncludedInputLevels = new boolean[] {true, true}; - boolean [] testDisplayOnCreate = new boolean[] {true, true}; + boolean [] testDisplayOnCreate = new boolean[] {true, false}; updateDataverseInputLevelsResponse = UtilIT.updateDataverseInputLevels(dataverseAlias, testInputLevelNames, testRequiredInputLevels, testIncludedInputLevels, testDisplayOnCreate, apiToken); - actualInputLevelName = updateDataverseInputLevelsResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); - int subtitleInputLevelIndex = actualInputLevelName.equals("subtitle") ? 0 : 1; - updateDataverseInputLevelsResponse.prettyPrint(); - + updateDataverseInputLevelsResponse.prettyPrint(); + int subtitleInputLevelIndex = 0; + int relatedMaterialInputLevelIndex = 0; + int i = 0; + + while (updateDataverseInputLevelsResponse.then().extract().path(String.format("data.inputLevels[%d].datasetFieldTypeName", i)) != null){ + actualInputLevelName = updateDataverseInputLevelsResponse.then().extract().path(String.format("data.inputLevels[%d].datasetFieldTypeName", i)).toString(); + if (actualInputLevelName.equals("subtitle")){ + subtitleInputLevelIndex = i; + } + if (actualInputLevelName.equals("relatedMaterial")){ + relatedMaterialInputLevelIndex = i; + } + i++; + } + updateDataverseInputLevelsResponse.then().assertThat() .body(String.format("data.inputLevels[%d].include", subtitleInputLevelIndex), equalTo(true)) .body(String.format("data.inputLevels[%d].required", subtitleInputLevelIndex), equalTo(false)) .body(String.format("data.inputLevels[%d].displayOnCreate", subtitleInputLevelIndex), equalTo(true)) - .body(String.format("data.inputLevels[%d].include", 1 - subtitleInputLevelIndex), equalTo(true)) - .body(String.format("data.inputLevels[%d].required", 1 - subtitleInputLevelIndex), equalTo(false)) - .body(String.format("data.inputLevels[%d].displayOnCreate", 1 - subtitleInputLevelIndex), equalTo(true)) + .body(String.format("data.inputLevels[%d].include", relatedMaterialInputLevelIndex), equalTo(true)) + .body(String.format("data.inputLevels[%d].required", relatedMaterialInputLevelIndex), equalTo(false)) + .body(String.format("data.inputLevels[%d].displayOnCreate", relatedMaterialInputLevelIndex), equalTo(false)) .statusCode(OK.getStatusCode()); actualFieldTypeName1 = updateDataverseInputLevelsResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); actualFieldTypeName2 = updateDataverseInputLevelsResponse.then().extract().path("data.inputLevels[1].datasetFieldTypeName"); From e001ff048dcb7593acbc2b7b44a46aef8eded424 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 20 Aug 2025 13:26:27 -0400 Subject: [PATCH 08/13] #11387 more array testing fun --- .../iq/dataverse/api/DataversesIT.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java index e650cd11f6f..682b2ddc8a3 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java @@ -1287,8 +1287,9 @@ public void testUpdateInputLevels() { .body(String.format("data.inputLevels[%d].required", relatedMaterialInputLevelIndex), equalTo(false)) .body(String.format("data.inputLevels[%d].displayOnCreate", relatedMaterialInputLevelIndex), equalTo(false)) .statusCode(OK.getStatusCode()); - actualFieldTypeName1 = updateDataverseInputLevelsResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); - actualFieldTypeName2 = updateDataverseInputLevelsResponse.then().extract().path("data.inputLevels[1].datasetFieldTypeName"); + + actualFieldTypeName1 = updateDataverseInputLevelsResponse.then().extract().path(String.format("data.inputLevels[%d].datasetFieldTypeName", subtitleInputLevelIndex)); + actualFieldTypeName2 = updateDataverseInputLevelsResponse.then().extract().path(String.format("data.inputLevels[%d].datasetFieldTypeName", relatedMaterialInputLevelIndex)); assertNotEquals(actualFieldTypeName1, actualFieldTypeName2); assertThat(testInputLevelNames, hasItemInArray(actualFieldTypeName1)); assertThat(testInputLevelNames, hasItemInArray(actualFieldTypeName2)); @@ -1302,9 +1303,21 @@ public void testUpdateInputLevels() { updateDataverseInputLevelsResponse = UtilIT.updateDataverseInputLevels(dataverseAlias, testInputLevelNames, testRequiredInputLevels, testIncludedInputLevels, testDisplayOnCreate, apiToken); updateDataverseInputLevelsResponse.prettyPrint(); - actualInputLevelName = updateDataverseInputLevelsResponse.then().extract().path("data.inputLevels[0].datasetFieldTypeName"); - subtitleInputLevelIndex = actualInputLevelName.equals("subtitle") ? 0 : 1; - + subtitleInputLevelIndex = 0; + int otherReferencesInputLevelIndex = 0; + i = 0; + + while (updateDataverseInputLevelsResponse.then().extract().path(String.format("data.inputLevels[%d].datasetFieldTypeName", i)) != null) { + actualInputLevelName = updateDataverseInputLevelsResponse.then().extract().path(String.format("data.inputLevels[%d].datasetFieldTypeName", i)).toString(); + if (actualInputLevelName.equals("subtitle")) { + subtitleInputLevelIndex = i; + } + if (actualInputLevelName.equals("otherReferences")) { + otherReferencesInputLevelIndex = i; + } + i++; + } + //make sure subtitle got changed to false updateDataverseInputLevelsResponse.then().assertThat() .body(String.format("data.inputLevels[%d].displayOnCreate", subtitleInputLevelIndex), equalTo(false)) From 1d5199bc79738ad7c3bf41d959c7b5957f2718c3 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 3 Sep 2025 10:06:59 -0400 Subject: [PATCH 09/13] Update native-api.rst --- doc/sphinx-guides/source/api/native-api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 04aaf59de98..f6b2cfa866b 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1106,7 +1106,7 @@ Update Collection Input Levels Updates the dataset field type input levels in a collection. -Please note that this endpoint overwrites all the input levels of the collection page, so if you want to keep the existing ones, you will need to add them to the JSON request body. +Please note that this endpoint does not change previously updated input levels of the collection page, so if you want to keep the modify exisitng ones, you will need to include them in the JSON request body. If one of the input levels corresponds to a dataset field type belonging to a metadata block that does not exist in the collection, the metadata block will be added to the collection. From 35f2dd40c650731cd5715cbba3768542706935e2 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 3 Sep 2025 10:07:49 -0400 Subject: [PATCH 10/13] #11387 update tests from code review --- .../java/edu/harvard/iq/dataverse/api/DataversesIT.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java index 682b2ddc8a3..f6b091f41f5 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java @@ -1264,8 +1264,8 @@ public void testUpdateInputLevels() { boolean [] testDisplayOnCreate = new boolean[] {true, false}; updateDataverseInputLevelsResponse = UtilIT.updateDataverseInputLevels(dataverseAlias, testInputLevelNames, testRequiredInputLevels, testIncludedInputLevels, testDisplayOnCreate, apiToken); updateDataverseInputLevelsResponse.prettyPrint(); - int subtitleInputLevelIndex = 0; - int relatedMaterialInputLevelIndex = 0; + int subtitleInputLevelIndex = -1; + int relatedMaterialInputLevelIndex = -1; int i = 0; while (updateDataverseInputLevelsResponse.then().extract().path(String.format("data.inputLevels[%d].datasetFieldTypeName", i)) != null){ @@ -1304,7 +1304,6 @@ public void testUpdateInputLevels() { updateDataverseInputLevelsResponse.prettyPrint(); subtitleInputLevelIndex = 0; - int otherReferencesInputLevelIndex = 0; i = 0; while (updateDataverseInputLevelsResponse.then().extract().path(String.format("data.inputLevels[%d].datasetFieldTypeName", i)) != null) { @@ -1312,9 +1311,6 @@ public void testUpdateInputLevels() { if (actualInputLevelName.equals("subtitle")) { subtitleInputLevelIndex = i; } - if (actualInputLevelName.equals("otherReferences")) { - otherReferencesInputLevelIndex = i; - } i++; } From a966923eb0ac27ea999fbf9138ff7746036aad83 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 3 Sep 2025 10:17:50 -0400 Subject: [PATCH 11/13] #11387 add release note. --- doc/release-notes/11387-modify-input-level-api.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/release-notes/11387-modify-input-level-api.md diff --git a/doc/release-notes/11387-modify-input-level-api.md b/doc/release-notes/11387-modify-input-level-api.md new file mode 100644 index 00000000000..ca18eabb515 --- /dev/null +++ b/doc/release-notes/11387-modify-input-level-api.md @@ -0,0 +1,3 @@ +### Update Collection Input Level API Changed + +- This endpoint will no longer delete the custom input levels previously modified for the given collection. In order to update a previously modified custom input level, it must be included in the JSON provided to the api. From 5b4eab384126e370f4af5c1bab38609c5bf69705 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 4 Sep 2025 14:13:28 -0400 Subject: [PATCH 12/13] Update changelog.rst --- doc/sphinx-guides/source/api/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/sphinx-guides/source/api/changelog.rst b/doc/sphinx-guides/source/api/changelog.rst index 16157459220..3de91d8d3b2 100644 --- a/doc/sphinx-guides/source/api/changelog.rst +++ b/doc/sphinx-guides/source/api/changelog.rst @@ -13,6 +13,7 @@ v6.8 - For POST /api/files/{id}/metadata passing an empty string ("description":"") or array ("categories":[]) will no longer be ignored. Empty fields will now clear out the values in the file's metadata. To ignore the fields simply do not include them in the JSON string. - For PUT /api/datasets/{id}/editMetadata the query parameter "sourceInternalVersionNumber" has been removed and replaced with "sourceLastUpdateTime" to verify that the data being edited hasn't been modified and isn't stale. - For GET /api/dataverses/$dataverse-alias/links the Json response has changed breaking the backward compatibility of the API. +- For PUT /api/dataverses/$dataverse-alias/inputLevels custom input levels that had been previously set will no longer be deleted. v6.7 ---- From ac935e853bd4bf22f1205e783d1bd19a0e25b804 Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Wed, 10 Sep 2025 16:01:04 -0400 Subject: [PATCH 13/13] update docs to explain how to delete input levels --- doc/sphinx-guides/source/api/changelog.rst | 2 +- doc/sphinx-guides/source/api/native-api.rst | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/api/changelog.rst b/doc/sphinx-guides/source/api/changelog.rst index 96629823673..b793981e761 100644 --- a/doc/sphinx-guides/source/api/changelog.rst +++ b/doc/sphinx-guides/source/api/changelog.rst @@ -13,7 +13,7 @@ v6.8 - For POST /api/files/{id}/metadata passing an empty string ("description":"") or array ("categories":[]) will no longer be ignored. Empty fields will now clear out the values in the file's metadata. To ignore the fields simply do not include them in the JSON string. - For PUT /api/datasets/{id}/editMetadata the query parameter "sourceInternalVersionNumber" has been removed and replaced with "sourceLastUpdateTime" to verify that the data being edited hasn't been modified and isn't stale. - For GET /api/dataverses/$dataverse-alias/links the Json response has changed breaking the backward compatibility of the API. -- For PUT /api/dataverses/$dataverse-alias/inputLevels custom input levels that had been previously set will no longer be deleted. +- For PUT /api/dataverses/$dataverse-alias/inputLevels custom input levels that had been previously set will no longer be deleted. To delete input levels send an empty list (deletes all), then send the new/modified list. - For GET /api/externalTools and /api/externalTools/{id} the responses are now formatted as JSON (previously the toolParameters and allowedApiCalls were a JSON object and array (respectively) that were serialized as JSON strings) and any configured "requirements" are included. v6.7 diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 35cd807ef96..65956904223 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1106,7 +1106,8 @@ Update Collection Input Levels Updates the dataset field type input levels in a collection. -Please note that this endpoint does not change previously updated input levels of the collection page, so if you want to keep the modify exisitng ones, you will need to include them in the JSON request body. +Please note that this endpoint does not change previously updated input levels of the collection page, so if you want to add new levels or modify existing ones, you will need to include them in the JSON request body. +In order to delete input levels you must call this API with an empty list to delete all of the input levels, then call this API with the new list of input levels. If one of the input levels corresponds to a dataset field type belonging to a metadata block that does not exist in the collection, the metadata block will be added to the collection.