diff --git a/solid/src/test/java/com/inrupt/client/solid/SolidClientTest.java b/solid/src/test/java/com/inrupt/client/solid/SolidClientTest.java index 775a86d3253..0536702e1aa 100644 --- a/solid/src/test/java/com/inrupt/client/solid/SolidClientTest.java +++ b/solid/src/test/java/com/inrupt/client/solid/SolidClientTest.java @@ -129,6 +129,21 @@ void testCustomHeaders() throws Exception { }).toCompletableFuture().join(); } + @Test + void testJsonResource() { + final URI uri = URI.create(config.get("solid_resource_uri") + "/transaction"); + client.read(uri, Transaction.class).thenAccept(transaction -> { + try (final Transaction t = transaction) { + assertEquals("sample description", t.getDescription()); + assertEquals(TransactionType.CREDIT, t.getType()); + final var err = assertThrows(CompletionException.class, client.update(t).toCompletableFuture()::join); + assertTrue(err.getCause() instanceof ForbiddenException); + t.setType(TransactionType.DEBIT); + t.setDescription("different description"); + assertDoesNotThrow(client.update(t).toCompletableFuture()::join); + } + }).toCompletableFuture().join(); + } @Test void testGetPlaylist() throws IOException, InterruptedException { diff --git a/solid/src/test/java/com/inrupt/client/solid/SolidMockHttpService.java b/solid/src/test/java/com/inrupt/client/solid/SolidMockHttpService.java index 6871eff5053..7c22febfd2f 100644 --- a/solid/src/test/java/com/inrupt/client/solid/SolidMockHttpService.java +++ b/solid/src/test/java/com/inrupt/client/solid/SolidMockHttpService.java @@ -216,6 +216,26 @@ private void setupMocks() { .willReturn(aResponse() .withStatus(204))); + wireMockServer.stubFor(get(urlEqualTo("/transaction")) + .withHeader("User-Agent", equalTo(USER_AGENT)) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", "application/json") + .withBodyFile("transaction.json"))); + + wireMockServer.stubFor(put(urlEqualTo("/transaction")) + .withHeader("User-Agent", equalTo(USER_AGENT)) + .withRequestBody(containing("DEBIT")) + .withRequestBody(containing("different description")) + .willReturn(aResponse() + .withStatus(204))); + + wireMockServer.stubFor(put(urlEqualTo("/transaction")) + .withHeader("User-Agent", equalTo(USER_AGENT)) + .withRequestBody(containing("CREDIT")) + .willReturn(aResponse() + .withStatus(403))); + wireMockServer.stubFor(get(urlEqualTo("/binary")) .atPriority(1) .withHeader("User-Agent", equalTo(USER_AGENT)) diff --git a/solid/src/test/java/com/inrupt/client/solid/Transaction.java b/solid/src/test/java/com/inrupt/client/solid/Transaction.java new file mode 100644 index 00000000000..7e7c805e08d --- /dev/null +++ b/solid/src/test/java/com/inrupt/client/solid/Transaction.java @@ -0,0 +1,105 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.spi.JsonService; +import com.inrupt.client.spi.ServiceProvider; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.net.URI; +import java.time.Instant; + +class Transaction extends SolidNonRDFSource { + + private final JsonService jsonService; + private final TransactionData data; + + public Transaction(final URI identifier, final String contentType, final InputStream entity) { + super(identifier, contentType, entity); + + this.jsonService = ServiceProvider.getJsonService(); + try { + this.data = jsonService.fromJson(super.getEntity(), TransactionData.class); + } catch (IOException ex) { + throw new UncheckedIOException("Unable to parse Transaction data", ex); + } + } + + public String getId() { + return data.getId(); + } + + public void setId(final String id) { + data.setId(id); + } + + public String getDescription() { + return data.getDescription(); + } + + public void setDescription(final String description) { + data.setDescription(description); + } + + public Instant getDate() { + return data.getDate(); + } + + public void setDate(final Instant date) { + data.setDate(date); + } + + public double getAmount() { + return data.getAmount(); + } + + public void setAmount(final double amount) { + data.setAmount(amount); + } + + public String getCategory() { + return data.getCategory(); + } + + public void setCategory(final String category) { + data.setCategory(category); + } + + public TransactionType getType() { + return data.getType(); + } + + public void setType(final TransactionType type) { + data.setType(type); + } + + @Override + public InputStream getEntity() throws IOException { + try (final ByteArrayOutputStream output = new ByteArrayOutputStream()) { + jsonService.toJson(data, output); + return new ByteArrayInputStream(output.toByteArray()); + } + } +} diff --git a/solid/src/test/java/com/inrupt/client/solid/TransactionData.java b/solid/src/test/java/com/inrupt/client/solid/TransactionData.java new file mode 100644 index 00000000000..9f8b551724d --- /dev/null +++ b/solid/src/test/java/com/inrupt/client/solid/TransactionData.java @@ -0,0 +1,81 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import java.time.Instant; + +class TransactionData { + + private String id; + private String description; + private Instant date; + private double amount; + private TransactionType type; + private String category; + + public String getId() { + return id; + } + + public void setId(final String id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + public Instant getDate() { + return date; + } + + public void setDate(final Instant date) { + this.date = date; + } + + public double getAmount() { + return amount; + } + + public void setAmount(final double amount) { + this.amount = amount; + } + + public TransactionType getType() { + return type; + } + + public void setType(final TransactionType type) { + this.type = type; + } + + public String getCategory() { + return category; + } + + public void setCategory(final String category) { + this.category = category; + } +} diff --git a/solid/src/test/java/com/inrupt/client/solid/TransactionType.java b/solid/src/test/java/com/inrupt/client/solid/TransactionType.java new file mode 100644 index 00000000000..ec9e2c29f17 --- /dev/null +++ b/solid/src/test/java/com/inrupt/client/solid/TransactionType.java @@ -0,0 +1,25 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +enum TransactionType { + CREDIT, DEBIT +} diff --git a/solid/src/test/resources/__files/transaction.json b/solid/src/test/resources/__files/transaction.json new file mode 100644 index 00000000000..39841a6cfe9 --- /dev/null +++ b/solid/src/test/resources/__files/transaction.json @@ -0,0 +1,8 @@ +{ + "id": "testid", + "date": "2025-09-28T15:37:00Z", + "description": "sample description", + "amount": 20.12, + "type": "CREDIT", + "category": "groceries" +}