Skip to content

Commit

Permalink
feat(tabs): adds e2e tests for tabs (#650)
Browse files Browse the repository at this point in the history
closes #549
  • Loading branch information
robertmesserle authored Jul 7, 2016
1 parent bbbc87f commit 3c74ae0
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 21 deletions.
97 changes: 97 additions & 0 deletions e2e/components/tabs/tabs.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import ElementArrayFinder = protractor.ElementArrayFinder;
import ElementFinder = protractor.ElementFinder;

describe('tabs', () => {
describe('basic behavior', () => {
let tabGroup: ElementFinder;
let tabLabels: ElementArrayFinder;
let tabBodies: ElementArrayFinder;

beforeEach(() => {
browser.get('/tabs');
tabGroup = element(by.css('md-tab-group'));
tabLabels = element.all(by.css('.md-tab-label'));
tabBodies = element.all(by.css('.md-tab-body'));
});

it('should change tabs when the label is clicked', () => {
tabLabels.get(1).click();
expect(getActiveStates(tabLabels)).toEqual([false, true, false]);
expect(getActiveStates(tabBodies)).toEqual([false, true, false]);

tabLabels.get(0).click();
expect(getActiveStates(tabLabels)).toEqual([true, false, false]);
expect(getActiveStates(tabBodies)).toEqual([true, false, false]);
});

it('should change focus with keyboard interaction', () => {
tabLabels.get(0).click();
expect(getFocusStates(tabLabels)).toEqual([true, false, false]);

pressKey(protractor.Key.RIGHT);
expect(getFocusStates(tabLabels)).toEqual([false, true, false]);

pressKey(protractor.Key.RIGHT);
expect(getFocusStates(tabLabels)).toEqual([false, false, true]);

pressKey(protractor.Key.RIGHT);
expect(getFocusStates(tabLabels)).toEqual([false, false, true]);

pressKey(protractor.Key.LEFT);
expect(getFocusStates(tabLabels)).toEqual([false, true, false]);

pressKey(protractor.Key.LEFT);
expect(getFocusStates(tabLabels)).toEqual([true, false, false]);

pressKey(protractor.Key.LEFT);
expect(getFocusStates(tabLabels)).toEqual([true, false, false]);
});
});
});

/**
* A helper function to perform the sendKey action
* @param key
*/
function pressKey(key: string) {
browser.actions().sendKeys(key).perform();
}

/**
* Returns an array of true/false that represents the focus states of the provided elements
* @param elements
* @returns {webdriver.promise.Promise<Promise<boolean>[]>|webdriver.promise.Promise<T[]>}
*/
function getFocusStates(elements: ElementArrayFinder) {
return elements.map(element => {
return element.getText().then(elementText => {
return browser.driver.switchTo().activeElement().getText().then(activeText => {
return activeText === elementText;
});
});
});
}

/**
* Returns an array of true/false that represents the active states for the provided elements
* @param elements
* @returns {webdriver.promise.Promise<Promise<boolean>[]>|webdriver.promise.Promise<T[]>}
*/
function getActiveStates(elements: ElementArrayFinder) {
return getClassStates(elements, 'md-active');
}

/**
* Returns an array of true/false values that represents whether the provided className is on
* each element
* @param elements
* @param className
* @returns {webdriver.promise.Promise<Promise<boolean>[]>|webdriver.promise.Promise<T[]>}
*/
function getClassStates(elements: ElementArrayFinder, className: string) {
return elements.map(element => {
return element.getAttribute('class').then(classes => {
return classes.split(/ +/g).indexOf(className) >= 0;
});
});
}
15 changes: 8 additions & 7 deletions src/components/tabs/tab-group.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<div class="md-tab-header" role="tablist"
(keydown.arrowRight)="focusNextTab()"
(keydown.arrowLeft)="focusPreviousTab()"
(keydown.enter)="selectedIndex = focusIndex">
(keydown)="handleKeydown($event)">
<div class="md-tab-label" role="tab" md-tab-label-wrapper
*ngFor="let tab of _tabs; let i = index"
[id]="_getTabLabelId(i)"
Expand All @@ -16,10 +14,13 @@
</div>
<div class="md-tab-body-wrapper">
<div class="md-tab-body"
*ngFor="let tab of tabs; let i = index"
[id]="getTabContentId(i)"
role="tabpanel"
*ngFor="let tab of _tabs; let i = index"
[id]="_getTabContentId(i)"
[class.md-active]="selectedIndex == i"
[attr.aria-labelledby]="getTabLabelId(i)">
<template role="tabpanel" [portalHost]="tab.content" [ngIf]="selectedIndex == i"></template>
[attr.aria-labelledby]="_getTabLabelId(i)">
<template [ngIf]="selectedIndex == i">
<template [portalHost]="tab.content"></template>
</template>
</div>
</div>
22 changes: 22 additions & 0 deletions src/components/tabs/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ import {MdInkBar} from './ink-bar';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';

// Due to a bug in the ChromeDriver, Angular 2 keyboard events are not triggered by `sendKeys`
// during E2E tests when using dot notation such as `(keydown.rightArrow)`. To get around this,
// we are temporarily using a single (keydown) handler.
// See: https://github.com/angular/angular/issues/9419
const RIGHT_ARROW = 39;
const LEFT_ARROW = 37;
const ENTER = 13;

/** Used to generate unique ID's for each tab component */
let nextId = 0;

Expand Down Expand Up @@ -159,6 +167,20 @@ export class MdTabGroup {
return `md-tab-content-${this._groupId}-${i}`;
}

handleKeydown(event: KeyboardEvent) {
switch (event.keyCode) {
case RIGHT_ARROW:
this.focusNextTab();
break;
case LEFT_ARROW:
this.focusPreviousTab();
break;
case ENTER:
this.selectedIndex = this.focusIndex;
break;
}
}

/** Increment the focus index by 1; prevent going over the number of tabs */
focusNextTab(): void {
if (this._labelWrappers && this.focusIndex < this._labelWrappers.length - 1) {
Expand Down
1 change: 1 addition & 0 deletions src/e2e-app/e2e-app/e2e-app.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<a md-list-item [routerLink]="['button']">Button</a>
<a md-list-item [routerLink]="['tabs']">Tabs</a>

<router-outlet></router-outlet>
14 changes: 0 additions & 14 deletions src/e2e-app/e2e-app/e2e-app.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import {Component} from '@angular/core';
import {ROUTER_DIRECTIVES} from '@angular/router';

import {Dir} from '@angular2-material/core/rtl/dir';
import {MdButton} from '@angular2-material/button/button';
import {MD_SIDENAV_DIRECTIVES} from '@angular2-material/sidenav/sidenav';
import {MD_LIST_DIRECTIVES} from '@angular2-material/list/list';
import {MdIcon} from '@angular2-material/icon/icon';
import {MdToolbar} from '@angular2-material/toolbar/toolbar';


@Component({
selector: 'home',
template: `
Expand All @@ -24,12 +16,6 @@ export class Home {}
templateUrl: 'e2e-app.html',
directives: [
ROUTER_DIRECTIVES,
Dir,
MdButton,
MdIcon,
MD_SIDENAV_DIRECTIVES,
MD_LIST_DIRECTIVES,
MdToolbar
],
pipes: []
})
Expand Down
2 changes: 2 additions & 0 deletions src/e2e-app/e2e-app/routes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {provideRouter, RouterConfig} from '@angular/router';
import {Home} from './e2e-app';
import {ButtonE2E} from '../button/button-e2e';
import {BasicTabs} from '../tabs/tabs-e2e';


export const routes: RouterConfig = [
{path: '', component: Home},
{path: 'button', component: ButtonE2E},
{path: 'tabs', component: BasicTabs},
];

export const E2E_APP_ROUTE_PROVIDER = provideRouter(routes);
16 changes: 16 additions & 0 deletions src/e2e-app/tabs/tabs-e2e.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<section>
<md-tab-group>
<md-tab>
<template md-tab-label>One</template>
<template md-tab-content>First tab's content</template>
</md-tab>
<md-tab>
<template md-tab-label>Two</template>
<template md-tab-content>Second tab's content</template>
</md-tab>
<md-tab>
<template md-tab-label>Three</template>
<template md-tab-content>Third tab's content</template>
</md-tab>
</md-tab-group>
</section>
10 changes: 10 additions & 0 deletions src/e2e-app/tabs/tabs-e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {Component} from '@angular/core';
import {MD_TABS_DIRECTIVES} from '@angular2-material/tabs/tabs';

@Component({
moduleId: module.id,
selector: 'tabs-e2e',
templateUrl: 'tabs-e2e.html',
directives: [MD_TABS_DIRECTIVES]
})
export class BasicTabs {}

0 comments on commit 3c74ae0

Please sign in to comment.