Skip to content

Commit cc2b223

Browse files
hansljelbourn
authored andcommitted
fix(sidenav): do not throw when there's no sidenav. (#270)
Fixes #269.
1 parent b9f5a43 commit cc2b223

File tree

2 files changed

+60
-22
lines changed

2 files changed

+60
-22
lines changed

src/components/sidenav/sidenav.spec.ts

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
iit,
23
it,
34
describe,
45
expect,
@@ -13,6 +14,7 @@ import {
1314
import {XHR} from 'angular2/src/compiler/xhr';
1415
import {
1516
Component,
17+
Type,
1618
ViewMetadata
1719
} from 'angular2/core';
1820

@@ -28,7 +30,7 @@ function fakeAsyncAdaptor(fn: () => void) {
2830
/**
2931
* Create a ComponentFixture from the builder. This takes a template and a style for sidenav.
3032
*/
31-
function createFixture(builder: TestComponentBuilder,
33+
function createFixture(appType: Type, builder: TestComponentBuilder,
3234
template: string, style: string): ComponentFixture {
3335
let fixture: ComponentFixture = null;
3436
// Remove the styles (which remove the animations/transitions).
@@ -38,7 +40,7 @@ function createFixture(builder: TestComponentBuilder,
3840
styles: [style],
3941
directives: [MdSidenav],
4042
}))
41-
.createAsync(BasicTestApp).then((f: ComponentFixture) => { fixture = f; });
43+
.createAsync(appType).then((f: ComponentFixture) => { fixture = f; });
4244
tick();
4345

4446
return fixture;
@@ -81,7 +83,7 @@ export function main() {
8183

8284
describe('methods', () => {
8385
it('should be able to open and close', fakeAsyncAdaptor(() => {
84-
let fixture = createFixture(builder, template, style);
86+
let fixture = createFixture(BasicTestApp, builder, template, style);
8587

8688
let testComponent: BasicTestApp = fixture.debugElement.componentInstance;
8789
let openButtonElement = fixture.debugElement.query(By.css('.open'));
@@ -130,12 +132,12 @@ export function main() {
130132
}));
131133

132134
it('open/close() return a promise that resolves after animation end', fakeAsyncAdaptor(() => {
133-
let fixture = createFixture(builder, template, style);
135+
let fixture = createFixture(BasicTestApp, builder, template, style);
134136
let sidenav: MdSidenav = fixture.debugElement
135137
.query(By.directive(MdSidenav)).componentInstance;
136138
let called = false;
137139

138-
sidenav.open().then((_: any) => {
140+
sidenav.open().then(() => {
139141
called = true;
140142
});
141143

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

147149
called = false;
148-
sidenav.close().then((_: any) => {
150+
sidenav.close().then(() => {
149151
called = true;
150152
});
151153

@@ -157,7 +159,7 @@ export function main() {
157159
}));
158160

159161
it('open/close() twice returns the same promise', fakeAsyncAdaptor(() => {
160-
let fixture = createFixture(builder, template, style);
162+
let fixture = createFixture(BasicTestApp, builder, template, style);
161163
let sidenav: MdSidenav = fixture.debugElement
162164
.query(By.directive(MdSidenav)).componentInstance;
163165

@@ -172,19 +174,18 @@ export function main() {
172174
}));
173175

174176
it('open() then close() cancel animations when called too fast', fakeAsyncAdaptor(() => {
175-
let fixture = createFixture(builder, template, style);
177+
let fixture = createFixture(BasicTestApp, builder, template, style);
176178
let sidenav: MdSidenav = fixture.debugElement
177179
.query(By.directive(MdSidenav)).componentInstance;
178180

179-
let closePromise: Promise<void>;
180181
let openCalled = false;
181182
let openCancelled = false;
182183
let closeCalled = false;
183184

184-
sidenav.open().then((_: any) => { openCalled = true; }, () => { openCancelled = true; });
185+
sidenav.open().then(() => { openCalled = true; }, () => { openCancelled = true; });
185186

186187
// We do not call transition end, close directly.
187-
closePromise = sidenav.close().then((_: any) => { closeCalled = true; });
188+
sidenav.close().then(() => { closeCalled = true; });
188189

189190
endSidenavTransition(fixture);
190191
tick();
@@ -196,7 +197,7 @@ export function main() {
196197
}));
197198

198199
it('close() then open() cancel animations when called too fast', fakeAsyncAdaptor(() => {
199-
let fixture = createFixture(builder, template, style);
200+
let fixture = createFixture(BasicTestApp, builder, template, style);
200201
let sidenav: MdSidenav = fixture.debugElement
201202
.query(By.directive(MdSidenav)).componentInstance;
202203

@@ -210,9 +211,9 @@ export function main() {
210211
tick();
211212

212213
// Then close and check behavior.
213-
sidenav.close().then((_: any) => { closeCalled = true; }, () => { closeCancelled = true; });
214+
sidenav.close().then(() => { closeCalled = true; }, () => { closeCancelled = true; });
214215
// We do not call transition end, open directly.
215-
sidenav.open().then((_: any) => { openCalled = true; });
216+
sidenav.open().then(() => { openCalled = true; });
216217

217218
endSidenavTransition(fixture);
218219
tick();
@@ -222,10 +223,55 @@ export function main() {
222223
expect(openCalled).toBe(true);
223224
tick();
224225
}));
226+
227+
it('does not throw when created without a sidenav', fakeAsyncAdaptor(() => {
228+
expect(() => {
229+
let fixture = createFixture(SidenavLayoutNoSidenavTestApp, builder, template, style);
230+
fixture.detectChanges();
231+
tick();
232+
}).not.toThrow();
233+
}));
234+
235+
it('does throw when created with two sidenav on the same side', fakeAsyncAdaptor(() => {
236+
expect(() => {
237+
let fixture = createFixture(SidenavLayoutTwoSidenavTestApp, builder, template, style);
238+
fixture.detectChanges();
239+
tick();
240+
}).toThrow();
241+
}));
225242
});
226243
});
227244
}
228245

246+
247+
/** Test component that contains an MdSidenavLayout but no MdSidenav. */
248+
@Component({
249+
selector: 'test-app',
250+
directives: [MD_SIDENAV_DIRECTIVES],
251+
template: `
252+
<md-sidenav-layout>
253+
</md-sidenav-layout>
254+
`,
255+
})
256+
class SidenavLayoutNoSidenavTestApp {
257+
}
258+
259+
260+
/** Test component that contains an MdSidenavLayout and 2 MdSidenav on the same side. */
261+
@Component({
262+
selector: 'test-app',
263+
directives: [MD_SIDENAV_DIRECTIVES],
264+
template: `
265+
<md-sidenav-layout>
266+
<md-sidenav> </md-sidenav>
267+
<md-sidenav> </md-sidenav>
268+
</md-sidenav-layout>
269+
`,
270+
})
271+
class SidenavLayoutTwoSidenavTestApp {
272+
}
273+
274+
229275
/** Test component that contains an MdSidenavLayout and one MdSidenav. */
230276
@Component({
231277
selector: 'test-app',

src/components/sidenav/sidenav.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@ import {Dir} from '../../core/rtl/dir';
1919
import {PromiseCompleter} from 'angular2/src/facade/promise';
2020

2121

22-
/**
23-
* Exception thrown when a MdSidenavLayout is missing both sidenavs.
24-
*/
25-
export class MdMissingSidenavException extends BaseException {}
26-
2722
/**
2823
* Exception thrown when two MdSidenav are matching the same side.
2924
*/
@@ -286,9 +281,6 @@ export class MdSidenavLayout implements AfterContentInit {
286281
*/
287282
private _validateDrawers() {
288283
this._start = this._end = null;
289-
if (this._sidenavs.length === 0) {
290-
throw new MdMissingSidenavException();
291-
}
292284

293285
// Ensure that we have at most one start and one end sidenav.
294286
this._sidenavs.forEach(sidenav => {

0 commit comments

Comments
 (0)