diff --git a/src/Styles.js b/src/Styles.js index ad0b612..60dbfdb 100644 --- a/src/Styles.js +++ b/src/Styles.js @@ -254,6 +254,33 @@ export default css` color: var(--http-method-label-subscribe-color, #3490dc); } + .method-label[data-method='query'], + .method-label[data-method='QUERY'] { + background-color: var( + --http-method-label-query-background-color, + rgba(15, 157, 157, 0.12) + ); + color: var(--http-method-label-query-color, #0f9d9d); + } + + .method-label[data-method='copy'], + .method-label[data-method='COPY'] { + background-color: var( + --http-method-label-copy-background-color, + rgba(92, 107, 192, 0.12) + ); + color: var(--http-method-label-copy-color, #5c6bc0); + } + + .method-label[data-method='move'], + .method-label[data-method='MOVE'] { + background-color: var( + --http-method-label-move-background-color, + rgba(184, 134, 11, 0.12) + ); + color: var(--http-method-label-move-color, #b8860b); + } + .stream-type-badge { display: inline-block; padding: 4px 8px; diff --git a/test/api-navigation.test.js b/test/api-navigation.test.js index 8bfd053..27d0838 100644 --- a/test/api-navigation.test.js +++ b/test/api-navigation.test.js @@ -1672,4 +1672,90 @@ describe('', () => { }); }); }); + + describe('OAS 3.2 methods (QUERY, COPY, MOVE)', () => { + // OAS 3.2 introduces the QUERY, COPY and MOVE HTTP methods. AMF emits their + // `apiContract#method` value verbatim in upper case ("QUERY"), unlike the + // classic verbs which arrive lower case ("get"). The navigation renders + // `data-method` straight from that raw value, so the color override keys on + // both casings. This inline expanded model (no `@context`) keeps the test + // independent of the model generator. + const DOC = 'http://a.ml/vocabularies/document#Document'; + const ENCODES = 'http://a.ml/vocabularies/document#encodes'; + const WEBAPI = 'http://a.ml/vocabularies/apiContract#WebAPI'; + const ENDPOINT = 'http://a.ml/vocabularies/apiContract#endpoint'; + const ENDPOINT_T = 'http://a.ml/vocabularies/apiContract#EndPoint'; + const OPERATION_T = 'http://a.ml/vocabularies/apiContract#Operation'; + const SUPPORTED_OP = 'http://a.ml/vocabularies/apiContract#supportedOperation'; + const PATH = 'http://a.ml/vocabularies/apiContract#path'; + const METHOD = 'http://a.ml/vocabularies/apiContract#method'; + + function buildQueryModel() { + return { + '@type': [DOC], + [ENCODES]: [{ + '@id': 'amf://id#1', + '@type': [WEBAPI], + [ENDPOINT]: [{ + '@id': 'amf://id#10', + '@type': [ENDPOINT_T], + [PATH]: [{ '@value': '/pets' }], + [SUPPORTED_OP]: [{ + '@id': 'amf://id#11', + '@type': [OPERATION_T], + [METHOD]: [{ '@value': 'get' }], + }, { + '@id': 'amf://id#12', + '@type': [OPERATION_T], + [METHOD]: [{ '@value': 'QUERY' }], + }, { + '@id': 'amf://id#13', + '@type': [OPERATION_T], + [METHOD]: [{ '@value': 'COPY' }], + }, { + '@id': 'amf://id#14', + '@type': [OPERATION_T], + [METHOD]: [{ '@value': 'MOVE' }], + }], + }], + }], + }; + } + + let element; + + beforeEach(async () => { + element = await basicFixture(); + element.amf = buildQueryModel(); + await aTimeout(0); + await nextFrame(); + }); + + it('renders a QUERY operation with data-method="QUERY"', () => { + const labels = Array.from( + element.shadowRoot.querySelectorAll('.operation .method-label') + ); + const methods = labels.map((node) => node.getAttribute('data-method')); + assert.include(methods, 'QUERY', 'a method-label carries the raw QUERY value'); + }); + + it('keeps the raw AMF casing (does not lower-case QUERY)', () => { + const methods = Array.from( + element.shadowRoot.querySelectorAll('.operation .method-label') + ).map((node) => node.getAttribute('data-method')); + assert.notInclude(methods, 'query', 'QUERY is not silently lower-cased'); + }); + + it('does not flag a QUERY-only REST API as gRPC', () => { + assert.isFalse(element._isGrpc, 'the API is treated as REST, not gRPC'); + }); + + it('renders COPY and MOVE operations with their raw data-method', () => { + const methods = Array.from( + element.shadowRoot.querySelectorAll('.operation .method-label') + ).map((node) => node.getAttribute('data-method')); + assert.include(methods, 'COPY', 'a method-label carries the raw COPY value'); + assert.include(methods, 'MOVE', 'a method-label carries the raw MOVE value'); + }); + }); });