From b5349bada1f662a88c13d495d50de64483719b21 Mon Sep 17 00:00:00 2001 From: Marcus Fedarko Date: Mon, 15 Jul 2019 16:55:41 -0700 Subject: [PATCH] ENH: Add optgroup headers to search field selects Closes #191. Although this might seem like a pretty simple change, it required a decent amount of restructuring to get the code + tests to play nicely. To elaborate a bit: - Refactored populateSelect() to support taking in an object of options, where keys correspond to optgroup labels and values correspond to a list of child option values/names - Added tests of this new populateSelect() behavior to test_dom_utils - This necessitated updating getChildValuesFromSelect() and assertSelected() to handle optgroups properly. This was kind of a pain, but it's working ok now. - Broke off some now-redundant code within populateSelect() to a helper function (addOptionsToParentElement()). - Stopped storing featureFields as a property of RRVDisplay (since it's only used once) - Also, moved "Feature ID" out of featureMetadataFields. This makes life a bit more convenient for us. (necessitated changing up the feature text DOM tests a bit, as well as changing up featureRowListToText() a bit to add in "Feature ID" to a copy of featureMetadataFields) I think that's it. Might add another test or two for the "empty" corner-case of populateSelect(), but this should be fine. --- CHANGELOG.md | 3 + docs/demos/byrd/js/display.js | 52 ++++------- docs/demos/byrd/js/dom_utils.js | 86 +++++++++++++++++-- docs/demos/q2_moving_pictures/js/display.js | 52 ++++------- docs/demos/q2_moving_pictures/js/dom_utils.js | 86 +++++++++++++++++-- docs/demos/red_sea/js/display.js | 52 ++++------- docs/demos/red_sea/js/dom_utils.js | 86 +++++++++++++++++-- docs/demos/sleep_apnea/js/display.js | 52 ++++------- docs/demos/sleep_apnea/js/dom_utils.js | 86 +++++++++++++++++-- qurro/support_files/js/display.js | 52 ++++------- qurro/support_files/js/dom_utils.js | 86 +++++++++++++++++-- qurro/tests/web_tests/tests/test_dom_utils.js | 81 ++++++++++++++++- ...test_rrvdisplay_update_feature_text_dom.js | 25 +++--- 13 files changed, 573 insertions(+), 226 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a774caa9..7c901212 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ ([#186](https://github.com/biocore/qurro/issues/186)) - Added feature rankings as searchable fields in the "Selecting Features" controls. +- Feature metadata fields and feature ranking fields are now grouped under + `Feature Metadata` or `Feature Ranking` headers in the searchable fields + dropdowns. ([#191](https://github.com/biocore/qurro/issues/191)) - Added numeric searching: now you can search through numeric feature metadata or feature rankings using basic comparison operators. (Non-numeric input search text will result in the search not identifying any features, and non-numeric diff --git a/docs/demos/byrd/js/display.js b/docs/demos/byrd/js/display.js index 1f97df8d..12b27bf7 100644 --- a/docs/demos/byrd/js/display.js +++ b/docs/demos/byrd/js/display.js @@ -89,10 +89,6 @@ define(["./feature_computation", "./dom_utils", "vega", "vega-embed"], function( this.rankOrdering = undefined; // Ordered list of all feature metadata fields this.featureMetadataFields = undefined; - // Ordered list of all feature metadata + feature ranking fields - // (starting with "Feature ID"). These are used to populate the - // s with featureFields. + this.featureMetadataFields = this.rankPlotJSON.datasets.qurro_feature_metadata_ordering; + var searchableFields = { + standalone: ["Feature ID"], + "Feature Metadata": this.featureMetadataFields, + "Feature Rankings": this.rankOrdering + }; dom_utils.populateSelect( "topSearch", - this.featureFields, - "Feature ID" + searchableFields, + "Feature ID", + true ); dom_utils.populateSelect( "botSearch", - this.featureFields, - "Feature ID" + searchableFields, + "Feature ID", + true ); // Figure out which bar size type to default to. // We determine this based on how many features there are. @@ -613,20 +599,20 @@ define(["./feature_computation", "./dom_utils", "vega", "vega-embed"], function( } var outputText = ""; var currVal, anotherFieldLeft; + // fmFields is just the feature metadata fields, with "Feature ID" + // added on at the beginning + var fmFields = this.featureMetadataFields.slice(); + fmFields.unshift("Feature ID"); for (var i = 0; i < featureRowList.length; i++) { if (i > 0) { outputText += "\n"; } - // Note that "Feature ID" is included in - // this.featureMetadataFields, since we added it in - // makeRankPlot() above - for (var c = 0; c < this.featureMetadataFields.length; c++) { - currVal = featureRowList[i][this.featureMetadataFields[c]]; + for (var c = 0; c < fmFields.length; c++) { + currVal = featureRowList[i][fmFields[c]]; // If currVal *is* null or undefined, this will look like // / / in the output for this metadata field -- which is // fine. - anotherFieldLeft = - c + 1 < this.featureMetadataFields.length; + anotherFieldLeft = c + 1 < fmFields.length; if (currVal !== null && currVal !== undefined) { outputText += currVal; if (anotherFieldLeft) { diff --git a/docs/demos/byrd/js/dom_utils.js b/docs/demos/byrd/js/dom_utils.js index 80979b9b..6530fe87 100644 --- a/docs/demos/byrd/js/dom_utils.js +++ b/docs/demos/byrd/js/dom_utils.js @@ -24,22 +24,90 @@ define(["vega"], function(vega) { return elementIDs; } - /* Populates a DOM element with a list or object of options. * * This will remove any options already present in the . + * + * If optgroupMap is truthy, this assumes that "options" is actually an + * object of the form {"g1": ["o1", ...], ..., "gX": ["oX", ...]}. + * This will still populate the directly. This functionality can be used to + * create "global" options that aren't within a specific .) */ - function populateSelect(selectID, optionList, defaultVal) { - if (optionList.length <= 0) { - throw new Error("optionList must have at least one value"); + function populateSelect(selectID, options, defaultVal, optgroupMap) { + var optgroups; + if (optgroupMap) { + optgroups = Object.keys(options); + if (optgroups.length <= 0) { + throw new Error( + "options must have at least one optgroup specified" + ); + } + } else { + if (options.length <= 0) { + throw new Error("options must have at least one value"); + } } - var optionEle; + var optionEle, groupEle; var selectEle = document.getElementById(selectID); // Remove any options already present in the + if (optgroupMap) { + for (var g = 0; g < optgroups.length; g++) { + // Ignore empty optgroups. (In practice, this means that + // datasets without any specified feature metadata won't have + // an empty "Feature Metadata" optgroup shown in the search + // field directly. + addOptionsToParentElement( + options["standalone"], + selectEle + ); + } else { + // For all other optgroups, though, actually create an + // element, populate that, then add that to + // the . Note that we escape this // value in quotes, just in case it contains a period or some other diff --git a/docs/demos/q2_moving_pictures/js/display.js b/docs/demos/q2_moving_pictures/js/display.js index 1f97df8d..12b27bf7 100644 --- a/docs/demos/q2_moving_pictures/js/display.js +++ b/docs/demos/q2_moving_pictures/js/display.js @@ -89,10 +89,6 @@ define(["./feature_computation", "./dom_utils", "vega", "vega-embed"], function( this.rankOrdering = undefined; // Ordered list of all feature metadata fields this.featureMetadataFields = undefined; - // Ordered list of all feature metadata + feature ranking fields - // (starting with "Feature ID"). These are used to populate the - // s with featureFields. + this.featureMetadataFields = this.rankPlotJSON.datasets.qurro_feature_metadata_ordering; + var searchableFields = { + standalone: ["Feature ID"], + "Feature Metadata": this.featureMetadataFields, + "Feature Rankings": this.rankOrdering + }; dom_utils.populateSelect( "topSearch", - this.featureFields, - "Feature ID" + searchableFields, + "Feature ID", + true ); dom_utils.populateSelect( "botSearch", - this.featureFields, - "Feature ID" + searchableFields, + "Feature ID", + true ); // Figure out which bar size type to default to. // We determine this based on how many features there are. @@ -613,20 +599,20 @@ define(["./feature_computation", "./dom_utils", "vega", "vega-embed"], function( } var outputText = ""; var currVal, anotherFieldLeft; + // fmFields is just the feature metadata fields, with "Feature ID" + // added on at the beginning + var fmFields = this.featureMetadataFields.slice(); + fmFields.unshift("Feature ID"); for (var i = 0; i < featureRowList.length; i++) { if (i > 0) { outputText += "\n"; } - // Note that "Feature ID" is included in - // this.featureMetadataFields, since we added it in - // makeRankPlot() above - for (var c = 0; c < this.featureMetadataFields.length; c++) { - currVal = featureRowList[i][this.featureMetadataFields[c]]; + for (var c = 0; c < fmFields.length; c++) { + currVal = featureRowList[i][fmFields[c]]; // If currVal *is* null or undefined, this will look like // / / in the output for this metadata field -- which is // fine. - anotherFieldLeft = - c + 1 < this.featureMetadataFields.length; + anotherFieldLeft = c + 1 < fmFields.length; if (currVal !== null && currVal !== undefined) { outputText += currVal; if (anotherFieldLeft) { diff --git a/docs/demos/q2_moving_pictures/js/dom_utils.js b/docs/demos/q2_moving_pictures/js/dom_utils.js index 80979b9b..6530fe87 100644 --- a/docs/demos/q2_moving_pictures/js/dom_utils.js +++ b/docs/demos/q2_moving_pictures/js/dom_utils.js @@ -24,22 +24,90 @@ define(["vega"], function(vega) { return elementIDs; } - /* Populates a DOM element with a list or object of options. * * This will remove any options already present in the . + * + * If optgroupMap is truthy, this assumes that "options" is actually an + * object of the form {"g1": ["o1", ...], ..., "gX": ["oX", ...]}. + * This will still populate the directly. This functionality can be used to + * create "global" options that aren't within a specific .) */ - function populateSelect(selectID, optionList, defaultVal) { - if (optionList.length <= 0) { - throw new Error("optionList must have at least one value"); + function populateSelect(selectID, options, defaultVal, optgroupMap) { + var optgroups; + if (optgroupMap) { + optgroups = Object.keys(options); + if (optgroups.length <= 0) { + throw new Error( + "options must have at least one optgroup specified" + ); + } + } else { + if (options.length <= 0) { + throw new Error("options must have at least one value"); + } } - var optionEle; + var optionEle, groupEle; var selectEle = document.getElementById(selectID); // Remove any options already present in the + if (optgroupMap) { + for (var g = 0; g < optgroups.length; g++) { + // Ignore empty optgroups. (In practice, this means that + // datasets without any specified feature metadata won't have + // an empty "Feature Metadata" optgroup shown in the search + // field directly. + addOptionsToParentElement( + options["standalone"], + selectEle + ); + } else { + // For all other optgroups, though, actually create an + // element, populate that, then add that to + // the . Note that we escape this // value in quotes, just in case it contains a period or some other diff --git a/docs/demos/red_sea/js/display.js b/docs/demos/red_sea/js/display.js index 1f97df8d..12b27bf7 100644 --- a/docs/demos/red_sea/js/display.js +++ b/docs/demos/red_sea/js/display.js @@ -89,10 +89,6 @@ define(["./feature_computation", "./dom_utils", "vega", "vega-embed"], function( this.rankOrdering = undefined; // Ordered list of all feature metadata fields this.featureMetadataFields = undefined; - // Ordered list of all feature metadata + feature ranking fields - // (starting with "Feature ID"). These are used to populate the - // s with featureFields. + this.featureMetadataFields = this.rankPlotJSON.datasets.qurro_feature_metadata_ordering; + var searchableFields = { + standalone: ["Feature ID"], + "Feature Metadata": this.featureMetadataFields, + "Feature Rankings": this.rankOrdering + }; dom_utils.populateSelect( "topSearch", - this.featureFields, - "Feature ID" + searchableFields, + "Feature ID", + true ); dom_utils.populateSelect( "botSearch", - this.featureFields, - "Feature ID" + searchableFields, + "Feature ID", + true ); // Figure out which bar size type to default to. // We determine this based on how many features there are. @@ -613,20 +599,20 @@ define(["./feature_computation", "./dom_utils", "vega", "vega-embed"], function( } var outputText = ""; var currVal, anotherFieldLeft; + // fmFields is just the feature metadata fields, with "Feature ID" + // added on at the beginning + var fmFields = this.featureMetadataFields.slice(); + fmFields.unshift("Feature ID"); for (var i = 0; i < featureRowList.length; i++) { if (i > 0) { outputText += "\n"; } - // Note that "Feature ID" is included in - // this.featureMetadataFields, since we added it in - // makeRankPlot() above - for (var c = 0; c < this.featureMetadataFields.length; c++) { - currVal = featureRowList[i][this.featureMetadataFields[c]]; + for (var c = 0; c < fmFields.length; c++) { + currVal = featureRowList[i][fmFields[c]]; // If currVal *is* null or undefined, this will look like // / / in the output for this metadata field -- which is // fine. - anotherFieldLeft = - c + 1 < this.featureMetadataFields.length; + anotherFieldLeft = c + 1 < fmFields.length; if (currVal !== null && currVal !== undefined) { outputText += currVal; if (anotherFieldLeft) { diff --git a/docs/demos/red_sea/js/dom_utils.js b/docs/demos/red_sea/js/dom_utils.js index 80979b9b..6530fe87 100644 --- a/docs/demos/red_sea/js/dom_utils.js +++ b/docs/demos/red_sea/js/dom_utils.js @@ -24,22 +24,90 @@ define(["vega"], function(vega) { return elementIDs; } - /* Populates a DOM element with a list or object of options. * * This will remove any options already present in the . + * + * If optgroupMap is truthy, this assumes that "options" is actually an + * object of the form {"g1": ["o1", ...], ..., "gX": ["oX", ...]}. + * This will still populate the directly. This functionality can be used to + * create "global" options that aren't within a specific .) */ - function populateSelect(selectID, optionList, defaultVal) { - if (optionList.length <= 0) { - throw new Error("optionList must have at least one value"); + function populateSelect(selectID, options, defaultVal, optgroupMap) { + var optgroups; + if (optgroupMap) { + optgroups = Object.keys(options); + if (optgroups.length <= 0) { + throw new Error( + "options must have at least one optgroup specified" + ); + } + } else { + if (options.length <= 0) { + throw new Error("options must have at least one value"); + } } - var optionEle; + var optionEle, groupEle; var selectEle = document.getElementById(selectID); // Remove any options already present in the + if (optgroupMap) { + for (var g = 0; g < optgroups.length; g++) { + // Ignore empty optgroups. (In practice, this means that + // datasets without any specified feature metadata won't have + // an empty "Feature Metadata" optgroup shown in the search + // field directly. + addOptionsToParentElement( + options["standalone"], + selectEle + ); + } else { + // For all other optgroups, though, actually create an + // element, populate that, then add that to + // the . Note that we escape this // value in quotes, just in case it contains a period or some other diff --git a/docs/demos/sleep_apnea/js/display.js b/docs/demos/sleep_apnea/js/display.js index 1f97df8d..12b27bf7 100644 --- a/docs/demos/sleep_apnea/js/display.js +++ b/docs/demos/sleep_apnea/js/display.js @@ -89,10 +89,6 @@ define(["./feature_computation", "./dom_utils", "vega", "vega-embed"], function( this.rankOrdering = undefined; // Ordered list of all feature metadata fields this.featureMetadataFields = undefined; - // Ordered list of all feature metadata + feature ranking fields - // (starting with "Feature ID"). These are used to populate the - // s with featureFields. + this.featureMetadataFields = this.rankPlotJSON.datasets.qurro_feature_metadata_ordering; + var searchableFields = { + standalone: ["Feature ID"], + "Feature Metadata": this.featureMetadataFields, + "Feature Rankings": this.rankOrdering + }; dom_utils.populateSelect( "topSearch", - this.featureFields, - "Feature ID" + searchableFields, + "Feature ID", + true ); dom_utils.populateSelect( "botSearch", - this.featureFields, - "Feature ID" + searchableFields, + "Feature ID", + true ); // Figure out which bar size type to default to. // We determine this based on how many features there are. @@ -613,20 +599,20 @@ define(["./feature_computation", "./dom_utils", "vega", "vega-embed"], function( } var outputText = ""; var currVal, anotherFieldLeft; + // fmFields is just the feature metadata fields, with "Feature ID" + // added on at the beginning + var fmFields = this.featureMetadataFields.slice(); + fmFields.unshift("Feature ID"); for (var i = 0; i < featureRowList.length; i++) { if (i > 0) { outputText += "\n"; } - // Note that "Feature ID" is included in - // this.featureMetadataFields, since we added it in - // makeRankPlot() above - for (var c = 0; c < this.featureMetadataFields.length; c++) { - currVal = featureRowList[i][this.featureMetadataFields[c]]; + for (var c = 0; c < fmFields.length; c++) { + currVal = featureRowList[i][fmFields[c]]; // If currVal *is* null or undefined, this will look like // / / in the output for this metadata field -- which is // fine. - anotherFieldLeft = - c + 1 < this.featureMetadataFields.length; + anotherFieldLeft = c + 1 < fmFields.length; if (currVal !== null && currVal !== undefined) { outputText += currVal; if (anotherFieldLeft) { diff --git a/docs/demos/sleep_apnea/js/dom_utils.js b/docs/demos/sleep_apnea/js/dom_utils.js index 80979b9b..6530fe87 100644 --- a/docs/demos/sleep_apnea/js/dom_utils.js +++ b/docs/demos/sleep_apnea/js/dom_utils.js @@ -24,22 +24,90 @@ define(["vega"], function(vega) { return elementIDs; } - /* Populates a DOM element with a list or object of options. * * This will remove any options already present in the . + * + * If optgroupMap is truthy, this assumes that "options" is actually an + * object of the form {"g1": ["o1", ...], ..., "gX": ["oX", ...]}. + * This will still populate the directly. This functionality can be used to + * create "global" options that aren't within a specific .) */ - function populateSelect(selectID, optionList, defaultVal) { - if (optionList.length <= 0) { - throw new Error("optionList must have at least one value"); + function populateSelect(selectID, options, defaultVal, optgroupMap) { + var optgroups; + if (optgroupMap) { + optgroups = Object.keys(options); + if (optgroups.length <= 0) { + throw new Error( + "options must have at least one optgroup specified" + ); + } + } else { + if (options.length <= 0) { + throw new Error("options must have at least one value"); + } } - var optionEle; + var optionEle, groupEle; var selectEle = document.getElementById(selectID); // Remove any options already present in the + if (optgroupMap) { + for (var g = 0; g < optgroups.length; g++) { + // Ignore empty optgroups. (In practice, this means that + // datasets without any specified feature metadata won't have + // an empty "Feature Metadata" optgroup shown in the search + // field directly. + addOptionsToParentElement( + options["standalone"], + selectEle + ); + } else { + // For all other optgroups, though, actually create an + // element, populate that, then add that to + // the . Note that we escape this // value in quotes, just in case it contains a period or some other diff --git a/qurro/support_files/js/display.js b/qurro/support_files/js/display.js index 1f97df8d..12b27bf7 100644 --- a/qurro/support_files/js/display.js +++ b/qurro/support_files/js/display.js @@ -89,10 +89,6 @@ define(["./feature_computation", "./dom_utils", "vega", "vega-embed"], function( this.rankOrdering = undefined; // Ordered list of all feature metadata fields this.featureMetadataFields = undefined; - // Ordered list of all feature metadata + feature ranking fields - // (starting with "Feature ID"). These are used to populate the - // s with featureFields. + this.featureMetadataFields = this.rankPlotJSON.datasets.qurro_feature_metadata_ordering; + var searchableFields = { + standalone: ["Feature ID"], + "Feature Metadata": this.featureMetadataFields, + "Feature Rankings": this.rankOrdering + }; dom_utils.populateSelect( "topSearch", - this.featureFields, - "Feature ID" + searchableFields, + "Feature ID", + true ); dom_utils.populateSelect( "botSearch", - this.featureFields, - "Feature ID" + searchableFields, + "Feature ID", + true ); // Figure out which bar size type to default to. // We determine this based on how many features there are. @@ -613,20 +599,20 @@ define(["./feature_computation", "./dom_utils", "vega", "vega-embed"], function( } var outputText = ""; var currVal, anotherFieldLeft; + // fmFields is just the feature metadata fields, with "Feature ID" + // added on at the beginning + var fmFields = this.featureMetadataFields.slice(); + fmFields.unshift("Feature ID"); for (var i = 0; i < featureRowList.length; i++) { if (i > 0) { outputText += "\n"; } - // Note that "Feature ID" is included in - // this.featureMetadataFields, since we added it in - // makeRankPlot() above - for (var c = 0; c < this.featureMetadataFields.length; c++) { - currVal = featureRowList[i][this.featureMetadataFields[c]]; + for (var c = 0; c < fmFields.length; c++) { + currVal = featureRowList[i][fmFields[c]]; // If currVal *is* null or undefined, this will look like // / / in the output for this metadata field -- which is // fine. - anotherFieldLeft = - c + 1 < this.featureMetadataFields.length; + anotherFieldLeft = c + 1 < fmFields.length; if (currVal !== null && currVal !== undefined) { outputText += currVal; if (anotherFieldLeft) { diff --git a/qurro/support_files/js/dom_utils.js b/qurro/support_files/js/dom_utils.js index 80979b9b..f8baf817 100644 --- a/qurro/support_files/js/dom_utils.js +++ b/qurro/support_files/js/dom_utils.js @@ -24,22 +24,90 @@ define(["vega"], function(vega) { return elementIDs; } - /* Populates a DOM element with a list or object of options. * * This will remove any options already present in the . + * + * If optgroupMap is truthy, this assumes that "options" is actually an + * object of the form {"g1": ["o1", ...], ..., "gX": ["oX", ...]}. + * This will still populate the directly. This functionality can be used to + * create "global" options that aren't within a specific .) */ - function populateSelect(selectID, optionList, defaultVal) { - if (optionList.length <= 0) { - throw new Error("optionList must have at least one value"); + function populateSelect(selectID, options, defaultVal, optgroupMap) { + var optgroups; + if (optgroupMap) { + optgroups = Object.keys(options); + if (optgroups.length <= 0) { + throw new Error( + "options must have at least one optgroup specified" + ); + } + } else { + if (options.length <= 0) { + throw new Error("options must have at least one value"); + } } - var optionEle; + var optionEle, groupEle; var selectEle = document.getElementById(selectID); // Remove any options already present in the + if (optgroupMap) { + for (var g = 0; g < optgroups.length; g++) { + // Ignore empty optgroups. (In practice, this means that + // datasets without any specified feature metadata won't have + // an empty "Feature Metadata" optgroup shown in the search + // field directly. + addOptionsToParentElement( + options.standalone, + selectEle + ); + } else { + // For all other optgroups, though, actually create an + // element, populate that, then add that to + // the . Note that we escape this // value in quotes, just in case it contains a period or some other diff --git a/qurro/tests/web_tests/tests/test_dom_utils.js b/qurro/tests/web_tests/tests/test_dom_utils.js index c03e74d9..e03ee630 100644 --- a/qurro/tests/web_tests/tests/test_dom_utils.js +++ b/qurro/tests/web_tests/tests/test_dom_utils.js @@ -5,21 +5,70 @@ define(["dom_utils", "mocha", "chai", "testing_utilities"], function( testing_utilities ) { describe("Various general DOM utilities", function() { + /* Returns a list of child values, with optgroups represented in the + * list as objects mapping the optgroup label to a list of child option + * values. + * + * Sorry this function is kind of gross; adding support for optgroups + * necessarily made these utility functions a lot less compact than + * they used to be. + */ var getChildValuesFromSelect = function(selectID) { var ele = document.getElementById(selectID); var outputValues = []; + var currOptgroupValues, currOptgroupObject; + var j; for (var i = 0; i < ele.children.length; i++) { - outputValues.push(ele.children[i].value); + // If this child element is an , we'll need to + // iterate over *its* children (which should be s when optgroupMap is truthy", function() { + var vals = { g1: ["o1", "o2"], g2: ["o3"] }; + dom_utils.populateSelect(selectID, vals, "o2", true); + // Check that the select has two optgroups with the correct + // options + chai.assert.sameDeepMembers( + getChildValuesFromSelect(selectID), + [{ g1: ["o1", "o2"] }, { g2: ["o3"] }] + ); + assertSelected(selectID, "o2"); + }); + it('Creates global options for optgroups labelled "standalone"', function() { + var vals = { + g1: ["o1", "o2"], + g2: ["o3"], + standalone: ["o4", "o5"] + }; + dom_utils.populateSelect(selectID, vals, "o3", true); + chai.assert.sameDeepMembers( + getChildValuesFromSelect(selectID), + [{ g1: ["o1", "o2"] }, { g2: ["o3"] }, "o4", "o5"] + ); + assertSelected(selectID, "o3"); + }); }); describe("Changing the enabled status of an element", function() { diff --git a/qurro/tests/web_tests/tests/test_rrvdisplay_update_feature_text_dom.js b/qurro/tests/web_tests/tests/test_rrvdisplay_update_feature_text_dom.js index d4d40c6e..0028ef33 100644 --- a/qurro/tests/web_tests/tests/test_rrvdisplay_update_feature_text_dom.js +++ b/qurro/tests/web_tests/tests/test_rrvdisplay_update_feature_text_dom.js @@ -68,20 +68,21 @@ define(["display", "mocha", "chai", "testing_utilities"], function( // Standard case // only checking a single feature metadata field here, for my // own sanity - rrv.featureMetadataFields = ["Feature ID"]; + rrv.featureMetadataFields = ["f1"]; rrv.topFeatures = [ - { "Feature ID": "abc" }, - { "Feature ID": "def" }, - { "Feature ID": "ghi" }, - { "Feature ID": "lmno pqrs" }, - { "Feature ID": "tuv" } + { "Feature ID": "abc", f1: 1 }, + { "Feature ID": "def", f1: 2 }, + { "Feature ID": "ghi", f1: 3 }, + { "Feature ID": "lmno pqrs", f1: 4 }, + { "Feature ID": "tuv", f1: null } ]; rrv.botFeatures = [ - { "Feature ID": "asdf" }, - { "Feature ID": "ghjk" } + { "Feature ID": "asdf", f1: null }, + { "Feature ID": "ghjk", f1: 7 } ]; - var expectedTopText = "abc\ndef\nghi\nlmno pqrs\ntuv"; - var expectedBotText = "asdf\nghjk"; + var expectedTopText = + "abc / 1\ndef / 2\nghi / 3\nlmno pqrs / 4\ntuv / "; + var expectedBotText = "asdf / \nghjk / 7"; rrv.updateFeaturesTextDisplays(); chai.assert.equal( document.getElementById("topFeaturesDisplay").value, @@ -95,8 +96,8 @@ define(["display", "mocha", "chai", "testing_utilities"], function( // Check case where there's only one feature in a list // In this case, the denominator + expected bottom text are the // same as before - rrv.topFeatures = [{ "Feature ID": "onlyfeature" }]; - expectedTopText = "onlyfeature"; + rrv.topFeatures = [{ "Feature ID": "onlyfeature", f1: 100 }]; + expectedTopText = "onlyfeature / 100"; rrv.updateFeaturesTextDisplays(); chai.assert.equal( document.getElementById("topFeaturesDisplay").value,