Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(drawer): re-add openedStart and closedStart events #7747

Merged
merged 1 commit into from
Nov 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/demo-app/drawer/drawer-demo.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h2>Basic Use Case</h2>

<mat-drawer-container class="demo-drawer-container">
<mat-drawer #start (open)="myinput.focus()" mode="side">
<mat-drawer #start (opened)="myinput.focus()" mode="side">
Start Side Drawer
<br>
<button mat-button (click)="start.close()">Close</button>
Expand Down
96 changes: 83 additions & 13 deletions src/lib/sidenav/drawer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,45 +28,98 @@ describe('MatDrawer', () => {
}));

describe('methods', () => {
it('should be able to open and close', fakeAsync(() => {
let fixture = TestBed.createComponent(BasicTestApp);
it('should be able to open', fakeAsync(() => {
const fixture = TestBed.createComponent(BasicTestApp);

fixture.detectChanges();

let testComponent: BasicTestApp = fixture.debugElement.componentInstance;
let drawer = fixture.debugElement.query(By.directive(MatDrawer));
let drawerBackdropElement = fixture.debugElement.query(By.css('.mat-drawer-backdrop'));
const testComponent: BasicTestApp = fixture.debugElement.componentInstance;
const drawer = fixture.debugElement.query(By.directive(MatDrawer));
const drawerBackdropElement = fixture.debugElement.query(By.css('.mat-drawer-backdrop'));

drawerBackdropElement.nativeElement.style.transition = 'none';
fixture.debugElement.query(By.css('.open')).nativeElement.click();
fixture.detectChanges();

expect(testComponent.openCount).toBe(0);
expect(testComponent.closeCount).toBe(0);
expect(testComponent.openStartCount).toBe(0);

tick();
expect(testComponent.openStartCount).toBe(1);
fixture.detectChanges();

expect(testComponent.openCount).toBe(1);
expect(testComponent.closeCount).toBe(0);
expect(testComponent.openStartCount).toBe(1);
expect(getComputedStyle(drawer.nativeElement).visibility).toBe('visible');
expect(getComputedStyle(drawerBackdropElement.nativeElement).visibility).toBe('visible');
}));

it('should be able to close', fakeAsync(() => {
const fixture = TestBed.createComponent(BasicTestApp);

fixture.detectChanges();

const testComponent: BasicTestApp = fixture.debugElement.componentInstance;
const drawer = fixture.debugElement.query(By.directive(MatDrawer));
const drawerBackdropElement = fixture.debugElement.query(By.css('.mat-drawer-backdrop'));

drawerBackdropElement.nativeElement.style.transition = 'none';
fixture.debugElement.query(By.css('.open')).nativeElement.click();
fixture.detectChanges();
tick();
fixture.detectChanges();

fixture.debugElement.query(By.css('.close')).nativeElement.click();
fixture.detectChanges();

expect(testComponent.openCount).toBe(1);
expect(testComponent.closeCount).toBe(0);
expect(testComponent.closeStartCount).toBe(0);

tick();
expect(testComponent.closeStartCount).toBe(1);
fixture.detectChanges();

expect(testComponent.openCount).toBe(1);
expect(testComponent.closeCount).toBe(1);
expect(testComponent.closeStartCount).toBe(1);
expect(getComputedStyle(drawer.nativeElement).visibility).toBe('hidden');
expect(getComputedStyle(drawerBackdropElement.nativeElement).visibility).toBe('hidden');
}));

it('should resolve the open method promise with an object', fakeAsync(() => {
const fixture = TestBed.createComponent(BasicTestApp);
fixture.detectChanges();
const drawer = fixture.debugElement.query(By.directive(MatDrawer));

drawer.componentInstance.open().then(result => {
expect(result).toBeTruthy();
expect(result.type).toBe('open');
expect(result.animationFinished).toBe(true);
});
fixture.detectChanges();
tick();
fixture.detectChanges();
}));

it('should resolve the close method promise with an object', fakeAsync(() => {
const fixture = TestBed.createComponent(BasicTestApp);
fixture.detectChanges();
const drawer = fixture.debugElement.query(By.directive(MatDrawer));

drawer.componentInstance.open();
fixture.detectChanges();
tick();
fixture.detectChanges();

drawer.componentInstance.close().then(result => {
expect(result).toBeTruthy();
expect(result.type).toBe('close');
expect(result.animationFinished).toBe(true);
});
fixture.detectChanges();
tick();
fixture.detectChanges();
}));

it('should be able to close while the open animation is running', fakeAsync(() => {
const fixture = TestBed.createComponent(BasicTestApp);
fixture.detectChanges();
Expand Down Expand Up @@ -139,13 +192,16 @@ describe('MatDrawer', () => {
tick();

expect(testComponent.openCount).toBe(1, 'Expected one open event.');
expect(testComponent.openStartCount).toBe(1, 'Expected one open start event.');
expect(testComponent.closeCount).toBe(0, 'Expected no close events.');
expect(testComponent.closeStartCount).toBe(0, 'Expected no close start events.');

dispatchKeyboardEvent(drawer.nativeElement, 'keydown', ESCAPE);
fixture.detectChanges();
tick();

expect(testComponent.closeCount).toBe(1, 'Expected one close event.');
expect(testComponent.closeStartCount).toBe(1, 'Expected one close start event.');
}));

it('should fire the open event when open on init', fakeAsync(() => {
Expand All @@ -172,6 +228,7 @@ describe('MatDrawer', () => {
tick();

expect(testComponent.closeCount).toBe(0);
expect(testComponent.closeStartCount).toBe(0);
}));

it('should not close by clicking on the backdrop when disableClose is set', fakeAsync(() => {
Expand All @@ -189,6 +246,7 @@ describe('MatDrawer', () => {
tick();

expect(testComponent.closeCount).toBe(0);
expect(testComponent.closeStartCount).toBe(0);
}));

it('should restore focus on close if focus is inside drawer', fakeAsync(() => {
Expand Down Expand Up @@ -490,17 +548,21 @@ class DrawerContainerTwoDrawerTestApp {
<mat-drawer-container (backdropClick)="backdropClicked()">
<mat-drawer #drawer position="start"
(opened)="open()"
(closed)="close()">
(openedStart)="openStart()"
(closed)="close()"
(closedStart)="closeStart()">
<button #drawerButton>Content.</button>
</mat-drawer>
<button (click)="drawer.open()" class="open" #openButton></button>
<button (click)="drawer.close()" class="close" #closeButton></button>
</mat-drawer-container>`,
})
class BasicTestApp {
openCount: number = 0;
closeCount: number = 0;
backdropClickedCount: number = 0;
openCount = 0;
openStartCount = 0;
closeCount = 0;
closeStartCount = 0;
backdropClickedCount = 0;

@ViewChild('drawerButton') drawerButton: ElementRef;
@ViewChild('openButton') openButton: ElementRef;
Expand All @@ -510,10 +572,18 @@ class BasicTestApp {
this.openCount++;
}

openStart() {
this.openStartCount++;
}

close() {
this.closeCount++;
}

closeStart() {
this.closeStartCount++;
}

backdropClicked() {
this.backdropClickedCount++;
}
Expand Down
28 changes: 24 additions & 4 deletions src/lib/sidenav/drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,21 +189,39 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
return this.openedChange.pipe(filter(o => o), map(() => {}));
}

/** Event emitted when the drawer has started opening. */
@Output()
get openedStart(): Observable<void> {
return this._animationStarted.pipe(
filter(e => e.fromState !== e.toState && e.toState.indexOf('open') === 0),
map(() => {})
);
}

/** Event emitted when the drawer has been closed. */
@Output('closed')
get _closedStream(): Observable<void> {
return this.openedChange.pipe(filter(o => !o), map(() => {}));
}

/** Event emitted when the drawer has started closing. */
@Output()
get closedStart(): Observable<void> {
return this._animationStarted.pipe(
filter(e => e.fromState !== e.toState && e.toState === 'void'),
map(() => {})
);
}

/**
* Event emitted when the drawer is fully opened.
* @deprecated Use `openedChange` instead.
* @deprecated Use `opened` instead.
*/
@Output('open') onOpen = this._openedStream;

/**
* Event emitted when the drawer is fully closed.
* @deprecated Use `openedChange` instead.
* @deprecated Use `closed` instead.
*/
@Output('close') onClose = this._closedStream;

Expand Down Expand Up @@ -323,8 +341,10 @@ export class MatDrawer implements AfterContentInit, OnDestroy {

// TODO(crisbeto): This promise is here for backwards-compatibility.
// It should be removed next time we do breaking changes in the drawer.
return new Promise(resolve => {
(isOpen ? this.onOpen : this.onClose).pipe(first()).subscribe(resolve);
return new Promise<any>(resolve => {
this.openedChange.pipe(first()).subscribe(open => {
resolve(new MatDrawerToggleResult(open ? 'open' : 'close', true));
});
});
}

Expand Down