From cc2b223d3c543f6cd337345744d9a55e07f0afb1 Mon Sep 17 00:00:00 2001 From: Hans Date: Thu, 7 Apr 2016 10:23:49 -0700 Subject: [PATCH] fix(sidenav): do not throw when there's no sidenav. (#270) Fixes #269. --- src/components/sidenav/sidenav.spec.ts | 74 +++++++++++++++++++++----- src/components/sidenav/sidenav.ts | 8 --- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/components/sidenav/sidenav.spec.ts b/src/components/sidenav/sidenav.spec.ts index a3e50fdcea33..63eafc2f9d88 100644 --- a/src/components/sidenav/sidenav.spec.ts +++ b/src/components/sidenav/sidenav.spec.ts @@ -1,4 +1,5 @@ import { + iit, it, describe, expect, @@ -13,6 +14,7 @@ import { import {XHR} from 'angular2/src/compiler/xhr'; import { Component, + Type, ViewMetadata } from 'angular2/core'; @@ -28,7 +30,7 @@ function fakeAsyncAdaptor(fn: () => void) { /** * Create a ComponentFixture from the builder. This takes a template and a style for sidenav. */ -function createFixture(builder: TestComponentBuilder, +function createFixture(appType: Type, builder: TestComponentBuilder, template: string, style: string): ComponentFixture { let fixture: ComponentFixture = null; // Remove the styles (which remove the animations/transitions). @@ -38,7 +40,7 @@ function createFixture(builder: TestComponentBuilder, styles: [style], directives: [MdSidenav], })) - .createAsync(BasicTestApp).then((f: ComponentFixture) => { fixture = f; }); + .createAsync(appType).then((f: ComponentFixture) => { fixture = f; }); tick(); return fixture; @@ -81,7 +83,7 @@ export function main() { describe('methods', () => { it('should be able to open and close', fakeAsyncAdaptor(() => { - let fixture = createFixture(builder, template, style); + let fixture = createFixture(BasicTestApp, builder, template, style); let testComponent: BasicTestApp = fixture.debugElement.componentInstance; let openButtonElement = fixture.debugElement.query(By.css('.open')); @@ -130,12 +132,12 @@ export function main() { })); it('open/close() return a promise that resolves after animation end', fakeAsyncAdaptor(() => { - let fixture = createFixture(builder, template, style); + let fixture = createFixture(BasicTestApp, builder, template, style); let sidenav: MdSidenav = fixture.debugElement .query(By.directive(MdSidenav)).componentInstance; let called = false; - sidenav.open().then((_: any) => { + sidenav.open().then(() => { called = true; }); @@ -145,7 +147,7 @@ export function main() { expect(called).toBe(true); called = false; - sidenav.close().then((_: any) => { + sidenav.close().then(() => { called = true; }); @@ -157,7 +159,7 @@ export function main() { })); it('open/close() twice returns the same promise', fakeAsyncAdaptor(() => { - let fixture = createFixture(builder, template, style); + let fixture = createFixture(BasicTestApp, builder, template, style); let sidenav: MdSidenav = fixture.debugElement .query(By.directive(MdSidenav)).componentInstance; @@ -172,19 +174,18 @@ export function main() { })); it('open() then close() cancel animations when called too fast', fakeAsyncAdaptor(() => { - let fixture = createFixture(builder, template, style); + let fixture = createFixture(BasicTestApp, builder, template, style); let sidenav: MdSidenav = fixture.debugElement .query(By.directive(MdSidenav)).componentInstance; - let closePromise: Promise; let openCalled = false; let openCancelled = false; let closeCalled = false; - sidenav.open().then((_: any) => { openCalled = true; }, () => { openCancelled = true; }); + sidenav.open().then(() => { openCalled = true; }, () => { openCancelled = true; }); // We do not call transition end, close directly. - closePromise = sidenav.close().then((_: any) => { closeCalled = true; }); + sidenav.close().then(() => { closeCalled = true; }); endSidenavTransition(fixture); tick(); @@ -196,7 +197,7 @@ export function main() { })); it('close() then open() cancel animations when called too fast', fakeAsyncAdaptor(() => { - let fixture = createFixture(builder, template, style); + let fixture = createFixture(BasicTestApp, builder, template, style); let sidenav: MdSidenav = fixture.debugElement .query(By.directive(MdSidenav)).componentInstance; @@ -210,9 +211,9 @@ export function main() { tick(); // Then close and check behavior. - sidenav.close().then((_: any) => { closeCalled = true; }, () => { closeCancelled = true; }); + sidenav.close().then(() => { closeCalled = true; }, () => { closeCancelled = true; }); // We do not call transition end, open directly. - sidenav.open().then((_: any) => { openCalled = true; }); + sidenav.open().then(() => { openCalled = true; }); endSidenavTransition(fixture); tick(); @@ -222,10 +223,55 @@ export function main() { expect(openCalled).toBe(true); tick(); })); + + it('does not throw when created without a sidenav', fakeAsyncAdaptor(() => { + expect(() => { + let fixture = createFixture(SidenavLayoutNoSidenavTestApp, builder, template, style); + fixture.detectChanges(); + tick(); + }).not.toThrow(); + })); + + it('does throw when created with two sidenav on the same side', fakeAsyncAdaptor(() => { + expect(() => { + let fixture = createFixture(SidenavLayoutTwoSidenavTestApp, builder, template, style); + fixture.detectChanges(); + tick(); + }).toThrow(); + })); }); }); } + +/** Test component that contains an MdSidenavLayout but no MdSidenav. */ +@Component({ + selector: 'test-app', + directives: [MD_SIDENAV_DIRECTIVES], + template: ` + + + `, +}) +class SidenavLayoutNoSidenavTestApp { +} + + +/** Test component that contains an MdSidenavLayout and 2 MdSidenav on the same side. */ +@Component({ + selector: 'test-app', + directives: [MD_SIDENAV_DIRECTIVES], + template: ` + + + + + `, +}) +class SidenavLayoutTwoSidenavTestApp { +} + + /** Test component that contains an MdSidenavLayout and one MdSidenav. */ @Component({ selector: 'test-app', diff --git a/src/components/sidenav/sidenav.ts b/src/components/sidenav/sidenav.ts index e6e99460e344..28a50ac25dda 100644 --- a/src/components/sidenav/sidenav.ts +++ b/src/components/sidenav/sidenav.ts @@ -19,11 +19,6 @@ import {Dir} from '../../core/rtl/dir'; import {PromiseCompleter} from 'angular2/src/facade/promise'; -/** - * Exception thrown when a MdSidenavLayout is missing both sidenavs. - */ -export class MdMissingSidenavException extends BaseException {} - /** * Exception thrown when two MdSidenav are matching the same side. */ @@ -286,9 +281,6 @@ export class MdSidenavLayout implements AfterContentInit { */ private _validateDrawers() { this._start = this._end = null; - if (this._sidenavs.length === 0) { - throw new MdMissingSidenavException(); - } // Ensure that we have at most one start and one end sidenav. this._sidenavs.forEach(sidenav => {