From 560db281f7176c69627425561e77cb2c062f8b36 Mon Sep 17 00:00:00 2001 From: Alan Richardson Date: Thu, 30 Jul 2026 14:55:58 +0100 Subject: [PATCH] Fix PATCH route documentation --- ...nfiguredWriteMethodsDocumentationTest.java | 8 +++-- .../ConfiguredWriteMethodsSwaggerTest.java | 6 ++++ .../api/docgen/WriteMethodRoutePolicy.java | 12 +++++++ .../RestApiDocumentationGeneratorTest.java | 31 +++++++++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/standAloneConfiguredWriteMethodsRestApi/src/test/java/uk/co/compendiumdev/configuredwritemethods/application/ConfiguredWriteMethodsDocumentationTest.java b/standAloneConfiguredWriteMethodsRestApi/src/test/java/uk/co/compendiumdev/configuredwritemethods/application/ConfiguredWriteMethodsDocumentationTest.java index 4564b9a2..de39c500 100644 --- a/standAloneConfiguredWriteMethodsRestApi/src/test/java/uk/co/compendiumdev/configuredwritemethods/application/ConfiguredWriteMethodsDocumentationTest.java +++ b/standAloneConfiguredWriteMethodsRestApi/src/test/java/uk/co/compendiumdev/configuredwritemethods/application/ConfiguredWriteMethodsDocumentationTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import uk.co.compendiumdev.thingifier.api.docgen.ApiRoutingDefinition; +import uk.co.compendiumdev.thingifier.api.docgen.RoutingDefinition; import uk.co.compendiumdev.thingifier.api.docgen.RoutingVerb; class ConfiguredWriteMethodsDocumentationTest { @@ -39,9 +40,12 @@ void blocksPutAndPatchOnTheCollectionRoute() { @Test void exposesPatchAndPutUpdateOnTheInstanceRoute() { final ApiRoutingDefinition definition = documentation(); + final RoutingDefinition patchRoute = route(definition, RoutingVerb.PATCH, "notes/:id"); - Assertions.assertTrue( - route(definition, RoutingVerb.PATCH, "notes/:id").status().isReturnedFromCall()); + Assertions.assertTrue(patchRoute.status().isReturnedFromCall()); + Assertions.assertEquals( + "patch a specific instance of note with a body containing the patch details", + patchRoute.getDocumentation()); Assertions.assertTrue( route(definition, RoutingVerb.PUT, "notes/:id").status().isReturnedFromCall()); } diff --git a/standAloneConfiguredWriteMethodsRestApi/src/test/java/uk/co/compendiumdev/configuredwritemethods/application/ConfiguredWriteMethodsSwaggerTest.java b/standAloneConfiguredWriteMethodsRestApi/src/test/java/uk/co/compendiumdev/configuredwritemethods/application/ConfiguredWriteMethodsSwaggerTest.java index 2cd70c34..d40a5715 100644 --- a/standAloneConfiguredWriteMethodsRestApi/src/test/java/uk/co/compendiumdev/configuredwritemethods/application/ConfiguredWriteMethodsSwaggerTest.java +++ b/standAloneConfiguredWriteMethodsRestApi/src/test/java/uk/co/compendiumdev/configuredwritemethods/application/ConfiguredWriteMethodsSwaggerTest.java @@ -30,6 +30,12 @@ void exposesPatchAndPutUpdateOnlyOnTheInstanceRoute() { Assertions.assertNull(instance.getPost()); Assertions.assertNotNull(instance.getPatch()); Assertions.assertNotNull(instance.getPut()); + Assertions.assertEquals( + "patch a specific instance of note with a body containing the patch details", + instance.getPatch().getSummary()); + Assertions.assertEquals( + "patch a specific instance of note with a body containing the patch details", + instance.getPatch().getDescription()); } @Test diff --git a/thingifier/src/main/java/uk/co/compendiumdev/thingifier/api/docgen/WriteMethodRoutePolicy.java b/thingifier/src/main/java/uk/co/compendiumdev/thingifier/api/docgen/WriteMethodRoutePolicy.java index 63df248b..e27a5628 100644 --- a/thingifier/src/main/java/uk/co/compendiumdev/thingifier/api/docgen/WriteMethodRoutePolicy.java +++ b/thingifier/src/main/java/uk/co/compendiumdev/thingifier/api/docgen/WriteMethodRoutePolicy.java @@ -122,6 +122,11 @@ private void returnedEntityWriteRoute( ensureStatus(route, 409); route.returnPayload(200, entityName); route.requestPayload(entityName); + replaceMethodNotAllowedDocumentation( + route, + String.format( + "patch a specific instance of %s with a body containing the patch details", + entityName)); } private void returnedEntityPutRoute( @@ -198,6 +203,13 @@ private void methodNotAllowed(final RoutingDefinition route) { route.replaceStatus(RoutingStatus.returnValue(405)); } + private void replaceMethodNotAllowedDocumentation( + final RoutingDefinition route, final String documentation) { + if ("method not allowed".equals(route.getDocumentation())) { + route.addDocumentation(documentation); + } + } + private void ensureStatus(final RoutingDefinition route, final int statusCode) { for (RoutingStatus status : route.getPossibleStatusReponses()) { if (status.value() == statusCode) { diff --git a/thingifier/src/test/java/uk/co/compendiumdev/thingifier/htmlgui/htmlgen/RestApiDocumentationGeneratorTest.java b/thingifier/src/test/java/uk/co/compendiumdev/thingifier/htmlgui/htmlgen/RestApiDocumentationGeneratorTest.java index 4f06e0aa..ab64e252 100644 --- a/thingifier/src/test/java/uk/co/compendiumdev/thingifier/htmlgui/htmlgen/RestApiDocumentationGeneratorTest.java +++ b/thingifier/src/test/java/uk/co/compendiumdev/thingifier/htmlgui/htmlgen/RestApiDocumentationGeneratorTest.java @@ -1,5 +1,7 @@ package uk.co.compendiumdev.thingifier.htmlgui.htmlgen; +import static uk.co.compendiumdev.thingifier.apiconfig.EntityPatchUpdateStyle.PARTIAL_JSON_UPDATE; + import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -98,6 +100,35 @@ void apiDocumentationShowsEntityDescriptions() { + "
  • Value must be a Boolean (true, false) value
  • ")); } + @Test + void apiDocumentationShowsConfiguredPatchInstanceRouteAsSupported() { + final Thingifier thingifier = new Thingifier(); + thingifier.setDocumentation("Task API", "Task API docs."); + final EntityDefinition task = thingifier.defineThing("task", "tasks"); + task.addAsPrimaryKeyField(Field.is("id", FieldType.AUTO_INCREMENT)); + task.addField(Field.is("title", FieldType.STRING)); + thingifier.apiConfig().writeMethods().entities().patchCan(PARTIAL_JSON_UPDATE); + + final String docs = + new RestApiDocumentationGenerator(thingifier, new DefaultGUIHTML()) + .getApiDocumentation( + new ApiRoutingDefinitionDocGenerator(thingifier).generate("/api"), + List.of(), + new ThingifierApiDocumentationDefn(), + "/api", + "https://example.com/api/docs"); + + Assertions.assertTrue(docs.contains("PATCH /api/tasks/:id")); + Assertions.assertTrue( + docs.contains( + "patch a specific instance of task with a body containing the patch" + + " details")); + Assertions.assertFalse( + docs.contains( + "PATCH /api/tasks/:id")); + } + @Test void apiDocumentationShowsTwoWayRelationshipsAsSeparateDirections() { final Thingifier thingifier = new Thingifier();