Skip to content

Commit

Permalink
fix(sidenav): do not throw when there's no sidenav. (#270)
Browse files Browse the repository at this point in the history
Fixes #269.
  • Loading branch information
hansl authored and jelbourn committed Apr 7, 2016
1 parent b9f5a43 commit cc2b223
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 22 deletions.
74 changes: 60 additions & 14 deletions src/components/sidenav/sidenav.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
iit,
it,
describe,
expect,
Expand All @@ -13,6 +14,7 @@ import {
import {XHR} from 'angular2/src/compiler/xhr';
import {
Component,
Type,
ViewMetadata
} from 'angular2/core';

Expand All @@ -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).
Expand All @@ -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;
Expand Down Expand Up @@ -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'));
Expand Down Expand Up @@ -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;
});

Expand All @@ -145,7 +147,7 @@ export function main() {
expect(called).toBe(true);

called = false;
sidenav.close().then((_: any) => {
sidenav.close().then(() => {
called = true;
});

Expand All @@ -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;

Expand All @@ -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<void>;
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();
Expand All @@ -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;

Expand All @@ -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();
Expand All @@ -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: `
<md-sidenav-layout>
</md-sidenav-layout>
`,
})
class SidenavLayoutNoSidenavTestApp {
}


/** Test component that contains an MdSidenavLayout and 2 MdSidenav on the same side. */
@Component({
selector: 'test-app',
directives: [MD_SIDENAV_DIRECTIVES],
template: `
<md-sidenav-layout>
<md-sidenav> </md-sidenav>
<md-sidenav> </md-sidenav>
</md-sidenav-layout>
`,
})
class SidenavLayoutTwoSidenavTestApp {
}


/** Test component that contains an MdSidenavLayout and one MdSidenav. */
@Component({
selector: 'test-app',
Expand Down
8 changes: 0 additions & 8 deletions src/components/sidenav/sidenav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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 => {
Expand Down

0 comments on commit cc2b223

Please sign in to comment.