From 1dfbc1e91244014aafcd75df6f030bd1f18f97fb Mon Sep 17 00:00:00 2001 From: flongo Date: Thu, 20 Feb 2014 16:59:21 +0100 Subject: [PATCH] fix #980 Correct MultiAutoComplete initialization when bound data is not empty When freeText option was set to false, items already present in the data model to which the value of the widget is bound were not taken into account. This commit reverts a fix done for another bug within commit 41d50bfe63ce93bc8d3116d28aeeb753d136b9dd: when freeText is equal to false, type some text for which there is no suggestion. Then blur. Then click inside the field and type something for which suggestions are returned. Pressing ENTER would cause all items to be duplicated. --- .../MultiAutoCompleteController.js | 17 +-- src/aria/widgets/form/MultiAutoComplete.js | 3 +- .../autocomplete/AutoCompleteTestSuite.js | 12 +- .../BaseMultiAutoCompleteTestCase.js | 136 ++++++++++++++++++ .../MultiAutoCompleteTestSuite.js | 34 +++++ .../DuplicateValuesAfterError.js | 66 +++++++++ .../template/MultiAutoTpl.tpl | 6 +- .../test4/MultiAutoPrefill.js | 56 +++++--- 8 files changed, 285 insertions(+), 45 deletions(-) create mode 100644 test/aria/widgets/form/autocomplete/multiautocomplete/BaseMultiAutoCompleteTestCase.js create mode 100644 test/aria/widgets/form/autocomplete/multiautocomplete/MultiAutoCompleteTestSuite.js create mode 100644 test/aria/widgets/form/autocomplete/multiautocomplete/duplicateValuesAfterError/DuplicateValuesAfterError.js diff --git a/src/aria/widgets/controllers/MultiAutoCompleteController.js b/src/aria/widgets/controllers/MultiAutoCompleteController.js index c16768e44..c636f0cc4 100644 --- a/src/aria/widgets/controllers/MultiAutoCompleteController.js +++ b/src/aria/widgets/controllers/MultiAutoCompleteController.js @@ -62,11 +62,6 @@ * @type Object */ this.editedSuggestion; - /** - * Suggestion to be added to the widget - * @type Object or Array - */ - this._suggestionToBeAdded = null; /** * Check if value is range of suggestions * @type Boolean @@ -120,7 +115,7 @@ } else { addedValue = trimText; } - this._suggestionToBeAdded = addedValue; + report.suggestionsToAdd = addedValue; addedValue = this._checkValidSuggestion(addedValue); } else { if (!dataModel.value) { @@ -154,7 +149,7 @@ dataModel.value = null; report.ok = true; reportVal = null; - } else if (value && !typeUtil.isString(value) && dataModel.value !== null) { + } else if (value && !typeUtil.isString(value)) { if (this._checkWithSuggestionBean(value, this._resourcesHandler.SUGGESTION_BEAN)) { var text = this._getLabelFromSuggestion(value); dataModel.text = text; @@ -186,14 +181,14 @@ } } - // var addedValue = rangeMatch || reportVal; - addedValue = this._suggestionToBeAdded = rangeMatch.length > 0 ? rangeMatch : reportVal; + var suggestionsToAdd = rangeMatch.length > 0 ? rangeMatch : reportVal; if (this.editMode) { - this._suggestionToBeAdded = ""; + suggestionsToAdd = ""; } - addedValue = this._checkValidSuggestion(this._suggestionToBeAdded); + addedValue = this._checkValidSuggestion(suggestionsToAdd); report.value = addedValue; report.text = dataModel.text; + report.suggestionsToAdd = suggestionsToAdd; return report; }, /** diff --git a/src/aria/widgets/form/MultiAutoComplete.js b/src/aria/widgets/form/MultiAutoComplete.js index 915433db3..2eb948668 100644 --- a/src/aria/widgets/form/MultiAutoComplete.js +++ b/src/aria/widgets/form/MultiAutoComplete.js @@ -133,7 +133,7 @@ Aria.classDefinition({ */ _addMultiselectValues : function (report, arg) { - var controller = this.controller, suggestionToBeAdded = controller._suggestionToBeAdded; + var controller = this.controller, suggestionToBeAdded = report.suggestionsToAdd; var isValid; var typeUtil = aria.utils.Type; var domUtil = aria.utils.Dom; @@ -168,7 +168,6 @@ Aria.classDefinition({ } domUtil.insertAdjacentHTML(this._textInputField, "beforeBegin", suggestionsMarkup); this.__createEllipsis(this._textInputField); - controller._suggestionToBeAdded = null; this._textInputField.value = ""; this._makeInputFieldLastChild(); if (controller.editMode) { diff --git a/test/aria/widgets/form/autocomplete/AutoCompleteTestSuite.js b/test/aria/widgets/form/autocomplete/AutoCompleteTestSuite.js index 29cbe1789..9b6279f69 100644 --- a/test/aria/widgets/form/autocomplete/AutoCompleteTestSuite.js +++ b/test/aria/widgets/form/autocomplete/AutoCompleteTestSuite.js @@ -49,16 +49,8 @@ Aria.classDefinition({ this.addTests("test.aria.widgets.form.autocomplete.helptext.test2.AutoCompleteHelptextTestCase"); this.addTests("test.aria.widgets.form.autocomplete.autoedit.AutoEditInput"); this.addTests("test.aria.widgets.form.autocomplete.issue697.EscKeyTestCase"); - this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test1.MultiAutoAdd"); - this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test2.MultiAutoRemove"); - this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test3.MultiAutoDataCheck"); - this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test4.MultiAutoPrefill"); - this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test5.MultiAutoEdit"); - this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test6.MultiAutoRange1"); - this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test6.MultiAutoRange2"); - this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test7.MultiAutoError"); - this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test8.MultiAutoMaxOptions"); - this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test9.MultiAutoBackSpace"); this.addTests("test.aria.widgets.form.autocomplete.errorhandling.AutoComplete"); + + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.MultiAutoCompleteTestSuite"); } }); diff --git a/test/aria/widgets/form/autocomplete/multiautocomplete/BaseMultiAutoCompleteTestCase.js b/test/aria/widgets/form/autocomplete/multiautocomplete/BaseMultiAutoCompleteTestCase.js new file mode 100644 index 000000000..4525f1063 --- /dev/null +++ b/test/aria/widgets/form/autocomplete/multiautocomplete/BaseMultiAutoCompleteTestCase.js @@ -0,0 +1,136 @@ +/* + * Copyright 2013 Amadeus s.a.s. + * 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. + */ + +Aria.classDefinition({ + $classpath : "test.aria.widgets.form.autocomplete.multiautocomplete.BaseMultiAutoCompleteTestCase", + $extends : "aria.jsunit.TemplateTestCase", + $dependencies : ["aria.utils.Type"], + $constructor : function () { + this.$TemplateTestCase.constructor.call(this); + + this.data = this.data || { + ac_airline_values : [], + freeText : true + }; + this.setTestEnv({ + template : "test.aria.widgets.form.autocomplete.multiautocomplete.template.MultiAutoTpl", + data : this.data + }); + + }, + $prototype : { + + clickAndType : function (text, cb, delay) { + if (aria.utils.Type.isString(text)) { + text = [text]; + } + this.synEvent.click(this._getField(), { + fn : this.type, + scope : this, + args : { + text : text, + cb : cb, + delay : delay || 800 + } + }); + }, + + type : function (evt, args) { + args = args || evt; + this.synEvent.type(this._getField(), args.text.shift(), { + fn : this.__wait, + scope : this, + args : args + }); + }, + + __wait : function (evt, args) { + var cb; + if (args.text.length === 0) { + cb = args.cb; + + } else { + cb = { + fn : this.type, + scope : this, + args : args + }; + } + cb.delay = args.delay; + aria.core.Timer.addCallback(cb); + }, + + checkSelectedItems : function (count, labels) { + var container = this._getContainer(); + var actualOptionCount = container.children.length - 1; + this.assertEquals(actualOptionCount, count, "The number of selected options should be " + count + + ". It is " + actualOptionCount + " instead."); + + if (labels) { + var element, text; + for (var i = 0; i < labels.length; i++) { + element = container.childNodes[i]; + text = element.innerText || element.textContent; + this.assertEquals(text, labels[i], "The Wrong values are added as for Autocomplete."); + } + } + }, + + checkDataModel : function (count, expectedValues) { + var data = this.data.ac_airline_values, message; + this.assertEquals(data.length, count, "The number of items in the data model is not correct."); + if (expectedValues) { + for (var j = 0; j < data.length; j++) { + var message = "Wrong value in position " + j + " of the data model."; + if (aria.utils.Type.isString(data[j])) { + this.assertEquals(data[j], expectedValues[j], message); + } else { + this.assertEquals(data[j].code, expectedValues[j].code, message); + this.assertEquals(data[j].label, expectedValues[j].label, message); + } + } + } + }, + + focusOut : function (cb) { + this.templateCtxt.$focus("justToFocusOut"); + cb.delay = cb.delay || 10; + aria.core.Timer.addCallback(cb); + }, + + checkInputValue : function (value) { + var actualValue = this._getField().value; + this.assertEquals(actualValue, value, "Input field should have value " + value + ". It has " + actualValue + + " instead."); + }, + + removeByCrossClick : function (index, cb) { + this.synEvent.click(this._getSelectedItemElement(index).lastChild, cb); + }, + + _getField : function () { + return this.getInputField("MultiAutoId"); + }, + + _getContainer : function () { + return this._getField().parentNode; + }, + + _getSelectedItemElement : function (index) { + return this._getContainer().childNodes[index]; + } + + } +}); diff --git a/test/aria/widgets/form/autocomplete/multiautocomplete/MultiAutoCompleteTestSuite.js b/test/aria/widgets/form/autocomplete/multiautocomplete/MultiAutoCompleteTestSuite.js new file mode 100644 index 000000000..47939626a --- /dev/null +++ b/test/aria/widgets/form/autocomplete/multiautocomplete/MultiAutoCompleteTestSuite.js @@ -0,0 +1,34 @@ +/* + * Copyright 2013 Amadeus s.a.s. + * 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. + */ + +Aria.classDefinition({ + $classpath : "test.aria.widgets.form.autocomplete.multiautocomplete.MultiAutoCompleteTestSuite", + $extends : "aria.jsunit.TestSuite", + $constructor : function () { + this.$TestSuite.constructor.call(this); + + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test1.MultiAutoAdd"); + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test2.MultiAutoRemove"); + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test3.MultiAutoDataCheck"); + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test4.MultiAutoPrefill"); + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test5.MultiAutoEdit"); + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test6.MultiAutoRange1"); + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test6.MultiAutoRange2"); + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test7.MultiAutoError"); + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test8.MultiAutoMaxOptions"); + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.test9.MultiAutoBackSpace"); + this.addTests("test.aria.widgets.form.autocomplete.multiautocomplete.duplicateValuesAfterError.DuplicateValuesAfterError"); + } +}); diff --git a/test/aria/widgets/form/autocomplete/multiautocomplete/duplicateValuesAfterError/DuplicateValuesAfterError.js b/test/aria/widgets/form/autocomplete/multiautocomplete/duplicateValuesAfterError/DuplicateValuesAfterError.js new file mode 100644 index 000000000..cb123d5fc --- /dev/null +++ b/test/aria/widgets/form/autocomplete/multiautocomplete/duplicateValuesAfterError/DuplicateValuesAfterError.js @@ -0,0 +1,66 @@ +/* + * Copyright 2013 Amadeus s.a.s. + * 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. + */ + +Aria.classDefinition({ + $classpath : "test.aria.widgets.form.autocomplete.multiautocomplete.duplicateValuesAfterError.DuplicateValuesAfterError", + $extends : "test.aria.widgets.form.autocomplete.multiautocomplete.BaseMultiAutoCompleteTestCase", + $constructor : function () { + + this.data = { + ac_airline_values : [{ + label : 'Air France', + code : 'AF' + + }, { + label : 'Air Canada', + code : 'AC' + }], + freeText : false + }; + this.$BaseMultiAutoCompleteTestCase.constructor.call(this); + + }, + $prototype : { + + runTemplateTest : function () { + this.checkSelectedItems(2, ["Air France", "Air Canada"]); + + this.clickAndType("o", { + fn : this._afterWrongType, + scope : this + }, 100); + }, + + _afterWrongType : function () { + this.focusOut({ + fn : this._afterFocusOut, + scope : this + }); + }, + + _afterFocusOut : function () { + this.clickAndType(["[right][backspace]P1", "[enter]"], { + fn : this._afterSelectionWithEnter, + scope : this + }, 200); + }, + + _afterSelectionWithEnter : function () { + this.checkSelectedItems(3, ["Air France", "Air Canada", "P1.some"]); + this.end(); + } + + } +}); diff --git a/test/aria/widgets/form/autocomplete/multiautocomplete/template/MultiAutoTpl.tpl b/test/aria/widgets/form/autocomplete/multiautocomplete/template/MultiAutoTpl.tpl index b125a4baf..e848aa3e2 100644 --- a/test/aria/widgets/form/autocomplete/multiautocomplete/template/MultiAutoTpl.tpl +++ b/test/aria/widgets/form/autocomplete/multiautocomplete/template/MultiAutoTpl.tpl @@ -33,8 +33,8 @@ width:400, block:false, labelWidth:180, - maxOptions: 8, - freeText:true, + maxOptions: data.maxOptions || 8, + freeText: (data.freeText !== false), resourcesHandler: getAirLinesHandler(), bind:{ "value" : { @@ -44,6 +44,8 @@ }, spellCheck: false }/} +
+ {/macro} {/Template} diff --git a/test/aria/widgets/form/autocomplete/multiautocomplete/test4/MultiAutoPrefill.js b/test/aria/widgets/form/autocomplete/multiautocomplete/test4/MultiAutoPrefill.js index 6fd61fd6e..c00dcae73 100644 --- a/test/aria/widgets/form/autocomplete/multiautocomplete/test4/MultiAutoPrefill.js +++ b/test/aria/widgets/form/autocomplete/multiautocomplete/test4/MultiAutoPrefill.js @@ -15,35 +15,51 @@ Aria.classDefinition({ $classpath : "test.aria.widgets.form.autocomplete.multiautocomplete.test4.MultiAutoPrefill", - $extends : "aria.jsunit.TemplateTestCase", + $extends : "test.aria.widgets.form.autocomplete.multiautocomplete.BaseMultiAutoCompleteTestCase", $constructor : function () { - this.$TemplateTestCase.constructor.call(this); this.data = { - ac_airline_values : ["Air France", "Air Canada", "Finnair"] + ac_airline_values : [], + freeText : true }; - // setTestEnv has to be invoked before runTemplateTest fires - this.setTestEnv({ - template : "test.aria.widgets.form.autocomplete.multiautocomplete.template.MultiAutoTpl", - data : this.data - }); + this.$BaseMultiAutoCompleteTestCase.constructor.call(this); }, $prototype : { - /** - * This method is always the first entry point to a template test Start the test by focusing the first field - */ + runTemplateTest : function () { - var parentNode = this.getInputField("MultiAutoId").parentNode, suggestionNode = parentNode.childNodes; - this.assertEquals(suggestionNode.length, 4, "The Wrong No. of elements are prefilled."); - var expectedVal = ["Air France", "Air Canada", "Finnair"]; - for (var j = 0; j < suggestionNode.length - 1; j++) { - this.assertEquals(suggestionNode[j].childNodes.length, 2, "The Wrong No. of elements are prefilled."); - var element = suggestionNode[j].firstChild.innerText || suggestionNode[j].firstChild.textContent; - this.assertEquals(element, expectedVal[j], "The Wrong values are prefilled as for Autocomplete."); - } - this.notifyTemplateTestEnd(); + this.checkSelectedItems(0); + + this.data.ac_airline_values = [{ + label : 'Air France', + code : 'AF' + + }, { + label : 'Air Canada', + code : 'AC' + }]; + this.templateCtxt.$refresh(); + this.checkSelectedItems(2, ["Air France", "Air Canada"]); + + this.data.freeText = false; + this.templateCtxt.$refresh(); + this.checkSelectedItems(2, ["Air France", "Air Canada"]); + + this.data.freeText = true; + this.data.ac_airline_values = [{ + label : 'Air France', + code : 'AF' + + }, "aaa", "bbb"]; + this.templateCtxt.$refresh(); + this.checkSelectedItems(3, ["Air France", "aaa", "bbb"]); + + this.data.freeText = false; + this.templateCtxt.$refresh(); + this.checkSelectedItems(3, ["Air France", "aaa", "bbb"]); + + this.end(); } } });