From 75c71a60ba353f7e3e2e31fcee0c88c050dc8cdf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 13 Nov 2025 14:00:10 +0000 Subject: [PATCH 1/3] Initial plan From d28cb81fbfd53a3ae1818c053942b7093de8eb20 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 13 Nov 2025 20:28:43 +0000 Subject: [PATCH 2/3] Fix SonarCloud issues: lambdas, exceptions, empty blocks, deprecated JWT API, duplicate tests Co-authored-by: thomasturrell <1552612+thomasturrell@users.noreply.github.com> --- .../DeleteActivityProfileRequestTests.java | 40 ----------------- .../learning/xapi/client/XapiClientTests.java | 45 ++++++++----------- ...entAutoConfigurationAuthorizationTest.java | 1 + ...AutoConfigurationUsernamePasswordTest.java | 1 + .../dev/learning/xapi/model/Statement.java | 5 +-- .../learning/xapi/model/AttachmentTests.java | 3 +- .../xapi/model/ContextActivitiesTests.java | 3 +- .../dev/learning/xapi/model/GroupTests.java | 6 +-- .../learning/xapi/model/StatementTests.java | 33 +++++--------- 9 files changed, 37 insertions(+), 100 deletions(-) diff --git a/xapi-client/src/test/java/dev/learning/xapi/client/DeleteActivityProfileRequestTests.java b/xapi-client/src/test/java/dev/learning/xapi/client/DeleteActivityProfileRequestTests.java index 32544fc6..9bfe01ca 100644 --- a/xapi-client/src/test/java/dev/learning/xapi/client/DeleteActivityProfileRequestTests.java +++ b/xapi-client/src/test/java/dev/learning/xapi/client/DeleteActivityProfileRequestTests.java @@ -39,21 +39,6 @@ void whenBuildingDeleteActivityProfileRequestWithAllParametersThenNoExceptionIsT } - @Test - void whenBuildingDeleteActivityProfileRequestWithoutRegistrationThenNoExceptionIsThrown() { - - // When Building DeleteActivityProfileRequest Without Registration - Builder builder = DeleteActivityProfileRequest.builder() - - .activityId(URI.create("https://example.com/activity/1")) - - .profileId("bookmark"); - - // Then No Exception Is Thrown - assertDoesNotThrow(builder::build); - - } - @Test void whenBuildingDeleteActivityProfileRequestWithoutActivityIdThenExceptionIsThrown() { @@ -105,29 +90,4 @@ void givenDeleteActivityProfileRequestWithAllParametersWhenGettingURLThenResultI } - @Test - void givenDeleteActivityProfileRequestWithoutRegistrationWhenGettingURLThenResultIsExpected() { - - // Given DeleteActivityProfileRequest Without Registration - DeleteActivityProfileRequest request = DeleteActivityProfileRequest.builder() - - .activityId(URI.create("https://example.com/activity/1")) - - .profileId("bookmark") - - .build(); - - Map queryParams = new HashMap<>(); - - // When Getting URL - URI result = - request.url(UriComponentsBuilder.fromUriString("https://example.com/xapi/"), queryParams) - .build(queryParams); - - // Then Result Is Expected - assertThat(result, is(URI.create( - "https://example.com/xapi/activities/profile?activityId=https%3A%2F%2Fexample.com%2Factivity%2F1&profileId=bookmark"))); - - } - } diff --git a/xapi-client/src/test/java/dev/learning/xapi/client/XapiClientTests.java b/xapi-client/src/test/java/dev/learning/xapi/client/XapiClientTests.java index 9de1dc59..26e88e7e 100644 --- a/xapi-client/src/test/java/dev/learning/xapi/client/XapiClientTests.java +++ b/xapi-client/src/test/java/dev/learning/xapi/client/XapiClientTests.java @@ -398,7 +398,7 @@ void givenApiResponseIsEmptyWhenPostingStatementThenMissingResponseBodyException .definition(d -> d.addName(Locale.ENGLISH, "Simple Statement"))))); // Then MissingResponseBodyException Is Thrown - assertThrows(MissingResponseBodyException.class, () -> response.block()); + assertThrows(MissingResponseBodyException.class, response::block); } @@ -418,7 +418,7 @@ void givenApiResponseIsBadRequestWhenPostingStatementThenBadRequestIsThrown() { .definition(d -> d.addName(Locale.ENGLISH, "Simple Statement"))))); // Then BadRequest Is Thrown - assertThrows(BadRequest.class, () -> response.block()); + assertThrows(BadRequest.class, response::block); } @@ -438,7 +438,7 @@ void givenApiResponseIsInternalServerErrorWhenPostingStatementThenInternalServer .definition(d -> d.addName(Locale.ENGLISH, "Simple Statement"))))); // Then InternalServerError Is Thrown - assertThrows(InternalServerError.class, () -> response.block()); + assertThrows(InternalServerError.class, response::block); } @@ -512,14 +512,14 @@ void whenGettingVoidedStatementWithAttachmentsThenPathIsExpected() throws Interr mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK")); // When Getting Voided Statement With Attachments - client.getStatement(r -> r.id("4df42866-40e7-45b6-bf7c-8d5fccbdccd6").attachments(true)) + client.getVoidedStatement(r -> r.id("4df42866-40e7-45b6-bf7c-8d5fccbdccd6").attachments(true)) .block(); final var recordedRequest = mockWebServer.takeRequest(); // Then Path Is Expected assertThat(recordedRequest.getPath(), - is("/statements?statementId=4df42866-40e7-45b6-bf7c-8d5fccbdccd6&attachments=true")); + is("/statements?voidedStatementId=4df42866-40e7-45b6-bf7c-8d5fccbdccd6&attachments=true")); } @Test @@ -530,7 +530,7 @@ void whenGettingVoidedStatementWithCanonicalFormatThenPathIsExpected() // When Getting Voided Statement With Canonical Format client - .getStatement( + .getVoidedStatement( r -> r.id("4df42866-40e7-45b6-bf7c-8d5fccbdccd6").format(StatementFormat.CANONICAL)) .block(); @@ -538,7 +538,7 @@ void whenGettingVoidedStatementWithCanonicalFormatThenPathIsExpected() // Then Path Is Expected assertThat(recordedRequest.getPath(), - is("/statements?statementId=4df42866-40e7-45b6-bf7c-8d5fccbdccd6&format=canonical")); + is("/statements?voidedStatementId=4df42866-40e7-45b6-bf7c-8d5fccbdccd6&format=canonical")); } // Get Statements @@ -791,8 +791,7 @@ void whenGettingASingleStateWithoutRegistrationThenPathIsExpected() throws Inter } @Test - void givenStateContentTypeIsTextPlainWhenGettingStateThenBodyIsInstanceOfString() - throws InterruptedException { + void givenStateContentTypeIsTextPlainWhenGettingStateThenBodyIsInstanceOfString() { // Given State Content Type Is Text Plain mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK").setBody("Hello World!") @@ -814,8 +813,7 @@ void givenStateContentTypeIsTextPlainWhenGettingStateThenBodyIsInstanceOfString( } @Test - void givenStateContentTypeIsTextPlainWhenGettingStateThenBodyIsExpected() - throws InterruptedException { + void givenStateContentTypeIsTextPlainWhenGettingStateThenBodyIsExpected() { // Given State Content Type Is Text Plain mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK").setBody("Hello World!") @@ -1304,8 +1302,7 @@ void whenGettingMultipleStatesWithoutRegistrationThenPathIsExpected() } @Test - void givenMultipleStatesExistWhenGettingMultipleStatesThenBodyIsInstanceOfStringArray() - throws InterruptedException { + void givenMultipleStatesExistWhenGettingMultipleStatesThenBodyIsInstanceOfStringArray() { // Given Multiple States Exist mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK") @@ -1326,8 +1323,7 @@ void givenMultipleStatesExistWhenGettingMultipleStatesThenBodyIsInstanceOfString } @Test - void givenMultipleStatesExistWhenGettingMultipleStatesThenBodyIsExpected() - throws InterruptedException { + void givenMultipleStatesExistWhenGettingMultipleStatesThenBodyIsExpected() { // Given Multiple States Exist mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK") @@ -2002,8 +1998,7 @@ void whenGettingASingleActivityProfileThenPathIsExpected() throws InterruptedExc } @Test - void givenActivityProfileContentTypeIsTextPlainWhenGettingActivityProfileThenBodyIsInstanceOfString() - throws InterruptedException { + void givenActivityProfileContentTypeIsTextPlainWhenGettingActivityProfileThenBodyIsInstanceOfString() { // Given ActivityProfile Content Type Is Text Plain mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK").setBody("Hello World!") @@ -2022,8 +2017,7 @@ void givenActivityProfileContentTypeIsTextPlainWhenGettingActivityProfileThenBod } @Test - void givenActivityProfileContentTypeIsTextPlainWhenGettingActivityProfileThenBodyIsExpected() - throws InterruptedException { + void givenActivityProfileContentTypeIsTextPlainWhenGettingActivityProfileThenBodyIsExpected() { // Given ActivityProfile Content Type Is Text Plain mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK").setBody("Hello World!") @@ -2363,7 +2357,7 @@ void givenApiResponseIsEmptyWhenGettingStatementIteratorThenMissingResponseBodyE final var response = client.getStatementIterator(); // Then MissingResponseBodyException Is Thrown - assertThrows(MissingResponseBodyException.class, () -> response.block()); + assertThrows(MissingResponseBodyException.class, response::block); } @@ -2490,8 +2484,7 @@ void whenGettingStatementIteratorAndProcessingItAsStreamThenRequestsAreExpected( } @Test - void givenEmptyStatementResultWhenGettingStatementIteratorThenHasNextIsFalse() - throws InterruptedException { + void givenEmptyStatementResultWhenGettingStatementIteratorThenHasNextIsFalse() { // Given Empty StatementResult final var body = """ @@ -2514,8 +2507,7 @@ void givenEmptyStatementResultWhenGettingStatementIteratorThenHasNextIsFalse() } @Test - void givenEmptyResponseWhenGettingStatementIteratorThenHasNextIsFalse() - throws InterruptedException { + void givenEmptyResponseWhenGettingStatementIteratorThenHasNextIsFalse() { // Given Empty Response // This response is technically invalid by the xAPI specification, but we cannot assume @@ -2535,8 +2527,7 @@ void givenEmptyResponseWhenGettingStatementIteratorThenHasNextIsFalse() } @Test - void givenEmptyResponseWhenGettingStatementIteratorThenNextThrowsAnException() - throws InterruptedException { + void givenEmptyResponseWhenGettingStatementIteratorThenNextThrowsAnException() { // Given Empty Response final var body = """ @@ -2554,7 +2545,7 @@ void givenEmptyResponseWhenGettingStatementIteratorThenNextThrowsAnException() final var iterator = client.getStatementIterator().block(); // Then Next Throws An Exception - assertThrows(NoSuchElementException.class, () -> iterator.next()); + assertThrows(NoSuchElementException.class, iterator::next); } diff --git a/xapi-client/src/test/java/dev/learning/xapi/client/configuration/XapiClientAutoConfigurationAuthorizationTest.java b/xapi-client/src/test/java/dev/learning/xapi/client/configuration/XapiClientAutoConfigurationAuthorizationTest.java index 54983f7d..d236eaca 100644 --- a/xapi-client/src/test/java/dev/learning/xapi/client/configuration/XapiClientAutoConfigurationAuthorizationTest.java +++ b/xapi-client/src/test/java/dev/learning/xapi/client/configuration/XapiClientAutoConfigurationAuthorizationTest.java @@ -47,6 +47,7 @@ public void accept(Builder builder) { try { mockWebServer.start(); } catch (final IOException e) { + // Ignore - test will fail if server doesn't start } builder.baseUrl(mockWebServer.url("").toString()); } diff --git a/xapi-client/src/test/java/dev/learning/xapi/client/configuration/XapiClientAutoConfigurationUsernamePasswordTest.java b/xapi-client/src/test/java/dev/learning/xapi/client/configuration/XapiClientAutoConfigurationUsernamePasswordTest.java index e1fa55ff..f3f20da6 100644 --- a/xapi-client/src/test/java/dev/learning/xapi/client/configuration/XapiClientAutoConfigurationUsernamePasswordTest.java +++ b/xapi-client/src/test/java/dev/learning/xapi/client/configuration/XapiClientAutoConfigurationUsernamePasswordTest.java @@ -47,6 +47,7 @@ public void accept(Builder builder) { try { mockWebServer.start(); } catch (final IOException e) { + // Ignore - test will fail if server doesn't start } builder.baseUrl(mockWebServer.url("").toString()); diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java index 52c1a361..edcee8ed 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java @@ -15,7 +15,6 @@ import dev.learning.xapi.model.validation.constraints.ValidStatementVerb; import dev.learning.xapi.model.validation.constraints.Variant; import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.lang.UnknownClassException; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; @@ -162,8 +161,8 @@ public Statement signAndBuild(PrivateKey privateKey) { claims.put("context", this.context); try { - final var token = Jwts.builder().setClaims(claims) - .signWith(privateKey, SignatureAlgorithm.RS512).compact(); + final var token = Jwts.builder().claims(claims) + .signWith(privateKey, Jwts.SIG.RS512).compact(); addAttachment(a -> a.usageType(URI.create("http://adlnet.gov/expapi/attachments/signature")) diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/AttachmentTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/AttachmentTests.java index 3b6c9a19..682910fc 100644 --- a/xapi-model/src/test/java/dev/learning/xapi/model/AttachmentTests.java +++ b/xapi-model/src/test/java/dev/learning/xapi/model/AttachmentTests.java @@ -247,8 +247,7 @@ void givenAttachmentWithStringDataWhenGettingSHA2ThenResultIsExpected() { } @Test - void givenAttachmentWithBinaryDataWhenGettingSHA2ThenResultIsExpected() - throws FileNotFoundException, IOException { + void givenAttachmentWithBinaryDataWhenGettingSHA2ThenResultIsExpected() throws IOException { final var data = Files.readAllBytes(ResourceUtils.getFile("classpath:attachment/example.jpg").toPath()); diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/ContextActivitiesTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/ContextActivitiesTests.java index 009a55fc..081475b4 100644 --- a/xapi-model/src/test/java/dev/learning/xapi/model/ContextActivitiesTests.java +++ b/xapi-model/src/test/java/dev/learning/xapi/model/ContextActivitiesTests.java @@ -202,8 +202,7 @@ void whenBuildingContextActivitiesWithTwoCategoriesThenCategoryIshasSizeTwo() { } @Test - void whenBuildingContextActivitiesWithTwoParentsWithSameIdThenParentIshasSizeTwo() - throws IOException { + void whenBuildingContextActivitiesWithTwoParentsWithSameIdThenParentIshasSizeTwo() { // When Building ContextActivities With Two Parents With Same Id final var contextActivities = ContextActivities.builder() diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java index 012d62c2..817cbb91 100644 --- a/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java +++ b/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java @@ -151,8 +151,7 @@ void givenGroupWithNameAndNoMembersWhenCallingIsAnonymousThenResultIsFalse() { } @Test - void givenGroupWithNameAndNullMembersWhenCallingIsAnonymousThenResultIsFalse() - throws IOException { + void givenGroupWithNameAndNullMembersWhenCallingIsAnonymousThenResultIsFalse() { // Given Group With Name And Null Members final Group group = Group.builder() @@ -194,8 +193,7 @@ void givenGroupWithMboxAndMembersWhenCallingIsAnonymousThenResultIsFalse() { } @Test - void givenGroupWithMboxSha1sumAndMembersWhenCallingIsAnonymousThenResultIsFalse() - throws IOException { + void givenGroupWithMboxSha1sumAndMembersWhenCallingIsAnonymousThenResultIsFalse() { // Given Group With MboxSha1sum And Members final Group group = Group.builder() diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java index 35252350..8fd165f0 100644 --- a/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java +++ b/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java @@ -759,8 +759,7 @@ void whenBuildingStatementWithTwoAttachmentsThenAttachmentsHasTwoEntries() { } @Test - void whenDeserializingStatementWithPositiveZeroHoursAndMinutesTimestampOffsetThenNoExceptionIsThrown() - throws IOException { + void whenDeserializingStatementWithPositiveZeroHoursAndMinutesTimestampOffsetThenNoExceptionIsThrown() { Assertions.assertDoesNotThrow(() -> { objectMapper.registerModule(new XapiStrictTimestampModule()).readValue(""" @@ -792,8 +791,7 @@ void whenDeserializingStatementWithPositiveZeroHoursAndMinutesTimestampOffsetThe } @Test - void whenDeserializingStatementWithPositiveFourZerosTimestampOffsetThenNoExceptionIsThrown() - throws IOException { + void whenDeserializingStatementWithPositiveFourZerosTimestampOffsetThenNoExceptionIsThrown() { Assertions.assertDoesNotThrow(() -> { objectMapper.registerModule(new XapiStrictTimestampModule()).readValue(""" @@ -824,8 +822,7 @@ void whenDeserializingStatementWithPositiveFourZerosTimestampOffsetThenNoExcepti } @Test - void whenDeserializingStatementWithPositiveTwoZerosTimestampOffsetThenNoExceptionIsThrown() - throws IOException { + void whenDeserializingStatementWithPositiveTwoZerosTimestampOffsetThenNoExceptionIsThrown() { Assertions.assertDoesNotThrow(() -> { objectMapper.registerModule(new XapiStrictTimestampModule()).readValue(""" @@ -858,8 +855,7 @@ void whenDeserializingStatementWithPositiveTwoZerosTimestampOffsetThenNoExceptio } @Test - void whenDeserializingStatementWithNegativeZeroHoursAndMinutesTimestampOffsetThenExceptionIsThrown() - throws IOException { + void whenDeserializingStatementWithNegativeZeroHoursAndMinutesTimestampOffsetThenExceptionIsThrown() { Assertions.assertThrows(ValueInstantiationException.class, () -> { objectMapper.registerModule(new XapiStrictTimestampModule()).readValue(""" @@ -891,8 +887,7 @@ void whenDeserializingStatementWithNegativeZeroHoursAndMinutesTimestampOffsetThe } @Test - void whenDeserializingStatementWithNegativeFourZerosTimestampOffsetThenExceptionIsThrown() - throws IOException { + void whenDeserializingStatementWithNegativeFourZerosTimestampOffsetThenExceptionIsThrown() { Assertions.assertThrows(ValueInstantiationException.class, () -> { objectMapper.registerModule(new XapiStrictTimestampModule()).readValue(""" @@ -923,8 +918,7 @@ void whenDeserializingStatementWithNegativeFourZerosTimestampOffsetThenException } @Test - void whenDeserializingStatementWithNegativeTwoZerosTimestampOffsetThenExceptionIsThrown() - throws IOException { + void whenDeserializingStatementWithNegativeTwoZerosTimestampOffsetThenExceptionIsThrown() { Assertions.assertThrows(ValueInstantiationException.class, () -> { objectMapper.registerModule(new XapiStrictTimestampModule()).readValue(""" @@ -957,8 +951,7 @@ void whenDeserializingStatementWithNegativeTwoZerosTimestampOffsetThenExceptionI } @Test - void whenDeserializingStatementWithoutTimestampOffsetThenNoExceptionIsThrown() - throws IOException { + void whenDeserializingStatementWithoutTimestampOffsetThenNoExceptionIsThrown() { Assertions.assertDoesNotThrow(() -> { objectMapper.registerModule(new XapiStrictTimestampModule()).readValue(""" @@ -1122,8 +1115,7 @@ void whenDeserializingStatementWithNullPropertyThenExceptionIsThrown() { } @Test - void whenDeserializingStatementWithInvalidActorObjectTypeThenExceptionIsThrown() - throws IOException { + void whenDeserializingStatementWithInvalidActorObjectTypeThenExceptionIsThrown() { Assertions.assertThrows(InvalidTypeIdException.class, () -> { objectMapper @@ -1154,8 +1146,7 @@ void whenDeserializingStatementWithInvalidActorObjectTypeThenExceptionIsThrown() } @Test - void whenDeserializingStatementWithLowercaseActivityObjectTypeThenExceptionIsThrown() - throws IOException { + void whenDeserializingStatementWithLowercaseActivityObjectTypeThenExceptionIsThrown() { Assertions.assertThrows(InvalidTypeIdException.class, () -> { objectMapper @@ -1186,8 +1177,7 @@ void whenDeserializingStatementWithLowercaseActivityObjectTypeThenExceptionIsThr } @Test - void whenDeserializingStatementWithActorWithoutObjectTypeThenNoExceptionIsThrown() - throws IOException { + void whenDeserializingStatementWithActorWithoutObjectTypeThenNoExceptionIsThrown() { Assertions.assertDoesNotThrow(() -> { objectMapper.readValue(""" @@ -1324,8 +1314,7 @@ void whenDeserializingStatementWithInvalidLocaleThenExceptionIsThrown() { } @Test - void whenDeserializingMinimalStatementWithAllTheModulesThenNoExceptionIsThrown() - throws IOException { + void whenDeserializingMinimalStatementWithAllTheModulesThenNoExceptionIsThrown() { Assertions.assertDoesNotThrow(() -> { From 16b2df65a93a9d5f798cd9f35d055ab2032c775b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 13 Nov 2025 22:42:48 +0000 Subject: [PATCH 3/3] Remove unused FileNotFoundException import from AttachmentTests Co-authored-by: thomasturrell <1552612+thomasturrell@users.noreply.github.com> --- .../src/test/java/dev/learning/xapi/model/AttachmentTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/AttachmentTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/AttachmentTests.java index 682910fc..7a2d0280 100644 --- a/xapi-model/src/test/java/dev/learning/xapi/model/AttachmentTests.java +++ b/xapi-model/src/test/java/dev/learning/xapi/model/AttachmentTests.java @@ -15,7 +15,6 @@ import jakarta.validation.ConstraintViolation; import jakarta.validation.Validation; import jakarta.validation.Validator; -import java.io.FileNotFoundException; import java.io.IOException; import java.net.URI; import java.nio.charset.StandardCharsets;