Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support x-examples vendor extension for requests #227

Merged
merged 4 commits into from
Mar 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ ReDoc makes use of the following [vendor extensions](http://swagger.io/specifica
* [`x-logo`](docs/redoc-vendor-extensions.md#x-logo) - is used to specify API logo
* [`x-traitTag`](docs/redoc-vendor-extensions.md#x-traitTag) - useful for handling out common things like Pagination, Rate-Limits, etc
* [`x-code-samples`](docs/redoc-vendor-extensions.md#x-code-samples) - specify operation code samples
* [`x-examples`](docs/redoc-vendor-extensions.md#x-examples) - specify JSON example for requests
* [`x-nullable`](docs/redoc-vendor-extensions.md#nullable) - mark schema param as a nullable
* [`x-displayName`](docs/redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories
* [`x-tagGroups`](docs/redoc-vendor-extensions.md#x-tagGroups) - group tags by categories in the side menu
Expand Down
11 changes: 11 additions & 0 deletions docs/redoc-vendor-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,17 @@ lang: JavaScript
source: console.log('Hello World');
```

### Parameter Object vendor extensions
Extends OpenAPI [Parameter Object](http://swagger.io/specification/#parameterObject)
#### x-examples
| Field Name | Type | Description |
| :------------- | :------: | :---------- |
| x-examples | [Example Object](http://swagger.io/specification/#exampleObject) | Object that contains examples for the request. Applies when `in` is `body` and mime-type is `application/json` |

###### Usage in ReDoc
`x-examples` are rendered in the JSON tab on the right panel of ReDoc.


### Schema Object vendor extensions
Extends OpenAPI [Schema Object](http://swagger.io/specification/#schemaObject)
#### x-nullable
Expand Down
4 changes: 2 additions & 2 deletions lib/components/ResponsesSamples/responses-samples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import { Component, Input, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { BaseComponent, SpecManager } from '../base';
import JsonPointer from '../../utils/JsonPointer';
import { statusCodeType } from '../../utils/helpers';
import { statusCodeType, getJsonLike } from '../../utils/helpers';


function isNumeric(n) {
return (!isNaN(parseFloat(n)) && isFinite(n));
}

function hasExample(response) {
return ((response.examples && response.examples['application/json']) ||
return ((response.examples && getJsonLike(response.examples)) ||
response.schema);
}

Expand Down
15 changes: 12 additions & 3 deletions lib/components/SchemaSample/schema-sample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
import { Component, ElementRef, Input, ChangeDetectionStrategy, OnInit } from '@angular/core';

import * as OpenAPISampler from 'openapi-sampler';

import JsonPointer from '../../utils/JsonPointer';
import { BaseComponent, SpecManager } from '../base';
import { SchemaNormalizer } from '../../services/schema-normalizer.service';
import { getJsonLike } from '../../utils/helpers';

@Component({
selector: 'schema-sample',
Expand Down Expand Up @@ -42,8 +43,16 @@ export class SchemaSample extends BaseComponent implements OnInit {
this.pointer += '/schema';
}

if (base.examples && base.examples['application/json']) {
sample = base.examples['application/json'];
// Support x-examples, allowing requests to specify an example.
let examplePointer:string = JsonPointer.join(JsonPointer.dirName(this.pointer), 'x-examples');
let requestExamples:any = this.specMgr.byPointer(examplePointer);
if (requestExamples) {
base.examples = requestExamples;
}

let jsonLikeSample = base.examples && getJsonLike(base.examples);
if (jsonLikeSample) {
sample = jsonLikeSample;
} else {
let selectedDescendant;

Expand Down
14 changes: 14 additions & 0 deletions lib/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,17 @@ export function snapshot(obj) {

return temp;
}

export function isJsonLike(contentType: string): boolean {
return contentType.search(/json/i) !== -1;
}

export function getJsonLike(object: object) {
const jsonLikeKeys = Object.keys(object).filter(isJsonLike);

if (!jsonLikeKeys.length) {
return false;
}

return object[jsonLikeKeys.shift()];
}
33 changes: 32 additions & 1 deletion tests/unit/helpers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

import {statusCodeType} from '../../lib/utils/helpers';
import {statusCodeType, isJsonLike, getJsonLike } from '../../lib/utils/helpers';

describe('Utils', () => {
describe('statusCodeType', () => {
it('Should return info for status codes within 100 and 200', ()=> {
Expand Down Expand Up @@ -30,4 +31,34 @@ describe('Utils', () => {
(() => statusCodeType(600)).should.throw('invalid HTTP code');
});
});

describe('isJsonLike', () => {
it('Should return true for a string that contains `json`', () => {
isJsonLike('application/json').should.be.equal(true);
});
it('Should return false for a string that does not contain `json`', () => {
isJsonLike('application/xml').should.be.equal(false);
});
});

describe('getJsonLike', () => {
it('Should return a value when a JSON-like key exists', () => {
const examples = {
"application/vnd.api+json": {
"message": "Hello World"
},
"application/xml": "<message>Hello World</message>"
};

(getJsonLike(examples).message).should.be.equal("Hello World");
});

it('Should return undefined when no JSON-like key exists', () => {
const examples = {
"application/xml": "<message>Hello World</message>"
};

getJsonLike(examples).should.be.equal(false);
});
})
});