diff --git a/lib/components/SideMenu/side-menu.spec.js b/lib/components/SideMenu/side-menu.spec.js index 517828e8..cf816ecf 100644 --- a/lib/components/SideMenu/side-menu.spec.js +++ b/lib/components/SideMenu/side-menu.spec.js @@ -1,7 +1,7 @@ 'use strict'; -import { getChildDebugElement } from 'tests/helpers'; -import {Component, View, provide} from 'angular2/core'; +import { getChildDebugElement, mouseclick} from 'tests/helpers'; +import {Component, View, provide, ViewMetadata} from 'angular2/core'; import { TestComponentBuilder, @@ -28,37 +28,140 @@ describe('Redoc components', () => { builder = tcb; return schemaMgr.load('/tests/schemas/extended-petstore.json').then(() => null, (err) => { throw err; }); })); - beforeEach((done) => { - builder.createAsync(TestApp).then(_fixture => { - fixture = _fixture; - component = getChildDebugElement(fixture.debugElement, 'side-menu').componentInstance; - fixture.detectChanges(); - done(); - }, err => { - throw err; - }); - }); afterEach(() => { if (fixture) fixture.destroy(); }); - it('should init component and component data', () => { - expect(component).not.toBeNull(); - expect(component.data).not.toBeNull(); + describe('window parent case', () => { + beforeEach((done) => { + builder.createAsync(TestApp).then(_fixture => { + fixture = _fixture; + component = getChildDebugElement(fixture.debugElement, 'side-menu').componentInstance; + fixture.detectChanges(); + done(); + }, err => { + throw err; + }); + }); + + it('should init component and component data', () => { + expect(component).not.toBeNull(); + expect(component.data).not.toBeNull(); + }); + + it('should use window as scrollParent', () => { + component.scrollParent.should.be.equal(window); + }); + + it('should run hashScroll when redoc bootstrapped', (done) => { + spyOn(component.adapter, 'getLocation').and.returnValue({hash: ''}); + spyOn(component, 'hashScroll').and.stub(); + spyOn(window, 'scrollTo').and.stub(); + redocEvents.bootstrapped.next(); + setTimeout(() => { + expect(component.hashScroll).toHaveBeenCalled(); + expect(window.scrollTo).not.toHaveBeenCalled(); + + window.scrollTo.and.callThrough(); + component.hashScroll.and.callThrough(); + done(); + }); + }); + + it('should scroll to method when location hash is present', (done) => { + let hash = '#pet/paths/~1pet~1findByStatus/get'; + spyOn(component.adapter, 'getLocation').and.returnValue({hash: hash}); + spyOn(component, 'hashScroll').and.callThrough(); + spyOn(window, 'scrollTo').and.stub(); + redocEvents.bootstrapped.next(); + setTimeout(() => { + expect(component.hashScroll).toHaveBeenCalled(); + let scrollY = window.scrollTo.calls.argsFor(0)[1]; + expect(scrollY).toBeGreaterThan(0); + done(); + }); + }); }); - it('should scroll to method when location hash is present', (done) => { - let hash = '#pet/paths/~1pet~1findByStatus/get'; - spyOn(component.adapter, 'getLocation').and.returnValue({hash: hash}); - spyOn(component, 'hashScroll').and.callThrough(); - spyOn(window, 'scrollTo').and.stub(); - redocEvents.bootstrapped.next(); - setTimeout(() => { - expect(component.hashScroll).toHaveBeenCalled(); - let scrollY = window.scrollTo.calls.argsFor(0)[1]; - expect(scrollY).toBeGreaterThan(0); - done(); + describe('scollable div parent case', () => { + let menuNativeEl; + beforeEach((done) => { + let scollableDivTmpl = + `
+ + +
`; + builder = builder.overrideView( + TestApp, new ViewMetadata({template: scollableDivTmpl, directives: [MethodsList, SideMenu]})); + + builder.createAsync(TestApp).then(_fixture => { + fixture = _fixture; + component = getChildDebugElement(fixture.debugElement, 'side-menu').componentInstance; + menuNativeEl = getChildDebugElement(fixture.debugElement, 'side-menu').nativeElement; + fixture.detectChanges(); + + done(); + }, err => { + throw err; + }); + }); + + + + it('should init component and component data', () => { + expect(component).not.toBeNull(); + expect(component.data).not.toBeNull(); + }); + + it('should use scrollable div as scrollParent', () => { + component.scrollParent.should.be.instanceof(Element); + }); + + it('should scroll to method when location hash is present', (done) => { + let hash = '#pet/paths/~1pet~1findByStatus/get'; + spyOn(component.adapter, 'getLocation').and.returnValue({hash: hash}); + spyOn(component, 'hashScroll').and.callThrough(); + redocEvents.bootstrapped.next(); + setTimeout(() => { + expect(component.hashScroll).toHaveBeenCalled(); + expect(component.scrollParent.scrollTop).toBeGreaterThan(0); + done(); + }); + }); + + it('should select next/prev menu item when scrolled down/up', () => { + component.activeCatIdx.should.be.equal(0); + component.activeMethodIdx.should.be.equal(-1); + let elTop = component.getCurrentMethodEl().getBoundingClientRect().bottom; + + component.scrollParent.scrollTop = elTop + 1; + //simulate scroll down + spyOn(component, 'scrollY').and.returnValue(elTop + 2); + component.scrollHandler(); + component.activeCatIdx.should.be.equal(1); + + + component.scrollParent.scrollTop = elTop - 1; + //simulate scroll up + component.scrollY.and.returnValue(elTop - 2); + component.scrollHandler(); + component.activeCatIdx.should.be.equal(0); + }); + + it('should activate menu item on click', () => { + let menuItemEl = menuNativeEl.querySelector('li'); + expect(menuItemEl).not.toHaveCssClass('active'); + mouseclick(menuItemEl); + fixture.detectChanges(); + expect(menuItemEl).toHaveCssClass('active'); + }); + + it('should scroll to appropriate element when click on menu label', () => { + component.scrollParent.scrollTop.should.be.equal(0); + let menuItemEl = menuNativeEl.querySelector('li'); + mouseclick(menuItemEl); + component.scrollParent.scrollTop.should.be.above(0); }); }); });