diff --git a/lib/components/Method/method.ts b/lib/components/Method/method.ts index 977f7a1d..0590c1d1 100644 --- a/lib/components/Method/method.ts +++ b/lib/components/Method/method.ts @@ -31,7 +31,7 @@ export class Method extends BaseComponent implements OnInit { @HostBinding('attr.operation-id') operationId; - private method: MethodInfo; + method: MethodInfo; constructor(specMgr:SpecManager, private optionsService: OptionsService) { super(specMgr); diff --git a/lib/components/MethodsList/methods-list.spec.ts b/lib/components/MethodsList/methods-list.spec.ts index 330cb754..6d2d56da 100644 --- a/lib/components/MethodsList/methods-list.spec.ts +++ b/lib/components/MethodsList/methods-list.spec.ts @@ -13,7 +13,7 @@ import { getChildDebugElement } from '../../../tests/helpers'; import { MethodsList } from './methods-list'; import { SpecManager } from '../../utils/spec-manager'; -describe('Redoc components', () => { +describe('Redoc components', () => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [ TestAppComponent ] }); }); @@ -42,13 +42,13 @@ describe('Redoc components', () => { expect(component).not.toBeNull(); }); - it('should get correct tags list', () => { + it('should build correct tags list', () => { expect(component.tags).not.toBeNull(); component.tags.should.have.lengthOf(2); component.tags[0].name.should.be.equal('traitTag'); - component.tags[0].methods.should.be.empty(); + should.not.exist(component.tags[0].items); component.tags[1].name.should.be.equal('tag1'); - component.tags[1].methods.should.have.lengthOf(2); + component.tags[1].items.should.have.lengthOf(2); }); }); }); diff --git a/lib/components/MethodsList/methods-list.ts b/lib/components/MethodsList/methods-list.ts index 9542bf51..ba434ec5 100644 --- a/lib/components/MethodsList/methods-list.ts +++ b/lib/components/MethodsList/methods-list.ts @@ -24,7 +24,7 @@ export class MethodsList extends BaseComponent implements OnInit { let emptyTag = { name: '', items: [] - } + }; flatMenuItems.forEach(menuItem => { // skip items that are not bound to swagger tags/methods if (!menuItem.metadata) return; diff --git a/lib/services/menu.service.spec.ts b/lib/services/menu.service.spec.ts index c34b7f57..3596fede 100644 --- a/lib/services/menu.service.spec.ts +++ b/lib/services/menu.service.spec.ts @@ -6,7 +6,7 @@ import { } from '@angular/core/testing'; import { MethodsList } from '../components/MethodsList/methods-list'; -import { MenuService } from './menu.service'; +import { MenuService, MenuItem } from './menu.service'; import { Hash } from './hash.service'; import { LazyTasksService } from '../shared/components/LazyFor/lazy-for'; import { ScrollService } from './scroll.service'; @@ -18,7 +18,7 @@ describe('Menu service', () => { TestBed.configureTestingModule({ declarations: [ TestAppComponent, MethodsList ] }); }); - let menu, hashService, scroll, tasks; + let menu:MenuService, hashService, scroll, tasks; let specMgr; beforeEach(inject([SpecManager, Hash, ScrollService, LazyTasksService], @@ -70,22 +70,113 @@ describe('Menu service', () => { }); it('should select next/prev menu item when scrolled down/up', () => { - scroll.$scrollParent = document.querySelector('#parent'); - menu.activeCatIdx.should.be.equal(0); - menu.activeMethodIdx.should.be.equal(-1); - let nextElTop = menu.getRelativeCatOrItem(1).getBoundingClientRect().top; + // enable all items + menu.items.forEach(item => item.ready = true); + scroll.$scrollParent = document.querySelector('#parent'); + menu.activeIdx.should.be.equal(-1); + + let nextElTop = menu.getEl(1).getBoundingClientRect().top; scroll.$scrollParent.scrollTop = nextElTop + 1; //simulate scroll down spyOn(scroll, 'scrollY').and.returnValue(nextElTop + 10); - menu.scrollUpdate(true); - menu.activeCatIdx.should.be.equal(1); + menu.onScroll(true); + menu.activeIdx.should.be.equal(1); scroll.scrollY.and.returnValue(nextElTop - 2); scroll.$scrollParent.scrollTop = nextElTop - 1; - menu.scrollUpdate(false); - menu.activeCatIdx.should.be.equal(0); + menu.onScroll(false); + menu.activeIdx.should.be.equal(0); + }); + + describe('buildMenu method', () => { + let suitSchema = { + tags: [ + {name: 'tag1', description: 'info1', 'x-traitTag': true}, + {name: 'tag2', description: 'info2'}, + {name: 'tag4', description: 'info2', 'x-displayName': 'Tag Four'} + ], + paths: { + test: { + put: { + tags: ['tag1', 'tag3'], + summary: 'test put' + }, + get: { + tags: ['tag1', 'tag2'], + summary: 'test get' + }, + delete: { + tags: ['tag4'], + summary: 'test delete' + }, + // no tags + post: { + summary: 'test post' + } + } + } + }; + + let items:MenuItem[]; + beforeEach(() => { + menu.items = null; + specMgr._schema = suitSchema; + menu.buildMenu(); + items = menu.items; + }); + + it('should return instance of Array', () => { + items.should.be.instanceof(Array); + }); + + it('should return Array with correct number of items', () => { + // 3 - defined tags, 1 - tag3 and 1 method item for method without tag + items.length.should.be.equal(3 + 1 + 1); + }); + + it('should append not defined tags to the end of list', () => { + let item = items[3]; + item.name.should.be.equal('tag3'); + item.items.length.should.be.equal(1); + item.items[0].name.should.be.equal('test put'); + }); + + it('should append method items without tags to the end of list', () => { + let methodItem = items[4]; + methodItem.name.should.be.equal('test post'); + methodItem.metadata.type.should.be.equal('method'); + should.not.exist(methodItem.items); + }); + + it('should map x-traitTag to empty method list', () => { + let item = items[0]; + should.not.exist(item.items); + }); + + it('methods for tag should contain valid pointer and name', () => { + for (let item of items) { + item.should.be.an.Object(); + if (item.items) { + for (let subItem of item.items) { + subItem.should.have.properties(['metadata']); + let pointer = subItem.metadata.pointer; + let methSchema = specMgr.byPointer(pointer); + should.exist(methSchema); + if (methSchema.summary) { + methSchema.summary.should.be.equal(subItem.name); + } + } + } + } + }); + + it('should use x-displayName to set custom names', () => { + let info = items[2]; + info.id.should.be.equal('tag/tag4'); + info.name.should.be.equal('Tag Four'); + }); }); }); diff --git a/lib/services/schema-helper.service.spec.ts b/lib/services/schema-helper.service.spec.ts index ac53571d..041bfe59 100644 --- a/lib/services/schema-helper.service.spec.ts +++ b/lib/services/schema-helper.service.spec.ts @@ -3,100 +3,6 @@ import { SchemaHelper } from './schema-helper.service'; import { SpecManager } from '../utils/spec-manager'; describe('Spec Helper', () => { - describe('buildMenuTree method', () => { - let suitSchema = { - tags: [ - {name: 'tag1', description: 'info1', 'x-traitTag': true}, - {name: 'tag2', description: 'info2'}, - {name: 'tag4', description: 'info2', 'x-displayName': 'Tag Four'} - ], - paths: { - test: { - put: { - tags: ['tag1', 'tag3'], - summary: 'test put' - }, - get: { - tags: ['tag1', 'tag2'], - summary: 'test get' - }, - delete: { - tags: ['tag4'], - summary: 'test delete' - }, - // 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', () => { - //3 - defined tags, 1 - tag3 and 1 [other] tag for no-tags method - menuTree.length.should.be.equal(3 + 1 + 1); - }); - - it('should append not defined tags to the end of list', () => { - let info = menuTree[3]; - 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[4]; - 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 section', () => { - let info = menuTree[0]; - info.empty.should.be.true(); - }); - - it('should map x-traitTag to empty methods list', () => { - let info = menuTree[0]; - 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); - } - } - } - }); - - it('should use x-displayName to set custom names', () => { - let info = menuTree[2]; - info.id.should.be.equal('tag/tag4'); - info.name.should.be.equal('Tag Four'); - }); - }); - describe('injectors', () => { it('should autodetect type if not-specified', () => { spyOn(console, 'warn').and.stub(); diff --git a/lib/shared/components/StickySidebar/sticky-sidebar.ts b/lib/shared/components/StickySidebar/sticky-sidebar.ts index d9429e83..f4e822af 100644 --- a/lib/shared/components/StickySidebar/sticky-sidebar.ts +++ b/lib/shared/components/StickySidebar/sticky-sidebar.ts @@ -84,7 +84,6 @@ export class StickySidebar implements OnInit, OnDestroy { this.$redocEl = this.$element.offsetParent.parentNode || DOM.defaultDoc().body; this.bind(); requestAnimationFrame(() => this.updatePosition()); - //this.updatePosition() } ngOnDestroy() { diff --git a/tests/e2e/index.html b/tests/e2e/index.html index 00af0530..a0ecb02c 100644 --- a/tests/e2e/index.html +++ b/tests/e2e/index.html @@ -4,8 +4,8 @@ ReDoc - - + + Loading... diff --git a/tests/e2e/redoc.e2e.js b/tests/e2e/redoc.e2e.js index 37733c91..1e6416b6 100644 --- a/tests/e2e/redoc.e2e.js +++ b/tests/e2e/redoc.e2e.js @@ -56,16 +56,16 @@ describe('Scroll sync', () => { it('should update active menu entries on page scroll forwards', () => { scrollToEl('[section="tag/store"]').then(() => { - expect($('.menu-cat-header.active').getInnerHtml()).toContain('store'); + expect($('.menu-item.active > .menu-item-header').getInnerHtml()).toContain('store'); expect($('.selected-tag').getInnerHtml()).toContain('store'); }); }); it('should update active menu entries on page scroll backwards', () => { scrollToEl('[operation-id="getPetById"]').then(() => { - expect($('.menu-cat-header.active').getInnerHtml()).toContain('pet'); + expect($('.menu-item.menu-item-depth-1.active .menu-item-header').getInnerHtml()).toContain('pet'); expect($('.selected-tag').getInnerHtml()).toContain('pet'); - expect($('.menu-cat li.active').getInnerHtml()).toContain('Find pet by ID'); + expect($('.menu-item.menu-item-depth-2.active .menu-item-header').getInnerHtml()).toContain('Find pet by ID'); expect($('.selected-endpoint').getInnerHtml()).toContain('Find pet by ID'); }); }); @@ -85,7 +85,7 @@ describe('Language tabs sync', () => { // check if correct item expect($item.getText()).toContain('PHP'); var EC = protractor.ExpectedConditions; - browser.wait(EC.elementToBeClickable($item), 2000); + browser.wait(EC.elementToBeClickable($item), 5000); $item.click().then(() => { expect($('[operation-id="updatePet"] li.active').getText()).toContain('PHP'); }); diff --git a/tests/helpers.ts b/tests/helpers.ts index 0d3b3662..05371243 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -1,7 +1,7 @@ 'use strict'; -import {By} from '@angular/platform-browser'; -import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; +import { By } from '@angular/platform-browser'; +import { getDOM } from '@angular/platform-browser/src/dom/dom_adapter'; /** Gets a child DebugElement by tag name. */ export function getChildDebugElement(parent, tagName) {