Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2860)

Unified Diff: dashboard/dashboard/elements/test-picker.html

Issue 2767433002: Start using /list_tests to populate subtest menus in test-picker (Closed)
Patch Set: fix typo Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | dashboard/dashboard/elements/test-picker-test.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dashboard/dashboard/elements/test-picker.html
diff --git a/dashboard/dashboard/elements/test-picker.html b/dashboard/dashboard/elements/test-picker.html
index 41f5470b5ee83ad22f7357b9236ca09eff296e3a..6dad572be15026e932a56306834dfc6d7d229f29 100644
--- a/dashboard/dashboard/elements/test-picker.html
+++ b/dashboard/dashboard/elements/test-picker.html
@@ -81,6 +81,52 @@ found in the LICENSE file.
<script>
'use strict';
+ // TODO(eakuefner): generalize this request memoization pattern. See
+ // https://github.com/catapult-project/catapult/issues/3441.
+ tr.exportTo('d', function() {
+ class Subtests {
+ constructor() {
+ this.subtestPromises_ = new Map();
+ }
+
+ // TODO(eakuefner): implemement cancellation by wrapping
+ async getSubtestsForPath(path) {
+ if (this.subtestPromises_.has(path)) {
+ return await this.subtestPromises_.get(path);
+ }
+ const subtests = this.fetchAndProcessSubtests_(path);
+ this.subtestPromises_[path] = subtests;
+ return await subtests;
+ }
+
+ prepopulate(obj) {
+ for (const [path, subtests] of Object.entries(obj)) {
+ this.subtestPromises_.set(path, Promise.resolve(subtests));
+ }
+ }
+
+ async fetchAndProcessSubtests_(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)});
+ }
+ return subtests;
+ }
+ }
+
+ return {Subtests};
+ });
+
Polymer({
is: 'test-picker',
@@ -134,6 +180,11 @@ found in the LICENSE file.
])
},
+ subtests: {
+ type: Object,
+ value: () => new d.Subtests()
+ },
+
xsrfToken: { notify: true }
},
@@ -146,6 +197,7 @@ found in the LICENSE file.
this.enableAddSeries = false;
this.selectedSuite = null;
this.suiteDescription = null;
+ this.updatingSubtestMenus = false;
this.set('selectionModels.0.datalist', this.getSuiteItems());
},
@@ -227,13 +279,12 @@ found in the LICENSE file.
onDropdownSelect: function(event) {
var model = event.model;
var boxIndex = model.index;
+ if (this.updatingSubtestMenus) return;
if (boxIndex === undefined) {
return;
} 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);
@@ -262,15 +313,17 @@ found in the LICENSE file.
/**
* Updates bot dropdown menu with bot items.
*/
- updateBotMenu: function() {
+ updateBotMenu: async function() {
var menu = this.getSelectionMenu(1);
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.updatingSubtestMenus = true;
+ await this.updateSubtestMenus(2);
+ this.updatingSubtestMenus = false;
} else {
// Clear all subtest menus.
this.splice('selectionModels', 2);
@@ -279,84 +332,52 @@ 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));
// 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.length === 0) {
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);
+ this.updatingSubtestMenus = true;
+ menu.set('items', subtests);
+ this.updatingSubtestMenus = false;
- // If there are selected item, update next menu.
+ // If there is a selected item, update the next menu.
if (menu.selectedItem) {
- subtestDict = subtestDict[menu.selectedName]['sub_tests'];
+ const selectedPath = this.getCurrentSelectedPathUpTo(i + 1, false);
+ if (selectedPath !== undefined) {
+ subtests = await this.subtests.getSubtestsForPath(selectedPath);
+ } else {
+ subtests = [];
+ }
} 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 the last extant subtest selection still has subtests and we need
+ // to put those in a new menu.
+ if (subtests.length > 0) {
this.push('selectionModels', {
placeholder: this.SUBTEST_LABEL,
- datalist: subtestItems,
+ datalist: subtests,
disabled: false,
});
+ this.updatingSubtestMenus = true;
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.updatingSubtestMenus = false;
}
this.updateAddButtonState();
@@ -367,32 +388,6 @@ found in the LICENSE file.
(await 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) {
@@ -437,29 +432,7 @@ found in the LICENSE file.
* Gets the current selection from the menus.
*/
getCurrentSelection: async function() {
- var level = 0;
- var parts = [];
- while (true) {
- var menu = this.getSelectionMenu(level);
- if (!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;
- break;
- } else {
- // We want to collect all the subtest components so we can form
- // the full test path after this loop is done.
- if (level >= 2) parts.push(menu.selectedItem.name);
- }
- level += 1;
- }
-
- var suite = this.getSelectionMenu(0).selectedItem.name;
- var bot = this.getCheckedBot();
- parts.unshift(suite);
- parts.unshift(bot);
-
- var path = parts.join('/');
+ const path = this.getCurrentSelectedPathUpTo(-1, true);
// If the paths are the same, this means that the selected path has
// already been confirmed as valid by the previous request to
@@ -478,7 +451,6 @@ found in the LICENSE file.
this.getSubtestsForPath(path, true),
this.getSubtestsForPath(path, false)]);
} catch (e) {
- // TODO(eakuefner): Improve this error handling.
this.loading = false;
return null;
}
@@ -486,10 +458,42 @@ found in the LICENSE file.
this.currentSelectedPath_ = path;
this.currentSelectedTests_ = selectedTests;
this.currentUnselectedTests_ = unselectedTests;
- this.updateSubtestMenus(2);
+ this.updatingSubtestMenus = true;
+ await this.updateSubtestMenus(2);
+ this.updatingSubtestMenus = false;
return selectedTests;
},
+ getCurrentSelectedPathUpTo: function(maxLevel, onlyValid) {
+ let level = 0;
+ const parts = [];
+ while (true) {
+ 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 undefined;
+ break;
+ } else {
+ // We want to collect all the subtest components so we can form
+ // the full test path after this loop is done.
+ if (level >= 2) parts.push(menu.selectedItem.name);
+ }
+ level += 1;
+ }
+
+ const suite = this.getSelectionMenu(0).selectedItem.name;
+ const bot = this.getCheckedBot();
+ parts.unshift(suite);
+ parts.unshift(bot);
+
+ if (parts.length < maxLevel) return undefined;
+ return parts.join('/');
+ },
+
getCurrentSelectedPath: function() {
return this.currentSelectedPath_;
},
« no previous file with comments | « no previous file | dashboard/dashboard/elements/test-picker-test.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698