From 9990e6186677c40f53a6248361a0ceb1c77ecdb5 Mon Sep 17 00:00:00 2001 From: Ed Pelc Date: Thu, 2 Jul 2015 09:52:56 -0400 Subject: [PATCH] fix(autocomplete): tests wait for promises to complete now Fixes #2462. Closes #2710. --- .../autocomplete/autocomplete.spec.js | 6 ++ .../autocomplete/js/autocompleteController.js | 70 +++++++++++++------ src/components/chips/chips.spec.js | 3 +- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/components/autocomplete/autocomplete.spec.js b/src/components/autocomplete/autocomplete.spec.js index 8068ced18ab..928d4d615bd 100644 --- a/src/components/autocomplete/autocomplete.spec.js +++ b/src/components/autocomplete/autocomplete.spec.js @@ -58,6 +58,8 @@ describe('', function() { ctrl.keydown({ keyCode: $mdConstant.KEY_CODE.DOWN_ARROW, preventDefault: angular.noop }); ctrl.keydown({ keyCode: $mdConstant.KEY_CODE.ENTER, preventDefault: angular.noop }); scope.$apply(); + $timeout.flush(); + expect(scope.searchText).toBe('foo'); expect(scope.selectedItem).toBe(scope.match(scope.searchText)[0]); })); @@ -96,6 +98,8 @@ describe('', function() { ctrl.keydown({ keyCode: $mdConstant.KEY_CODE.DOWN_ARROW, preventDefault: angular.noop }); ctrl.keydown({ keyCode: $mdConstant.KEY_CODE.ENTER, preventDefault: angular.noop }); scope.$apply(); + $timeout.flush(); + expect(scope.searchText).toBe('foo'); expect(scope.selectedItem).toBe(scope.match(scope.searchText)[0]); })); @@ -153,6 +157,7 @@ describe('', function() { ctrl.select(0); element.scope().$apply(); + $timeout.flush(); expect(scope.searchText).toBe('foo'); expect(scope.selectedItem).not.toBeNull(); @@ -196,6 +201,7 @@ describe('', function() { ctrl.select(0); element.scope().$apply(); + $timeout.flush(); expect(scope.itemChanged).toHaveBeenCalled(); expect(scope.itemChanged.calls.mostRecent().args[0].display).toBe('foo'); diff --git a/src/components/autocomplete/js/autocompleteController.js b/src/components/autocomplete/js/autocompleteController.js index 160d69cc317..76bdefa4399 100644 --- a/src/components/autocomplete/js/autocompleteController.js +++ b/src/components/autocomplete/js/autocompleteController.js @@ -239,8 +239,19 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $timeout, $ $scope.searchText = val; }); } - if (angular.isFunction($scope.itemChange) && selectedItem !== previousSelectedItem) - $scope.itemChange(getItemScope(selectedItem)); + + if (selectedItem !== previousSelectedItem) announceItemChange(selectedItem); + } + + /** + * Use the user-defined expression to announce changes each time a new item is selected + */ + function announceItemChange( current ) { + angular.isFunction($scope.itemChange) && $scope.itemChange( getItemAsNameVal(current) ); + } + + function announceTextChange( value ) { + angular.isFunction($scope.textChange) && $scope.textChange(value); } /** @@ -283,25 +294,27 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $timeout, $ */ function handleSearchText (searchText, previousSearchText) { ctrl.index = getDefaultIndex(); - //-- do nothing on init + // do nothing on init if (searchText === previousSearchText) return; getDisplayValue($scope.selectedItem).then(function(val) { - //-- clear selected item if search text no longer matches it - if (searchText !== val) $scope.selectedItem = null; - else return; - - //-- trigger change event if available - if (angular.isFunction($scope.textChange) && searchText !== previousSearchText) - $scope.textChange(getItemScope($scope.selectedItem)); - //-- cancel results if search text is not long enough - if (!isMinLengthMet()) { - ctrl.loading = false; - ctrl.matches = []; - ctrl.hidden = shouldHide(); - updateMessages(); - } else { - handleQuery(); + // clear selected item if search text no longer matches it + if (searchText !== val) + { + $scope.selectedItem = null; + + // trigger change event if available + if ( searchText !== previousSearchText ) announceTextChange(searchText); + + // cancel results if search text is not long enough + if (!isMinLengthMet()) { + ctrl.loading = false; + ctrl.matches = []; + ctrl.hidden = shouldHide(); + updateMessages(); + } else { + handleQuery(); + } } }); @@ -378,7 +391,15 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $timeout, $ * @returns {*} */ function getDisplayValue (item) { - return (item && $scope.itemText) ? $q.when($scope.itemText(getItemScope(item))) : $q.when(item); + return $q.when( getItemText(item) || item ); + + /** + * Getter function to invoke user-defined expression (in the directive) + * to convert your object to a single string. + */ + function getItemText(item) { + return (item && $scope.itemText) ? $scope.itemText(getItemAsNameVal(item)) : null; + } } /** @@ -386,13 +407,18 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $timeout, $ * @param item * @returns {{}} */ - function getItemScope (item) { - if (!item) return; + function getItemAsNameVal (item) { + if (!item) return undefined; + var locals = {}; if (ctrl.itemName) locals[ctrl.itemName] = item; + return locals; } + + + /** * Returns the default index based on whether or not autoselect is enabled. * @returns {number} @@ -414,7 +440,7 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $timeout, $ * @returns {*} */ function getCurrentDisplayValue () { - return getDisplayValue(ctrl.matches[ctrl.index]); + return getDisplayValue( ctrl.matches[ctrl.index] ); } /** diff --git a/src/components/chips/chips.spec.js b/src/components/chips/chips.spec.js index b1d4fe1d00b..dd09e9a5a43 100644 --- a/src/components/chips/chips.spec.js +++ b/src/components/chips/chips.spec.js @@ -159,7 +159,8 @@ describe('', function() { element.scope().$apply(function() { autocompleteCtrl.select(0); }); - + $timeout.flush(); + expect(scope.items.length).toBe(4); expect(scope.items[3]).toBe('Kiwi'); }));