Merge commit 'a2beb2432dc62f48b23a6f1c7487d0b3a31b3b19' into releases

This commit is contained in:
RedocBot 2016-07-01 15:44:33 +00:00 committed by travis@localhost
commit e26aa7834c
38 changed files with 356 additions and 503 deletions

View File

@ -39,7 +39,6 @@ module.exports = function (config) {
//load angular dependencies and browser polyfills //load angular dependencies and browser polyfills
files: [ files: [
'node_modules/zone.js/dist/zone.js', 'node_modules/zone.js/dist/zone.js',
'node_modules/zone.js/dist/fake-async-test.js',
'node_modules/zone.js/dist/async-test.js', 'node_modules/zone.js/dist/async-test.js',
'node_modules/zone.js/dist/jasmine-patch.js', 'node_modules/zone.js/dist/jasmine-patch.js',
'node_modules/zone.js/dist/long-stack-trace-zone.js', 'node_modules/zone.js/dist/long-stack-trace-zone.js',

View File

@ -1,47 +1,32 @@
'use strict'; 'use strict';
import { getChildDebugElement } from '../../../tests/helpers'; import { getChildDebugElement } from '../../../tests/helpers';
import { Component, provide } from '@angular/core'; import { Component } from '@angular/core';
import { import {
inject, inject,
async, async,
expect, TestComponentBuilder
beforeEach,
beforeEachProviders,
it
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { ApiInfo } from './api-info'; import { ApiInfo } from './api-info';
import { SpecManager } from '../../utils/SpecManager'; import { SpecManager } from '../../utils/SpecManager';
import { OptionsService } from '../../services/index';
describe('Redoc components', () => { describe('Redoc components', () => {
describe('ApiInfo Component', () => { describe('ApiInfo Component', () => {
let builder; let builder;
let component; let component;
let fixture; let fixture;
beforeEachProviders(() => [
provide(SpecManager, {useValue: new SpecManager()}),
provide(OptionsService, {useClass: OptionsService})
]);
beforeEach(async(inject([TestComponentBuilder, SpecManager], (tcb, specMgr) => { beforeEach(async(inject([TestComponentBuilder, SpecManager], (tcb, specMgr) => {
builder = tcb; builder = tcb;
return specMgr.load('/tests/schemas/api-info-test.json'); return specMgr.load('/tests/schemas/api-info-test.json');
}))); })));
beforeEach((done) => { beforeEach(() => {
builder.createAsync(TestAppComponent).then(_fixture => { fixture = builder.createSync(TestAppComponent);
fixture = _fixture; component = getChildDebugElement(fixture.debugElement, 'api-info').componentInstance;
component = getChildDebugElement(fixture.debugElement, 'api-info').componentInstance; fixture.detectChanges();
fixture.detectChanges();
done();
}, err => {
done.fail(err);
});
}); });
@ -54,7 +39,7 @@ describe('Redoc components', () => {
it('should render api name and version', () => { it('should render api name and version', () => {
let nativeElement = getChildDebugElement(fixture.debugElement, 'api-info').nativeElement; let nativeElement = getChildDebugElement(fixture.debugElement, 'api-info').nativeElement;
let headerElement = nativeElement.querySelector('h1'); let headerElement = nativeElement.querySelector('h1');
expect(headerElement).toHaveText('Swagger Petstore (1.0.0)'); expect(headerElement.innerText).toContain('Swagger Petstore (v1.0.0)');
}); });
}); });
}); });

View File

@ -18,5 +18,8 @@ export class ApiInfo extends BaseComponent {
prepareModel() { prepareModel() {
this.data = this.componentSchema.info; this.data = this.componentSchema.info;
this.specUrl = this.optionsService.options.specUrl; this.specUrl = this.optionsService.options.specUrl;
if (parseInt(this.data.version.substring(0, 1)) !== NaN) {
this.data.version = 'v' + this.data.version;
}
} }
} }

View File

@ -1,18 +1,14 @@
'use strict'; 'use strict';
import { getChildDebugElement } from '../../../tests/helpers'; import { getChildDebugElement } from '../../../tests/helpers';
import {Component, provide} from '@angular/core'; import { Component } from '@angular/core';
import { import {
inject, inject,
async, async,
beforeEach, TestComponentBuilder
beforeEachProviders,
it
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { ApiLogo } from './api-logo'; import { ApiLogo } from './api-logo';
import { SpecManager } from '../../utils/SpecManager'; import { SpecManager } from '../../utils/SpecManager';
@ -25,21 +21,15 @@ describe('Redoc components', () => {
let specMgr; let specMgr;
let schemaUrl = '/tests/schemas/api-info-test.json'; let schemaUrl = '/tests/schemas/api-info-test.json';
beforeEachProviders(() => [
provide(SpecManager, {useValue: new SpecManager()})
]);
beforeEach(async(inject([TestComponentBuilder, SpecManager], (tcb, _specMgr) => { beforeEach(async(inject([TestComponentBuilder, SpecManager], (tcb, _specMgr) => {
builder = tcb; builder = tcb;
specMgr = _specMgr; specMgr = _specMgr;
return specMgr.load(schemaUrl); return specMgr.load(schemaUrl);
}))); })));
beforeEach((done) => { beforeEach(() => {
builder.createAsync(TestAppComponent).then(_fixture => { fixture = builder.createSync(TestAppComponent);
fixture = _fixture; component = getChildDebugElement(fixture.debugElement, 'api-logo').componentInstance;
component = getChildDebugElement(fixture.debugElement, 'api-logo').componentInstance; fixture.detectChanges();
fixture.detectChanges();
done();
}, err => done.fail(err));
}); });

View File

@ -87,6 +87,11 @@ $sub-schema-offset: ($bullet-size/2) + $bullet-margin;
display: inline-block; display: inline-block;
} }
.param-type-file {
font-weight: bold;
text-transform: capitalize;
}
/* tree */ /* tree */
// Bullet // Bullet

View File

@ -1,41 +1,33 @@
'use strict'; 'use strict';
import { getChildDebugElement } from '../../../tests/helpers'; import { getChildDebugElement } from '../../../tests/helpers';
import { Component, provide } from '@angular/core'; import { Component } from '@angular/core';
import { import {
inject, inject,
beforeEach, TestComponentBuilder
beforeEachProviders,
it
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { JsonSchemaLazy } from './json-schema-lazy'; import { JsonSchemaLazy } from './json-schema-lazy';
import { SpecManager } from '../../utils/SpecManager';
describe('Redoc components', () => { describe('Redoc components', () => {
describe('JsonSchemaLazy Component', () => { describe('JsonSchemaLazy Component', () => {
let builder; let builder;
let component; let component;
let specMgr = new SpecManager();
let fixture; let fixture;
beforeEachProviders(() => [
provide(SpecManager, {useValue: specMgr}) beforeEach(inject([TestComponentBuilder], (tcb) => {
]);
beforeEach(inject([TestComponentBuilder], (tcb, dcl) => {
builder = tcb; builder = tcb;
})); }));
beforeEach((done) => { beforeEach(() => {
builder.createAsync(TestAppComponent).then(_fixture => { fixture = builder.createSync(TestAppComponent);
fixture = _fixture; let debugEl = getChildDebugElement(fixture.debugElement, 'json-schema-lazy');
let debugEl = getChildDebugElement(fixture.debugElement, 'json-schema-lazy'); component = <JsonSchemaLazy>debugEl.componentInstance;
component = <JsonSchemaLazy>debugEl.componentInstance; spyOn(component, '_loadAfterSelf').and.stub();
spyOn(component, '_loadAfterSelf').and.callThrough(); });
done();
}, err => done.fail(err)); afterEach(() => {
component._loadAfterSelf.and.callThrough();
}); });
it('should init component', () => { it('should init component', () => {

View File

@ -1,10 +1,14 @@
<span *ngIf="schema.isFile" class="param-wrap"> <span *ngIf="schema.isFile" class="param-wrap">
<span class="param-file">file</span> <span class="param-type-file">file</span>
<div *ngIf="schema._produces && !isRequestSchema" class="file produces"> <div *ngIf="schema._produces && !isRequestSchema" class="file produces">
Produces: {{ schema._produces | json }} <ul>
<li *ngFor="let type of schema._produces">{{type}}</li>
</ul>
</div> </div>
<div *ngIf="schema._consumes && isRequestSchema" class="file consume"> <div *ngIf="schema._consumes && isRequestSchema" class="file consume">
Consumes: {{ schema._consumes | json }} <ul>
<li *ngFor="let type of schema._consumes">{{type}}</li>
</ul>
</div> </div>
</span> </span>
<span *ngIf="schema.isTrivial && !schema.isFile" class="param-wrap"> <span *ngIf="schema.isTrivial && !schema.isFile" class="param-wrap">

View File

@ -180,31 +180,16 @@ $array-marker-line-height: 1.5;
} }
} }
ul { ul, li {
text-align: left;
margin: 0; margin: 0;
padding: 0;
display: block;
} }
li { ul {
margin: 0.5em 0.3em 0.2em 0; list-style: none;
font-family: $headers-font, $headers-font-family; padding-left: 1em;
font-size: .929em; }
line-height: .929em;
border: 0; li:before {
color: white; content: "- ";
padding: 2px 8px 4px 8px; font-weight: bold;
border-radius: $border-radius;
background-color: rgba($black, 0.3);
display: inline-block;
cursor: pointer;
&:last-of-type {
margin-right: 0;
}
&.active {
background-color: $primary-color;
}
} }

View File

@ -1,13 +1,10 @@
'use strict'; 'use strict';
import { Component, provide } from '@angular/core'; import { Component } from '@angular/core';
import { import {
inject, inject,
beforeEach, TestComponentBuilder
beforeEachProviders,
it
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { getChildDebugElement } from '../../../tests/helpers'; import { getChildDebugElement } from '../../../tests/helpers';
@ -19,21 +16,17 @@ describe('Redoc components', () => {
describe('JsonSchema Component', () => { describe('JsonSchema Component', () => {
let builder; let builder;
let component; let component;
let specMgr = new SpecManager();
let fixture; let fixture;
beforeEachProviders(() => [ let specMgr;
provide(SpecManager, {useValue: specMgr})
]); beforeEach(inject([TestComponentBuilder, SpecManager], (tcb, _spec) => {
beforeEach(inject([TestComponentBuilder], (tcb) => {
builder = tcb; builder = tcb;
specMgr = _spec;
})); }));
beforeEach((done) => { beforeEach(() => {
builder.createAsync(TestAppComponent).then(_fixture => { fixture = builder.createSync(TestAppComponent);
fixture = _fixture; let debugEl = getChildDebugElement(fixture.debugElement, 'json-schema');
let debugEl = getChildDebugElement(fixture.debugElement, 'json-schema'); component = debugEl.componentInstance;
component = debugEl.componentInstance;
done();
}, err => done.fail(err));
}); });
it('should init component', () => { it('should init component', () => {

View File

@ -1,7 +1,7 @@
<div class="method"> <div class="method">
<div class="method-content"> <div class="method-content">
<h2 class="method-header sharable-header"> <h2 class="method-header sharable-header">
<a class="share-link" href="#{{data.methodAnchor}}"></a>{{data.methodInfo.summary}} <a class="share-link" href="#{{data.methodAnchor}}"></a>{{data.summary}}
</h2> </h2>
<div class="method-tags" *ngIf="data.methodInfo.tags.length"> <div class="method-tags" *ngIf="data.methodInfo.tags.length">
<a *ngFor="let tag of data.methodInfo.tags" attr.href="#{{tag}}"> {{tag}} </a> <a *ngFor="let tag of data.methodInfo.tags" attr.href="#{{tag}}"> {{tag}} </a>

View File

@ -38,7 +38,7 @@ responses-list, params-list {
} }
.api-url { .api-url {
color: rgba(#ffffff, .8); color: rgba(#ffffff, .6);
margin-left: 10px; margin-left: 10px;
margin-top: 2px; margin-top: 2px;
position: relative; position: relative;

View File

@ -1,14 +1,11 @@
'use strict'; 'use strict';
import { Component, provide } from '@angular/core'; import { Component } from '@angular/core';
import { import {
inject, inject,
async, async,
beforeEach, TestComponentBuilder
beforeEachProviders,
it
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { getChildDebugElement } from '../../../tests/helpers'; import { getChildDebugElement } from '../../../tests/helpers';
@ -19,19 +16,16 @@ describe('Redoc components', () => {
describe('Method Component', () => { describe('Method Component', () => {
let builder; let builder;
let component; let component;
beforeEachProviders(() => [
provide(SpecManager, {useValue: new SpecManager()})
]);
beforeEach(async(inject([TestComponentBuilder, SpecManager], (tcb, specMgr) => { beforeEach(async(inject([TestComponentBuilder, SpecManager], (tcb, specMgr) => {
builder = tcb; builder = tcb;
return specMgr.load('/tests/schemas/extended-petstore.yml'); return specMgr.load('/tests/schemas/extended-petstore.yml');
}))); })));
beforeEach((done) => {
builder.createAsync(TestAppComponent).then(fixture => { beforeEach(() => {
component = getChildDebugElement(fixture.debugElement, 'method').componentInstance; let fixture = builder.createSync(TestAppComponent);
fixture.detectChanges(); component = getChildDebugElement(fixture.debugElement, 'method').componentInstance;
done(); fixture.detectChanges();
}, err => done.fail(err));
}); });

View File

@ -8,6 +8,7 @@ import { ResponsesList } from '../ResponsesList/responses-list';
import { ResponsesSamples } from '../ResponsesSamples/responses-samples'; import { ResponsesSamples } from '../ResponsesSamples/responses-samples';
import { SchemaSample } from '../SchemaSample/schema-sample'; import { SchemaSample } from '../SchemaSample/schema-sample';
import { RequestSamples } from '../RequestSamples/request-samples'; import { RequestSamples } from '../RequestSamples/request-samples';
import { SchemaHelper } from '../../services/schema-helper.service';
@RedocComponent({ @RedocComponent({
selector: 'method', selector: 'method',
@ -31,6 +32,7 @@ export class Method extends BaseComponent {
this.data.methodInfo = this.componentSchema; this.data.methodInfo = this.componentSchema;
this.data.methodInfo.tags = this.filterMainTags(this.data.methodInfo.tags); this.data.methodInfo.tags = this.filterMainTags(this.data.methodInfo.tags);
this.data.bodyParam = this.findBodyParam(); this.data.bodyParam = this.findBodyParam();
this.data.summary = SchemaHelper.methodSummary(this.componentSchema);
if (this.componentSchema.operationId) { if (this.componentSchema.operationId) {
this.data.methodAnchor = 'operation/' + encodeURIComponent(this.componentSchema.operationId); this.data.methodAnchor = 'operation/' + encodeURIComponent(this.componentSchema.operationId);
} else { } else {

View File

@ -1,6 +1,6 @@
<div class="methods"> <div class="methods">
<div class="tag" *ngFor="let tag of data.tags"> <div class="tag" *ngFor="let tag of data.tags;trackBy:trackByTagName">
<div class="tag-info" [attr.tag]="tag.name"> <div class="tag-info" [attr.tag]="tag.name" *ngIf="!tag.empty">
<h1 class="sharable-header"> <a class="share-link" href="#tag/{{tag.name | encodeURIComponent}}"></a>{{tag.name}} </h1> <h1 class="sharable-header"> <a class="share-link" href="#tag/{{tag.name | encodeURIComponent}}"></a>{{tag.name}} </h1>
<p *ngIf="tag.description" [innerHtml]="tag.description | marked"> </p> <p *ngIf="tag.description" [innerHtml]="tag.description | marked"> </p>
</div> </div>

View File

@ -1,14 +1,11 @@
'use strict'; 'use strict';
import { Component, provide } from '@angular/core'; import { Component } from '@angular/core';
import { import {
inject, inject,
async, async,
beforeEach, TestComponentBuilder
beforeEachProviders,
it
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { getChildDebugElement } from '../../../tests/helpers'; import { getChildDebugElement } from '../../../tests/helpers';
@ -21,20 +18,15 @@ describe('Redoc components', () => {
let builder; let builder;
let component; let component;
let fixture; let fixture;
beforeEachProviders(() => [
provide(SpecManager, {useValue: new SpecManager()})
]);
beforeEach(async(inject([TestComponentBuilder, SpecManager], (tcb, specMgr) => { beforeEach(async(inject([TestComponentBuilder, SpecManager], (tcb, specMgr) => {
builder = tcb; builder = tcb;
return specMgr.load('/tests/schemas/methods-list-component.json'); return specMgr.load('/tests/schemas/methods-list-component.json');
}))); })));
beforeEach((done) => { beforeEach(() => {
builder.createAsync(TestAppComponent).then(_fixture => { fixture = builder.createSync(TestAppComponent);
fixture = _fixture; component = getChildDebugElement(fixture.debugElement, 'methods-list').componentInstance;
component = getChildDebugElement(fixture.debugElement, 'methods-list').componentInstance; fixture.detectChanges();
fixture.detectChanges();
done();
}, err => done.fail(err) );
}); });

View File

@ -4,6 +4,7 @@ import { forwardRef } from '@angular/core';
import { RedocComponent, BaseComponent, SpecManager } from '../base'; import { RedocComponent, BaseComponent, SpecManager } from '../base';
import { Method } from '../Method/method'; import { Method } from '../Method/method';
import { EncodeURIComponentPipe } from '../../utils/pipes'; import { EncodeURIComponentPipe } from '../../utils/pipes';
import { SchemaHelper } from '../../services/index';
@RedocComponent({ @RedocComponent({
selector: 'methods-list', selector: 'methods-list',
@ -24,21 +25,14 @@ export class MethodsList extends BaseComponent {
// follow SwaggerUI behavior for cases when one method has more than one tag: // follow SwaggerUI behavior for cases when one method has more than one tag:
// duplicate methods // duplicate methods
let menuStructure = this.specMgr.buildMenuTree(); let tags = SchemaHelper.buildMenuTree(this.specMgr.schema);
let tags = Array.from<any>(menuStructure.entries()) tags.forEach(tagInfo => {
.map((entry) => { // inject tag name into method info
let [tag, {description, methods}] = entry; tagInfo.methods = tagInfo.methods || [];
// inject tag name into method info tagInfo.methods.forEach(method => {
methods = methods || []; method.tag = tagInfo.name;
methods.forEach(method => {
method.tag = tag;
});
return {
name: tag,
description: description,
methods: methods
};
}); });
});
this.data.tags = tags; this.data.tags = tags;
// TODO: check $ref field // TODO: check $ref field
} }
@ -46,4 +40,8 @@ export class MethodsList extends BaseComponent {
trackByPointer(idx, el) { trackByPointer(idx, el) {
return el.pointer; return el.pointer;
} }
trackByTagName(idx, el) {
return el.name;
}
} }

View File

@ -1,15 +1,12 @@
'use strict'; 'use strict';
import { getChildDebugElement } from '../../../tests/helpers'; import { getChildDebugElement } from '../../../tests/helpers';
import { Component, provide, ComponentRef } from '@angular/core'; import { Component, ComponentRef } from '@angular/core';
import { BrowserDomAdapter } from '@angular/platform-browser/src/browser/browser_adapter'; import { BrowserDomAdapter } from '@angular/platform-browser/src/browser/browser_adapter';
import { import {
inject, inject,
async, async
beforeEach,
beforeEachProviders,
it
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing'; import { TestComponentBuilder } from '@angular/compiler/testing';
@ -24,40 +21,27 @@ describe('Redoc components', () => {
describe('Redoc Component', () => { describe('Redoc Component', () => {
let builder; let builder;
let specMgr; let specMgr;
beforeEachProviders(() => [
provide(SpecManager, {useValue: new SpecManager()}),
]);
beforeEach(async(inject([TestComponentBuilder, SpecManager, OptionsService], beforeEach(async(inject([TestComponentBuilder, SpecManager, OptionsService],
(tcb, _specMgr, _optsMgr) => { (tcb, _specMgr, _optsMgr) => {
optsMgr = _optsMgr; optsMgr = _optsMgr;
builder = tcb; builder = tcb;
specMgr = _specMgr; specMgr = _specMgr;
return specMgr.load('/tests/schemas/extended-petstore.yml');
}))); })));
beforeEach((done) => {
return specMgr.load('/tests/schemas/extended-petstore.yml') it('should init component', () => {
.then(() => done()) let fixture = builder.createSync(TestAppComponent);
.catch(err => done.fail(err)); let component = getChildDebugElement(fixture.debugElement, 'redoc').componentInstance;
expect(component).not.toBeNull();
fixture.destroy();
}); });
it('should init components tree without errors', () => {
it('should init component', (done) => { let fixture = builder.createSync(TestAppComponent);
builder.createAsync(TestAppComponent).then(fixture => { (() => fixture.detectChanges()).should.not.throw();
let component = getChildDebugElement(fixture.debugElement, 'redoc').componentInstance; fixture.destroy();
expect(component).not.toBeNull();
fixture.destroy();
done();
}, err => done.fail(err));
});
it('should init components tree without errors', (done) => {
builder.createAsync(TestAppComponent).then(fixture => {
(() => fixture.detectChanges()).should.not.throw();
fixture.destroy();
done();
}, err => {
return done.fail(err);
});
}); });
}); });
@ -74,7 +58,7 @@ describe('Redoc components', () => {
}); });
it('should return promise', () => { it('should return promise', () => {
let res = Redoc.init(); let res = Redoc.init().catch(() => {/**/});
res.should.be.instanceof(Promise); res.should.be.instanceof(Promise);
}); });
@ -82,7 +66,7 @@ describe('Redoc components', () => {
spyOn(Redoc, 'hideLoadingAnimation').and.callThrough(); spyOn(Redoc, 'hideLoadingAnimation').and.callThrough();
spyOn(Redoc, 'displayError').and.callThrough(); spyOn(Redoc, 'displayError').and.callThrough();
let res = Redoc.init(); let res = Redoc.init();
return res.then(() => { return res.catch(() => {
expect(Redoc.hideLoadingAnimation).toHaveBeenCalled(); expect(Redoc.hideLoadingAnimation).toHaveBeenCalled();
expect(Redoc.displayError).toHaveBeenCalled(); expect(Redoc.displayError).toHaveBeenCalled();
}); });
@ -103,29 +87,25 @@ describe('Redoc components', () => {
let builder; let builder;
let fixture; let fixture;
let element; let element;
let dom;
let destroySpy; let destroySpy;
let dom = new BrowserDomAdapter();
beforeEachProviders(() => [ beforeEach(async(inject([TestComponentBuilder, SpecManager, OptionsService, BrowserDomAdapter],
provide(SpecManager, {useValue: new SpecManager()}), (tcb, specMgr, opts, _dom) => {
provide(BrowserDomAdapter, {useValue: new BrowserDomAdapter()}),
provide(OptionsService, {useValue: optsMgr})
]);
beforeEach(async(inject([TestComponentBuilder, SpecManager], (tcb, specMgr) => {
builder = tcb; builder = tcb;
return specMgr.load('/tests/schemas/methods-list-component.json'); optsMgr = opts;
dom = _dom;
return specMgr.load('/tests/schemas/extended-petstore.yml');
}))); })));
beforeEach((done) => { beforeEach(() => {
builder.createAsync(TestAppComponent).then(_fixture => { fixture = builder.createSync(TestAppComponent);
fixture = _fixture; element = getChildDebugElement(fixture.debugElement, 'methods-list').nativeElement;
element = getChildDebugElement(fixture.debugElement, 'methods-list').nativeElement; destroySpy = jasmine.createSpy('spy');
destroySpy = jasmine.createSpy('spy'); Redoc.appRef = <ComponentRef<any>>{
Redoc.appRef = <ComponentRef<any>>{ destroy: destroySpy
destroy: destroySpy };
}; fixture.detectChanges();
fixture.detectChanges();
done();
}, err => { throw err; });
}); });
afterEach(()=> { afterEach(()=> {

View File

@ -79,10 +79,10 @@ export class Redoc extends BaseComponent implements AfterViewInit {
Redoc.hideLoadingAnimation(); Redoc.hideLoadingAnimation();
Redoc.appRef = appRef; Redoc.appRef = appRef;
console.log('ReDoc bootstrapped!'); console.log('ReDoc bootstrapped!');
}, err => { }).catch(err => {
console.log(err);
Redoc.hideLoadingAnimation(); Redoc.hideLoadingAnimation();
Redoc.displayError(err); Redoc.displayError(err);
throw err;
}); });
} }
@ -97,7 +97,6 @@ export class Redoc extends BaseComponent implements AfterViewInit {
} }
static displayError(err) { static displayError(err) {
console.log(err);
let redocEl = dom.query('redoc'); let redocEl = dom.query('redoc');
if (!redocEl) return; if (!redocEl) return;
let heading = 'Oops... ReDoc failed to render this spec'; let heading = 'Oops... ReDoc failed to render this spec';

View File

@ -9,7 +9,8 @@
<h5 class="menu-header"> API reference </h5> <h5 class="menu-header"> API reference </h5>
<div *ngFor="let cat of data.menu; let idx = index" class="menu-cat"> <div *ngFor="let cat of data.menu; let idx = index" class="menu-cat">
<label class="menu-cat-header" (click)="activateAndScroll(idx, -1)" [ngClass]="{active: cat.active}"> {{cat.name}}</label> <label class="menu-cat-header" (click)="activateAndScroll(idx, -1)" [hidden]="cat.empty"
[ngClass]="{active: cat.active}"> {{cat.name}}</label>
<ul class="menu-subitems" @itemAnimation="cat.active ? 'expanded' : 'collapsed'"> <ul class="menu-subitems" @itemAnimation="cat.active ? 'expanded' : 'collapsed'">
<li *ngFor="let method of cat.methods; let methIdx = index" <li *ngFor="let method of cat.methods; let methIdx = index"
[ngClass]="{active: method.active}" [ngClass]="{active: method.active}"

View File

@ -29,6 +29,10 @@ $mobile-menu-compact-breakpoint: 550px;
color: $primary-color; color: $primary-color;
background-color: $side-menu-active-bg-color; background-color: $side-menu-active-bg-color;
} }
&[hidden] {
display: none;
}
} }
.menu-subitems { .menu-subitems {

View File

@ -1,15 +1,12 @@
'use strict'; 'use strict';
import { getChildDebugElement } from '../../../tests/helpers'; import { getChildDebugElement } from '../../../tests/helpers';
import { Component, provide } from '@angular/core'; import { Component } from '@angular/core';
import { OptionsService } from '../../services/index'; import { OptionsService } from '../../services/index';
import { import {
inject, inject,
async, async
beforeEach,
beforeEachProviders,
it
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing'; import { TestComponentBuilder } from '@angular/compiler/testing';
@ -25,9 +22,7 @@ describe('Redoc components', () => {
let builder; let builder;
let component; let component;
let fixture; let fixture;
beforeEachProviders(() => [
provide(SpecManager, {useValue: new SpecManager()})
]);
beforeEach(async(inject([TestComponentBuilder, SpecManager, OptionsService], beforeEach(async(inject([TestComponentBuilder, SpecManager, OptionsService],
(tcb, specMgr, opts) => { (tcb, specMgr, opts) => {
builder = tcb; builder = tcb;
@ -39,15 +34,10 @@ describe('Redoc components', () => {
return specMgr.load('/tests/schemas/extended-petstore.yml'); return specMgr.load('/tests/schemas/extended-petstore.yml');
}))); })));
beforeEach((done) => { beforeEach(() => {
builder.createAsync(TestAppComponent).then(_fixture => { fixture = builder.createSync(TestAppComponent);
fixture = _fixture; component = getChildDebugElement(fixture.debugElement, 'side-menu').componentInstance;
component = getChildDebugElement(fixture.debugElement, 'side-menu').componentInstance; fixture.detectChanges();
fixture.detectChanges();
done();
}, err => {
throw err;
});
}); });
afterEach(() => { afterEach(() => {

View File

@ -60,9 +60,7 @@ export function RedocComponent(options) {
inputs: inputs, inputs: inputs,
outputs: options.outputs, outputs: options.outputs,
providers: options.providers, providers: options.providers,
changeDetection: options.detect ? changeDetection: options.onPushOnly ? ChangeDetectionStrategy.OnPush : ChangeDetectionStrategy.Default,
(options.onPushOnly ? ChangeDetectionStrategy.OnPush : ChangeDetectionStrategy.Default) :
ChangeDetectionStrategy.Detached,
animations: options.animations, animations: options.animations,
templateUrl: options.templateUrl, templateUrl: options.templateUrl,
template: options.template, template: options.template,

View File

@ -1,17 +1,11 @@
'use strict'; 'use strict';
import { provide, Component } from '@angular/core'; import { Component } from '@angular/core';
import { BrowserDomAdapter } from '@angular/platform-browser/src/browser/browser_adapter';
import { import {
inject, inject,
beforeEach, async,
describe, TestComponentBuilder
beforeEachProviders,
it,
async
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { MenuService } from './menu.service'; import { MenuService } from './menu.service';
import { Hash } from './hash.service'; import { Hash } from './hash.service';
import { ScrollService } from './scroll.service'; import { ScrollService } from './scroll.service';
@ -21,37 +15,21 @@ import { SpecManager } from '../utils/SpecManager';;
describe('Menu service', () => { describe('Menu service', () => {
let menu, hashService, scroll; let menu, hashService, scroll;
let builder; let builder;
let specMgr = new SpecManager(); let specMgr;
beforeEachProviders(() => [ beforeEach(async(inject([TestComponentBuilder, SpecManager, Hash, ScrollService],
provide(BrowserDomAdapter, {useClass: BrowserDomAdapter}), (tcb, _specMgr, _hash, _scroll, _menu) => {
provide(Hash, {useClass: Hash}),
provide(ScrollService, {useClass: ScrollService}),
provide(SpecManager, {useValue: new SpecManager()})
]);
beforeEach(async(inject([Hash, ScrollService, TestComponentBuilder, SpecManager],
(_hash, _scroll, tcb, _specMgr) => {
hashService = _hash; hashService = _hash;
scroll = _scroll; scroll = _scroll;
builder = tcb; builder = tcb;
specMgr = _specMgr; specMgr = _specMgr;
return specMgr.load('/tests/schemas/extended-petstore.yml');
}))); })));
beforeEach(done => { beforeEach(() => {
specMgr.load('/tests/schemas/extended-petstore.yml').then(r => {
done();
}).catch(e => {
done.fail(e);
});
});
beforeEach(done => {
menu = new MenuService(hashService, scroll, specMgr); menu = new MenuService(hashService, scroll, specMgr);
builder.createAsync(TestAppComponent).then(fixture => { let fixture = builder.createSync(TestAppComponent);
fixture.detectChanges(); fixture.detectChanges();
done();
}).catch(err => done.fail(err) );
}); });
it('should run hashScroll when hash changed', (done) => { it('should run hashScroll when hash changed', (done) => {

View File

@ -3,6 +3,7 @@ import { Injectable, EventEmitter } from '@angular/core';
import { ScrollService, INVIEW_POSITION } from './scroll.service'; import { ScrollService, INVIEW_POSITION } from './scroll.service';
import { Hash } from './hash.service'; import { Hash } from './hash.service';
import { SpecManager } from '../utils/SpecManager'; import { SpecManager } from '../utils/SpecManager';
import { SchemaHelper } from './schema-helper.service';
const CHANGE = { const CHANGE = {
NEXT : 1, NEXT : 1,
@ -21,9 +22,7 @@ export class MenuService {
constructor(private hash:Hash, private scrollService:ScrollService, specMgr:SpecManager) { constructor(private hash:Hash, private scrollService:ScrollService, specMgr:SpecManager) {
this.hash = hash; this.hash = hash;
this.categories = Array.from(specMgr.buildMenuTree().entries()).map( this.categories = SchemaHelper.buildMenuTree(specMgr.schema);
el => ({name: el[0], description: el[1].description, methods: el[1].methods})
);
scrollService.scroll.subscribe((evt) => { scrollService.scroll.subscribe((evt) => {
this.scrollUpdate(evt.isScrolledDown); this.scrollUpdate(evt.isScrolledDown);

View File

@ -1,10 +1,6 @@
'use strict'; 'use strict';
import { BrowserDomAdapter } from '@angular/platform-browser/src/browser/browser_adapter'; import { BrowserDomAdapter } from '@angular/platform-browser/src/browser/browser_adapter';
import {
it
} from '@angular/core/testing';
import { OptionsService } from './options.service'; import { OptionsService } from './options.service';
describe('Options Service', () => { describe('Options Service', () => {

View File

@ -0,0 +1,84 @@
'use strict';
import { SchemaHelper } from './schema-helper.service';
import { SpecManager } from '../utils/SpecManager';
describe('Spec Helper', () => {
describe('buildMenuTree method', () => {
let suitSchema = {
tags: [
{name: 'tag1', description: 'info1', 'x-traitTag': true},
{name: 'tag2', description: 'info2'}
],
paths: {
test: {
put: {
tags: ['tag1', 'tag3'],
summary: 'test put'
},
get: {
tags: ['tag1', 'tag2'],
summary: 'test get'
},
// no tags
post: {
summary: 'test post'
}
}
}
};
let menuTree;
let specMgr;
beforeAll(() => {
specMgr = new SpecManager();
specMgr._schema = suitSchema;
menuTree = SchemaHelper.buildMenuTree(suitSchema);
});
it('should return instance of Array', () => {
menuTree.should.be.instanceof(Array);
});
it('should return Array with correct number of items', () => {
//2 - defined tags, 1 - tag3 and 1 [other] tag for no-tags method
menuTree.length.should.be.equal(2 + 1 + 1);
});
it('should append not defined tags to the end of list', () => {
let info = menuTree[2];
info.name.should.be.equal('tag3');
info.methods.length.should.be.equal(1);
info.methods[0].summary.should.be.equal('test put');
});
it('should append methods without tags to [other] tag', () => {
let info = menuTree[3];
info.name.should.be.equal('');
info.methods.length.should.be.equal(1);
info.methods[0].summary.should.be.equal('test post');
});
it('should map x-traitTag to empty methods list', () => {
let info = menuTree[0];
info['x-traitTag'].should.be.true();
info.methods.should.be.empty();
});
it('methods for tag should contain valid pointer and summary', () => {
for (let entr of menuTree) {
let info = entr;
info.should.be.an.Object();
info.methods.should.be.an.Array();
for (let methodInfo of info.methods) {
methodInfo.should.have.properties(['pointer', 'summary']);
let methSchema = specMgr.byPointer(methodInfo.pointer);
expect(methSchema).not.toBeNull();
if (methSchema.summary) {
methSchema.summary.should.be.equal(methodInfo.summary);
}
}
}
});
});
});

View File

@ -1,6 +1,7 @@
'use strict'; 'use strict';
import { JsonPointer } from '../utils/JsonPointer'; import { JsonPointer } from '../utils/JsonPointer';
import { SpecManager } from '../utils/SpecManager'; import { SpecManager } from '../utils/SpecManager';
import {methods as swaggerMethods} from '../utils/swagger-defs';
interface PropertyPreprocessOptions { interface PropertyPreprocessOptions {
childFor: string; childFor: string;
@ -218,4 +219,57 @@ export class SchemaHelper {
} }
return res; return res;
} }
static methodSummary(method) {
return method.summary || method.operationId || method.description.substring(0, 50);
}
static buildMenuTree(schema) {
let tag2MethodMapping = {};
let definedTags = schema.tags || [];
// add tags into map to preserve order
for (let tag of definedTags) {
tag2MethodMapping[tag.name] = {
'description': tag.description,
'name': tag.name,
'x-traitTag': tag['x-traitTag'],
'methods': []
};
}
let paths = schema.paths;
for (let path of Object.keys(paths)) {
let methods = Object.keys(paths[path]).filter((k) => swaggerMethods.has(k));
for (let method of methods) {
let methodInfo = paths[path][method];
let tags = methodInfo.tags;
if (!tags || !tags.length) {
tags = [''];
}
let methodPointer = JsonPointer.compile(['paths', path, method]);
let methodSummary = SchemaHelper.methodSummary(methodInfo);
for (let tag of tags) {
let tagDetails = tag2MethodMapping[tag];
if (!tag2MethodMapping[tag]) {
tagDetails = {
name: tag,
empty: tag === ''
};
tag2MethodMapping[tag] = tagDetails;
}
if (tagDetails['x-traitTag']) continue;
if (!tagDetails.methods) tagDetails.methods = [];
tagDetails.methods.push({
pointer: methodPointer,
summary: methodSummary,
operationId: methodInfo.operationId,
tag: tag
});
}
}
}
return Object.keys(tag2MethodMapping).map(tag => tag2MethodMapping[tag]);
}
} }

View File

@ -1,10 +1,5 @@
'use strict'; 'use strict';
import { SchemaNormalizer } from './schema-normalizer.service'; import { SchemaNormalizer } from './schema-normalizer.service';
import {
describe,
it
} from '@angular/core/testing';
import { SpecManager } from '../utils/SpecManager';; import { SpecManager } from '../utils/SpecManager';;
describe('Spec Helper', () => { describe('Spec Helper', () => {
@ -116,9 +111,18 @@ describe('Spec Helper', () => {
let resolved; let resolved;
beforeAll(() => { beforeAll(() => {
let pointer = '/paths/test5/get/parameters/0'; let pointer = '/paths/test5/get/parameters/0';
spyOn(console, 'warn').and.stub();
resolved = normalizer.normalize(specMgr.byPointer(pointer), pointer); resolved = normalizer.normalize(specMgr.byPointer(pointer), pointer);
}); });
afterAll(() => {
(<jasmine.Spy>console.warn).and.callThrough();
});
it('should print warning to console', () => {
expect(console.warn).toHaveBeenCalled();
});
it('should skip other fields', () => { it('should skip other fields', () => {
expect(resolved.$ref).toBeUndefined(); expect(resolved.$ref).toBeUndefined();
expect(resolved.title).toBeDefined(); expect(resolved.title).toBeDefined();

View File

@ -1,18 +1,12 @@
'use strict'; 'use strict';
import { getChildDebugElementByType } from '../../../../tests/helpers'; import { getChildDebugElementByType } from '../../../../tests/helpers';
import { Component, provide } from '@angular/core'; import { Component } from '@angular/core';
import { BrowserDomAdapter } from '@angular/platform-browser/src/browser/browser_adapter';
import { import {
inject, inject,
beforeEach, TestComponentBuilder
beforeEachProviders,
it
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { StickySidebar } from '../index'; import { StickySidebar } from '../index';
describe('Common components', () => { describe('Common components', () => {
@ -21,20 +15,12 @@ describe('Common components', () => {
let component; let component;
let fixture; let fixture;
beforeEachProviders(() => [
provide(BrowserDomAdapter, {useValue: new BrowserDomAdapter()})
]);
beforeEach(inject([TestComponentBuilder], (tcb) => { beforeEach(inject([TestComponentBuilder], (tcb) => {
builder = tcb; builder = tcb;
fixture = builder.createSync(TestApp);
let debugEl = getChildDebugElementByType(fixture.debugElement, StickySidebar);
component = debugEl.injector.get(StickySidebar);
})); }));
beforeEach((done) => {
builder.createAsync(TestApp).then(_fixture => {
fixture = _fixture;
let debugEl = getChildDebugElementByType(fixture.debugElement, StickySidebar);
component = debugEl.injector.get(StickySidebar);
done();
}, err => done.fail(err));
});
it('should init component', () => { it('should init component', () => {

View File

@ -1,7 +1,7 @@
'use strict'; 'use strict';
import { Directive, ElementRef, Input, OnInit, OnDestroy } from '@angular/core'; import { Directive, ElementRef, Input, OnInit, OnDestroy } from '@angular/core';
import {BrowserDomAdapter} from '@angular/platform-browser/src/browser/browser_adapter'; import { BrowserDomAdapter } from '@angular/platform-browser/src/browser/browser_adapter';
@Directive({ @Directive({
selector: '[sticky-sidebar]' selector: '[sticky-sidebar]'

View File

@ -5,12 +5,9 @@ import { Component } from '@angular/core';
import { import {
inject, inject,
beforeEach, TestComponentBuilder
it
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import {Tabs, Tab} from '../index'; import {Tabs, Tab} from '../index';
describe('Common components', () => { describe('Common components', () => {
@ -24,18 +21,12 @@ describe('Common components', () => {
beforeEach(inject([TestComponentBuilder], (tcb) => { beforeEach(inject([TestComponentBuilder], (tcb) => {
builder = tcb; builder = tcb;
fixture = builder.createSync(TestApp);
hostComponent = fixture.debugElement.componentInstance;
debugEl = getChildDebugElement(fixture.debugElement, 'tabs');
childDebugEls = getChildDebugElementAll(debugEl, 'tab');
component = debugEl.componentInstance;
})); }));
beforeEach((done) => {
builder.createAsync(TestApp).then(_fixture => {
fixture = _fixture;
hostComponent = fixture.debugElement.componentInstance;
debugEl = getChildDebugElement(fixture.debugElement, 'tabs');
childDebugEls = getChildDebugElementAll(debugEl, 'tab');
component = debugEl.componentInstance;
done();
}, err => done.fail(err));
});
it('should init component', () => { it('should init component', () => {
expect(component).not.toBeNull(); expect(component).not.toBeNull();

View File

@ -5,12 +5,10 @@ import { getChildDebugElement, mouseclick } from '../../../../tests/helpers';
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { import {
inject, inject,
beforeEach, expect,
it, TestComponentBuilder
expect
} from '@angular/core/testing'; } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { Zippy } from '../index'; import { Zippy } from '../index';
describe('Common components', () => { describe('Common components', () => {
@ -22,17 +20,11 @@ describe('Common components', () => {
beforeEach(inject([TestComponentBuilder], (tcb) => { beforeEach(inject([TestComponentBuilder], (tcb) => {
builder = tcb; builder = tcb;
fixture = builder.createSync(TestApp);
let debugEl = getChildDebugElement(fixture.debugElement, 'zippy');
component = debugEl.componentInstance;
nativeElement = debugEl.nativeElement;
})); }));
beforeEach((done) => {
builder.createAsync(TestApp).then(_fixture => {
fixture = _fixture;
let debugEl = getChildDebugElement(fixture.debugElement, 'zippy');
component = debugEl.componentInstance;
nativeElement = debugEl.nativeElement;
done();
}, err => done.fail(err));
});
it('should init component', () => { it('should init component', () => {
expect(component).not.toBeNull(); expect(component).not.toBeNull();

View File

@ -2,7 +2,6 @@
import JsonSchemaRefParser from 'json-schema-ref-parser'; import JsonSchemaRefParser from 'json-schema-ref-parser';
import JsonPointer from './JsonPointer'; import JsonPointer from './JsonPointer';
import {methods as swaggerMethods} from './swagger-defs';
export class SpecManager { export class SpecManager {
public _schema:any = {}; public _schema:any = {};
@ -114,52 +113,6 @@ export class SpecManager {
return tagsMap; return tagsMap;
} }
/* returns ES6 Map */
buildMenuTree():Map<string, any> {
let tag2MethodMapping = new Map();
let definedTags = this._schema.tags || [];
// add tags into map to preserve order
for (let tag of definedTags) {
tag2MethodMapping.set(tag.name, {
'description': tag.description,
'x-traitTag': tag['x-traitTag'],
'methods': []
});
}
let paths = this._schema.paths;
for (let path of Object.keys(paths)) {
let methods = Object.keys(paths[path]).filter((k) => swaggerMethods.has(k));
for (let method of methods) {
let methodInfo = paths[path][method];
let tags = methodInfo.tags;
//TODO: mb need to do something cleverer
if (!tags || !tags.length) {
tags = ['[Other]'];
}
let methodPointer = JsonPointer.compile(['paths', path, method]);
let methodSummary = methodInfo.summary || methodInfo.operationId;
for (let tag of tags) {
let tagDetails = tag2MethodMapping.get(tag);
if (!tagDetails) {
tagDetails = {};
tag2MethodMapping.set(tag, tagDetails);
}
if (tagDetails['x-traitTag']) continue;
if (!tagDetails.methods) tagDetails.methods = [];
tagDetails.methods.push({
pointer: methodPointer,
summary: methodSummary,
operationId: methodInfo.operationId
});
}
}
}
return tag2MethodMapping;
}
findDerivedDefinitions(defPointer) { findDerivedDefinitions(defPointer) {
let definition = this.byPointer(defPointer); let definition = this.byPointer(defPointer);
if (!definition) throw new Error(`Can't load schema at ${defPointer}`); if (!definition) throw new Error(`Can't load schema at ${defPointer}`);

View File

@ -1,7 +1,7 @@
{ {
"name": "redoc", "name": "redoc",
"description": "Swagger-generated API Reference Documentation", "description": "Swagger-generated API Reference Documentation",
"version": "0.15.1", "version": "0.15.2",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/Rebilly/ReDoc" "url": "git://github.com/Rebilly/ReDoc"
@ -32,17 +32,11 @@
"jspm": { "jspm": {
"configFile": "system.config.js", "configFile": "system.config.js",
"dependencies": { "dependencies": {
"@angular/common": "npm:@angular/common@^2.0.0-rc.2", "@angular/common@2.0.0-rc.4": "npm:@angular/common@2.0.0-rc.4",
"@angular/common@2.0.0-rc.3": "npm:@angular/common@2.0.0-rc.3", "@angular/compiler@2.0.0-rc.4": "npm:@angular/compiler@2.0.0-rc.4",
"@angular/compiler": "npm:@angular/compiler@^2.0.0-rc.2", "@angular/core@2.0.0-rc.4": "npm:@angular/core@2.0.0-rc.4",
"@angular/compiler@2.0.0-rc.3": "npm:@angular/compiler@2.0.0-rc.3", "@angular/platform-browser-dynamic@2.0.0-rc.4": "npm:@angular/platform-browser-dynamic@2.0.0-rc.4",
"@angular/core": "npm:@angular/core@^2.0.0-rc.2", "@angular/platform-browser@2.0.0-rc.4": "npm:@angular/platform-browser@2.0.0-rc.4",
"@angular/core@2.0.0-rc.3": "npm:@angular/core@2.0.0-rc.3",
"@angular/platform-browser": "npm:@angular/platform-browser@^2.0.0-rc.2",
"@angular/platform-browser-dynamic": "npm:@angular/platform-browser-dynamic@^2.0.0-rc.2",
"@angular/platform-browser-dynamic@2.0.0-rc.3": "npm:@angular/platform-browser-dynamic@2.0.0-rc.3",
"@angular/platform-browser@2.0.0-rc.3": "npm:@angular/platform-browser@2.0.0-rc.3",
"@angular/platform-server@2.0.0-rc.3": "npm:@angular/platform-server@2.0.0-rc.3",
"dropkickjs": "npm:dropkickjs@^2.1.8", "dropkickjs": "npm:dropkickjs@^2.1.8",
"es6-shim": "github:es-shims/es6-shim@^0.33.6", "es6-shim": "github:es-shims/es6-shim@^0.33.6",
"hint.css": "npm:hint.css@^2.2.1", "hint.css": "npm:hint.css@^2.2.1",
@ -82,12 +76,12 @@
} }
}, },
"devDependencies": { "devDependencies": {
"@angular/common": "^2.0.0-rc.3", "@angular/common": "^2.0.0-rc.4",
"@angular/compiler": "^2.0.0-rc.3", "@angular/compiler": "^2.0.0-rc.4",
"@angular/core": "^2.0.0-rc.2", "@angular/core": "^2.0.0-rc.4",
"@angular/platform-browser": "^2.0.0-rc.3", "@angular/platform-browser": "^2.0.0-rc.4",
"@angular/platform-browser-dynamic": "^2.0.0-rc.3", "@angular/platform-browser-dynamic": "^2.0.0-rc.4",
"@angular/platform-server": "^2.0.0-rc.3", "@angular/platform-server": "^2.0.0-rc.4",
"babel-polyfill": "^6.3.14", "babel-polyfill": "^6.3.14",
"branch-release": "^1.0.3", "branch-release": "^1.0.3",
"browser-sync": "^2.10.1", "browser-sync": "^2.10.1",
@ -139,7 +133,7 @@
"should": "^9.0.2", "should": "^9.0.2",
"sinon": "^1.17.2", "sinon": "^1.17.2",
"systemjs-builder": "^0.15.16", "systemjs-builder": "^0.15.16",
"tslint": "^3.11.0", "tslint": "^3.13.0",
"tslint-stylish": "^2.1.0-beta", "tslint-stylish": "^2.1.0-beta",
"typescript": "^1.8.10", "typescript": "^1.8.10",
"vinyl-paths": "^2.0.0", "vinyl-paths": "^2.0.0",

View File

@ -16,17 +16,11 @@ System.config({
}, },
map: { map: {
"@angular/common": "npm:@angular/common@2.0.0-rc.3", "@angular/common": "npm:@angular/common@2.0.0-rc.4",
"@angular/common@2.0.0-rc.3": "npm:@angular/common@2.0.0-rc.3", "@angular/compiler": "npm:@angular/compiler@2.0.0-rc.4",
"@angular/compiler": "npm:@angular/compiler@2.0.0-rc.3", "@angular/core": "npm:@angular/core@2.0.0-rc.4",
"@angular/compiler@2.0.0-rc.3": "npm:@angular/compiler@2.0.0-rc.3", "@angular/platform-browser-dynamic": "npm:@angular/platform-browser-dynamic@2.0.0-rc.4",
"@angular/core": "npm:@angular/core@2.0.0-rc.3", "@angular/platform-browser": "npm:@angular/platform-browser@2.0.0-rc.4",
"@angular/core@2.0.0-rc.3": "npm:@angular/core@2.0.0-rc.3",
"@angular/platform-browser": "npm:@angular/platform-browser@2.0.0-rc.3",
"@angular/platform-browser-dynamic": "npm:@angular/platform-browser-dynamic@2.0.0-rc.3",
"@angular/platform-browser-dynamic@2.0.0-rc.3": "npm:@angular/platform-browser-dynamic@2.0.0-rc.3",
"@angular/platform-browser@2.0.0-rc.3": "npm:@angular/platform-browser@2.0.0-rc.3",
"@angular/platform-server@2.0.0-rc.3": "npm:@angular/platform-server@2.0.0-rc.3",
"babel": "npm:babel-core@5.8.34", "babel": "npm:babel-core@5.8.34",
"babel-runtime": "npm:babel-runtime@5.8.34", "babel-runtime": "npm:babel-runtime@5.8.34",
"clean-css": "npm:clean-css@3.4.17", "clean-css": "npm:clean-css@3.4.17",
@ -122,39 +116,32 @@ System.config({
"github:jspm/nodelibs-zlib@0.1.0": { "github:jspm/nodelibs-zlib@0.1.0": {
"browserify-zlib": "npm:browserify-zlib@0.1.4" "browserify-zlib": "npm:browserify-zlib@0.1.4"
}, },
"npm:@angular/common@2.0.0-rc.3": { "npm:@angular/common@2.0.0-rc.4": {
"@angular/core": "npm:@angular/core@2.0.0-rc.3", "@angular/core": "npm:@angular/core@2.0.0-rc.4",
"process": "github:jspm/nodelibs-process@0.1.2" "process": "github:jspm/nodelibs-process@0.1.2"
}, },
"npm:@angular/compiler@2.0.0-rc.3": { "npm:@angular/compiler@2.0.0-rc.4": {
"@angular/core": "npm:@angular/core@2.0.0-rc.3", "@angular/core": "npm:@angular/core@2.0.0-rc.4",
"process": "github:jspm/nodelibs-process@0.1.2" "process": "github:jspm/nodelibs-process@0.1.2"
}, },
"npm:@angular/core@2.0.0-rc.3": { "npm:@angular/core@2.0.0-rc.4": {
"process": "github:jspm/nodelibs-process@0.1.2", "process": "github:jspm/nodelibs-process@0.1.2",
"rxjs": "npm:rxjs@5.0.0-beta.6", "rxjs": "npm:rxjs@5.0.0-beta.6",
"zone.js": "npm:zone.js@0.6.12" "zone.js": "npm:zone.js@0.6.12"
}, },
"npm:@angular/platform-browser-dynamic@2.0.0-rc.3": { "npm:@angular/platform-browser-dynamic@2.0.0-rc.4": {
"@angular/common": "npm:@angular/common@2.0.0-rc.3", "@angular/common": "npm:@angular/common@2.0.0-rc.4",
"@angular/compiler": "npm:@angular/compiler@2.0.0-rc.3", "@angular/compiler": "npm:@angular/compiler@2.0.0-rc.4",
"@angular/core": "npm:@angular/core@2.0.0-rc.3", "@angular/core": "npm:@angular/core@2.0.0-rc.4",
"@angular/platform-browser": "npm:@angular/platform-browser@2.0.0-rc.3", "@angular/platform-browser": "npm:@angular/platform-browser@2.0.0-rc.4",
"process": "github:jspm/nodelibs-process@0.1.2" "process": "github:jspm/nodelibs-process@0.1.2"
}, },
"npm:@angular/platform-browser@2.0.0-rc.3": { "npm:@angular/platform-browser@2.0.0-rc.4": {
"@angular/common": "npm:@angular/common@2.0.0-rc.3", "@angular/common": "npm:@angular/common@2.0.0-rc.4",
"@angular/compiler": "npm:@angular/compiler@2.0.0-rc.3", "@angular/compiler": "npm:@angular/compiler@2.0.0-rc.4",
"@angular/core": "npm:@angular/core@2.0.0-rc.3", "@angular/core": "npm:@angular/core@2.0.0-rc.4",
"process": "github:jspm/nodelibs-process@0.1.2" "process": "github:jspm/nodelibs-process@0.1.2"
}, },
"npm:@angular/platform-server@2.0.0-rc.3": {
"@angular/common": "npm:@angular/common@2.0.0-rc.3",
"@angular/compiler": "npm:@angular/compiler@2.0.0-rc.3",
"@angular/core": "npm:@angular/core@2.0.0-rc.3",
"@angular/platform-browser": "npm:@angular/platform-browser@2.0.0-rc.3",
"parse5": "npm:parse5@1.3.2"
},
"npm:amdefine@1.0.0": { "npm:amdefine@1.0.0": {
"fs": "github:jspm/nodelibs-fs@0.1.2", "fs": "github:jspm/nodelibs-fs@0.1.2",
"module": "github:jspm/nodelibs-module@0.1.0", "module": "github:jspm/nodelibs-module@0.1.0",
@ -686,9 +673,6 @@ System.config({
"pbkdf2": "npm:pbkdf2@3.0.4", "pbkdf2": "npm:pbkdf2@3.0.4",
"systemjs-json": "github:systemjs/plugin-json@0.1.2" "systemjs-json": "github:systemjs/plugin-json@0.1.2"
}, },
"npm:parse5@1.3.2": {
"process": "github:jspm/nodelibs-process@0.1.2"
},
"npm:path-browserify@0.0.0": { "npm:path-browserify@0.0.0": {
"process": "github:jspm/nodelibs-process@0.1.2" "process": "github:jspm/nodelibs-process@0.1.2"
}, },

View File

@ -110,8 +110,6 @@
"parameters": [ "parameters": [
{ {
"$ref": "#/definitions/CircularTransitive", "$ref": "#/definitions/CircularTransitive",
"title": "test",
"description": "test"
} }
] ]
} }

View File

@ -2,7 +2,8 @@
import {setBaseTestProviders} from '@angular/core/testing'; import {setBaseTestProviders} from '@angular/core/testing';
import { BrowserDomAdapter } from '@angular/platform-browser/src/browser/browser_adapter'; import { BrowserDomAdapter } from '@angular/platform-browser/src/browser/browser_adapter';
import { OptionsService, RedocEventsService} from '../lib/services/index'; import { OptionsService, RedocEventsService, Hash, ScrollService, MenuService } from '../lib/services/index';
import { SpecManager } from '../lib/utils/SpecManager';
import { provide } from '@angular/core'; import { provide } from '@angular/core';
import { import {
@ -15,6 +16,10 @@ setBaseTestProviders(
TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
provide(BrowserDomAdapter, {useClass: BrowserDomAdapter}), provide(BrowserDomAdapter, {useClass: BrowserDomAdapter}),
provide(OptionsService, {useClass: OptionsService}), provide(OptionsService, {useClass: OptionsService}),
provide(RedocEventsService, {useClass: RedocEventsService}) provide(RedocEventsService, {useClass: RedocEventsService}),
provide(SpecManager, {useClass: SpecManager}),
provide(Hash, {useClass: Hash}),
provide(ScrollService, {useClass: ScrollService}),
provide(MenuService, {useClass: MenuService})
], ],
[TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS]); [TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS]);

View File

@ -93,85 +93,6 @@ describe('Utils', () => {
}); });
}); });
describe('buildMenuTree method', () => {
let suitSchema = {
tags: [
{name: 'tag1', description: 'info1', 'x-traitTag': true},
{name: 'tag2', description: 'info2'}
],
paths: {
test: {
put: {
tags: ['tag1', 'tag3'],
summary: 'test put'
},
get: {
tags: ['tag1', 'tag2'],
summary: 'test get'
},
// no tags
post: {
summary: 'test post'
}
}
}
};
let menuTree;
let entries;
beforeAll(() => {
specMgr._schema = suitSchema;
menuTree = specMgr.buildMenuTree();
entries = Array.from(menuTree.entries());
});
it('should return instance of Map', () => {
menuTree.should.be.instanceof(Map);
});
it('should return Map with correct number of entries', () => {
//2 - defined tags, 1 - tag3 and 1 [other] tag for no-tags method
entries.length.should.be.equal(2 + 1 + 1);
});
it('should append not defined tags to the end of list', () => {
let [tag, info] = entries[2];
tag.should.be.equal('tag3');
info.methods.length.should.be.equal(1);
info.methods[0].summary.should.be.equal('test put');
});
it('should append methods without tags to [other] tag', () => {
let [tag, info] = entries[3];
tag.should.be.equal('[Other]');
info.methods.length.should.be.equal(1);
info.methods[0].summary.should.be.equal('test post');
});
it('should map x-traitTag to empty methods list', () => {
let [, info] = entries[0];
info['x-traitTag'].should.be.true();
info.methods.should.be.empty();
});
it('methods for tag should contain valid pointer and summary', () => {
for (let entr of entries) {
let [, info] = entr;
info.should.be.an.Object();
info.methods.should.be.an.Array();
for (let methodInfo of info.methods) {
methodInfo.should.have.properties(['pointer', 'summary']);
let methSchema = specMgr.byPointer(methodInfo.pointer);
expect(methSchema).not.toBeNull();
if (methSchema.summary) {
methSchema.summary.should.be.equal(methodInfo.summary);
}
}
}
});
});
describe('getMethodParams method', () => { describe('getMethodParams method', () => {
beforeAll((done) => { beforeAll((done) => {
specMgr.load('/tests/schemas/schema-mgr-methodparams.json').then(() => { specMgr.load('/tests/schemas/schema-mgr-methodparams.json').then(() => {