Skip to content

Commit 1497c17

Browse files
Fix message schema rendering for Subscribe operations (#35)
* chore(model): add APIC-582 API * chore(deps): regenerate package-lock.json * test(api-url): fix test after AMF bug fix * fix: message schema not being shown for subscribe operation For AsyncAPI, only return or expects is defined Always set the message object to the expects node Do not render response section for AsyncAPI * test: ensure message schema is rendered as body document * 5.1.10 * chore: remove unused _getMessagesTemplate method
1 parent d461729 commit 1497c17

File tree

7 files changed

+1719
-1651
lines changed

7 files changed

+1719
-1651
lines changed

demo/APIC-582/APIC-582.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
asyncapi: 2.0.0
2+
info:
3+
title: Account service
4+
version: 1.0.0
5+
description: This service is in charge of processing user signups
6+
channels:
7+
user/signedup:
8+
subscribe:
9+
message:
10+
$ref: '#/components/messages/UserSignedUp'
11+
components:
12+
messages:
13+
UserSignedUp:
14+
payload:
15+
type: object
16+
properties:
17+
displayName:
18+
type: string
19+
description: Name of the user
20+
email:
21+
type: string
22+
format: email
23+
description: Email of user

demo/apis.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
"multi-server/multi-server.yaml": { "type": "OAS 3.0", "mime": "application/yaml" },
1313
"async-api/async-api.yaml": "ASYNC 2.0",
1414
"APIC-553/APIC-553.raml": "RAML 1.0",
15-
"APIC-560/APIC-560.yaml": "ASYNC 2.0"
15+
"APIC-560/APIC-560.yaml": "ASYNC 2.0",
16+
"APIC-582/APIC-582.yaml": "ASYNC 2.0"
1617
}

package-lock.json

Lines changed: 1615 additions & 1632 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@api-components/api-method-documentation",
33
"description": "A HTTP method documentation build from AMF model",
4-
"version": "5.1.9",
4+
"version": "5.1.10",
55
"license": "Apache-2.0",
66
"main": "index.js",
77
"module": "index.js",

src/ApiMethodDocumentation.js

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,10 @@ export class ApiMethodDocumentation extends AmfHelperMixin(LitElement) {
321321
return this.endpointUri + this._computeMethodParametersUri(this.method);
322322
}
323323

