diff --git a/components/Channels.js b/components/Channels.js deleted file mode 100644 index f17b224d8..000000000 --- a/components/Channels.js +++ /dev/null @@ -1,94 +0,0 @@ -import { Text } from "@asyncapi/generator-react-sdk"; -import { SchemaHelpers } from "../helpers/schema"; - -import { Header } from "./common"; -import { Message } from "./Message"; -import { Schema } from "./Schema"; - -export function Channels({ asyncapi }) { - const channels = Object.entries(asyncapi.channels()).map(([channelName, channel]) => ( - - )); - - return ( - <> -
- Channels -
- {channels} - - ); -} - -function Channel({ channelName, channel }) { - return ( - -
- {`**${channelName}** Channel`} -
- {channel.hasDescription() && ( - - {channel.description()} - - )} - {channel.hasParameters() && ( - - )} - {channel.hasPublish() && ( - - )} - {channel.hasSubscribe() && ( - - )} -
- ); -} - -function Parameters({ parameters }) { - const parametersSchema = SchemaHelpers.parametersToSchema(parameters); - return ( - -
Channel Parameters
- -
- ); -} - -function OperationMessages({ messages }) { - return ( - <> - {messages.length > 1 && - - Accepts **one of** the following messages: - - } - {messages.map(msg => ( - - )) - } - - ) -} - -function Operation({ operation }) { - const type = operation.isPublish() ? 'publish' : 'subscribe'; - const hasMessages = operation.hasMultipleMessages() || !!operation.message(0); - return ( - -
{`\`${type}\` Operation`}
- {operation.summary() && ( - - *{operation.summary()}* - - )} - {operation.hasDescription() && ( - - {operation.description()} - - )} - {hasMessages && ( - - )} -
- ); -} diff --git a/components/Info.js b/components/Info.js index 5c0000592..8cd77f5e2 100644 --- a/components/Info.js +++ b/components/Info.js @@ -112,9 +112,10 @@ export function Info({ asyncapi, params = {} }) { )} {asyncapi.hasTags() && ( - + <> +
Specification tags
-
+ )} ); diff --git a/components/Message.js b/components/Message.js index 2d3478663..4e52bd236 100644 --- a/components/Message.js +++ b/components/Message.js @@ -1,44 +1,105 @@ -import { Text } from "@asyncapi/generator-react-sdk"; +import { IndentationTypes, Text } from "@asyncapi/generator-react-sdk"; import { generateExample, getPayloadExamples, getHeadersExamples } from "@asyncapi/generator-filters"; import { Schema } from "./Schema"; import { Tags } from "./Tags"; -import { Header, CodeBlock, BlockQuote } from "./common"; +import { Header, ListItem, Link, BlockQuote, CodeBlock, NewLine } from "./common"; + +export function Message({ message }) { + if (!message) { + return null; + } + + const headers = message.headers(); + const payload = message.payload(); + const correlationId = message.correlationId(); + const contentType = message.contentType(); + const externalDocs = message.externalDocs(); + const showInfoList = contentType || externalDocs; + + let header = `Message`; + if (message.title()) { + header += ` ${message.title()}` + } + if (message.uid()) { + header += ` \`${message.uid()}\`` + } -export function Message({ message, title = 'Message' }) { return ( <> -
{title}
+
{header}
+ {message.summary() && ( *{message.summary()}* )} + + {showInfoList ? ( + + {contentType && ( + + Content type:{' '} + + {contentType} + + + )} + {correlationId && ( + <> + + Correlation ID: `{correlationId.location()}` + + {correlationId.hasDescription() && ( + <> + + + {correlationId.description()} + + + )} + + )} + + ) : null} + {message.hasDescription() && ( {message.description()} )} - {message.headers() && ( + {externalDocs && ( + + + {externalDocs.hasDescription() ? externalDocs.description() : 'Find more info here.'} + + + )} + + {headers && ( <> -
Headers
- +
Headers
+ )} - {message.payload() && ( + {payload && ( <> -
Payload
- +
Payload
+ )} {message.hasTags() && ( <> -
Tags
+
Message tags
)} @@ -95,7 +156,7 @@ function Example({ examples = [] }) { return examples.map(ex => ( - {ex.name && **{ex.name}**} + {ex.name && _{ex.name}_} {ex.summary && {ex.summary}} {JSON.stringify(ex.example, null, 2)} diff --git a/components/Operations.js b/components/Operations.js new file mode 100644 index 000000000..736ff9b42 --- /dev/null +++ b/components/Operations.js @@ -0,0 +1,159 @@ +import { Text } from "@asyncapi/generator-react-sdk"; + +import { Message } from "./Message"; +import { Schema } from "./Schema"; +import { Tags } from "./Tags"; +import { Header, ListItem, Link } from "./common"; + +import { SchemaHelpers } from "../helpers/schema"; +import { FormatHelpers } from "../helpers/format"; + +export function Operations({ asyncapi }) { + const channels = asyncapi.channels(); + if (!Object.keys(channels).length) { + return null; + } + + const operationsList = []; + Object.entries(channels).forEach(([channelName, channel]) => { + if (channel.hasPublish()) { + operationsList.push( + + ); + } + if (channel.hasSubscribe()) { + operationsList.push( + + ); + } + }); + + return ( + <> +
+ Operations +
+ {operationsList} + + ); +} + +function Operation({ type, operation, channelName, channel }) { + if (!operation || !channel) { + return null; + } + + const operationId = operation.id(); + const externalDocs = operation.externalDocs(); + // check typeof as fallback for older version than `2.2.0` + const servers = typeof channel.servers === 'function' && channel.servers(); + const renderedType = type === 'publish' ? 'PUB' : 'SUB'; + const showInfoList = operationId || (servers && servers.length); + + return ( + +
+ {`${renderedType} \`${channelName}\` Operation`} +
+ + {operation.summary() && ( + + *{operation.summary()}* + + )} + + {showInfoList ? ( + + {operationId && Operation ID: `{operationId}`} + {servers && servers.length && ( + + Available only on servers:{' '} + {servers.map(s => { + const slug = FormatHelpers.slugify(s); + return `[${s}](#${slug}-server)`; + }).join(', ')} + + )} + + ) : null} + + {channel.hasDescription() && ( + + {channel.description()} + + )} + {operation.hasDescription() && ( + + {operation.description()} + + )} + + {externalDocs && ( + + + {externalDocs.hasDescription() ? externalDocs.description() : 'Find more info here.'} + + + )} + + {operation.hasTags() && ( + <> +
Operation tags
+ + + )} + + + +
+ ); +} + +function OperationParameters({ channel }) { + const parameters = SchemaHelpers.parametersToSchema(channel.parameters()); + if (!parameters) { + return null; + } + + return ( + +
Parameters
+ +
+ ); +} + +function OperationMessages({ operation }) { + const hasMessages = operation.hasMultipleMessages() || !!operation.message(0); + if (!hasMessages) { + return null; + } + const messages = operation.messages(); + + return ( + <> + {messages.length > 1 && ( + + Accepts **one of** the following messages: + + )} + {messages.map(msg => ( + + ))} + + ); +} diff --git a/components/Schema.js b/components/Schema.js index cea6c28db..eba2e1b78 100644 --- a/components/Schema.js +++ b/components/Schema.js @@ -8,7 +8,7 @@ export function Schema({ schema, schemaName, hideTitle = false }) { const headers = ['Name', 'Type', 'Description', 'Value', 'Constraints', 'Notes']; return ( - {hideTitle === false ?
{schemaName}
: null} + {schemaName && hideTitle === false ?
{schemaName}
: null} @@ -301,6 +301,12 @@ function schemaNotes({ schema, required = false, dependentRequired = [], isCircu notes.push(`**required when defined (${dependentRequired.map(v => `\`${v}\``).join(', ')})**`); } + // location for channel parameter + const parameterLocation = schema.ext(SchemaHelpers.extParameterLocation); + if (parameterLocation) { + notes.push(`**parameter location (${parameterLocation})**`); + } + if (isCircular) notes.push('**circular**'); if (schema.writeOnly()) notes.push('**write-only**'); if (schema.readOnly()) notes.push('**read-only**'); diff --git a/components/TableOfContents.js b/components/TableOfContents.js index e2a3b0ddd..ef9ae38e6 100644 --- a/components/TableOfContents.js +++ b/components/TableOfContents.js @@ -2,24 +2,38 @@ import { Text, Indent, IndentationTypes } from "@asyncapi/generator-react-sdk"; import { Header, Link, ListItem } from "../components/common"; +import { FormatHelpers } from "../helpers/format"; + export function TableOfContents({ asyncapi }) { const serversList = Object.keys(asyncapi.servers()).map(serverName => { return ( - {serverName} + {serverName} ); }); - const channelsList = Object.keys(asyncapi.channels()).map(channelName => { - return ( - - - {channelName} - - - ); + const operationsList = []; + Object.entries(asyncapi.channels()).map(([channelName, channel]) => { + if (channel.hasPublish()) { + operationsList.push( + + + PUB {channelName} + + + ); + } + if (channel.hasSubscribe()) { + operationsList.push( + + + SUB {channelName} + + + ); + } }); return ( @@ -34,52 +48,11 @@ export function TableOfContents({ asyncapi }) { {serversList.length > 0 && serversList} {asyncapi.hasChannels() && - Channels + Operations } - {channelsList.length > 0 && channelsList} + {operationsList.length > 0 && operationsList}
); } - -/** - * Slugify (change value to appropriate hash) the url part of a markdown link. - * - * @param {String} `str` The string to slugify - * @return {String} - */ -function slugify(str) { - str = getTitle(str); - str = str.toLowerCase(); - - // `split(...).join(...)` is faster than `replace(..., ...)` - // for spaces - str = str.split(' ').join('-'); - // for tabs - str = str.split(/\t/).join('--'); - // for html tags - str = str.split(/<\/?[^>]{1,100}>/).join(''); - // for special characters from ASCII (part 1) - str = str.split(/[|$&`~=\\\/@+*!?({[\]})<>.,;:'"^]/).join(''); - // for special characters from ASCII (part 2) - str = str.split(/[。?!,、;:【】()〔〕[]﹃﹄“ ”‘’﹁﹂—…-~《》〈〉「」]/).join(''); - - return str; -} - -/** - * Get the "title" from a markdown link - * - * @param {String} `str` The string to retrieve title - * @return {String} - */ -function getTitle(str) { - // check if in `str` is "title" from a markdown link (use `(` char at the end for easy markdown link checking) - if (/^\[[^\]]+\]\(/.test(str)) { - // retrieve "title" from a markdown link - var m = /^\[([^\]]+)\]/.exec(str); - if (m) return m[1]; - } - return str; -} diff --git a/helpers/format.js b/helpers/format.js index ffb12693f..c1806d39d 100644 --- a/helpers/format.js +++ b/helpers/format.js @@ -1,4 +1,10 @@ export class FormatHelpers { + /** + * Wrap input string to markdown's inline code + * + * @param {String} `value` The string to wrap + * @return {String} + */ static inlineCode(value) { if ( value === null || @@ -9,4 +15,45 @@ export class FormatHelpers { ) return ''; return `\`${value}\``; } + + /** + * Slugify (change value to appropriate hash) the url part of a markdown link. + * + * @param {String} `str` The string to slugify + * @return {String} + */ + static slugify(str) { + str = this.getTitle(str); + str = str.toLowerCase(); + + // `split(...).join(...)` is faster than `replace(..., ...)` + // for spaces + str = str.split(' ').join('-'); + // for tabs + str = str.split(/\t/).join('--'); + // for html tags + str = str.split(/<\/?[^>]{1,100}>/).join(''); + // for special characters from ASCII (part 1) + str = str.split(/[|$&`~=\\\/@+*!?({[\]})<>.,;:'"^]/).join(''); + // for special characters from ASCII (part 2) + str = str.split(/[。?!,、;:【】()〔〕[]﹃﹄“ ”‘’﹁﹂—…-~《》〈〉「」]/).join(''); + + return str; + } + + /** + * Get the "title" from a markdown link + * + * @param {String} `str` The string to retrieve title + * @return {String} + */ + static getTitle(str) { + // check if in `str` is "title" from a markdown link (use `(` char at the end for easy markdown link checking) + if (/^\[[^\]]+\]\(/.test(str)) { + // retrieve "title" from a markdown link + var m = /^\[([^\]]+)\]/.exec(str); + if (m) return m[1]; + } + return str; + } } diff --git a/helpers/schema.js b/helpers/schema.js index 5d1e0206b..af2d0ae62 100644 --- a/helpers/schema.js +++ b/helpers/schema.js @@ -55,6 +55,7 @@ export class SchemaHelpers { static extRenderType = 'x-schema-private-render-type'; static extRenderAdditionalInfo = 'x-schema-private-render-additional-info'; static extRawValue = 'x-schema-private-raw-value'; + static extParameterLocation = 'x-schema-private-parameter-location'; static toSchemaType(schema) { if (!schema || typeof schema.json !== 'function') { @@ -207,6 +208,7 @@ export class SchemaHelpers { obj[paramaterName] = Object.assign({}, parameter.schema().json()); obj[paramaterName].description = parameter.description() || obj[paramaterName].description; + obj[paramaterName][this.extParameterLocation] = parameter.location(); return obj; }, {}, diff --git a/template/asyncapi.js b/template/asyncapi.js index 70a15034b..9e36bce15 100644 --- a/template/asyncapi.js +++ b/template/asyncapi.js @@ -2,7 +2,7 @@ import { File } from "@asyncapi/generator-react-sdk"; import { Info } from "../components/Info"; import { Servers } from "../components/Servers"; -import { Channels } from "../components/Channels"; +import { Operations } from "../components/Operations"; import { FrontMatter } from "../components/FrontMatter"; import { TableOfContents } from "../components/TableOfContents"; @@ -14,7 +14,7 @@ export default function({ asyncapi, params = {} }) { {params.toc !== 'false' && } - + ); } diff --git a/test/components/Info.test.js b/test/components/Info.test.js index 45d8991d1..6c4feb644 100644 --- a/test/components/Info.test.js +++ b/test/components/Info.test.js @@ -76,6 +76,8 @@ The Smartylighting Streetlights API allows you to remotely manage the city light * Dim a specific streetlight 😎 * Receive real-time information about environmental lighting conditions 📈 +###### Specification tags + * root-tag1 [External docs description 1](https://www.asyncapi.com/) diff --git a/test/components/Message.test.js b/test/components/Message.test.js new file mode 100644 index 000000000..52ef6d10a --- /dev/null +++ b/test/components/Message.test.js @@ -0,0 +1,340 @@ +import { render } from '@asyncapi/generator-react-sdk'; + +import { Message } from "../../components/Message"; +import MessageModel from '@asyncapi/parser/lib/models/message'; + +describe('Message component', () => { + it('should render simple message', () => { + const message = new MessageModel({ + "title": "User signup", + "name": "UserSignup", + "summary": "Action to sign a user up.", + "headers": { + "type": "object", + "properties": { + "correlationId": { + "description": "Correlation ID set by application", + "type": "string" + }, + "applicationInstanceId": { + "description": "Unique identifier for a given instance of the publishing application", + "type": "string" + } + } + }, + "payload": { + "type": "object", + "properties": { + "user": { + "type": "string" + }, + "signup": { + "type": "string" + } + } + }, + }); + const expected = ` +#### Message User signup \`UserSignup\` + +*Action to sign a user up.* + +##### Headers + +| Name | Type | Description | Value | Constraints | Notes | +|---|---|---|---|---|---| +| (root) | object | - | - | - | **additional properties are allowed** | +| correlationId | string | Correlation ID set by application | - | - | - | +| applicationInstanceId | string | Unique identifier for a given instance of the publishing application | - | - | - | + +> Examples of headers _(generated)_ + +\`\`\`json +{ + "correlationId": "string", + "applicationInstanceId": "string" +} +\`\`\` + + +##### Payload + +| Name | Type | Description | Value | Constraints | Notes | +|---|---|---|---|---|---| +| (root) | object | - | - | - | **additional properties are allowed** | +| user | string | - | - | - | - | +| signup | string | - | - | - | - | + +> Examples of payload _(generated)_ + +\`\`\`json +{ + "user": "string", + "signup": "string" +} +\`\`\` +`; + + const result = render(); + expect(result.trim()).toEqual(expected.trim()); + }); + + it('should render complete message', () => { + const message = new MessageModel({ + "name": "UserSignup", + "title": "User signup", + "summary": "Action to sign a user up.", + "description": "A longer description", + "contentType": "application/json", + "tags": [ + { "name": "user" }, + { "name": "signup" }, + { "name": "register" } + ], + "headers": { + "type": "object", + "properties": { + "correlationId": { + "description": "Correlation ID set by application", + "type": "string" + }, + "applicationInstanceId": { + "description": "Unique identifier for a given instance of the publishing application", + "type": "string" + } + } + }, + "payload": { + "type": "object", + "properties": { + "user": { + "type": "string" + }, + "signup": { + "type": "string" + } + } + }, + "correlationId": { + "description": "Default Correlation ID", + "location": "$message.header#/correlationId" + }, + "examples": [ + { + "name": "SimpleSignup", + "summary": "A simple UserSignup example message", + "headers": { + "correlationId": "my-correlation-id", + "applicationInstanceId": "myInstanceId" + }, + "payload": { + "user": { + "someUserKey": "someUserValue" + }, + "signup": { + "someSignupKey": "someSignupValue" + } + } + } + ] + }); + const expected = ` +#### Message User signup \`UserSignup\` + +*Action to sign a user up.* + +* Content type: [application/json](https://www.iana.org/assignments/media-types/application/json) +* Correlation ID: \`$message.header#/correlationId\` + + Default Correlation ID + +A longer description + +##### Headers + +| Name | Type | Description | Value | Constraints | Notes | +|---|---|---|---|---|---| +| (root) | object | - | - | - | **additional properties are allowed** | +| correlationId | string | Correlation ID set by application | - | - | - | +| applicationInstanceId | string | Unique identifier for a given instance of the publishing application | - | - | - | + +> Examples of headers + +_SimpleSignup_ + +A simple UserSignup example message + +\`\`\`json +{ + "correlationId": "my-correlation-id", + "applicationInstanceId": "myInstanceId" +} +\`\`\` + + +##### Payload + +| Name | Type | Description | Value | Constraints | Notes | +|---|---|---|---|---|---| +| (root) | object | - | - | - | **additional properties are allowed** | +| user | string | - | - | - | - | +| signup | string | - | - | - | - | + +> Examples of payload + +_SimpleSignup_ + +A simple UserSignup example message + +\`\`\`json +{ + "user": { + "someUserKey": "someUserValue" + }, + "signup": { + "someSignupKey": "someSignupValue" + } +} +\`\`\` + + +###### Message tags + +* user + +* signup + +* register +`; + + const result = render(); + expect(result.trim()).toEqual(expected.trim()); + }); + + it('should render multiple messages', () => { + const message = new MessageModel({ + "name": "UserSignup", + "title": "User signup", + "headers": { + "type": "object", + }, + "payload": { + "type": "object", + }, + "examples": [ + { + "name": "SimpleSignup", + "summary": "A simple UserSignup example message", + "headers": { + "correlationId": "my-correlation-id", + "applicationInstanceId": "myInstanceId" + }, + "payload": { + "user": { + "someUserKey": "someUserValue" + }, + "signup": { + "someSignupKey": "someSignupValue" + } + } + }, + { + "name": "ExtendedSimpleSignup", + "summary": "A simple ExtendedSimpleSignup example message", + "headers": { + "correlationId": "my-correlation-id", + }, + "payload": { + "user": { + "someUserKey": "foobar" + }, + "signup": { + "someSignupKey": "barfoo" + } + } + } + ] + }); + const expected = ` +#### Message User signup \`UserSignup\` + +##### Headers + +| Name | Type | Description | Value | Constraints | Notes | +|---|---|---|---|---|---| +| (root) | object | - | - | - | **additional properties are allowed** | + +> Examples of headers + +_SimpleSignup_ + +A simple UserSignup example message + +\`\`\`json +{ + "correlationId": "my-correlation-id", + "applicationInstanceId": "myInstanceId" +} +\`\`\` + + +_ExtendedSimpleSignup_ + +A simple ExtendedSimpleSignup example message + +\`\`\`json +{ + "correlationId": "my-correlation-id" +} +\`\`\` + + +##### Payload + +| Name | Type | Description | Value | Constraints | Notes | +|---|---|---|---|---|---| +| (root) | object | - | - | - | **additional properties are allowed** | + +> Examples of payload + +_SimpleSignup_ + +A simple UserSignup example message + +\`\`\`json +{ + "user": { + "someUserKey": "someUserValue" + }, + "signup": { + "someSignupKey": "someSignupValue" + } +} +\`\`\` + + +_ExtendedSimpleSignup_ + +A simple ExtendedSimpleSignup example message + +\`\`\`json +{ + "user": { + "someUserKey": "foobar" + }, + "signup": { + "someSignupKey": "barfoo" + } +} +\`\`\` +`; + + const result = render(); + expect(result.trim()).toEqual(expected.trim()); + }); + + it('should render nothing if message prop is undefined', () => { + const result = render(); + expect(result).toEqual(''); + }); +}); diff --git a/test/components/Operations.test.js b/test/components/Operations.test.js new file mode 100644 index 000000000..86fce8488 --- /dev/null +++ b/test/components/Operations.test.js @@ -0,0 +1,225 @@ +import { render } from '@asyncapi/generator-react-sdk'; + +import { Operations } from "../../components/Operations"; +import AsyncAPIDocument from '@asyncapi/parser/lib/models/asyncapi'; + +describe('Operations component', () => { + it('should render operation', () => { + const asyncapi = new AsyncAPIDocument({ + "channels": { + "user/signedup": { + "description": "This channel is used to exchange messages about users signing up", + "servers": [ + "rabbitmqBrokerInProd", + "rabbitmqBrokerInStaging", + ], + "subscribe": { + "operationId": "signedupuser", + "externalDocs": { + "description": "More info here", + "url": "https://example.com" + }, + "tags": [ + { "name": "user" }, + { "name": "signup" }, + { "name": "register" } + ], + "summary": "A user signed up.", + "message": { + "description": "A longer description of the message", + "payload": { + "type": "object", + "properties": { + "user": { + "type": "string" + }, + "signup": { + "type": "number" + } + } + } + } + }, + }, + }, + }); + const expected = ` +## Operations + +### SUB \`user/signedup\` Operation + +*A user signed up.* + +* Operation ID: \`signedupuser\` +* Available only on servers: [rabbitmqBrokerInProd](#rabbitmqbrokerinprod-server), [rabbitmqBrokerInStaging](#rabbitmqbrokerinstaging-server) + +This channel is used to exchange messages about users signing up + +[More info here](https://example.com) + +###### Operation tags + +* user + +* signup + +* register + +#### Message \`\` + +A longer description of the message + +##### Payload + +| Name | Type | Description | Value | Constraints | Notes | +|---|---|---|---|---|---| +| (root) | object | - | - | - | **additional properties are allowed** | +| user | string | - | - | - | - | +| signup | number | - | - | - | - | + +> Examples of payload _(generated)_ + +\`\`\`json +{ + "user": "string", + "signup": 0 +} +\`\`\` +`; + + const result = render(); + expect(result.trim()).toEqual(expected.trim()); + }); + + it('should render parameters for operation', () => { + const asyncapi = new AsyncAPIDocument({ + "channels": { + "user/{userId}/signup/{foobar}": { + "parameters": { + "userId": { + "description": "Id of the user.", + "schema": { + "type": "string" + }, + "location": "$message.payload#/user/id" + }, + "foobar": { + "schema": { + "type": "string" + }, + } + }, + "publish": {} + } + }, + }); + const expected = ` +## Operations + +### PUB \`user/{userId}/signup/{foobar}\` Operation + +#### Parameters + +| Name | Type | Description | Value | Constraints | Notes | +|---|---|---|---|---|---| +| userId | string | Id of the user. | - | - | **required**, **parameter location ($message.payload#/user/id)** | +| foobar | string | - | - | - | **required** | +`; + + const result = render(); + expect(result.trim()).toEqual(expected.trim()); + }); + + it('should render multiple messages', () => { + const asyncapi = new AsyncAPIDocument({ + "channels": { + "user/{userId}/signup/{foobar}": { + "publish": { + "message": { + "oneOf": [ + { + "description": "A longer description of the message", + "payload": { + "type": "object", + "properties": { + "signup": { + "type": "number" + } + } + } + }, + { + "description": "A longer description of the message", + "payload": { + "type": "object", + "properties": { + "user": { + "type": "string" + }, + } + } + }, + ] + } + } + } + }, + }); + const expected = ` +## Operations + +### PUB \`user/{userId}/signup/{foobar}\` Operation + +Accepts **one of** the following messages: + +#### Message \`\` + +A longer description of the message + +##### Payload + +| Name | Type | Description | Value | Constraints | Notes | +|---|---|---|---|---|---| +| (root) | object | - | - | - | **additional properties are allowed** | +| signup | number | - | - | - | - | + +> Examples of payload _(generated)_ + +\`\`\`json +{ + "signup": 0 +} +\`\`\` + + +#### Message \`\` + +A longer description of the message + +##### Payload + +| Name | Type | Description | Value | Constraints | Notes | +|---|---|---|---|---|---| +| (root) | object | - | - | - | **additional properties are allowed** | +| user | string | - | - | - | - | + +> Examples of payload _(generated)_ + +\`\`\`json +{ + "user": "string" +} +\`\`\` +`; + + const result = render(); + expect(result.trim()).toEqual(expected.trim()); + }); + + it('should render nothing if operations prop is undefined', () => { + const asyncapi = new AsyncAPIDocument({}); + + const result = render(); + expect(result).toEqual(''); + }); +}); diff --git a/test/components/TableOfContents.test.js b/test/components/TableOfContents.test.js index 6f20ce83a..0991e414f 100644 --- a/test/components/TableOfContents.test.js +++ b/test/components/TableOfContents.test.js @@ -12,8 +12,16 @@ describe('TableOfContents component', () => { canary: {}, }, channels: { - testChannel: {}, - 'smartylighting/streetlights/1/0': {}, + testChannel: { + publish: {}, + subscribe: {}, + }, + 'smartylighting/streetlights/1/0': { + subscribe: {}, + }, + 'smartylighting/streetlights': { + publish: {}, + }, }, }); const expected = ` @@ -23,9 +31,11 @@ describe('TableOfContents component', () => { * [production](#production-server) * [testing](#testing-server) * [canary](#canary-server) -* [Channels](#channels) - * [testChannel](#testchannel-channel) - * [smartylighting/streetlights/1/0](#smartylightingstreetlights10-channel) +* [Operations](#operations) + * [PUB testChannel](#pub-testchannel-operation) + * [SUB testChannel](#sub-testchannel-operation) + * [SUB smartylighting/streetlights/1/0](#sub-smartylightingstreetlights10-operation) + * [PUB smartylighting/streetlights](#pub-smartylightingstreetlights-operation) `; const result = render(); diff --git a/test/helpers/schema.test.js b/test/helpers/schema.test.js index 02b471286..38faca16c 100644 --- a/test/helpers/schema.test.js +++ b/test/helpers/schema.test.js @@ -325,10 +325,12 @@ describe('SchemaHelpers', () => { foo: { type: 'string', description: undefined, + "x-schema-private-parameter-location": undefined }, bar: { type: 'string', description: 'Some description', + "x-schema-private-parameter-location": "$message.payload#/user/id" }, }, required: ['foo', 'bar'],