Implement user dashboard view
This changes the way the change list view is layed out (flexbox instead of tables) for a couple reasons: + Table elements (td, tr, etc.) cannot be arbitrarily appended to just any DOM node, which caused breakage when I originally attempted to use a <content> tag to bring in the header or group title content into gr-change-list-item. + The flexibility of flexbox allows us to style the change list much easier on smaller screens, so it was probably going to happen anyway. + Full-width (colspan="<total number of columns in the table>") rows for the headers is much more difficult when using elements outside of the gr-change-list-item brought in via <content> as described above. + gr-change-list-item was doing too much anyway. Feature: Issue 3700 Change-Id: I6536bf7d18adfa460507f8050a15d83e84af82a7
This commit is contained in:
parent
a75837c6b5
commit
7aa52d3d0a
@ -15,25 +15,22 @@ limitations under the License.
|
||||
-->
|
||||
|
||||
<link rel="import" href="../bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="../styles/gr-change-list-styles.html">
|
||||
<link rel="import" href="gr-date-formatter.html">
|
||||
|
||||
<dom-module id="gr-change-list-item">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: table-row;
|
||||
display: flex;
|
||||
}
|
||||
:host([selected]) {
|
||||
background-color: #d8EdF9;
|
||||
}
|
||||
th, td {
|
||||
.cell {
|
||||
border-bottom: 1px solid #eee;
|
||||
flex-shrink: 0;
|
||||
padding: .3em .5em;
|
||||
vertical-align: top;
|
||||
}
|
||||
th {
|
||||
background: #ddd;
|
||||
text-align: left;
|
||||
}
|
||||
a {
|
||||
color: var(--default-text-color);
|
||||
@ -64,48 +61,29 @@ limitations under the License.
|
||||
color: #D32F2F;
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[header]]">
|
||||
<th></th> <!-- keyboard position indicator -->
|
||||
<th>Subject</th>
|
||||
<th>Status</th>
|
||||
<th>Owner</th>
|
||||
<th>Project</th>
|
||||
<th>Branch</th>
|
||||
<th>Updated</th>
|
||||
<th>Size</th>
|
||||
<th title="Code-Review">CR</th>
|
||||
<th title="Verified">V</th>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!header]]">
|
||||
<td>
|
||||
<span class="positionIndicator">▶</span>
|
||||
</td>
|
||||
<td>
|
||||
<a href$="[[changeURL]]">[[change.subject]]</a>
|
||||
</td>
|
||||
<td>[[_computeChangeStatusString(change)]]</td>
|
||||
<td>
|
||||
<template is="dom-if" if="[[showAvatar]]">
|
||||
<img class="avatarImage" src$="[[_computeAvatarURL(change.owner)]]">
|
||||
</template>
|
||||
<a href$="[[_computeOwnerLink(change.owner.email)]]"
|
||||
title$="[[_computeOwnerTitle(change.owner)]]">[[change.owner.name]]</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href$="[[_computeProjectURL(change.project)]]">[[change.project]]</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href$="[[_computeProjectBranchURL(change.project, change.branch)]]">[[change.branch]]</a>
|
||||
</td>
|
||||
<td><gr-date-formatter date-str="[[change.updated]]"></gr-date-formatter></td>
|
||||
<td class="u-monospace">
|
||||
<span class="u-green"><span>+</span>[[change.insertions]]</span>,
|
||||
<span class="u-red"><span>-</span>[[change.deletions]]</span>
|
||||
</td>
|
||||
<td title="Code-Review"
|
||||
class$="[[_computeCodeReviewClass(change.labels.Code-Review)]]">[[_computeCodeReviewLabel(change.labels.Code-Review)]]</td>
|
||||
<td title="Verified" class="u-green">[[_computeVerifiedLabel(change.labels.Verified)]]</td>
|
||||
</template>
|
||||
<style include="gr-change-list-styles"></style>
|
||||
<span class="cell keyboard">
|
||||
<span class="positionIndicator">▶</span>
|
||||
</span>
|
||||
<a class="cell subject" href$="[[changeURL]]">[[change.subject]]</a>
|
||||
<span class="cell status">[[_computeChangeStatusString(change)]]</span>
|
||||
<span class="cell owner">
|
||||
<template is="dom-if" if="[[showAvatar]]">
|
||||
<img class="avatarImage" src$="[[_computeAvatarURL(change.owner)]]">
|
||||
</template>
|
||||
<a href$="[[_computeOwnerLink(change.owner.email)]]"
|
||||
title$="[[_computeOwnerTitle(change.owner)]]">[[change.owner.name]]</a>
|
||||
</span>
|
||||
<a class="cell project" href$="[[_computeProjectURL(change.project)]]">[[change.project]]</a>
|
||||
<a class="cell branch" href$="[[_computeProjectBranchURL(change.project, change.branch)]]">[[change.branch]]</a>
|
||||
<gr-date-formatter class="cell updated" date-str="[[change.updated]]"></gr-date-formatter>
|
||||
<span class="cell size u-monospace">
|
||||
<span class="u-green"><span>+</span>[[change.insertions]]</span>,
|
||||
<span class="u-red"><span>-</span>[[change.deletions]]</span>
|
||||
</span>
|
||||
<span title="Code-Review"
|
||||
class$="[[_computeCodeReviewClass(change.labels.Code-Review)]]">[[_computeCodeReviewLabel(change.labels.Code-Review)]]</span>
|
||||
<span class="cell verified u-green" title="Verified">[[_computeVerifiedLabel(change.labels.Verified)]]</span>
|
||||
</template>
|
||||
<script>
|
||||
(function() {
|
||||
@ -115,11 +93,6 @@ limitations under the License.
|
||||
is: 'gr-change-list-item',
|
||||
|
||||
properties: {
|
||||
header: {
|
||||
type: Boolean,
|
||||
reflectToAttribute: true,
|
||||
value: false,
|
||||
},
|
||||
selected: {
|
||||
type: Boolean,
|
||||
reflectToAttribute: true,
|
||||
@ -147,24 +120,40 @@ limitations under the License.
|
||||
},
|
||||
|
||||
_computeChangeStatusString: function(change) {
|
||||
if (!change.mergeable) {
|
||||
if (change.mergeable != null && change.mergeable == false) {
|
||||
return 'Merge Conflict';
|
||||
}
|
||||
if (change.status == Changes.Status.MERGED) {
|
||||
return 'Merged';
|
||||
}
|
||||
if (change.status == Changes.Status.DRAFT) {
|
||||
return 'Draft';
|
||||
}
|
||||
if (change.status == Changes.Status.ABANDONED) {
|
||||
return 'Abandoned';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
_computeCodeReviewClass: function(codeReview) {
|
||||
if (!codeReview) { return ''; }
|
||||
if (codeReview.approved) {
|
||||
return 'u-green';
|
||||
// Mimic a Set.
|
||||
var classes = {
|
||||
'cell': true,
|
||||
'codeReview': true,
|
||||
};
|
||||
if (codeReview) {
|
||||
if (codeReview.approved) {
|
||||
classes['u-green'] = true;
|
||||
}
|
||||
if (codeReview.value == 1) {
|
||||
classes['u-monospace'] = true;
|
||||
classes['u-green'] = true;
|
||||
} else if (codeReview.value == -1) {
|
||||
classes['u-monospace'] = true;
|
||||
classes['u-red'] = true;
|
||||
}
|
||||
}
|
||||
if (codeReview.value == 1) {
|
||||
return 'u-monospace u-green';
|
||||
}
|
||||
if (codeReview.value == -1) {
|
||||
return 'u-monospace u-red';
|
||||
}
|
||||
return '';
|
||||
return Object.keys(classes).sort().join(' ');
|
||||
},
|
||||
|
||||
_computeCodeReviewLabel: function(codeReview) {
|
||||
|
@ -16,20 +16,51 @@ limitations under the License.
|
||||
|
||||
<link rel="import" href="../bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="../bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
|
||||
<link rel="import" href="../styles/gr-change-list-styles.html">
|
||||
<link rel="import" href="gr-change-list-item.html">
|
||||
|
||||
<dom-module id="gr-change-list">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: table;
|
||||
border-collapse: collapse;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.headerRow {
|
||||
display: flex;
|
||||
}
|
||||
.topHeader,
|
||||
.groupHeader {
|
||||
border-bottom: 1px solid #eee;
|
||||
font-weight: bold;
|
||||
padding: .3em .5em;
|
||||
}
|
||||
.topHeader {
|
||||
background-color: #ddd;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
<gr-change-list-item header></gr-change-list-item>
|
||||
<template is="dom-repeat" items="{{changes}}" as="change">
|
||||
<gr-change-list-item change="[[change]]"
|
||||
selected="[[_isSelected(index)]]"></gr-change-list-item>
|
||||
<style include="gr-change-list-styles"></style>
|
||||
<div class="headerRow">
|
||||
<span class="topHeader keyboard"></span> <!-- keyboard position indicator -->
|
||||
<span class="topHeader subject">Subject</span>
|
||||
<span class="topHeader status">Status</span>
|
||||
<span class="topHeader owner">Owner</span>
|
||||
<span class="topHeader project">Project</span>
|
||||
<span class="topHeader branch">Branch</span>
|
||||
<span class="topHeader updated">Updated</span>
|
||||
<span class="topHeader size">Size</span>
|
||||
<span class="topHeader codeReview" title="Code-Review">CR</span>
|
||||
<span class="topHeader verified" title="Verified">V</span>
|
||||
</div>
|
||||
<template is="dom-repeat" items="{{groups}}" as="changeGroup" index-as="groupIndex">
|
||||
<template is="dom-if" if="[[_groupTitle(groupIndex)]]">
|
||||
<div class="groupHeader">[[_groupTitle(groupIndex)]]</div>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[changeGroup]]" as="change">
|
||||
<gr-change-list-item change="[[change]]"
|
||||
selected="[[_isSelected(groupIndex, index)]]"></gr-change-list-item>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@ -53,13 +84,25 @@ limitations under the License.
|
||||
* An array of ChangeInfo objects to render.
|
||||
* https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#change-info
|
||||
*/
|
||||
changes: Array,
|
||||
changes: {
|
||||
type: Array,
|
||||
observer: '_changesChanged',
|
||||
},
|
||||
/**
|
||||
* ChangeInfo objects grouped into arrays. The groups and changes
|
||||
* properties should not be used together.
|
||||
*/
|
||||
groups: Array,
|
||||
keyEventTarget: {
|
||||
type: Object,
|
||||
value: function() {
|
||||
return document.body;
|
||||
}
|
||||
},
|
||||
groupTitles: {
|
||||
type: Array,
|
||||
value: [],
|
||||
},
|
||||
selectedIndex: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
@ -71,13 +114,22 @@ limitations under the License.
|
||||
'j k o enter': '_handleKey',
|
||||
},
|
||||
|
||||
_isSelected: function(index) {
|
||||
_isSelected: function(groupIndex, index) {
|
||||
return index == this.selectedIndex;
|
||||
},
|
||||
|
||||
_changesChanged: function(changes) {
|
||||
this.groups = [changes];
|
||||
},
|
||||
|
||||
_groupTitle: function(groupIndex) {
|
||||
if (groupIndex > this.groupTitles.length - 1) { return null; }
|
||||
return this.groupTitles[groupIndex];
|
||||
},
|
||||
|
||||
_selectedIndexChanged: function(value) {
|
||||
// Don't re-render the entire list.
|
||||
var changeEls = this._getNonHeaderListItems();
|
||||
var changeEls = this._getListItems();
|
||||
for (var i = 0; i < changeEls.length; i++) {
|
||||
changeEls[i].toggleAttribute('selected', i == value);
|
||||
}
|
||||
@ -86,7 +138,11 @@ limitations under the License.
|
||||
_handleKey: function(e) {
|
||||
if (util.shouldSupressKeyboardShortcut(e)) { return; }
|
||||
|
||||
var len = (this.changes && this.changes.length) || 0;
|
||||
if (this.groups == null) { return; }
|
||||
var len = 0;
|
||||
this.groups.forEach(function(group) {
|
||||
len += group.length;
|
||||
});
|
||||
switch(e.detail.combo) {
|
||||
case 'j':
|
||||
if (this.selectedIndex == len - 1) { return; }
|
||||
@ -104,16 +160,15 @@ limitations under the License.
|
||||
},
|
||||
|
||||
_changeURLForIndex: function(index) {
|
||||
var changeEls = this._getNonHeaderListItems();
|
||||
var changeEls = this._getListItems();
|
||||
if (index < changeEls.length && changeEls[index]) {
|
||||
return changeEls[index].changeURL;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
_getNonHeaderListItems: function() {
|
||||
return Polymer.dom(this.root).querySelectorAll(
|
||||
'gr-change-list-item:not([header])');
|
||||
_getListItems: function() {
|
||||
return Polymer.dom(this.root).querySelectorAll('gr-change-list-item');
|
||||
},
|
||||
|
||||
});
|
||||
|
@ -18,6 +18,17 @@ limitations under the License.
|
||||
|
||||
<dom-module id="gr-dashboard-view">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
background-color: var(--view-background-color);
|
||||
display: block;
|
||||
margin: 0 1.25rem;
|
||||
}
|
||||
gr-change-list {
|
||||
margin-top: 1em;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<iron-ajax id="xhr"
|
||||
auto
|
||||
url="/changes/"
|
||||
@ -25,6 +36,8 @@ limitations under the License.
|
||||
last-response="{{_results}}"
|
||||
json-prefix=")]}'"
|
||||
debounce-duration="300"></iron-ajax>
|
||||
<gr-change-list groups="{{_results}}"
|
||||
group-titles="[[_groupTitles]]"></gr-change-list>
|
||||
</template>
|
||||
<script>
|
||||
(function() {
|
||||
@ -35,6 +48,14 @@ limitations under the License.
|
||||
|
||||
properties: {
|
||||
_results: Array,
|
||||
_groupTitles: {
|
||||
type: Array,
|
||||
value: [
|
||||
'Outgoing reviews',
|
||||
'Incoming reviews',
|
||||
'Recently closed',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
_computeQueryParams: function() {
|
||||
|
@ -25,6 +25,13 @@ Changes.DiffType = {
|
||||
REWRITE: 'REWRITE',
|
||||
};
|
||||
|
||||
Changes.Status = {
|
||||
NEW: 'NEW',
|
||||
MERGED: 'MERGED',
|
||||
ABANDONED: 'ABANDONED',
|
||||
DRAFT: 'DRAFT',
|
||||
};
|
||||
|
||||
// Must be kept in sync with the ListChangesOption enum and protobuf.
|
||||
Changes.ListChangesOption = {
|
||||
LABELS: 0,
|
||||
|
63
polygerrit-ui/app/styles/gr-change-list-styles.html
Normal file
63
polygerrit-ui/app/styles/gr-change-list-styles.html
Normal file
@ -0,0 +1,63 @@
|
||||
<!--
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<dom-module id="gr-change-list-styles">
|
||||
<template>
|
||||
<style>
|
||||
.keyboard {
|
||||
width: 2em;
|
||||
}
|
||||
.subject {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
.status {
|
||||
width: 9em;
|
||||
}
|
||||
.owner {
|
||||
width: 15em;
|
||||
}
|
||||
.project,
|
||||
.branch {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.project {
|
||||
width: 10em;
|
||||
}
|
||||
.branch {
|
||||
width: 7em;
|
||||
}
|
||||
.updated {
|
||||
width: 6em;
|
||||
text-align: right;
|
||||
}
|
||||
.size {
|
||||
width: 9em;
|
||||
text-align: right;
|
||||
}
|
||||
.codeReview {
|
||||
width: 2.6em;
|
||||
text-align: center;
|
||||
}
|
||||
.verified {
|
||||
width: 2em;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</template>
|
||||
</dom-module>
|
@ -20,6 +20,7 @@ limitations under the License.
|
||||
|
||||
<script src="../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
|
||||
<script src="../../bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../scripts/changes.js"></script>
|
||||
<script src="../scripts/fake-app.js"></script>
|
||||
|
||||
<link rel="import" href="../elements/gr-change-list-item.html">
|
||||
@ -42,15 +43,22 @@ limitations under the License.
|
||||
assert.equal(element._computeChangeStatusString({mergeable: true}), '');
|
||||
assert.equal(element._computeChangeStatusString({mergeable: false}),
|
||||
'Merge Conflict');
|
||||
assert.equal(element._computeChangeStatusString({status: 'NEW'}), '');
|
||||
assert.equal(element._computeChangeStatusString({status: 'MERGED'}),
|
||||
'Merged');
|
||||
assert.equal(element._computeChangeStatusString({status: 'ABANDONED'}),
|
||||
'Abandoned');
|
||||
assert.equal(element._computeChangeStatusString({status: 'DRAFT'}),
|
||||
'Draft');
|
||||
|
||||
assert.equal(element._computeCodeReviewClass(), '');
|
||||
assert.equal(element._computeCodeReviewClass({}), '');
|
||||
assert.equal(element._computeCodeReviewClass(), 'cell codeReview');
|
||||
assert.equal(element._computeCodeReviewClass({}), 'cell codeReview');
|
||||
assert.equal(element._computeCodeReviewClass({approved: true, value: 1}),
|
||||
'u-green');
|
||||
'cell codeReview u-green u-monospace');
|
||||
assert.equal(element._computeCodeReviewClass({value: 1}),
|
||||
'u-monospace u-green');
|
||||
'cell codeReview u-green u-monospace');
|
||||
assert.equal(element._computeCodeReviewClass({value: -1}),
|
||||
'u-monospace u-red');
|
||||
'cell codeReview u-monospace u-red');
|
||||
|
||||
assert.equal(element._computeCodeReviewLabel(), '');
|
||||
assert.equal(element._computeCodeReviewLabel({}), '');
|
||||
|
@ -22,6 +22,7 @@ limitations under the License.
|
||||
<script src="../../bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../bower_components/page/page.js"></script>
|
||||
<script src="../scripts/fake-app.js"></script>
|
||||
<script src="../scripts/changes.js"></script>
|
||||
<script src="../scripts/util.js"></script>
|
||||
|
||||
<link rel="import" href="../../bower_components/iron-test-helpers/iron-test-helpers.html">
|
||||
@ -33,49 +34,115 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="grouped">
|
||||
<template>
|
||||
<gr-change-list></gr-change-list>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-change-list tests', function() {
|
||||
var changeList;
|
||||
suite('gr-change-list basic tests', function() {
|
||||
var element;
|
||||
|
||||
setup(function() {
|
||||
changeList = fixture('basic');
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
test('keyboard shortcuts', function() {
|
||||
changeList.changes = [
|
||||
element.changes = [
|
||||
{_number: 0},
|
||||
{_number: 1},
|
||||
{_number: 2},
|
||||
];
|
||||
flushAsynchronousOperations();
|
||||
var changeListItems = Polymer.dom(changeList.root).querySelectorAll(
|
||||
'gr-change-list-item:not([header])');
|
||||
assert.equal(changeListItems.length, 3);
|
||||
assert.equal(changeList.selectedIndex, 0);
|
||||
var elementItems = Polymer.dom(element.root).querySelectorAll(
|
||||
'gr-change-list-item');
|
||||
assert.equal(elementItems.length, 3);
|
||||
assert.equal(element.selectedIndex, 0);
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(changeList, 74); // 'j'
|
||||
assert.equal(changeList.selectedIndex, 1);
|
||||
MockInteractions.pressAndReleaseKeyOn(changeList, 74); // 'j'
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 74); // 'j'
|
||||
assert.equal(element.selectedIndex, 1);
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 74); // 'j'
|
||||
|
||||
var showStub = sinon.stub(page, 'show');
|
||||
assert.equal(changeList.selectedIndex, 2);
|
||||
MockInteractions.pressAndReleaseKeyOn(changeList, 13); // 'enter'
|
||||
assert.equal(element.selectedIndex, 2);
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 13); // 'enter'
|
||||
assert(showStub.lastCall.calledWithExactly('/c/2/'),
|
||||
'Should navigate to /c/2/');
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(changeList, 75); // 'k'
|
||||
assert.equal(changeList.selectedIndex, 1);
|
||||
MockInteractions.pressAndReleaseKeyOn(changeList, 13); // 'enter'
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 75); // 'k'
|
||||
assert.equal(element.selectedIndex, 1);
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 13); // 'enter'
|
||||
assert(showStub.lastCall.calledWithExactly('/c/1/'),
|
||||
'Should navigate to /c/1/');
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(changeList, 75); // 'k'
|
||||
MockInteractions.pressAndReleaseKeyOn(changeList, 75); // 'k'
|
||||
MockInteractions.pressAndReleaseKeyOn(changeList, 75); // 'k'
|
||||
assert.equal(changeList.selectedIndex, 0);
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 75); // 'k'
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 75); // 'k'
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 75); // 'k'
|
||||
assert.equal(element.selectedIndex, 0);
|
||||
|
||||
showStub.restore();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('gr-change-list groups', function() {
|
||||
var element;
|
||||
|
||||
setup(function() {
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
test('keyboard shortcuts', function() {
|
||||
element.groups = [
|
||||
[
|
||||
{_number: 0},
|
||||
{_number: 1},
|
||||
{_number: 2},
|
||||
],
|
||||
[
|
||||
{_number: 3},
|
||||
{_number: 4},
|
||||
{_number: 5},
|
||||
],
|
||||
[
|
||||
{_number: 6},
|
||||
{_number: 7},
|
||||
{_number: 8},
|
||||
]
|
||||
];
|
||||
element.groupTitles = ['Group 1', 'Group 2', 'Group 3'];
|
||||
flushAsynchronousOperations();
|
||||
var elementItems = Polymer.dom(element.root).querySelectorAll(
|
||||
'gr-change-list-item');
|
||||
assert.equal(elementItems.length, 9);
|
||||
assert.equal(element.selectedIndex, 0);
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 74); // 'j'
|
||||
assert.equal(element.selectedIndex, 1);
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 74); // 'j'
|
||||
|
||||
var showStub = sinon.stub(page, 'show');
|
||||
assert.equal(element.selectedIndex, 2);
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 13); // 'enter'
|
||||
assert(showStub.lastCall.calledWithExactly('/c/2/'),
|
||||
'Should navigate to /c/2/');
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 75); // 'k'
|
||||
assert.equal(element.selectedIndex, 1);
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 13); // 'enter'
|
||||
assert(showStub.lastCall.calledWithExactly('/c/1/'),
|
||||
'Should navigate to /c/1/');
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 74); // 'j'
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 74); // 'j'
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 74); // 'j'
|
||||
assert.equal(element.selectedIndex, 4);
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 13); // 'enter'
|
||||
assert(showStub.lastCall.calledWithExactly('/c/4/'),
|
||||
'Should navigate to /c/4/');
|
||||
showStub.restore();
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user