324+
get message() {
325+
return this._getMessageForMethod(this.methodName);
326+
}
327+
324328
constructor() {
325329
super();
326330
this.callbacksOpened = false;
@@ -376,6 +380,9 @@ export class ApiMethodDocumentation extends AmfHelperMixin(LitElement) {
376380
this.hasCustomProperties = this._computeHasCustomProperties(method);
377381
this.expects = this._computeExpects(method);
378382
this.returns = this._computeReturns(method);
383+
if (this._isAsyncAPI(this.amf)) {
384+
this._overwriteExpects();
385+
}
379386
this.security = this._computeSecurity(method) || this._computeSecurity(this.server);
380387
const extendsTypes = this._computeExtends(method);
381388
this.extendsTypes = extendsTypes;
@@ -385,6 +392,14 @@ export class ApiMethodDocumentation extends AmfHelperMixin(LitElement) {
385392
this.callbacks = this._computeCallbacks(method);
386393
}
387394

395+
_overwriteExpects() {
396+
let expects = this.message;
397+
if (Array.isArray(expects)) {
398+
[expects] = expects;
399+
}
400+
this.expects = expects;
401+
}
402+
388403
_processEndpointChange() {
389404
this.__endpointProcessingDebouncer = false;
390405
this._processServerInfo();
@@ -733,14 +748,7 @@ export class ApiMethodDocumentation extends AmfHelperMixin(LitElement) {
733748
${this._getTraitsTemplate()}
734749
${hasCustomProperties ? html`<api-annotation-document .shape="${method}"></api-annotation-document>` : ''}
735750
${this._getDescriptionTemplate()}
736-
<section class="request-documentation">
737-
${this._getCodeSnippetsTemplate()}
738-
${this._getSecurityTemplate()}
739-
${this._getParametersTemplate()}
740-
${this._getHeadersTemplate()}
741-
${this._getBodyTemplate()}
742-
${this._callbacksTemplate()}
743-
</section>
751+
${this._getRequestTemplate()}
744752
${this._getReturnsTemplate()}
745753
${this._getNavigationTemplate()}`;
746754
}
@@ -955,9 +963,20 @@ export class ApiMethodDocumentation extends AmfHelperMixin(LitElement) {
955963
.body="${payload}"></api-body-document>`;
956964
}
957965

966+
_getRequestTemplate() {
967+
return html`<section class="request-documentation">
968+
${this._getCodeSnippetsTemplate()}
969+
${this._getSecurityTemplate()}
970+
${this._getParametersTemplate()}
971+
${this._getHeadersTemplate()}
972+
${this._getBodyTemplate()}
973+
${this._callbacksTemplate()}
974+
</section>`
975+
}
976+
958977
_getReturnsTemplate() {
959978
const { returns } = this;
960-
if (!returns || !returns.length) {
979+
if (!returns || !returns.length || this._isAsyncAPI(this.amf)) {
961980
return '';
962981
}
963982
const {
@@ -1135,6 +1154,27 @@ export class ApiMethodDocumentation extends AmfHelperMixin(LitElement) {
11351154
return undefined;
11361155
}
11371156

1157+
/**
1158+
* Returns message value depending on operation node method
1159+
* Subscribe -> returns
1160+
* Publish -> expects
1161+
* `undefined` otherwise
1162+
* @param {String} method Operation method
1163+
*/
1164+
_getMessageForMethod(method) {
1165+
if (!method) {
1166+
return undefined;
1167+
}
1168+
switch(method.toLowerCase()) {
1169+
case 'subscribe':
1170+
return this.returns;
1171+
case 'publish':
1172+
return this.expects;
1173+
default:
1174+
return undefined;
1175+
}
1176+
}
1177+
11381178
/**
11391179
* Dispatched when the user requested the "Try it" view.
11401180
* @event tryit-requested

test/api-method-documentation.test.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ describe('<api-method-documentation>', () => {
282282
const callbacksApi = 'oas-callbacks';
283283
const asyncApi = 'async-api';
284284
const apic553 = 'APIC-553';
285+
const apic582 = 'APIC-582';
285286

286287
describe('Basic AMF computations', () => {
287288
let amf;
@@ -888,7 +889,27 @@ describe('<api-method-documentation>', () => {
888889
assert.equal(newLocal.url, 'http://domain.org/cmt-with-qp-example?orx=foo');
889890
});
890891
});
891-
})
892+
});
893+
894+
describe('APIC-582', () => {
895+
let amf;
896+
let element;
897+
898+
before(async () => {
899+
amf = await AmfLoader.load(apic582, compact);
900+
});
901+
902+
beforeEach(async () => {
903+
const [endpoint, method] = AmfLoader.lookupEndpointOperation(amf, 'user/signedup', 'subscribe');
904+
element = await modelFixture(amf, endpoint, method);
905+
await nextFrame();
906+
});
907+
908+
it('should render channel message in request documentation section', async () => {
909+
await waitUntil(() => !!element.shadowRoot.querySelector('.request-documentation'), 'request documentation section not rendered');
910+
await waitUntil(() => !!element.shadowRoot.querySelector('api-body-document'), 'api-body-document not rendered');
911+
});
912+
});
892913
});
893914
});
894915
});

test/api-url.test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { fixture, assert, nextFrame, html, waitUntil } from '@open-wc/testing';
22
import { AmfLoader } from './amf-loader.js';
33
import '../api-url.js';
44

5-
describe('<api-url>', function () {
5+
describe('<api-url>', () => {
66
async function basicFixture() {
77
return fixture(`<api-url></api-url>`);
88
}
@@ -50,7 +50,7 @@ describe('<api-url>', function () {
5050
element.amf = amf;
5151
server = AmfLoader.getEncodes(amf)[element._getAmfKey(element.ns.aml.vocabularies.apiContract.server)];
5252
if (Array.isArray(server)) {
53-
server = server[0];
53+
[server] = server;
5454
}
5555
element = await operationFixture({ amf, endpoint, operation, server });
5656
// model change debouncer
@@ -100,7 +100,7 @@ describe('<api-url>', function () {
100100
element.amf = amf;
101101
server = AmfLoader.getEncodes(amf)[element._getAmfKey(element.ns.aml.vocabularies.apiContract.server)];
102102
if (Array.isArray(server)) {
103-
server = server[0];
103+
[server] = server;
104104
}
105105
element = await operationFixture({ amf, endpoint, operation, server });
106106
// model change debouncer
@@ -131,12 +131,12 @@ describe('<api-url>', function () {
131131

132132
beforeEach(async () => {
133133
const endpointName = 'smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured'
134-
const [endpoint, operation] = AmfLoader.lookupEndpointOperation(amf, endpointName, 'kafka');
134+
const [endpoint, operation] = AmfLoader.lookupEndpointOperation(amf, endpointName, 'subscribe');
135135
element = await basicFixture();
136136
element.amf = amf;
137137
server = AmfLoader.getEncodes(amf)[element._getAmfKey(element.ns.aml.vocabularies.apiContract.server)];
138138
if (Array.isArray(server)) {
139-
server = server[0];
139+
[server] = server;
140140
}
141141
element = await operationFixture({ amf, endpoint, operation, server });
142142
// model change debouncer
@@ -150,9 +150,9 @@ describe('<api-url>', function () {
150150
});
151151

152152
it('should render server', async () => {
153-
const server = 'Servermqtt://api.streetlights.smartylighting.com:{port}'
153+
const expectedServer = 'Servermqtt://api.streetlights.smartylighting.com:{port}'
154154
await waitUntil(() => element.shadowRoot.querySelector('.url-server-value'));
155-
assert.equal(element.shadowRoot.querySelector('.url-server-value').textContent, server);
155+
assert.equal(element.shadowRoot.querySelector('.url-server-value').textContent, expectedServer);
156156
});
157157

158158
it('should only render url value when no operation selected', async () => {

0 commit comments

Comments
 (0)