Index: dashboard/dashboard/elements/test-picker.html |
diff --git a/dashboard/dashboard/elements/test-picker.html b/dashboard/dashboard/elements/test-picker.html |
index 770e073a41ac9a369c9659ca24f0feec0c604d5e..139bf073f84bb9c8ba15a98bf3f801c373d5f986 100644 |
--- a/dashboard/dashboard/elements/test-picker.html |
+++ b/dashboard/dashboard/elements/test-picker.html |
@@ -13,6 +13,8 @@ found in the LICENSE file. |
<link rel="import" href="/dashboard/elements/autocomplete-box.html"> |
<link rel="import" href="/dashboard/static/simple_xhr.html"> |
+<link rel="import" href="/tracing/base/base.html"> |
+ |
<dom-module id="test-picker"> |
<template> |
<style include="iron-flex iron-flex-alignment"> |
@@ -101,6 +103,48 @@ found in the LICENSE file. |
<script> |
'use strict'; |
+ // TODO(eakuefner): https://github.com/catapult-project/catapult/issues/3441 |
+ tr.exportTo('d', function() { |
+ class Subtests { |
+ constructor() { |
+ this.subtests_ = new Map(); |
+ } |
+ |
+ // TODO(eakuefner): implemement cancellation by wrapping |
+ async getSubtestsForPath(path) { |
+ if (this.subtests_.has(path)) { |
+ return await this.subtests_.get(path); |
+ } |
+ |
+ const params = { |
+ type: 'pattern' |
+ }; |
+ params.p = `${path}/*`; |
+ const fullSubtests = await simple_xhr.asPromise( |
+ '/list_tests', params); |
+ // TODO(eakuefner): Standardize logic for dealing with test paths on |
+ // the client side. See |
+ // https://github.com/catapult-project/catapult/issues/3443. |
+ const subtests = []; |
+ for (const fullSubtest of fullSubtests) { |
+ subtests.push({ |
+ name: fullSubtest.substring(fullSubtest.lastIndexOf('/') + 1)}); |
+ } |
+ |
+ this.subtests_[path] = subtests; |
+ return subtests; |
+ } |
+ |
+ prepopulate(obj) { |
+ for (const [path, subtests] of obj) { |
+ this.subtests_.set(path, Promise.resolve(subtests)); |
+ } |
+ } |
+ } |
+ |
+ return {Subtests}; |
+ }); |
+ |
Polymer({ |
is: 'test-picker', |
@@ -154,6 +198,11 @@ found in the LICENSE file. |
]) |
}, |
+ subtests: { |
+ type: Object, |
+ value: () => new d.Subtests() |
+ }, |
+ |
xsrfToken: { notify: true } |
}, |
@@ -253,8 +302,6 @@ found in the LICENSE file. |
} else if (boxIndex == 0) { |
this.updateTestSuiteDescription(); |
this.updateBotMenu(); |
- } else if (boxIndex == 1) { |
- this.sendSubtestRequest(); |
} else { |
// Update all the next dropdown menus for subtests. |
this.updateSubtestMenus(boxIndex + 1); |
@@ -288,10 +335,9 @@ found in the LICENSE file. |
var botItems = this.getBotItems(); |
menu.set('items', botItems); |
menu.set('disabled', botItems.length === 0); |
- this.subtestDict = null; |
- // If there's a selection, send a subtest request. |
+ // If there's a selection, update the subtest menus. |
if (menu.selectedItem) { |
- this.sendSubtestRequest(); |
+ this.updateSubtestMenus(2); |
} else { |
// Clear all subtest menus. |
this.splice('selectionModels', 2); |
@@ -300,84 +346,43 @@ found in the LICENSE file. |
}, |
/** |
- * Sends a request for subtestDict base on selected test suite and bot. |
- */ |
- sendSubtestRequest: function() { |
- if (this.subtestXhr) { |
- this.subtestXhr.abort(); |
- this.subtestXhr = null; |
- } |
- var bot = this.getCheckedBot(); |
- // If no bot is selected, just leave the current subtests. |
- if (bot === null) { |
- return; |
- } |
- var suite = this.getCheckedSuite(); |
- if (!suite) { |
- return; |
- } |
- |
- this.loading = true; |
- |
- var params = { |
- type: 'sub_tests', |
- suite: suite, |
- bots: bot, |
- xsrf_token: this.xsrfToken |
- }; |
- this.subtestXhr = simple_xhr.send( |
- '/list_tests', |
- params, |
- function(response) { |
- this.loading = false; |
- this.subtestDict = response; |
- // Start at first subtest menu. |
- this.updateSubtestMenus(2); |
- }.bind(this), |
- function(error) { |
- // TODO: Display error. |
- this.loading = false; |
- }.bind(this) |
- ); |
- }, |
- |
- /** |
* Updates all subtest menus starting at 'startIndex'. |
*/ |
- updateSubtestMenus: function(startIndex) { |
- var subtestDict = this.getSubtestAtIndex(startIndex); |
- |
+ updateSubtestMenus: async function(startIndex) { |
+ let subtests = await this.subtests.getSubtestsForPath( |
+ this.getCurrentSelectedPathUpTo(startIndex - 1)); |
// Update existing subtest menu. |
for (var i = startIndex; i < this.selectionModels.length; i++) { |
- // Remove the rest of the menu if no subtestDict. |
- if (!subtestDict || Object.keys(subtestDict).length == 0) { |
+ // Remove the rest of the menu if no subtests. |
+ if (subtests === []) { |
this.splice('selectionModels', i); |
this.updateAddButtonState(); |
return; |
} |
- var subtestItems = this.getSubtestItems(subtestDict); |
- var menu = this.getSelectionMenu(i); |
- menu.set('items', subtestItems); |
+ const menu = this.getSelectionMenu(i); |
+ menu.set('items', subtests); |
// If there are selected item, update next menu. |
if (menu.selectedItem) { |
- subtestDict = subtestDict[menu.selectedName]['sub_tests']; |
+ subtests = await this.subtests.getSubtestsForPath( |
+ this.getCurrentSelectedPathUpTo(i - 1, false)); |
} else { |
- subtestDict = null; |
+ subtests = []; |
} |
} |
- // Check if we still need to add a subtest menu. |
- if (subtestDict && Object.keys(subtestDict).length > 0) { |
- var subtestItems = this.getSubtestItems(subtestDict); |
+ // If we reached the last iteration but still have subtests, that means |
+ // that means that the last extant subtest selection still has subtests |
+ // and we need to put those in a new menu. |
+ if (subtests !== []) { |
this.push('selectionModels', { |
placeholder: this.SUBTEST_LABEL, |
- datalist: subtestItems, |
+ datalist: subtests, |
disabled: false, |
}); |
Polymer.dom.flush(); |
- var menu = this.getSelectionMenu(this.selectionModels.length - 1); |
- menu.set('items', subtestItems); |
+ const menu = this.getSelectionMenu(this.selectionModels.length - 1); |
+ menu.set('items', subtests); |
} |
this.updateAddButtonState(); |
@@ -387,32 +392,6 @@ found in the LICENSE file. |
this.enableAddSeries = this.getCurrentSelection() instanceof Array; |
}, |
- getSubtestAtIndex: function(index) { |
- var subtestDict = this.subtestDict; |
- for (var i = 2; i < index; i++) { |
- var test = this.getSelectionMenu(i).selectedName; |
- if (test in subtestDict) { |
- subtestDict = subtestDict[test]['sub_tests']; |
- } else { |
- return null; |
- } |
- } |
- return subtestDict; |
- }, |
- |
- getSubtestItems: function(subtestDict) { |
- var subtestItems = []; |
- var subtestNames = Object.keys(subtestDict).sort(); |
- for (var i = 0; i < subtestNames.length; i++) { |
- var name = subtestNames[i]; |
- subtestItems.push({ |
- name: name, |
- tag: (subtestDict[name]['deprecated'] ? this.DEPRECATED_TAG : '') |
- }); |
- } |
- return subtestItems; |
- }, |
- |
getCheckedBot: function() { |
var botMenu = this.getSelectionMenu(1); |
if (botMenu.selectedItem) { |
@@ -458,14 +437,27 @@ found in the LICENSE file. |
* is a valid selection. |
*/ |
getCurrentSelection: function() { |
- var level = 0; |
- var parts = []; |
+ const path = this.getCurrentSelectedPathUpTo(-1, true); |
+ |
+ if (this.currentSelectedPath_ === path) { |
+ return this.currentSelectedTests_; |
+ } |
+ this.sendListTestsRequest(path); |
+ return null; |
+ }, |
+ |
+ getCurrentSelectedPathUpTo: function(maxLevel, onlyValid) { |
+ let level = 0; |
+ const parts = []; |
while (true) { |
- var menu = this.getSelectionMenu(level); |
- if (!menu || !menu.selectedItem) { |
+ if (maxLevel !== -1 && level <= maxLevel) { |
+ break; |
+ } |
+ const menu = this.getSelectionMenu(level); |
+ if (onlyValid && (!menu || !menu.selectedItem)) { |
// A selection is only valid if it specifies at least one subtest |
// component, which is the third level. |
- if (level <= 2) return null; |
+ if (level <= 2) return undefined; |
break; |
} else { |
// We want to collect all the subtest components so we can form |
@@ -475,17 +467,12 @@ found in the LICENSE file. |
level += 1; |
} |
- var suite = this.getSelectionMenu(0).selectedItem.name; |
- var bot = this.getCheckedBot(); |
+ const suite = this.getSelectionMenu(0).selectedItem.name; |
+ const bot = this.getCheckedBot(); |
parts.unshift(suite); |
parts.unshift(bot); |
- var path = parts.join('/'); |
- |
- if (this.currentSelectedPath_ === path) |
- return this.currentSelectedTests_; |
- this.sendListTestsRequest(path); |
- return null; |
+ return parts.join('/'); |
}, |
getCurrentSelectedPath: function() { |