diff --git a/README.md b/README.md index 79163d2..30274ce 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # OpenAPI -[![Build Status](https://travis-ci.org/zweidenker/OpenAPI.svg?branch=master)](https://travis-ci.org/zweidenker/OpenAPI) +[![Build Status](https://github.com/zweidenker/OpenAPI/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/zweidenker/OpenAPI/actions/workflows/build.yml) diff --git a/source/OpenAPI-Core-Tests/PetsAPI.class.st b/source/OpenAPI-Core-Tests/PetsAPI.class.st index 07d4c26..1a464d2 100644 --- a/source/OpenAPI-Core-Tests/PetsAPI.class.st +++ b/source/OpenAPI-Core-Tests/PetsAPI.class.st @@ -5,11 +5,6 @@ Class { #package : 'OpenAPI-Core-Tests' } -{ #category : 'as yet unclassified' } -PetsAPI class >> rootCallClass [ - ^ OpenAPICall -] - { #category : 'accessing' } PetsAPI >> openapi [ ^ '3.0.2' diff --git a/source/OpenAPI-Core/JSONSchemaArray.extension.st b/source/OpenAPI-Core/JSONSchemaArray.extension.st index 7f7f523..706954a 100644 --- a/source/OpenAPI-Core/JSONSchemaArray.extension.st +++ b/source/OpenAPI-Core/JSONSchemaArray.extension.st @@ -1,8 +1,9 @@ Extension { #name : 'JSONSchemaArray' } { #category : '*OpenAPI-Core' } -JSONSchemaArray >> acceptOpenApi: aVisitor [ - self flag: #todo. - "should be recurse into sub elements later" +JSONSchemaArray >> acceptOpenApi: aVisitor [ + "See JSONSchemaObject>>acceptOpenApi: - same confirmed-harmless reasoning applies + (reached via OAVisitor>>visitComponents:, but only after schemas are already fully + resolved via #processSchema: earlier in the same pass)." ^ self ] diff --git a/source/OpenAPI-Core/JSONSchemaObject.extension.st b/source/OpenAPI-Core/JSONSchemaObject.extension.st index 45e2d09..33b1806 100644 --- a/source/OpenAPI-Core/JSONSchemaObject.extension.st +++ b/source/OpenAPI-Core/JSONSchemaObject.extension.st @@ -1,8 +1,14 @@ Extension { #name : 'JSONSchemaObject' } { #category : '*OpenAPI-Core' } -JSONSchemaObject >> acceptOpenApi: aVisitor [ - self flag: #todo. - "should be recurse into sub elements later" +JSONSchemaObject >> acceptOpenApi: aVisitor [ + "Confirmed reached (2026-08-01, traced): OAVisitor>>visitComponents: visits + components.schemas' values directly (self visitAll: aComponents schemas), hitting + this for every top-level named schema. But by the time that runs, those schemas are + already fully resolved - OAReferenceResolveVisitor>>visitOpenApi: converts and + resolves them via #processSchema:/JSONSchemaReferenceResolveVisitor earlier in the + very same pass, before calling super visitOpenApi: (which is what reaches here). + Recursing into sub-elements here would repeat work already done; returning self + unchanged is correct given today's call order, not a missing feature." ^ self ] diff --git a/source/OpenAPI-REST-Tests/OpenAPIRestPetTests.class.st b/source/OpenAPI-REST-Tests/OpenAPIRestPetTests.class.st index eaebb94..12f2f74 100644 --- a/source/OpenAPI-REST-Tests/OpenAPIRestPetTests.class.st +++ b/source/OpenAPI-REST-Tests/OpenAPIRestPetTests.class.st @@ -10,6 +10,24 @@ OpenAPIRestPetTests >> rootCallClass [ ^ OpenAPIBasePetCall ] +{ #category : 'tests' } +OpenAPIRestPetTests >> testGetSpecCallReturnsGeneratedDocument [ + "Regression: OpenAPICall class>>isAbstract only treated the literal OpenAPICall as + abstract (not OpenAPIBasePetCall, a shared intermediate base with no #path of its + own), and PetsAPI class>>rootCallClass answered the literal OpenAPICall instead of + its own OpenAPIBasePetCall root - together, OpenAPI>>buildPaths (via + #withAllSubclasses) tried to build a pathItem for OpenAPIBasePetCall itself, + crashing with doesNotUnderstand: #path. /spec (OpenAPISpecCall>>get calls + PetsAPI new specString) was therefore unreachable." + | response | + response := self delegate handleRequest: (ZnClient new + url: '/spec'; + method: #GET; + prepareRequest) request. + self assert: response isSuccess. + self assert: (response entity contents includesSubstring: '/pets') +] + { #category : 'tests' } OpenAPIRestPetTests >> testGetPetCall [ diff --git a/source/OpenAPI-REST-Tests/PetsAPI.extension.st b/source/OpenAPI-REST-Tests/PetsAPI.extension.st new file mode 100644 index 0000000..36f7147 --- /dev/null +++ b/source/OpenAPI-REST-Tests/PetsAPI.extension.st @@ -0,0 +1,11 @@ +Extension { #name : 'PetsAPI' } + +{ #category : '*OpenAPI-REST-Tests' } +PetsAPI class >> rootCallClass [ + "OpenAPIBasePetCall, not the literal OpenAPICall - the latter is the base of every + OpenAPICall subclass in the whole image, not just PetsAPI's own call hierarchy, + which made buildPaths (via #withAllSubclasses) pull in unrelated call classes too. + Lives as an OpenAPI-REST-Tests extension (not in PetsAPI's own OpenAPI-Core-Tests + home package) since OpenAPIBasePetCall is only defined there." + ^ OpenAPIBasePetCall +] diff --git a/source/OpenAPI-REST/OpenAPICall.class.st b/source/OpenAPI-REST/OpenAPICall.class.st index 11c0348..33afeba 100644 --- a/source/OpenAPI-REST/OpenAPICall.class.st +++ b/source/OpenAPI-REST/OpenAPICall.class.st @@ -80,7 +80,12 @@ OpenAPICall class >> implementedMethods [ { #category : 'testing' } OpenAPICall class >> isAbstract [ - ^ self = OpenAPICall + "Structural check instead of a literal-class comparison: a class is abstract for + URI-space/path-building purposes if it does not (itself or via inheritance) answer a + concrete #path - the one thing every real endpoint must define. Catches + user-defined intermediate base classes (e.g. OpenAPIBasePetCall), not just the + literal OpenAPICall root, which the previous 'self = OpenAPICall' check missed." + ^ (self respondsTo: #path) not ] { #category : 'testing' }