Best JavaScript code snippet using appium
autocomplete.spec.js
Source:autocomplete.spec.js
1describe('<md-autocomplete>', function() {2 var element, scope;3 beforeEach(module('material.components.autocomplete'));4 afterEach(function() {5 scope && scope.$destroy();6 });7 function compile(template, scope) {8 inject(function($compile) {9 element = $compile(template)(scope);10 scope.$apply();11 });12 return element;13 }14 function createScope(items, scopeData, matchLowercase) {15 items = items || ['foo', 'bar', 'baz'].map(function(item) {16 return { display: item };17 });18 inject(function($rootScope, $timeout) {19 scope = $rootScope.$new();20 scope.match = function(term) {21 return items.filter(function(item) {22 return item.display.indexOf(matchLowercase ? term.toLowerCase() : term) === 0;23 });24 };25 scope.asyncMatch = function(term) {26 return $timeout(function() {27 return scope.match(term);28 }, 1000);29 };30 scope.searchText = '';31 scope.selectedItem = null;32 scope.items = items;33 angular.forEach(scopeData, function(value, key) {34 scope[key] = value;35 });36 });37 return scope;38 }39 function keydownEvent(keyCode) {40 return {41 keyCode: keyCode,42 stopPropagation: angular.noop,43 preventDefault: angular.noop44 };45 }46 function waitForVirtualRepeat() {47 // Because the autocomplete does not make the suggestions menu visible48 // off the bat, the virtual repeat needs a couple more iterations to49 // figure out how tall it is and then how tall the repeated items are.50 // Using md-item-size would reduce this to a single flush, but given that51 // autocomplete allows for custom row templates, it's better to measure52 // rather than assuming a given size.53 inject(function($material, $timeout) {54 $material.flushOutstandingAnimations();55 $timeout.flush();56 });57 }58 describe('basic functionality', function() {59 it('updates selected item and search text', inject(function($timeout, $mdConstant, $material) {60 var scope = createScope();61 var template = '\62 <md-autocomplete\63 md-selected-item="selectedItem"\64 md-search-text="searchText"\65 md-items="item in match(searchText)"\66 md-item-text="item.display"\67 placeholder="placeholder">\68 <span md-highlight-text="searchText">{{item.display}}</span>\69 </md-autocomplete>';70 var element = compile(template, scope);71 var ctrl = element.controller('mdAutocomplete');72 var ul = element.find('ul');73 $material.flushInterimElement();74 expect(scope.searchText).toBe('');75 expect(scope.selectedItem).toBe(null);76 // Focus the input77 ctrl.focus();78 // Update the scope79 element.scope().searchText = 'fo';80 waitForVirtualRepeat(element);81 // Check expectations82 expect(scope.searchText).toBe('fo');83 expect(scope.match(scope.searchText).length).toBe(1);84 expect(ul.find('li').length).toBe(1);85 // Run our key events86 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.DOWN_ARROW));87 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ENTER));88 $timeout.flush();89 // Check expectations again90 expect(scope.searchText).toBe('foo');91 expect(scope.selectedItem).toBe(scope.match(scope.searchText)[0]);92 element.remove();93 }));94 it('should clear the searchText when the selectedItem manually got cleared',95 inject(function($timeout, $material, $mdConstant) {96 var scope = createScope();97 var template =98 '<md-autocomplete ' +99 'md-selected-item="selectedItem" ' +100 'md-search-text="searchText" ' +101 'md-items="item in match(searchText)" ' +102 'md-item-text="item.display" ' +103 'placeholder="placeholder"> ' +104 '<span md-highlight-text="searchText">{{item.display}}</span>' +105 '</md-autocomplete>';106 var element = compile(template, scope);107 var ctrl = element.controller('mdAutocomplete');108 var ul = element.find('ul');109 $material.flushInterimElement();110 expect(scope.searchText).toBe('');111 expect(scope.selectedItem).toBe(null);112 ctrl.focus();113 scope.$apply('searchText = "fo"');114 waitForVirtualRepeat(element);115 expect(scope.searchText).toBe('fo');116 expect(scope.match(scope.searchText).length).toBe(1);117 expect(ul.find('li').length).toBe(1);118 // Run our key events to trigger a select action119 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.DOWN_ARROW));120 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ENTER));121 $timeout.flush();122 expect(scope.searchText).toBe('foo');123 expect(scope.selectedItem).toBe(scope.match(scope.searchText)[0]);124 // Reset / Clear the current selected item.125 scope.$apply('selectedItem = null');126 waitForVirtualRepeat(element);127 // Run our key events to trigger a select action128 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.DOWN_ARROW));129 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ENTER));130 $timeout.flush();131 // The autocomplete automatically clears the searchText when the selectedItem was cleared.132 expect(scope.searchText).toBe('');133 expect(scope.selectedItem).toBeFalsy();134 element.remove();135 }));136 it('should should not clear the searchText when clearing the selected item from the input',137 inject(function($timeout, $material, $mdConstant) {138 var scope = createScope();139 var template =140 '<md-autocomplete ' +141 'md-selected-item="selectedItem" ' +142 'md-search-text="searchText" ' +143 'md-items="item in match(searchText)" ' +144 'md-item-text="item.display" ' +145 'placeholder="placeholder"> ' +146 '<span md-highlight-text="searchText">{{item.display}}</span>' +147 '</md-autocomplete>';148 var element = compile(template, scope);149 var ctrl = element.controller('mdAutocomplete');150 var input = element.find('input');151 var ul = element.find('ul');152 $material.flushInterimElement();153 expect(scope.searchText).toBe('');154 expect(scope.selectedItem).toBe(null);155 ctrl.focus();156 scope.$apply('searchText = "fo"');157 waitForVirtualRepeat(element);158 expect(scope.searchText).toBe('fo');159 expect(scope.match(scope.searchText).length).toBe(1);160 expect(ul.find('li').length).toBe(1);161 // Run our key events to trigger a select action162 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.DOWN_ARROW));163 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ENTER));164 $timeout.flush();165 expect(scope.searchText).toBe('foo');166 expect(scope.selectedItem).toBe(scope.match(scope.searchText)[0]);167 scope.$apply('searchText = "food"');168 $timeout.flush();169 // The autocomplete automatically clears the searchText when the selectedItem was cleared.170 expect(scope.searchText).toBe('food');171 expect(scope.selectedItem).toBeFalsy();172 element.remove();173 }));174 it('allows you to set an input id without floating label', inject(function() {175 var scope = createScope(null, {inputId: 'custom-input-id'});176 var template = '\177 <md-autocomplete\178 md-input-id="{{inputId}}"\179 md-selected-item="selectedItem"\180 md-search-text="searchText"\181 md-items="item in match(searchText)"\182 md-item-text="item.display"\183 placeholder="placeholder">\184 <span md-highlight-text="searchText">{{item.display}}</span>\185 </md-autocomplete>';186 var element = compile(template, scope);187 var input = element.find('input');188 expect(input.attr('id')).toBe(scope.inputId);189 element.remove();190 }));191 it('allows using ng-readonly', inject(function() {192 var scope = createScope(null, {inputId: 'custom-input-id'});193 var template = '\194 <md-autocomplete\195 md-input-id="{{inputId}}"\196 md-selected-item="selectedItem"\197 md-search-text="searchText"\198 md-items="item in match(searchText)"\199 md-item-text="item.display"\200 placeholder="placeholder"\201 ng-readonly="readonly">\202 <span md-highlight-text="searchText">{{item.display}}</span>\203 </md-autocomplete>';204 var element = compile(template, scope);205 var input = element.find('input');206 scope.readonly = true;207 scope.$digest();208 expect(input.attr('readonly')).toBe('readonly');209 scope.readonly = false;210 scope.$digest();211 expect(input.attr('readonly')).toBeUndefined();212 element.remove();213 }));214 it('should forward focus to the input element with md-autofocus', inject(function($timeout) {215 var scope = createScope();216 var template =217 '<md-autocomplete ' +218 ' md-selected-item="selectedItem" ' +219 ' md-search-text="searchText" ' +220 ' md-items="item in match(searchText)" ' +221 ' md-item-text="item.display" ' +222 ' placeholder="placeholder"' +223 ' md-autofocus>' +224 ' <span md-highlight-text="searchText">{{item.display}}</span>' +225 '</md-autocomplete>';226 var element = compile(template, scope);227 var input = element.find('input');228 document.body.appendChild(element[0]);229 // Initial timeout for gathering elements230 $timeout.flush();231 element.triggerHandler('focus');232 expect(document.activeElement).toBe(input[0]);233 element.remove();234 }));235 it('allows using an empty readonly attribute', inject(function() {236 var scope = createScope(null, {inputId: 'custom-input-id'});237 var template = '\238 <md-autocomplete\239 md-input-id="{{inputId}}"\240 md-selected-item="selectedItem"\241 md-search-text="searchText"\242 md-items="item in match(searchText)"\243 md-item-text="item.display"\244 placeholder="placeholder"\245 readonly>\246 <span md-highlight-text="searchText">{{item.display}}</span>\247 </md-autocomplete>';248 var element = compile(template, scope);249 var input = element.find('input');250 expect(input.attr('readonly')).toBe('readonly');251 element.remove();252 }));253 it('allows you to set an input id with floating label', inject(function() {254 var scope = createScope(null, {inputId: 'custom-input-id'});255 var template = '\256 <md-autocomplete\257 md-floating-label="Some Label"\258 md-input-id="{{inputId}}"\259 md-selected-item="selectedItem"\260 md-search-text="searchText"\261 md-items="item in match(searchText)"\262 md-item-text="item.display"\263 placeholder="placeholder">\264 <span md-highlight-text="searchText">{{item.display}}</span>\265 </md-autocomplete>';266 var element = compile(template, scope);267 var input = element.find('input');268 expect(input.attr('id')).toBe(scope.inputId);269 element.remove();270 }));271 it('forwards the `md-select-on-focus` attribute to the input', inject(function() {272 var scope = createScope(null, {inputId: 'custom-input-id'});273 var template =274 '<md-autocomplete ' +275 'md-input-id="{{inputId}}" ' +276 'md-selected-item="selectedItem" ' +277 'md-search-text="searchText" ' +278 'md-items="item in match(searchText)" ' +279 'md-item-text="item.display" ' +280 'md-select-on-focus="" ' +281 'tabindex="3"' +282 'placeholder="placeholder">' +283 '<span md-highlight-text="searchText">{{item.display}}</span>' +284 '</md-autocomplete>';285 var element = compile(template, scope);286 var input = element.find('input');287 expect(input.attr('md-select-on-focus')).toBe("");288 element.remove();289 }));290 it('should support ng-trim for the search input', inject(function() {291 var scope = createScope(null, {inputId: 'custom-input-id'});292 var template =293 '<md-autocomplete ' +294 'md-selected-item="selectedItem" ' +295 'md-search-text="searchText" ' +296 'md-items="item in match(searchText)" ' +297 'md-item-text="item.display" ' +298 'ng-trim="false" ' +299 'placeholder="placeholder">' +300 '<span md-highlight-text="searchText">{{item.display}}</span>' +301 '</md-autocomplete>';302 var element = compile(template, scope);303 var input = element.find('input');304 expect(input.attr('ng-trim')).toBe("false");305 scope.$apply('searchText = " Text "');306 expect(scope.searchText).not.toBe('Text');307 element.remove();308 }));309 it('should support ng-pattern for the search input', inject(function() {310 var scope = createScope(null, {inputId: 'custom-input-id'});311 var template =312 '<form name="testForm">' +313 '<md-autocomplete ' +314 'md-input-name="autocomplete" ' +315 'md-selected-item="selectedItem" ' +316 'md-search-text="searchText" ' +317 'md-items="item in match(searchText)" ' +318 'md-item-text="item.display" ' +319 'ng-pattern="/^[0-9]$/" ' +320 'placeholder="placeholder">' +321 '<span md-highlight-text="searchText">{{item.display}}</span>' +322 '</md-autocomplete>' +323 '</form>';324 var element = compile(template, scope);325 var input = element.find('input');326 expect(input.attr('ng-pattern')).toBeTruthy();327 scope.$apply('searchText = "Test"');328 expect(scope.testForm.autocomplete.$error['pattern']).toBeTruthy();329 scope.$apply('searchText = "3"');330 expect(scope.testForm.autocomplete.$error['pattern']).toBeFalsy();331 element.remove();332 }));333 it('forwards the tabindex to the input', inject(function() {334 var scope = createScope(null, {inputId: 'custom-input-id'});335 var template =336 '<md-autocomplete ' +337 'md-input-id="{{inputId}}" ' +338 'md-selected-item="selectedItem" ' +339 'md-search-text="searchText" ' +340 'md-items="item in match(searchText)" ' +341 'md-item-text="item.display" ' +342 'tabindex="3"' +343 'placeholder="placeholder">' +344 '<span md-highlight-text="searchText">{{item.display}}</span>' +345 '</md-autocomplete>';346 var element = compile(template, scope);347 var input = element.find('input');348 expect(input.attr('tabindex')).toBe('3');349 element.remove();350 }));351 it('always sets the tabindex of the autcomplete to `-1`', inject(function() {352 var scope = createScope(null, {inputId: 'custom-input-id'});353 var template =354 '<md-autocomplete ' +355 'md-input-id="{{inputId}}" ' +356 'md-selected-item="selectedItem" ' +357 'md-search-text="searchText" ' +358 'md-items="item in match(searchText)" ' +359 'md-item-text="item.display" ' +360 'tabindex="3"' +361 'placeholder="placeholder">' +362 '<span md-highlight-text="searchText">{{item.display}}</span>' +363 '</md-autocomplete>';364 var element = compile(template, scope);365 expect(element.attr('tabindex')).toBe('-1');366 element.remove();367 }));368 it('should emit the ngBlur event from the input', inject(function() {369 var scope = createScope(null, {370 onBlur: jasmine.createSpy('onBlur event')371 });372 var template =373 '<md-autocomplete ' +374 'md-selected-item="selectedItem" ' +375 'md-search-text="searchText" ' +376 'md-items="item in match(searchText)" ' +377 'md-item-text="item.display" ' +378 'ng-blur="onBlur($event)" ' +379 'placeholder="placeholder">' +380 '<span md-highlight-text="searchText">{{item.display}}</span>' +381 '</md-autocomplete>';382 var element = compile(template, scope);383 var input = element.find('input');384 input.triggerHandler('blur');385 expect(scope.onBlur).toHaveBeenCalledTimes(1);386 // Confirm that the ngFocus event was called with the $event local.387 var focusEvent = scope.onBlur.calls.mostRecent().args[0];388 expect(focusEvent.target).toBe(input[0]);389 element.remove();390 }));391 it('should emit the ngFocus event from the input', inject(function() {392 var scope = createScope(null, {393 onFocus: jasmine.createSpy('onFocus event')394 });395 var template =396 '<md-autocomplete ' +397 'md-selected-item="selectedItem" ' +398 'md-search-text="searchText" ' +399 'md-items="item in match(searchText)" ' +400 'md-item-text="item.display" ' +401 'ng-focus="onFocus($event)" ' +402 'placeholder="placeholder">' +403 '<span md-highlight-text="searchText">{{item.display}}</span>' +404 '</md-autocomplete>';405 var element = compile(template, scope);406 var input = element.find('input');407 input.triggerHandler('focus');408 expect(scope.onFocus).toHaveBeenCalledTimes(1);409 // Confirm that the ngFocus event was called with the $event object.410 var focusEvent = scope.onFocus.calls.mostRecent().args[0];411 expect(focusEvent.target).toBe(input[0]);412 element.remove();413 }));414 it('should not show a loading progress when the items object is invalid', inject(function() {415 var scope = createScope(null, {416 match: function() {417 // Return an invalid object, which is not an array, neither a promise.418 return {}419 }420 });421 var template =422 '<md-autocomplete ' +423 'md-input-id="{{inputId}}" ' +424 'md-selected-item="selectedItem" ' +425 'md-search-text="searchText" ' +426 'md-items="item in match(searchText)" ' +427 'md-item-text="item.display" ' +428 'tabindex="3"' +429 'placeholder="placeholder">' +430 '<span md-highlight-text="searchText">{{item.display}}</span>' +431 '</md-autocomplete>';432 var element = compile(template, scope);433 var ctrl = element.controller('mdAutocomplete');434 scope.$apply('searchText = "test"');435 expect(ctrl.loading).toBe(false);436 element.remove();437 }));438 it('clears the value when hitting escape', inject(function($mdConstant, $timeout) {439 var scope = createScope();440 var template = '\441 <md-autocomplete\442 md-search-text="searchText"\443 md-items="item in match(searchText)"\444 md-item-text="item.display"\445 placeholder="placeholder">\446 <span md-highlight-text="searchText">{{item.display}}</span>\447 </md-autocomplete>';448 var element = compile(template, scope);449 var input = element.find('input');450 var ctrl = element.controller('mdAutocomplete');451 expect(scope.searchText).toBe('');452 scope.$apply('searchText = "test"');453 expect(scope.searchText).toBe('test');454 $timeout.flush();455 scope.$apply(function() {456 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ESCAPE));457 });458 expect(scope.searchText).toBe('');459 element.remove();460 }));461 describe('md-input-maxlength', function() {462 it('should correctly set the form to invalid if floating label is present', inject(function($timeout) {463 var scope = createScope(null, {inputId: 'custom-input-id'});464 var template =465 '<form name="testForm">' +466 '<md-autocomplete ' +467 'md-input-id="{{inputId}}" ' +468 'md-input-maxlength="2" ' +469 'md-input-name="testAutocomplete" ' +470 'md-selected-item="selectedItem" ' +471 'md-search-text="searchText" ' +472 'md-items="item in match(searchText)" ' +473 'md-item-text="item.display" ' +474 'tabindex="3"' +475 'md-floating-label="Favorite state">' +476 '<span md-highlight-text="searchText">{{item.display}}</span>' +477 '</md-autocomplete>' +478 '</form>';479 var element = compile(template, scope);480 var input = element.find('input');481 expect(scope.searchText).toBe('');482 expect(scope.testForm.$valid).toBe(true);483 scope.$apply('searchText = "Exceeded"');484 expect(scope.testForm.$valid).toBe(false);485 element.remove();486 }));487 it('should correctly set the form to invalid when no floating label is present', inject(function($timeout) {488 var scope = createScope(null, {inputId: 'custom-input-id'});489 var template =490 '<form name="testForm">' +491 '<md-autocomplete ' +492 'md-input-id="{{inputId}}" ' +493 'md-input-maxlength="5" ' +494 'md-input-name="testAutocomplete" ' +495 'md-selected-item="selectedItem" ' +496 'md-search-text="searchText" ' +497 'md-items="item in match(searchText)" ' +498 'md-item-text="item.display" >' +499 '<span md-highlight-text="searchText">{{item.display}}</span>' +500 '</md-autocomplete>' +501 '</form>';502 var element = compile(template, scope);503 var input = element.find('input');504 expect(scope.searchText).toBe('');505 expect(scope.testForm.$valid).toBe(true);506 scope.$apply('searchText = "Exceeded"');507 expect(scope.testForm.$valid).toBe(false);508 element.remove();509 }));510 it('should not clear the view value if the input is invalid', inject(function($timeout) {511 var scope = createScope(null, {inputId: 'custom-input-id'});512 var template =513 '<form name="testForm">' +514 '<md-autocomplete ' +515 'md-input-id="{{inputId}}" ' +516 'md-input-maxlength="2" ' +517 'md-input-name="testAutocomplete" ' +518 'md-selected-item="selectedItem" ' +519 'md-search-text="searchText" ' +520 'md-items="item in match(searchText)" ' +521 'md-item-text="item.display" ' +522 'tabindex="3"' +523 'md-floating-label="Favorite state">' +524 '<span md-highlight-text="searchText">{{item.display}}</span>' +525 '</md-autocomplete>' +526 '</form>';527 var element = compile(template, scope);528 var input = element.find('input');529 expect(scope.searchText).toBe('');530 expect(scope.testForm.$valid).toBe(true);531 input.val('Exceeded');532 input.triggerHandler('change');533 scope.$digest();534 expect(scope.testForm.$valid).toBe(false);535 expect(scope.searchText).toBe('Exceeded');536 element.remove();537 }));538 });539 describe('md-input-minlength', function() {540 it('should correctly set the form to invalid when floating label is present', inject(function($timeout) {541 var scope = createScope(null, {inputId: 'custom-input-id'});542 var template =543 '<form name="testForm">' +544 '<md-autocomplete ' +545 'md-input-id="{{inputId}}" ' +546 'md-input-minlength="4" ' +547 'md-input-name="testAutocomplete" ' +548 'md-selected-item="selectedItem" ' +549 'md-search-text="searchText" ' +550 'md-items="item in match(searchText)" ' +551 'md-item-text="item.display" ' +552 'tabindex="3"' +553 'md-floating-label="Favorite state">' +554 '<span md-highlight-text="searchText">{{item.display}}</span>' +555 '</md-autocomplete>' +556 '</form>';557 var element = compile(template, scope);558 var input = element.find('input');559 scope.$apply('searchText = "abc"');560 expect(scope.testForm.$valid).toBe(false);561 scope.$apply('searchText = "abcde"');562 expect(scope.testForm.$valid).toBe(true);563 element.remove();564 }));565 it('should correctly set the form to invalid when no floating label is present', inject(function($timeout) {566 var scope = createScope(null, {inputId: 'custom-input-id'});567 var template =568 '<form name="testForm">' +569 '<md-autocomplete ' +570 'md-input-id="{{inputId}}" ' +571 'md-input-minlength="4" ' +572 'md-input-name="testAutocomplete" ' +573 'md-selected-item="selectedItem" ' +574 'md-search-text="searchText" ' +575 'md-items="item in match(searchText)" ' +576 'md-item-text="item.display" >' +577 '<span md-highlight-text="searchText">{{item.display}}</span>' +578 '</md-autocomplete>' +579 '</form>';580 var element = compile(template, scope);581 var input = element.find('input');582 scope.$apply('searchText = "abc"');583 expect(scope.testForm.$valid).toBe(false);584 scope.$apply('searchText = "abcde"');585 expect(scope.testForm.$valid).toBe(true);586 element.remove();587 }));588 });589 describe('md-escape-options checks', function() {590 var scope, ctrl, element;591 var template = '\592 <md-autocomplete\593 md-escape-options="{{escapeOptions}}"\594 md-search-text="searchText"\595 md-items="item in match(searchText)"\596 md-item-text="item.display"\597 placeholder="placeholder">\598 <span md-highlight-text="searchText">{{item.display}}</span>\599 </md-autocomplete>';600 beforeEach( inject(function($timeout, $material) {601 scope = createScope();602 element = compile(template, scope);603 ctrl = element.controller('mdAutocomplete');604 $material.flushInterimElement();605 // Update the scope606 element.scope().searchText = 'fo';607 waitForVirtualRepeat(element);608 // Focus the input609 ctrl.focus();610 $timeout.flush();611 expect(ctrl.hidden).toBe(false);612 expect(scope.searchText).toBe('fo');613 waitForVirtualRepeat(element);614 $timeout.flush();615 expect(ctrl.hidden).toBe(false);616 }));617 afterEach(function() { element.remove() });618 it('does not clear the value nor blur when hitting escape', inject(function($mdConstant, $document, $timeout) {619 scope.$apply('escapeOptions = "none"');620 scope.$apply(function() {621 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ESCAPE));622 $timeout.flush();623 expect(ctrl.hidden).toBe(true);624 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ESCAPE));625 $timeout.flush();626 });627 expect(scope.searchText).toBe('fo');628 expect($document.activeElement).toBe(ctrl[0]);629 }));630 it('does not clear the value but does blur when hitting escape', inject(function($mdConstant, $document, $timeout) {631 scope.$apply('escapeOptions = "blur"');632 scope.$apply(function() {633 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ESCAPE));634 $timeout.flush();635 expect(ctrl.hidden).toBe(true);636 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ESCAPE));637 $timeout.flush();638 });639 expect(scope.searchText).toBe('fo');640 expect($document.activeElement).toBe(undefined);641 }));642 it('clear the value but does not blur when hitting escape', inject(function($mdConstant, $document, $timeout) {643 scope.$apply('escapeOptions = "clear"');644 scope.$apply(function() {645 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ESCAPE));646 $timeout.flush();647 expect(ctrl.hidden).toBe(true);648 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ESCAPE));649 $timeout.flush();650 });651 expect(scope.searchText).toBe('');652 expect($document.activeElement).toBe(ctrl[0]);653 }));654 });655 it('should not show the progressbar when hitting escape on an empty input', inject(function($mdConstant, $timeout) {656 var scope = createScope();657 var template = '\658 <md-autocomplete\659 md-search-text="searchText"\660 md-items="item in match(searchText)">\661 </md-autocomplete>';662 var element = compile(template, scope);663 var ctrl = element.controller('mdAutocomplete');664 $timeout.flush();665 scope.$apply(function() {666 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ESCAPE));667 });668 expect(element.find('md-progress-linear').length).toBe(0);669 element.remove();670 }));671 it('should not close list on ENTER key if nothing is selected', inject(function($timeout, $mdConstant, $material) {672 var scope = createScope();673 var template = '\674 <md-autocomplete\675 md-selected-item="selectedItem"\676 md-search-text="searchText"\677 md-items="item in match(searchText)"\678 md-item-text="item.display"\679 placeholder="placeholder">\680 <span md-highlight-text="searchText">{{item.display}}</span>\681 </md-autocomplete>';682 var element = compile(template, scope);683 var ctrl = element.controller('mdAutocomplete');684 var ul = element.find('ul');685 $material.flushInterimElement();686 // Update the scope687 element.scope().searchText = 'fo';688 waitForVirtualRepeat(element);689 // Focus the input690 ctrl.focus();691 $timeout.flush();692 expect(ctrl.hidden).toBe(false);693 // Run our key events694 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ENTER));695 $timeout.flush();696 // Check expectations again697 expect(ctrl.hidden).toBe(false);698 element.remove();699 }));700 });701 describe('basic functionality with template', function() {702 it('updates selected item and search text', inject(function($timeout, $material, $mdConstant) {703 var scope = createScope();704 var template = '\705 <md-autocomplete\706 md-selected-item="selectedItem"\707 md-search-text="searchText"\708 md-items="item in match(searchText)"\709 md-item-text="item.display"\710 placeholder="placeholder">\711 <md-item-template>\712 <span md-highlight-text="searchText">{{item.display}}</span>\713 </md-item-template>\714 </md-autocomplete>';715 var element = compile(template, scope);716 var ctrl = element.controller('mdAutocomplete');717 var ul = element.find('ul');718 expect(scope.searchText).toBe('');719 expect(scope.selectedItem).toBe(null);720 $material.flushInterimElement();721 // Focus the input722 ctrl.focus();723 element.scope().searchText = 'fo';724 waitForVirtualRepeat(element);725 expect(scope.searchText).toBe('fo');726 expect(scope.match(scope.searchText).length).toBe(1);727 expect(ul.find('li').length).toBe(1);728 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.DOWN_ARROW));729 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ENTER));730 $timeout.flush();731 expect(scope.searchText).toBe('foo');732 expect(scope.selectedItem).toBe(scope.match(scope.searchText)[0]);733 element.remove();734 }));735 it('properly clears values when the item ends in a space character', inject(function($timeout, $material, $mdConstant) {736 var myItems = ['foo ', 'bar', 'baz'].map(function(item) {737 return {display: item};738 });739 var scope = createScope(myItems);740 var template = '\741 <md-autocomplete\742 md-selected-item="selectedItem"\743 md-search-text="searchText"\744 md-items="item in match(searchText)"\745 md-item-text="item.display"\746 placeholder="placeholder">\747 <md-item-template>\748 <span md-highlight-text="searchText">{{item.display}}</span>\749 </md-item-template>\750 </md-autocomplete>';751 var element = compile(template, scope);752 var ctrl = element.controller('mdAutocomplete');753 var ul = element.find('ul');754 expect(scope.searchText).toBe('');755 expect(scope.selectedItem).toBe(null);756 $material.flushInterimElement();757 // Focus the input758 ctrl.focus();759 element.scope().searchText = 'fo';760 waitForVirtualRepeat(element);761 expect(scope.searchText).toBe('fo');762 expect(scope.match(scope.searchText).length).toBe(1);763 expect(ul.find('li').length).toBe(1);764 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.DOWN_ARROW));765 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.ENTER));766 $timeout.flush();767 expect(scope.searchText).toBe('foo ');768 expect(scope.selectedItem).toBe(scope.match(scope.searchText)[0]);769 ctrl.clear();770 $timeout.flush();771 expect(scope.searchText).toBe('');772 expect(scope.selectedItem).toBe(null);773 element.remove();774 }));775 it('compiles the template against the parent scope', inject(function($timeout, $material) {776 var scope = createScope(null, {bang: 'boom'});777 var template =778 '<md-autocomplete' +779 ' md-selected-item="selectedItem"' +780 ' md-search-text="searchText"' +781 ' md-items="item in match(searchText)"' +782 ' md-item-text="item.display"' +783 ' placeholder="placeholder">' +784 ' <md-item-template>' +785 ' <span class="find-parent-scope">{{bang}}</span>' +786 ' <span class="find-index">{{$index}}</span>' +787 ' <span class="find-item">{{item.display}}</span>' +788 ' </md-item-template>' +789 '</md-autocomplete>';790 var element = compile(template, scope);791 var ctrl = element.controller('mdAutocomplete');792 var ul = element.find('ul');793 $material.flushOutstandingAnimations();794 expect(scope.bang).toBe('boom');795 // Focus the input796 ctrl.focus();797 element.scope().searchText = 'fo';798 // Run our initial flush799 $timeout.flush();800 waitForVirtualRepeat(element);801 // Wait for the next tick when the values will be updated802 $timeout.flush();803 var li = ul.find('li')[0];804 // Expect it to be compiled against the parent scope and have our variables copied805 expect(li.querySelector('.find-parent-scope').innerHTML).toBe('boom');806 expect(li.querySelector('.find-index').innerHTML).toBe('0');807 expect(li.querySelector('.find-item').innerHTML).toBe('foo');808 // Make sure we wrap up anything and remove the element809 $timeout.flush();810 element.remove();811 }));812 it('removes the md-scroll-mask on cleanup', inject(function($mdUtil, $timeout, $material) {813 spyOn($mdUtil, 'enableScrolling').and.callThrough();814 var scope = createScope();815 var template =816 '<md-autocomplete' +817 ' md-selected-item="selectedItem"' +818 ' md-search-text="searchText"' +819 ' md-items="item in match(searchText)"' +820 ' md-item-text="item.display"' +821 ' placeholder="placeholder">' +822 ' <md-item-template>{{item.display}}</md-item-template>' +823 ' <md-not-found>Sorry, not found...</md-not-found>' +824 '</md-autocomplete>';825 var element = compile(template, scope);826 var ctrl = element.controller('mdAutocomplete');827 $material.flushOutstandingAnimations();828 // Focus our input829 ctrl.focus();830 // Set our search text to a value that we know doesn't exist831 scope.searchText = 'somethingthatdoesnotexist';832 // Run our initial flush833 $timeout.flush();834 waitForVirtualRepeat(element);835 // Wait for the next tick when the values will be updated836 $timeout.flush();837 expect(ctrl.hidden).toBeFalsy();838 // Make sure we wrap up anything and remove the element839 $timeout.flush();840 element.remove();841 scope.$destroy();842 // Should be hidden on once the scope is destroyed to ensure proper cleanup (like md-scroll-mask is removed from the DOM)843 expect($mdUtil.enableScrolling).toHaveBeenCalled();844 }));845 it('removes the md-scroll-mask when md-autocomplete removed on change', inject(function($mdUtil, $timeout, $material) {846 spyOn($mdUtil, 'enableScrolling').and.callThrough();847 var scope = createScope();848 var template =849 '<div>' +850 ' <md-autocomplete' +851 ' ng-if="!removeAutocomplete"' +852 ' md-selected-item="selectedItem"' +853 ' md-search-text="searchText"' +854 ' md-items="item in match(searchText)"' +855 ' md-item-text="item.display"' +856 ' placeholder="placeholder">' +857 ' <md-item-template>{{item.display}}</md-item-template>' +858 ' <md-not-found>Sorry, not found...</md-not-found>' +859 ' </md-autocomplete>' +860 '</div>';861 var element = compile(template, scope);862 var ctrl = element.children().controller('mdAutocomplete');863 $material.flushOutstandingAnimations();864 // Focus our input865 ctrl.focus();866 // Set our search text to a value to make md-scroll-mask added to DOM867 scope.$apply('searchText = "searchText"');868 $timeout.flush();869 // Set removeAutocomplete to false to remove the md-autocomplete870 scope.$apply('removeAutocomplete = true');871 expect($mdUtil.enableScrolling).toHaveBeenCalled();872 }));873 it('should initialize the search text with an empty string', inject(function($mdUtil, $timeout, $material) {874 var scope = createScope();875 // Delete our searchText variable from the generated scope, because we876 // want to confirm, that the autocomplete uses an empty string by default.877 delete scope.searchText;878 var template =879 '<md-autocomplete' +880 ' md-selected-item="selectedItem"' +881 ' md-search-text="searchText"' +882 ' md-items="item in match(searchText)"' +883 ' md-item-text="item.display"' +884 ' placeholder="placeholder">' +885 ' <md-item-template>{{item.display}}</md-item-template>' +886 ' <md-not-found>Sorry, not found...</md-not-found>' +887 '</md-autocomplete>';888 var element = compile(template, scope);889 var ctrl = element.controller('mdAutocomplete');890 $material.flushOutstandingAnimations();891 // Run our initial flush892 $timeout.flush();893 waitForVirtualRepeat(element);894 // Set our search text to a value that we know doesn't exist895 expect(scope.searchText).toBe('');896 // Make sure we wrap up anything and remove the element897 $timeout.flush();898 element.remove();899 }));900 it('ensures the parent scope digests along with the current scope', inject(function($timeout, $material) {901 var scope = createScope(null, {bang: 'boom'});902 var template =903 '<md-autocomplete' +904 ' md-selected-item="selectedItem"' +905 ' md-search-text="searchText"' +906 ' md-items="item in match(searchText)"' +907 ' md-item-text="item.display"' +908 ' placeholder="placeholder">' +909 ' <md-item-template>' +910 ' <span class="find-parent-scope">{{bang}}</span>' +911 ' <span class="find-index">{{$index}}</span>' +912 ' <span class="find-item">{{item.display}}</span>' +913 ' </md-item-template>' +914 '</md-autocomplete>';915 var element = compile(template, scope);916 var ctrl = element.controller('mdAutocomplete');917 var ul = element.find('ul');918 $material.flushOutstandingAnimations();919 // Focus the input920 ctrl.focus();921 element.scope().searchText = 'fo';922 // Run our initial flush923 $timeout.flush();924 waitForVirtualRepeat(element);925 // Wait for the next tick when the values will be updated926 $timeout.flush();927 var li = ul.find('li')[0];928 var parentScope = angular.element(li.querySelector('.find-parent-scope')).scope();929 // When the autocomplete item's scope digests, ensure that the parent930 // scope does too.931 parentScope.bang = 'big';932 scope.$digest();933 expect(li.querySelector('.find-parent-scope').innerHTML).toBe('big');934 // Make sure we wrap up anything and remove the element935 $timeout.flush();936 element.remove();937 }));938 it('is hidden when no matches are found without an md-not-found template', inject(function($timeout, $material) {939 var scope = createScope();940 var template =941 '<md-autocomplete' +942 ' md-selected-item="selectedItem"' +943 ' md-search-text="searchText"' +944 ' md-items="item in match(searchText)"' +945 ' md-item-text="item.display"' +946 ' placeholder="placeholder">' +947 ' <md-item-template>{{item.display}}</md-item-template>' +948 '</md-autocomplete>';949 var element = compile(template, scope);950 var ctrl = element.controller('mdAutocomplete');951 $material.flushOutstandingAnimations();952 // Focus our input953 ctrl.focus();954 // Set our search text to a value that we know doesn't exist955 scope.searchText = 'somethingthatdoesnotexist';956 // Run our initial flush957 $timeout.flush();958 waitForVirtualRepeat(element);959 // Wait for the next tick when the values will be updated960 $timeout.flush();961 // We should be hidden since no md-not-found template was provided962 expect(ctrl.hidden).toBe(true);963 // Make sure we wrap up anything and remove the element964 $timeout.flush();965 element.remove();966 }));967 it('is visible when no matches are found with an md-not-found template', inject(function($timeout, $material) {968 var scope = createScope();969 var template =970 '<md-autocomplete' +971 ' md-selected-item="selectedItem"' +972 ' md-search-text="searchText"' +973 ' md-items="item in match(searchText)"' +974 ' md-item-text="item.display"' +975 ' placeholder="placeholder">' +976 ' <md-item-template>{{item.display}}</md-item-template>' +977 ' <md-not-found>Sorry, not found...</md-not-found>' +978 '</md-autocomplete>';979 var element = compile(template, scope);980 var ctrl = element.controller('mdAutocomplete');981 $material.flushOutstandingAnimations();982 // Focus our input983 ctrl.focus();984 // Set our search text to a value that we know doesn't exist985 scope.searchText = 'somethingthatdoesnotexist';986 // Run our initial flush987 $timeout.flush();988 waitForVirtualRepeat(element);989 // Wait for the next tick when the values will be updated990 $timeout.flush();991 // We should be visible since an md-not-found template was provided992 expect(ctrl.hidden).toBe(false);993 // Make sure we wrap up anything and remove the element994 $timeout.flush();995 element.remove();996 }));997 it('properly sets hasNotFound when element is hidden through ng-if', inject(function() {998 var scope = createScope();999 var template1 =1000 '<div>' +1001 '<md-autocomplete ' +1002 'md-selected-item="selectedItem" ' +1003 'md-search-text="searchText" ' +1004 'md-items="item in match(searchText)" ' +1005 'md-item-text="item.display" ' +1006 'placeholder="placeholder" ' +1007 'ng-if="showAutocomplete">' +1008 '<md-item-template>{{item.display}}</md-item-template>' +1009 '<md-not-found>Sorry, not found...</md-not-found>' +1010 '</md-autocomplete>' +1011 '</div>';1012 var element = compile(template1, scope);1013 var ctrl = element.children().controller('mdAutocomplete');1014 expect(ctrl).toBeUndefined();1015 scope.$apply('showAutocomplete = true');1016 ctrl = element.children().controller('mdAutocomplete');1017 expect(ctrl.hasNotFound).toBe(true);1018 }));1019 it('properly sets hasNotFound with multiple autocompletes', inject(function($timeout, $material) {1020 var scope = createScope();1021 var template1 =1022 '<md-autocomplete' +1023 ' md-selected-item="selectedItem"' +1024 ' md-search-text="searchText"' +1025 ' md-items="item in match(searchText)"' +1026 ' md-item-text="item.display"' +1027 ' placeholder="placeholder">' +1028 ' <md-item-template>{{item.display}}</md-item-template>' +1029 ' <md-not-found>Sorry, not found...</md-not-found>' +1030 '</md-autocomplete>';1031 var element1 = compile(template1, scope);1032 var ctrl1 = element1.controller('mdAutocomplete');1033 var template2 =1034 '<md-autocomplete' +1035 ' md-selected-item="selectedItem"' +1036 ' md-search-text="searchText"' +1037 ' md-items="item in match(searchText)"' +1038 ' md-item-text="item.display"' +1039 ' placeholder="placeholder">' +1040 ' <md-item-template>{{item.display}}</md-item-template>' +1041 '</md-autocomplete>';1042 var element2 = compile(template2, scope);1043 var ctrl2 = element2.controller('mdAutocomplete');1044 // The first autocomplete has a template, the second one does not1045 expect(ctrl1.hasNotFound).toBe(true);1046 expect(ctrl2.hasNotFound).toBe(false);1047 }));1048 it('shows the md-not-found template even if we have lost focus', inject(function($timeout) {1049 var scope = createScope();1050 var template =1051 '<md-autocomplete' +1052 ' md-selected-item="selectedItem"' +1053 ' md-search-text="searchText"' +1054 ' md-items="item in match(searchText)"' +1055 ' md-item-text="item.display"' +1056 ' placeholder="placeholder">' +1057 ' <md-item-template>{{item.display}}</md-item-template>' +1058 ' <md-not-found>Sorry, not found...</md-not-found>' +1059 '</md-autocomplete>';1060 var element = compile(template, scope);1061 var controller = element.controller('mdAutocomplete');1062 controller.focus();1063 scope.searchText = 'somethingthatdoesnotexist';1064 $timeout.flush();1065 controller.listEnter();1066 expect(controller.notFoundVisible()).toBe(true);1067 controller.blur();1068 expect(controller.notFoundVisible()).toBe(true);1069 controller.listLeave();1070 expect(controller.notFoundVisible()).toBe(false);1071 $timeout.flush();1072 element.remove();1073 }));1074 it('should not show the md-not-found template if we lost focus and left the list', inject(function($timeout) {1075 var scope = createScope();1076 var template =1077 '<md-autocomplete' +1078 ' md-selected-item="selectedItem"' +1079 ' md-search-text="searchText"' +1080 ' md-items="item in match(searchText)"' +1081 ' md-item-text="item.display"' +1082 ' placeholder="placeholder">' +1083 ' <md-item-template>{{item.display}}</md-item-template>' +1084 ' <md-not-found>Sorry, not found...</md-not-found>' +1085 '</md-autocomplete>';1086 var element = compile(template, scope);1087 var controller = element.controller('mdAutocomplete');1088 controller.focus();1089 scope.searchText = 'somethingthatdoesnotexist';1090 $timeout.flush();1091 controller.listEnter();1092 expect(controller.notFoundVisible()).toBe(true);1093 controller.listLeave();1094 controller.blur();1095 expect(controller.notFoundVisible()).toBe(false);1096 $timeout.flush();1097 element.remove();1098 }));1099 it('should log a warning if the display text does not evaluate to a string',1100 inject(function($log) {1101 spyOn($log, 'warn');1102 var scope = createScope();1103 var template =1104 '<md-autocomplete ' +1105 'md-selected-item="selectedItem" ' +1106 'md-search-text="searchText"' +1107 'md-items="item in match(searchText)"> ' +1108 '</md-autocomplete>';1109 var element = compile(template, scope);1110 scope.$apply(function() {1111 scope.selectedItem = { display: 'foo' };1112 });1113 expect($log.warn).toHaveBeenCalled();1114 expect($log.warn.calls.mostRecent().args[0]).toMatch(/md-item-text/);1115 element.remove();1116 })1117 );1118 });1119 describe('clear button', function() {1120 it('should show the clear button for inset autocomplete', function() {1121 var scope = createScope();1122 var template =1123 '<md-autocomplete ' +1124 'md-selected-item="selectedItem" ' +1125 'md-search-text="searchText" ' +1126 'md-items="item in match(searchText)" ' +1127 'md-item-text="item.display" ' +1128 'placeholder="placeholder"> ' +1129 '<span md-highlight-text="searchText">{{item.display}}</span>' +1130 '</md-autocomplete>';1131 var element = compile(template, scope);1132 var ctrl = element.controller('mdAutocomplete');1133 var wrapEl = element.find('md-autocomplete-wrap');1134 expect(ctrl.scope.clearButton).toBe(true);1135 expect(wrapEl).toHaveClass('md-show-clear-button');1136 });1137 it('should not show the clear button for floating label autocomplete', function() {1138 var scope = createScope();1139 var template =1140 '<md-autocomplete ' +1141 'md-selected-item="selectedItem" ' +1142 'md-search-text="searchText" ' +1143 'md-items="item in match(searchText)" ' +1144 'md-item-text="item.display" ' +1145 'md-floating-label="Label"> ' +1146 '<span md-highlight-text="searchText">{{item.display}}</span>' +1147 '</md-autocomplete>';1148 var element = compile(template, scope);1149 var ctrl = element.controller('mdAutocomplete');1150 var wrapEl = element.find('md-autocomplete-wrap');1151 expect(ctrl.scope.clearButton).toBe(false);1152 expect(wrapEl).not.toHaveClass('md-show-clear-button');1153 });1154 it('should allow developers to toggle the clear button', function() {1155 var scope = createScope();1156 var template =1157 '<md-autocomplete ' +1158 'md-selected-item="selectedItem" ' +1159 'md-search-text="searchText" ' +1160 'md-items="item in match(searchText)" ' +1161 'md-item-text="item.display" ' +1162 'md-floating-label="Label" ' +1163 'md-clear-button="showButton">' +1164 '<span md-highlight-text="searchText">{{item.display}}</span>' +1165 '</md-autocomplete>';1166 var element = compile(template, scope);1167 var ctrl = element.controller('mdAutocomplete');1168 var wrapEl = element.find('md-autocomplete-wrap');1169 expect(ctrl.scope.clearButton).toBeFalsy();1170 expect(wrapEl).not.toHaveClass('md-show-clear-button');1171 scope.$apply('showButton = true');1172 expect(ctrl.scope.clearButton).toBe(true);1173 expect(wrapEl).toHaveClass('md-show-clear-button');1174 });1175 });1176 describe('xss prevention', function() {1177 it('should not allow html to slip through', inject(function($timeout, $material) {1178 var html = 'foo <img src="img" onerror="alert(1)" />';1179 var scope = createScope([{ display: html }]);1180 var template = '\1181 <md-autocomplete\1182 md-selected-item="selectedItem"\1183 md-search-text="searchText"\1184 md-items="item in match(searchText)"\1185 md-item-text="item.display"\1186 md-min-length="0"\1187 placeholder="placeholder">\1188 <span md-highlight-text="searchText">{{item.display}}</span>\1189 </md-autocomplete>';1190 var element = compile(template, scope);1191 var ctrl = element.controller('mdAutocomplete');1192 var ul = element.find('ul');1193 $material.flushOutstandingAnimations();1194 expect(scope.searchText).toBe('');1195 expect(scope.selectedItem).toBe(null);1196 // Focus the input1197 ctrl.focus();1198 scope.$apply('searchText = "fo"');1199 $timeout.flush();1200 waitForVirtualRepeat(element);1201 expect(scope.searchText).toBe('fo');1202 expect(scope.match(scope.searchText).length).toBe(1);1203 expect(ul.find('li').length).toBe(1);1204 expect(ul.find('li').find('img').length).toBe(0);1205 element.remove();1206 }));1207 });1208 describe('Async matching', function() {1209 it('properly stops the loading indicator when clearing', inject(function($timeout, $material) {1210 var scope = createScope();1211 var template =1212 '<md-autocomplete ' +1213 ' md-search-text="searchText"' +1214 ' md-items="item in asyncMatch(searchText)" ' +1215 ' md-item-text="item.display" ' +1216 ' placeholder="placeholder">' +1217 ' <span md-highlight-text="searchText">{{item.display}}</span>' +1218 '</md-autocomplete>';1219 var element = compile(template, scope);1220 var input = element.find('input');1221 var ctrl = element.controller('mdAutocomplete');1222 $material.flushInterimElement();1223 scope.$apply('searchText = "test"');1224 ctrl.clear();1225 expect(ctrl.loading).toBe(true);1226 $timeout.flush();1227 expect(ctrl.loading).toBe(false);1228 }));1229 });1230 describe('accessibility', function() {1231 var $mdLiveAnnouncer, $timeout, $mdConstant = null;1232 var liveEl, scope, element, ctrl = null;1233 var BASIC_TEMPLATE =1234 '<md-autocomplete' +1235 ' md-selected-item="selectedItem"' +1236 ' md-search-text="searchText"' +1237 ' md-items="item in match(searchText)"' +1238 ' md-item-text="item.display"' +1239 ' md-min-length="0"' +1240 ' placeholder="placeholder">' +1241 ' <span md-highlight-text="searchText">{{item.display}}</span>' +1242 '</md-autocomplete>';1243 beforeEach(inject(function ($injector) {1244 $mdLiveAnnouncer = $injector.get('$mdLiveAnnouncer');1245 $mdConstant = $injector.get('$mdConstant');1246 $timeout = $injector.get('$timeout');1247 liveEl = $mdLiveAnnouncer._liveElement;1248 scope = createScope();1249 element = compile(BASIC_TEMPLATE, scope);1250 ctrl = element.controller('mdAutocomplete');1251 // Flush the initial autocomplete timeout to gather the elements.1252 $timeout.flush();1253 }));1254 it('should announce count on dropdown open', function() {1255 ctrl.focus();1256 waitForVirtualRepeat();1257 expect(ctrl.hidden).toBe(false);1258 expect(liveEl.textContent).toBe('There are 3 matches available.');1259 });1260 it('should announce count and selection on dropdown open', function() {1261 // Manually enable md-autoselect for the autocomplete.1262 ctrl.index = 0;1263 ctrl.focus();1264 waitForVirtualRepeat();1265 expect(ctrl.hidden).toBe(false);1266 // Expect the announcement to contain the current selection in the dropdown.1267 expect(liveEl.textContent).toBe(scope.items[0].display + ' There are 3 matches available.');1268 });1269 it('should announce the selection when using the arrow keys', function() {1270 ctrl.focus();1271 waitForVirtualRepeat();1272 expect(ctrl.hidden).toBe(false);1273 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.DOWN_ARROW));1274 // Flush twice, because the display value will be resolved asynchronously and then the live-announcer will1275 // be triggered.1276 $timeout.flush();1277 $timeout.flush();1278 expect(ctrl.index).toBe(0);1279 expect(liveEl.textContent).toBe(scope.items[0].display);1280 ctrl.keydown(keydownEvent($mdConstant.KEY_CODE.DOWN_ARROW));1281 // Flush twice, because the display value will be resolved asynchronously and then the live-announcer will1282 // be triggered.1283 $timeout.flush();1284 $timeout.flush();1285 expect(ctrl.index).toBe(1);1286 expect(liveEl.textContent).toBe(scope.items[1].display);1287 });1288 it('should announce the count when matches change', function() {1289 ctrl.focus();1290 waitForVirtualRepeat();1291 expect(ctrl.hidden).toBe(false);1292 expect(liveEl.textContent).toBe('There are 3 matches available.');1293 scope.$apply('searchText = "fo"');1294 $timeout.flush();1295 expect(liveEl.textContent).toBe('There is 1 match available.');1296 });1297 });1298 describe('API access', function() {1299 it('clears the selected item', inject(function($timeout) {1300 var scope = createScope();1301 var template = '\1302 <md-autocomplete\1303 md-selected-item="selectedItem"\1304 md-search-text="searchText"\1305 md-items="item in match(searchText)"\1306 md-item-text="item.display"\1307 placeholder="placeholder">\1308 <span md-highlight-text="searchText">{{item.display}}</span>\1309 </md-autocomplete>';1310 var element = compile(template, scope);1311 var ctrl = element.controller('mdAutocomplete');1312 element.scope().searchText = 'fo';1313 $timeout.flush();1314 ctrl.select(0);1315 $timeout.flush();1316 expect(scope.searchText).toBe('foo');1317 expect(scope.selectedItem).not.toBeNull();1318 expect(scope.selectedItem.display).toBe('foo');1319 expect(scope.match(scope.searchText).length).toBe(1);1320 ctrl.clear();1321 element.scope().$apply();1322 expect(scope.searchText).toBe('');1323 expect(scope.selectedItem).toBe(null);1324 element.remove();1325 }));1326 it('notifies selected item watchers', inject(function($timeout) {1327 var scope = createScope();1328 scope.itemChanged = jasmine.createSpy('itemChanged');1329 var registeredWatcher = jasmine.createSpy('registeredWatcher');1330 var template = '\1331 <md-autocomplete\1332 md-selected-item="selectedItem"\1333 md-search-text="searchText"\1334 md-items="item in match(searchText)"\1335 md-selected-item-change="itemChanged(selectedItem)"\1336 md-item-text="item.display"\1337 placeholder="placeholder">\1338 <span md-highlight-text="searchText">{{item.display}}</span>\1339 </md-autocomplete>';1340 var element = compile(template, scope);1341 var ctrl = element.controller('mdAutocomplete');1342 ctrl.registerSelectedItemWatcher(registeredWatcher);1343 element.scope().searchText = 'fo';1344 $timeout.flush();1345 ctrl.select(0);1346 $timeout.flush();1347 expect(scope.itemChanged).toHaveBeenCalled();1348 expect(scope.itemChanged.calls.mostRecent().args[0].display).toBe('foo');1349 expect(registeredWatcher).toHaveBeenCalled();1350 expect(registeredWatcher.calls.mostRecent().args[0].display).toBe('foo');1351 expect(registeredWatcher.calls.mostRecent().args[1]).toBeNull();1352 expect(scope.selectedItem).not.toBeNull();1353 expect(scope.selectedItem.display).toBe('foo');1354 // Un-register the watcher1355 ctrl.unregisterSelectedItemWatcher(registeredWatcher);1356 ctrl.clear();1357 element.scope().$apply();1358 expect(registeredWatcher.calls.count()).toBe(1);1359 expect(scope.itemChanged.calls.count()).toBe(2);1360 expect(scope.itemChanged.calls.mostRecent().args[0]).toBeNull();1361 expect(scope.selectedItem).toBeNull();1362 element.remove();1363 }));1364 it('passes the value to the item watcher', inject(function($timeout) {1365 var scope = createScope();1366 var itemValue = null;1367 var template = '\1368 <md-autocomplete\1369 md-selected-item="selectedItem"\1370 md-search-text="searchText"\1371 md-items="item in match(searchText)"\1372 md-selected-item-change="itemChanged(item)"\1373 md-item-text="item.display"\1374 placeholder="placeholder">\1375 <span md-highlight-text="searchText">{{item.display}}</span>\1376 </md-autocomplete>';1377 scope.itemChanged = function(item) {1378 itemValue = item;1379 };1380 var element = compile(template, scope);1381 var ctrl = element.controller('mdAutocomplete');1382 element.scope().searchText = 'fo';1383 $timeout.flush();1384 ctrl.select(0);1385 $timeout.flush();1386 expect(itemValue).not.toBeNull();1387 expect(itemValue.display).toBe('foo');1388 ctrl.clear();1389 element.scope().$apply();1390 element.remove();1391 }));1392 });1393 describe('md-select-on-match', function() {1394 it('selects matching item on exact match when `md-select-on-match` is toggled', inject(function($timeout) {1395 var scope = createScope();1396 var template = '\1397 <md-autocomplete\1398 md-select-on-match\1399 md-selected-item="selectedItem"\1400 md-search-text="searchText"\1401 md-items="item in match(searchText)"\1402 md-item-text="item.display"\1403 placeholder="placeholder">\1404 <span md-highlight-text="searchText">{{item.display}}</span>\1405 </md-autocomplete>';1406 var element = compile(template, scope);1407 expect(scope.searchText).toBe('');1408 expect(scope.selectedItem).toBe(null);1409 element.scope().searchText = 'foo';1410 $timeout.flush();1411 expect(scope.selectedItem).not.toBe(null);1412 expect(scope.selectedItem.display).toBe('foo');1413 element.remove();1414 }));1415 it('selects matching item on exact match with caching enabled', inject(function($timeout) {1416 var scope = createScope();1417 var template = '\1418 <md-autocomplete\1419 md-select-on-match\1420 md-selected-item="selectedItem"\1421 md-search-text="searchText"\1422 md-items="item in match(searchText)"\1423 md-item-text="item.display"\1424 placeholder="placeholder">\1425 <span md-highlight-text="searchText">{{item.display}}</span>\1426 </md-autocomplete>';1427 var element = compile(template, scope);1428 expect(scope.searchText).toBe('');1429 expect(scope.selectedItem).toBe(null);1430 scope.$apply('searchText = "foo"');1431 $timeout.flush();1432 expect(scope.selectedItem).not.toBe(null);1433 expect(scope.selectedItem.display).toBe('foo');1434 scope.$apply('searchText = ""');1435 $timeout.flush();1436 expect(scope.selectedItem).toBeFalsy();1437 scope.$apply('searchText = "foo"');1438 $timeout.flush();1439 expect(scope.selectedItem).not.toBe(null);1440 expect(scope.selectedItem.display).toBe('foo');1441 element.remove();1442 }));1443 it('should not select matching item on exact match when `md-select-on-match` is NOT toggled', inject(function($timeout) {1444 var scope = createScope();1445 var template = '\1446 <md-autocomplete\1447 md-selected-item="selectedItem"\1448 md-search-text="searchText"\1449 md-items="item in match(searchText)"\1450 md-item-text="item.display"\1451 placeholder="placeholder">\1452 <span md-highlight-text="searchText">{{item.display}}</span>\1453 </md-autocomplete>';1454 var element = compile(template, scope);1455 expect(scope.searchText).toBe('');1456 expect(scope.selectedItem).toBe(null);1457 element.scope().searchText = 'foo';1458 $timeout.flush();1459 expect(scope.selectedItem).toBe(null);1460 element.remove();1461 }));1462 it('selects matching item using case insensitive', inject(function($timeout) {1463 var scope = createScope(null, null, true);1464 var template =1465 '<md-autocomplete ' +1466 'md-select-on-match ' +1467 'md-selected-item="selectedItem" ' +1468 'md-search-text="searchText" ' +1469 'md-items="item in match(searchText)" ' +1470 'md-item-text="item.display" ' +1471 'placeholder="placeholder" ' +1472 'md-match-case-insensitive="true">' +1473 '<span md-highlight-text="searchText">{{item.display}}</span>' +1474 '</md-autocomplete>';1475 var element = compile(template, scope);1476 expect(scope.searchText).toBe('');1477 expect(scope.selectedItem).toBe(null);1478 element.scope().searchText = 'FoO';1479 $timeout.flush();1480 expect(scope.selectedItem).not.toBe(null);1481 expect(scope.selectedItem.display).toBe('foo');1482 element.remove();1483 }));1484 });1485 describe('when requiring a match', function() {1486 it('should correctly update the validity', inject(function($timeout) {1487 var scope = createScope();1488 var template = '\1489 <form name="form">\1490 <md-autocomplete\1491 md-input-name="autocomplete"\1492 md-selected-item="selectedItem"\1493 md-search-text="searchText"\1494 md-items="item in match(searchText)"\1495 md-item-text="item.display"\1496 placeholder="placeholder"\1497 md-require-match="true">\1498 <span md-highlight-text="searchText">{{item.display}}</span>\1499 </md-autocomplete>\1500 </form>';1501 var element = compile(template, scope);1502 var ctrl = element.find('md-autocomplete').controller('mdAutocomplete');1503 // Flush the element gathering.1504 $timeout.flush();1505 scope.$apply('searchText = "fo"');1506 $timeout.flush();1507 ctrl.select(0);1508 $timeout.flush();1509 expect(scope.searchText).toBe('foo');1510 expect(scope.selectedItem).not.toBeNull();1511 expect(scope.selectedItem.display).toBe('foo');1512 expect(scope.match(scope.searchText).length).toBe(1);1513 expect(scope.form.autocomplete.$error['md-require-match']).toBeFalsy();1514 scope.$apply('searchText = "food"');1515 $timeout.flush();1516 expect(scope.searchText).toBe('food');1517 expect(scope.selectedItem).toBeNull();1518 expect(scope.form.autocomplete.$error['md-require-match']).toBeTruthy();1519 }));1520 it('should not set to invalid if searchText is empty', inject(function($timeout) {1521 var scope = createScope();1522 var template = '\1523 <form name="form">\1524 <md-autocomplete\1525 md-input-name="autocomplete"\1526 md-selected-item="selectedItem"\1527 md-search-text="searchText"\1528 md-items="item in match(searchText)"\1529 md-item-text="item.display"\1530 placeholder="placeholder"\1531 md-require-match="true">\1532 <span md-highlight-text="searchText">{{item.display}}</span>\1533 </md-autocomplete>\1534 </form>';1535 compile(template, scope);1536 // Flush the element gathering.1537 $timeout.flush();1538 scope.$apply('searchText = "food"');1539 $timeout.flush();1540 expect(scope.searchText).toBe('food');1541 expect(scope.selectedItem).toBeNull();1542 expect(scope.form.autocomplete.$error['md-require-match']).toBeTruthy();1543 scope.$apply('searchText = ""');1544 expect(scope.searchText).toBe('');1545 expect(scope.selectedItem).toBeNull();1546 expect(scope.form.autocomplete.$error['md-require-match']).toBeFalsy();1547 }));1548 });1549 describe('when required', function() {1550 it('properly handles md-min-length="0" and undefined searchText', function() {1551 var scope = createScope();1552 var template = '\1553 <md-autocomplete\1554 md-selected-item="selectedItem"\1555 md-search-text="searchText"\1556 md-items="item in match(searchText)"\1557 md-item-text="item.display"\1558 md-min-length="0" \1559 required\1560 placeholder="placeholder">\1561 <span md-highlight-text="searchText">{{item.display}}</span>\1562 </md-autocomplete>';1563 var error;1564 try {1565 var element = compile(template, scope);1566 scope.searchText = undefined;1567 scope.$digest();1568 } catch (e) {1569 error = e;1570 }1571 expect(error).toBe(undefined);1572 element.remove();1573 });1574 it('validates an empty `required` as true', function() {1575 var scope = createScope();1576 var template = '\1577 <md-autocomplete\1578 md-selected-item="selectedItem"\1579 md-search-text="searchText"\1580 md-items="item in match(searchText)"\1581 md-item-text="item.display"\1582 md-min-length="0" \1583 required\1584 placeholder="placeholder">\1585 <span md-highlight-text="searchText">{{item.display}}</span>\1586 </md-autocomplete>';1587 var element = compile(template, scope);1588 var ctrl = element.controller('mdAutocomplete');1589 expect(ctrl.isRequired).toBe(true);1590 });1591 it('correctly validates an interpolated `ng-required` value', function() {1592 var scope = createScope();1593 var template = '\1594 <md-autocomplete\1595 md-selected-item="selectedItem"\1596 md-search-text="searchText"\1597 md-items="item in match(searchText)"\1598 md-item-text="item.display"\1599 md-min-length="0" \1600 ng-required="interpolateRequired"\1601 placeholder="placeholder">\1602 <span md-highlight-text="searchText">{{item.display}}</span>\1603 </md-autocomplete>';1604 var element = compile(template, scope);1605 var ctrl = element.controller('mdAutocomplete');1606 expect(ctrl.isRequired).toBe(false);1607 scope.interpolateRequired = false;1608 scope.$apply();1609 expect(ctrl.isRequired).toBe(false);1610 scope.interpolateRequired = true;1611 scope.$apply();1612 expect(ctrl.isRequired).toBe(true);1613 });1614 it('forwards the md-no-asterisk attribute', function() {1615 var scope = createScope();1616 var template = '\1617 <md-autocomplete\1618 md-selected-item="selectedItem"\1619 md-search-text="searchText"\1620 md-items="item in match(searchText)"\1621 md-item-text="item.display"\1622 md-min-length="0" \1623 required\1624 md-no-asterisk="true"\1625 md-floating-label="Asterisk Label">\1626 <span md-highlight-text="searchText">{{item.display}}</span>\1627 </md-autocomplete>';1628 var element = compile(template, scope);1629 var input = element.find('input');1630 expect(input.attr('md-no-asterisk')).toBe('true');1631 });1632 });1633 describe('dropdown position', function() {1634 var DEFAULT_MAX_ITEMS = 5;1635 var DEFAULT_ITEM_HEIGHT = 48;1636 var dropdownItems = DEFAULT_MAX_ITEMS;1637 /**1638 * Function to create fake matches with the given dropdown items.1639 * Useful when running tests against the dropdown max items calculations.1640 * @returns {Array} Fake matches.1641 */1642 function fakeItemMatch() {1643 var matches = [];1644 for (var i = 0; i < dropdownItems; i++) {1645 matches.push('Item ' + i);1646 }1647 return matches;1648 }1649 it('should adjust the width when the window resizes', inject(function($timeout, $window) {1650 var scope = createScope();1651 var template =1652 '<div style="width: 400px">' +1653 '<md-autocomplete ' +1654 'md-search-text="searchText" ' +1655 'md-items="item in match(searchText)" ' +1656 'md-item-text="item.display" ' +1657 'md-min-length="0" ' +1658 'placeholder="placeholder">' +1659 '<span md-highlight-text="searchText">{{item.display}}</span>' +1660 '</md-autocomplete>' +1661 '</div>';1662 var parent = compile(template, scope);1663 var element = parent.find('md-autocomplete');1664 var ctrl = element.controller('mdAutocomplete');1665 // Add container to the DOM to be able to test the rect calculations.1666 document.body.appendChild(parent[0]);1667 $timeout.flush();1668 expect(ctrl.positionDropdown).toBeTruthy();1669 // Focus the Autocomplete to open the dropdown.1670 ctrl.focus();1671 scope.$apply('searchText = "fo"');1672 waitForVirtualRepeat(element);1673 // The scroll repeat container has been moved to the body element to avoid1674 // z-index / overflow issues.1675 var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');1676 expect(scrollContainer).toBeTruthy();1677 // Expect the current width of the scrollContainer to be the same as of the parent element1678 // at initialization.1679 expect(scrollContainer.style.minWidth).toBe('400px');1680 // Change the parents width, to be shrink the scrollContainers width.1681 parent.css('width', '200px');1682 // Update the scrollContainers rectangle, by triggering a reposition of the dropdown.1683 angular.element($window).triggerHandler('resize');1684 $timeout.flush();1685 // The scroll container should have a width of 200px, since we changed the parents width.1686 expect(scrollContainer.style.minWidth).toBe('200px');1687 document.body.removeChild(parent[0]);1688 }));1689 it('should adjust the width when manually repositioning', inject(function($timeout) {1690 var scope = createScope();1691 var template =1692 '<div style="width: 400px">' +1693 '<md-autocomplete ' +1694 'md-search-text="searchText" ' +1695 'md-items="item in match(searchText)" ' +1696 'md-item-text="item.display" ' +1697 'md-min-length="0" ' +1698 'placeholder="placeholder">' +1699 '<span md-highlight-text="searchText">{{item.display}}</span>' +1700 '</md-autocomplete>' +1701 '</div>';1702 var parent = compile(template, scope);1703 var element = parent.find('md-autocomplete');1704 var ctrl = element.controller('mdAutocomplete');1705 // Add container to the DOM to be able to test the rect calculations.1706 document.body.appendChild(parent[0]);1707 $timeout.flush();1708 expect(ctrl.positionDropdown).toBeTruthy();1709 // Focus the Autocomplete to open the dropdown.1710 ctrl.focus();1711 scope.$apply('searchText = "fo"');1712 waitForVirtualRepeat(element);1713 // The scroll repeat container has been moved to the body element to avoid1714 // z-index / overflow issues.1715 var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');1716 expect(scrollContainer).toBeTruthy();1717 // Expect the current width of the scrollContainer to be the same as of the parent element1718 // at initialization.1719 expect(scrollContainer.style.minWidth).toBe('400px');1720 // Change the parents width, to be shrink the scrollContainers width.1721 parent.css('width', '200px');1722 // Update the scrollContainers rectangle, by triggering a reposition of the dropdown.1723 ctrl.positionDropdown();1724 // The scroll container should have a width of 200px, since we changed the parents width.1725 expect(scrollContainer.style.minWidth).toBe('200px');1726 document.body.removeChild(parent[0]);1727 }));1728 it('should show on focus when min-length is met', inject(function($timeout) {1729 var scope = createScope();1730 // Overwrite the match function to always show some results.1731 scope.match = function() {1732 return scope.items;1733 };1734 var template =1735 '<div style="width: 400px">' +1736 '<md-autocomplete ' +1737 'md-search-text="searchText" ' +1738 'md-items="item in match(searchText)" ' +1739 'md-item-text="item.display" ' +1740 'md-min-length="0" ' +1741 'placeholder="placeholder">' +1742 '<span md-highlight-text="searchText">{{item.display}}</span>' +1743 '</md-autocomplete>' +1744 '</div>';1745 var parent = compile(template, scope);1746 var element = parent.find('md-autocomplete');1747 var ctrl = element.controller('mdAutocomplete');1748 // Add container to the DOM to be able to test the rect calculations.1749 document.body.appendChild(parent[0]);1750 ctrl.focus();1751 waitForVirtualRepeat(element);1752 // The scroll repeat container has been moved to the body element to avoid1753 // z-index / overflow issues.1754 var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');1755 expect(scrollContainer).toBeTruthy();1756 // Expect the current width of the scrollContainer to be the same as of the parent element1757 // at initialization.1758 expect(scrollContainer.offsetParent).toBeTruthy();1759 document.body.removeChild(parent[0]);1760 }));1761 it('should not show on focus when min-length is not met', inject(function($timeout) {1762 var scope = createScope();1763 // Overwrite the match function to always show some results.1764 scope.match = function() {1765 return scope.items;1766 };1767 var template =1768 '<div style="width: 400px">' +1769 '<md-autocomplete ' +1770 'md-search-text="searchText" ' +1771 'md-items="item in match(searchText)" ' +1772 'md-item-text="item.display" ' +1773 'md-min-length="1" ' +1774 'placeholder="placeholder">' +1775 '<span md-highlight-text="searchText">{{item.display}}</span>' +1776 '</md-autocomplete>' +1777 '</div>';1778 var parent = compile(template, scope);1779 var element = parent.find('md-autocomplete');1780 var ctrl = element.controller('mdAutocomplete');1781 // Add container to the DOM to be able to test the rect calculations.1782 document.body.appendChild(parent[0]);1783 ctrl.focus();1784 waitForVirtualRepeat(element);1785 // The scroll repeat container has been moved to the body element to avoid1786 // z-index / overflow issues.1787 var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');1788 expect(scrollContainer).toBeTruthy();1789 // Expect the dropdown to not show up, because the min-length is not met.1790 expect(scrollContainer.offsetParent).toBeFalsy();1791 ctrl.blur();1792 // Add one char to the searchText to match the minlength.1793 scope.$apply('searchText = "X"');1794 ctrl.focus();1795 waitForVirtualRepeat(element);1796 // Expect the dropdown to not show up, because the min-length is not met.1797 expect(scrollContainer.offsetParent).toBeTruthy();1798 document.body.removeChild(parent[0]);1799 }));1800 it('should calculate the height from the default max items', inject(function($timeout) {1801 var scope = createScope();1802 scope.match = fakeItemMatch;1803 var template =1804 '<div>' +1805 '<md-autocomplete ' +1806 'md-search-text="searchText" ' +1807 'md-items="item in match(searchText)" ' +1808 'md-item-text="item" ' +1809 'md-min-length="0" ' +1810 'placeholder="placeholder">' +1811 '<span md-highlight-text="searchText">{{item}}</span>' +1812 '</md-autocomplete>' +1813 '</div>';1814 var parent = compile(template, scope);1815 var element = parent.find('md-autocomplete');1816 var ctrl = element.controller('mdAutocomplete');1817 // Add container to the DOM to be able to test the rect calculations.1818 document.body.appendChild(parent[0]);1819 $timeout.flush();1820 // Focus the autocomplete and trigger a query to be able to open the dropdown.1821 ctrl.focus();1822 scope.$apply('searchText = "Query 1"');1823 waitForVirtualRepeat(element);1824 var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');1825 expect(scrollContainer).toBeTruthy();1826 expect(scrollContainer.style.maxHeight).toBe(DEFAULT_MAX_ITEMS * DEFAULT_ITEM_HEIGHT + 'px');1827 dropdownItems = 6;1828 // Trigger a new query to request an update of the items and dropdown.1829 scope.$apply('searchText = "Query 2"');1830 // The dropdown should not increase its height because of the new extra item.1831 expect(scrollContainer.style.maxHeight).toBe(DEFAULT_MAX_ITEMS * DEFAULT_ITEM_HEIGHT + 'px');1832 document.body.removeChild(parent[0]);1833 }));1834 it('should calculate its height from the specified max items', inject(function($timeout) {1835 var scope = createScope();1836 var maxDropdownItems = 2;1837 // Set the current dropdown items to the new maximum.1838 dropdownItems = maxDropdownItems;1839 scope.match = fakeItemMatch;1840 var template =1841 '<div>' +1842 '<md-autocomplete ' +1843 'md-search-text="searchText" ' +1844 'md-items="item in match(searchText)" ' +1845 'md-item-text="item" ' +1846 'md-min-length="0" ' +1847 'md-dropdown-items="' + maxDropdownItems +'"' +1848 'placeholder="placeholder">' +1849 '<span md-highlight-text="searchText">{{item}}</span>' +1850 '</md-autocomplete>' +1851 '</div>';1852 var parent = compile(template, scope);1853 var element = parent.find('md-autocomplete');1854 var ctrl = element.controller('mdAutocomplete');1855 // Add container to the DOM to be able to test the rect calculations.1856 document.body.appendChild(parent[0]);1857 $timeout.flush();1858 // Focus the autocomplete and trigger a query to be able to open the dropdown.1859 ctrl.focus();1860 scope.$apply('searchText = "Query 1"');1861 waitForVirtualRepeat(element);1862 var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');1863 expect(scrollContainer).toBeTruthy();1864 expect(scrollContainer.style.maxHeight).toBe(maxDropdownItems * DEFAULT_ITEM_HEIGHT + 'px');1865 dropdownItems = 6;1866 // Trigger a new query to request an update of the items and dropdown.1867 scope.$apply('searchText = "Query 2"');1868 // The dropdown should not increase its height because of the new extra item.1869 expect(scrollContainer.style.maxHeight).toBe(maxDropdownItems * DEFAULT_ITEM_HEIGHT + 'px');1870 document.body.removeChild(parent[0]);1871 }));1872 it('should allow dropdown position to be specified', inject(function($timeout, $window) {1873 var scope = createScope();1874 scope.match = fakeItemMatch;1875 scope.position = 'top';1876 var template = '<div>' +1877 '<md-autocomplete ' +1878 'md-search-text="searchText" ' +1879 'md-items="item in match(searchText)" ' +1880 'md-item-text="item" ' +1881 'md-min-length="0" ' +1882 'md-dropdown-position="{{position}}" ' +1883 'placeholder="placeholder">' +1884 '<span md-highlight-text="searchText">{{item}}</span>' +1885 '</md-autocomplete>' +1886 '</div>';1887 var parent = compile(template, scope);1888 var element = parent.find('md-autocomplete');1889 var ctrl = element.controller('mdAutocomplete');1890 // Add container to the DOM to be able to test the rect calculations.1891 document.body.appendChild(parent[0]);1892 $timeout.flush();1893 // Focus the autocomplete and trigger a query to be able to open the dropdown.1894 ctrl.focus();1895 scope.$apply('searchText = "Query 1"');1896 waitForVirtualRepeat(element);1897 var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');1898 expect(scrollContainer).toBeTruthy();1899 expect(scrollContainer.style.top).toBe('auto');1900 expect(scrollContainer.style.bottom).toMatch(/[0-9]+px/);1901 // Change position and resize to force a DOM update.1902 scope.$apply('position = "bottom"');1903 angular.element($window).triggerHandler('resize');1904 $timeout.flush();1905 expect(scrollContainer.style.top).toMatch(/[0-9]+px/);1906 expect(scrollContainer.style.bottom).toBe('auto');1907 parent.remove();1908 }));1909 it('should not position dropdown on resize when being hidden', inject(function($window, $timeout) {1910 var scope = createScope();1911 var template =1912 '<div style="width: 400px">' +1913 '<md-autocomplete ' +1914 'md-search-text="searchText" ' +1915 'md-items="item in match(searchText)" ' +1916 'md-item-text="item.display" ' +1917 'md-min-length="0" ' +1918 'placeholder="placeholder">' +1919 '<span md-highlight-text="searchText">{{item.display}}</span>' +1920 '</md-autocomplete>' +1921 '</div>';1922 var parent = compile(template, scope);1923 var element = parent.find('md-autocomplete');1924 var ctrl = element.controller('mdAutocomplete');1925 // Add container to the DOM to be able to test the rect calculations.1926 document.body.appendChild(parent[0]);1927 $timeout.flush();1928 expect(ctrl.positionDropdown).toBeTruthy();1929 // The scroll repeat container has been moved to the body element to avoid1930 // z-index / overflow issues.1931 var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');1932 expect(scrollContainer).toBeTruthy();1933 // Expect the scroll container to not have minWidth set, because it was never positioned.1934 expect(scrollContainer.style.minWidth).toBe('');1935 // Change the parents width, to be shrink the scrollContainers width.1936 parent.css('width', '200px');1937 // Trigger a window resize, which should adjust the width of the scroll container.1938 angular.element($window).triggerHandler('resize');1939 $timeout.flush();1940 // The scroll container should still have no minWidth, because there was no positioning called yet.1941 expect(scrollContainer.style.minWidth).toBe('');1942 document.body.removeChild(parent[0]);1943 }));1944 it('should grow and shrink depending on the amount of items', inject(function($timeout) {1945 var scope = createScope();1946 dropdownItems = 2;1947 scope.match = fakeItemMatch;1948 var template =1949 '<div>' +1950 '<md-autocomplete ' +1951 'md-search-text="searchText" ' +1952 'md-items="item in match(searchText)" ' +1953 'md-item-text="item" ' +1954 'md-min-length="0" ' +1955 'placeholder="placeholder">' +1956 '<span md-highlight-text="searchText">{{item}}</span>' +1957 '</md-autocomplete>' +1958 '</div>';1959 var parent = compile(template, scope);1960 var element = parent.find('md-autocomplete');1961 var ctrl = element.controller('mdAutocomplete');1962 // Add container to the DOM to be able to test the rect calculations.1963 document.body.appendChild(parent[0]);1964 $timeout.flush();1965 // Focus the autocomplete and trigger a query to be able to open the dropdown.1966 ctrl.focus();1967 scope.$apply('searchText = "A"');1968 waitForVirtualRepeat(element);1969 var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');1970 expect(scrollContainer).toBeTruthy();1971 expect(scrollContainer.style.height).toBe(dropdownItems * DEFAULT_ITEM_HEIGHT + 'px');1972 dropdownItems = DEFAULT_MAX_ITEMS;1973 // Trigger a new query to request an update of the items and dropdown.1974 scope.$apply('searchText = "B"');1975 expect(scrollContainer.style.height).toBe(dropdownItems * DEFAULT_ITEM_HEIGHT + 'px');1976 document.body.removeChild(parent[0]);1977 }));1978 });1979 describe('md-highlight-text', function() {1980 it('updates when content is modified', inject(function() {1981 var template = '<div md-highlight-text="query">{{message}}</div>';1982 var scope = createScope(null, {message: 'some text', query: 'some'});1983 var element = compile(template, scope);1984 expect(element.html()).toBe('<span class="highlight">some</span> text');1985 scope.query = 'so';1986 scope.$apply();1987 expect(element.html()).toBe('<span class="highlight">so</span>me text');1988 scope.message = 'some more text';1989 scope.$apply();1990 expect(element.html()).toBe('<span class="highlight">so</span>me more text');1991 element.remove();1992 }));1993 it('should properly apply highlight flags', function() {1994 var template = '<div md-highlight-text="query" md-highlight-flags="{{flags}}">{{message}}</div>';1995 var scope = createScope(null, {message: 'Some text', query: 'some', flags: '^i'});1996 var element = compile(template, scope);1997 expect(element.html()).toBe('<span class="highlight">Some</span> text');1998 scope.query = 'text';1999 scope.$apply();2000 expect(element.html()).toBe('Some text');2001 scope.message = 'Some text, some flags';2002 scope.query = 'some';2003 scope.flags = 'ig';2004 element = compile(template, scope);2005 expect(element.html()).toBe('<span class="highlight">Some</span> text, <span class="highlight">some</span> flags');2006 scope.query = 'some';2007 scope.flags = '^i';2008 element = compile(template, scope);2009 expect(element.html()).toBe('<span class="highlight">Some</span> text, some flags');2010 scope.query = 's';2011 scope.flags = '$i';2012 element = compile(template, scope);2013 expect(element.html()).toBe('Some text, some flag<span class="highlight">s</span>');2014 element.remove();2015 });2016 it('should correctly parse special text identifiers', function() {2017 var template = '<div md-highlight-text="query">{{message}}</div>';2018 var scope = createScope(null, {2019 message: 'Angular&Material',2020 query: 'Angular&'2021 });2022 var element = compile(template, scope);2023 expect(element.html()).toBe('<span class="highlight">Angular&</span>Material');2024 scope.query = 'Angular&Material';2025 scope.$apply();2026 expect(element.html()).toBe('<span class="highlight">Angular&Material</span>');2027 element.remove();2028 });2029 it('should properly parse html entity identifiers', function() {2030 var template = '<div md-highlight-text="query">{{message}}</div>';2031 var scope = createScope(null, {2032 message: 'Angular&Material',2033 query: ''2034 });2035 var element = compile(template, scope);2036 expect(element.html()).toBe('Angular&amp;Material');2037 scope.query = 'Angular&Material';2038 scope.$apply();2039 expect(element.html()).toBe('<span class="highlight">Angular&amp;Material</span>');2040 scope.query = 'Angular&';2041 scope.$apply();2042 expect(element.html()).toBe('<span class="highlight">Angular&</span>amp;Material');2043 element.remove();2044 });2045 it('should prevent XSS attacks from the highlight text', function() {2046 spyOn(window, 'alert');2047 var template = '<div md-highlight-text="query">{{message}}</div>';2048 var scope = createScope(null, {2049 message: 'Angular Material',2050 query: '<img src="img" onerror="alert(1)">'2051 });2052 var element = compile(template, scope);2053 expect(element.html()).toBe('Angular Material');2054 expect(window.alert).not.toHaveBeenCalled();2055 element.remove();2056 });2057 });2058 it('should prevent XSS attacks from the content text', function() {2059 spyOn(window, 'alert');2060 var template = '<div md-highlight-text="query">{{message}}</div>';2061 var scope = createScope(null, {2062 message: '<img src="img" onerror="alert(1)">',2063 query: ''2064 });2065 var element = compile(template, scope);2066 // Expect the image to be escaped due to XSS protection.2067 expect(element.html()).toBe('<img src="img" onerror="alert(1)">');2068 expect(window.alert).not.toHaveBeenCalled();2069 element.remove();2070 });2071 describe('md-autocomplete-snap', function() {2072 it('should match the width of the snap element if width is set', inject(function($timeout, $material) {2073 var template = '\2074 <div style="width: 1000px" md-autocomplete-snap="width">\2075 <md-autocomplete\2076 md-selected-item="selectedItem"\2077 md-search-text="searchText"\2078 md-items="item in match(searchText)"\2079 md-item-text="item.display"\2080 placeholder="placeholder"\2081 style="width:200px">\2082 <span md-highlight-text="searchText">{{item.display}}</span>\2083 </md-autocomplete>\2084 </div>';2085 var scope = createScope();2086 var element = compile(template, scope);2087 var autoEl = element.find('md-autocomplete');2088 var ctrl = autoEl.controller('mdAutocomplete');2089 var ul = element.find('ul');2090 angular.element(document.body).append(element);2091 $material.flushInterimElement();2092 ctrl.focus();2093 autoEl.scope().searchText = 'fo';2094 waitForVirtualRepeat(autoEl);2095 expect(ul[0].offsetWidth).toBe(1000);2096 element.remove();2097 }));2098 it('should match the width of the wrap element if width is not set', inject(function($timeout, $material) {2099 var template = '\2100 <div style="width: 1000px" md-autocomplete-snap>\2101 <md-autocomplete\2102 md-selected-item="selectedItem"\2103 md-search-text="searchText"\2104 md-items="item in match(searchText)"\2105 md-item-text="item.display"\2106 placeholder="placeholder"\2107 style="width:200px">\2108 <span md-highlight-text="searchText">{{item.display}}</span>\2109 </md-autocomplete>\2110 </div>';2111 var scope = createScope();2112 var element = compile(template, scope);2113 var autoEl = element.find('md-autocomplete');2114 var ctrl = autoEl.controller('mdAutocomplete');2115 var ul = element.find('ul');2116 angular.element(document.body).append(element);2117 $material.flushInterimElement();2118 ctrl.focus();2119 autoEl.scope().searchText = 'fo';2120 waitForVirtualRepeat(autoEl);2121 expect(ul[0].offsetWidth).toBe(200);2122 element.remove();2123 }));2124 });...
AutoComplete.js
Source:AutoComplete.js
1/* */ 2(function(process) {3 'use strict';4 Object.defineProperty(exports, "__esModule", {value: true});5 var _extends = Object.assign || function(target) {6 for (var i = 1; i < arguments.length; i++) {7 var source = arguments[i];8 for (var key in source) {9 if (Object.prototype.hasOwnProperty.call(source, key)) {10 target[key] = source[key];11 }12 }13 }14 return target;15 };16 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {17 return typeof obj;18 } : function(obj) {19 return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;20 };21 var _createClass = function() {22 function defineProperties(target, props) {23 for (var i = 0; i < props.length; i++) {24 var descriptor = props[i];25 descriptor.enumerable = descriptor.enumerable || false;26 descriptor.configurable = true;27 if ("value" in descriptor)28 descriptor.writable = true;29 Object.defineProperty(target, descriptor.key, descriptor);30 }31 }32 return function(Constructor, protoProps, staticProps) {33 if (protoProps)34 defineProperties(Constructor.prototype, protoProps);35 if (staticProps)36 defineProperties(Constructor, staticProps);37 return Constructor;38 };39 }();40 var _simpleAssign = require('simple-assign');41 var _simpleAssign2 = _interopRequireDefault(_simpleAssign);42 var _react = require('react');43 var _react2 = _interopRequireDefault(_react);44 var _reactDom = require('react-dom');45 var _reactDom2 = _interopRequireDefault(_reactDom);46 var _keycode = require('keycode');47 var _keycode2 = _interopRequireDefault(_keycode);48 var _TextField = require('../TextField/index');49 var _TextField2 = _interopRequireDefault(_TextField);50 var _Menu = require('../Menu/index');51 var _Menu2 = _interopRequireDefault(_Menu);52 var _MenuItem = require('../MenuItem/index');53 var _MenuItem2 = _interopRequireDefault(_MenuItem);54 var _Divider = require('../Divider/index');55 var _Divider2 = _interopRequireDefault(_Divider);56 var _Popover = require('../Popover/Popover');57 var _Popover2 = _interopRequireDefault(_Popover);58 var _propTypes = require('../utils/propTypes');59 var _propTypes2 = _interopRequireDefault(_propTypes);60 var _warning = require('warning');61 var _warning2 = _interopRequireDefault(_warning);62 var _deprecatedPropType = require('../utils/deprecatedPropType');63 var _deprecatedPropType2 = _interopRequireDefault(_deprecatedPropType);64 function _interopRequireDefault(obj) {65 return obj && obj.__esModule ? obj : {default: obj};66 }67 function _objectWithoutProperties(obj, keys) {68 var target = {};69 for (var i in obj) {70 if (keys.indexOf(i) >= 0)71 continue;72 if (!Object.prototype.hasOwnProperty.call(obj, i))73 continue;74 target[i] = obj[i];75 }76 return target;77 }78 function _classCallCheck(instance, Constructor) {79 if (!(instance instanceof Constructor)) {80 throw new TypeError("Cannot call a class as a function");81 }82 }83 function _possibleConstructorReturn(self, call) {84 if (!self) {85 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");86 }87 return call && (typeof call === "object" || typeof call === "function") ? call : self;88 }89 function _inherits(subClass, superClass) {90 if (typeof superClass !== "function" && superClass !== null) {91 throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);92 }93 subClass.prototype = Object.create(superClass && superClass.prototype, {constructor: {94 value: subClass,95 enumerable: false,96 writable: true,97 configurable: true98 }});99 if (superClass)100 Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;101 }102 function getStyles(props, context, state) {103 var anchorEl = state.anchorEl;104 var fullWidth = props.fullWidth;105 var styles = {106 root: {107 display: 'inline-block',108 position: 'relative',109 width: fullWidth ? '100%' : 256110 },111 menu: {width: '100%'},112 list: {113 display: 'block',114 width: fullWidth ? '100%' : 256115 },116 innerDiv: {overflow: 'hidden'}117 };118 if (anchorEl && fullWidth) {119 styles.popover = {width: anchorEl.clientWidth};120 }121 return styles;122 }123 var AutoComplete = function(_Component) {124 _inherits(AutoComplete, _Component);125 function AutoComplete() {126 var _Object$getPrototypeO;127 var _temp,128 _this,129 _ret;130 _classCallCheck(this, AutoComplete);131 for (var _len = arguments.length,132 args = Array(_len),133 _key = 0; _key < _len; _key++) {134 args[_key] = arguments[_key];135 }136 return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_Object$getPrototypeO = Object.getPrototypeOf(AutoComplete)).call.apply(_Object$getPrototypeO, [this].concat(args))), _this), _this.state = {137 anchorEl: null,138 focusTextField: true,139 open: false,140 searchText: undefined141 }, _this.handleRequestClose = function() {142 if (!_this.state.focusTextField) {143 _this.close();144 }145 }, _this.handleMouseDown = function(event) {146 event.preventDefault();147 }, _this.handleItemTouchTap = function(event, child) {148 var dataSource = _this.props.dataSource;149 var index = parseInt(child.key, 10);150 var chosenRequest = dataSource[index];151 var searchText = typeof chosenRequest === 'string' ? chosenRequest : chosenRequest.text;152 _this.props.onNewRequest(chosenRequest, index);153 _this.timerTouchTapCloseId = setTimeout(function() {154 _this.setState({searchText: searchText});155 _this.close();156 _this.timerTouchTapCloseId = null;157 }, _this.props.menuCloseDelay);158 }, _this.handleEscKeyDown = function() {159 _this.close();160 }, _this.handleKeyDown = function(event) {161 if (_this.props.onKeyDown)162 _this.props.onKeyDown(event);163 switch ((0, _keycode2.default)(event)) {164 case 'enter':165 _this.close();166 var searchText = _this.state.searchText;167 if (searchText !== '') {168 _this.props.onNewRequest(searchText, -1);169 }170 break;171 case 'esc':172 _this.close();173 break;174 case 'down':175 event.preventDefault();176 _this.setState({177 open: true,178 focusTextField: false,179 anchorEl: _reactDom2.default.findDOMNode(_this.refs.searchTextField)180 });181 break;182 default:183 break;184 }185 }, _this.handleChange = function(event) {186 var searchText = event.target.value;187 if (searchText === _this.state.searchText) {188 return;189 }190 _this.setState({191 searchText: searchText,192 open: true,193 anchorEl: _reactDom2.default.findDOMNode(_this.refs.searchTextField)194 }, function() {195 _this.props.onUpdateInput(searchText, _this.props.dataSource);196 });197 }, _this.handleBlur = function(event) {198 if (_this.state.focusTextField && _this.timerTouchTapCloseId === null) {199 _this.close();200 }201 if (_this.props.onBlur) {202 _this.props.onBlur(event);203 }204 }, _this.handleFocus = function(event) {205 if (!_this.state.open && (_this.props.triggerUpdateOnFocus || _this.props.openOnFocus)) {206 _this.setState({207 open: true,208 anchorEl: _reactDom2.default.findDOMNode(_this.refs.searchTextField)209 });210 }211 _this.setState({focusTextField: true});212 if (_this.props.onFocus) {213 _this.props.onFocus(event);214 }215 }, _temp), _possibleConstructorReturn(_this, _ret);216 }217 _createClass(AutoComplete, [{218 key: 'componentWillMount',219 value: function componentWillMount() {220 this.requestsList = [];221 this.setState({222 open: this.props.open,223 searchText: this.props.searchText224 });225 this.timerTouchTapCloseId = null;226 }227 }, {228 key: 'componentWillReceiveProps',229 value: function componentWillReceiveProps(nextProps) {230 if (this.props.searchText !== nextProps.searchText) {231 this.setState({searchText: nextProps.searchText});232 }233 }234 }, {235 key: 'componentWillUnmount',236 value: function componentWillUnmount() {237 clearTimeout(this.timerTouchTapCloseId);238 }239 }, {240 key: 'close',241 value: function close() {242 this.setState({243 open: false,244 anchorEl: null245 });246 }247 }, {248 key: 'setValue',249 value: function setValue(textValue) {250 process.env.NODE_ENV !== "production" ? (0, _warning2.default)(false, 'setValue() is deprecated, use the searchText property.') : void 0;251 this.setState({searchText: textValue});252 }253 }, {254 key: 'getValue',255 value: function getValue() {256 process.env.NODE_ENV !== "production" ? (0, _warning2.default)(false, 'getValue() is deprecated.') : void 0;257 return this.state.searchText;258 }259 }, {260 key: 'blur',261 value: function blur() {262 this.refs.searchTextField.blur();263 }264 }, {265 key: 'focus',266 value: function focus() {267 this.refs.searchTextField.focus();268 }269 }, {270 key: 'render',271 value: function render() {272 var _this2 = this;273 var _props = this.props;274 var anchorOrigin = _props.anchorOrigin;275 var animated = _props.animated;276 var style = _props.style;277 var errorStyle = _props.errorStyle;278 var floatingLabelText = _props.floatingLabelText;279 var hintText = _props.hintText;280 var fullWidth = _props.fullWidth;281 var menuStyle = _props.menuStyle;282 var menuProps = _props.menuProps;283 var listStyle = _props.listStyle;284 var targetOrigin = _props.targetOrigin;285 var disableFocusRipple = _props.disableFocusRipple;286 var triggerUpdateOnFocus = _props.triggerUpdateOnFocus;287 var openOnFocus = _props.openOnFocus;288 var maxSearchResults = _props.maxSearchResults;289 var dataSource = _props.dataSource;290 var other = _objectWithoutProperties(_props, ['anchorOrigin', 'animated', 'style', 'errorStyle', 'floatingLabelText', 'hintText', 'fullWidth', 'menuStyle', 'menuProps', 'listStyle', 'targetOrigin', 'disableFocusRipple', 'triggerUpdateOnFocus', 'openOnFocus', 'maxSearchResults', 'dataSource']);291 var _state = this.state;292 var open = _state.open;293 var anchorEl = _state.anchorEl;294 var searchText = _state.searchText;295 var focusTextField = _state.focusTextField;296 var prepareStyles = this.context.muiTheme.prepareStyles;297 var styles = getStyles(this.props, this.context, this.state);298 var requestsList = [];299 dataSource.every(function(item, index) {300 switch (typeof item === 'undefined' ? 'undefined' : _typeof(item)) {301 case 'string':302 if (_this2.props.filter(searchText, item, item)) {303 requestsList.push({304 text: item,305 value: _react2.default.createElement(_MenuItem2.default, {306 innerDivStyle: styles.innerDiv,307 value: item,308 primaryText: item,309 disableFocusRipple: disableFocusRipple,310 key: index311 })312 });313 }314 break;315 case 'object':316 if (item && typeof item.text === 'string') {317 if (_this2.props.filter(searchText, item.text, item)) {318 if (item.value.type && (item.value.type.muiName === _MenuItem2.default.muiName || item.value.type.muiName === _Divider2.default.muiName)) {319 requestsList.push({320 text: item.text,321 value: _react2.default.cloneElement(item.value, {322 key: index,323 disableFocusRipple: _this2.props.disableFocusRipple324 })325 });326 } else {327 requestsList.push({328 text: item.text,329 value: _react2.default.createElement(_MenuItem2.default, {330 innerDivStyle: styles.innerDiv,331 primaryText: item.value,332 disableFocusRipple: disableFocusRipple,333 key: index334 })335 });336 }337 }338 }339 break;340 default:341 }342 return !(maxSearchResults && maxSearchResults > 0 && requestsList.length === maxSearchResults);343 });344 this.requestsList = requestsList;345 var menu = open && requestsList.length > 0 && _react2.default.createElement(_Menu2.default, _extends({}, menuProps, {346 ref: 'menu',347 autoWidth: false,348 disableAutoFocus: focusTextField,349 onEscKeyDown: this.handleEscKeyDown,350 initiallyKeyboardFocused: false,351 onItemTouchTap: this.handleItemTouchTap,352 onMouseDown: this.handleMouseDown,353 style: (0, _simpleAssign2.default)(styles.menu, menuStyle),354 listStyle: (0, _simpleAssign2.default)(styles.list, listStyle)355 }), requestsList.map(function(i) {356 return i.value;357 }));358 return _react2.default.createElement('div', {style: prepareStyles((0, _simpleAssign2.default)(styles.root, style))}, _react2.default.createElement(_TextField2.default, _extends({}, other, {359 ref: 'searchTextField',360 autoComplete: 'off',361 value: searchText,362 onChange: this.handleChange,363 onBlur: this.handleBlur,364 onFocus: this.handleFocus,365 onKeyDown: this.handleKeyDown,366 floatingLabelText: floatingLabelText,367 hintText: hintText,368 fullWidth: fullWidth,369 multiLine: false,370 errorStyle: errorStyle371 })), _react2.default.createElement(_Popover2.default, {372 style: styles.popover,373 canAutoPosition: false,374 anchorOrigin: anchorOrigin,375 targetOrigin: targetOrigin,376 open: open,377 anchorEl: anchorEl,378 useLayerForClickAway: false,379 onRequestClose: this.handleRequestClose,380 animated: animated381 }, menu));382 }383 }]);384 return AutoComplete;385 }(_react.Component);386 AutoComplete.propTypes = {387 anchorOrigin: _propTypes2.default.origin,388 animated: _react.PropTypes.bool,389 dataSource: _react.PropTypes.array.isRequired,390 disableFocusRipple: _react.PropTypes.bool,391 errorStyle: _react.PropTypes.object,392 errorText: _react.PropTypes.node,393 filter: _react.PropTypes.func,394 floatingLabelText: _react.PropTypes.node,395 fullWidth: _react.PropTypes.bool,396 hintText: _react.PropTypes.node,397 listStyle: _react.PropTypes.object,398 maxSearchResults: _react.PropTypes.number,399 menuCloseDelay: _react.PropTypes.number,400 menuProps: _react.PropTypes.object,401 menuStyle: _react.PropTypes.object,402 onBlur: _react.PropTypes.func,403 onFocus: _react.PropTypes.func,404 onKeyDown: _react.PropTypes.func,405 onNewRequest: _react.PropTypes.func,406 onUpdateInput: _react.PropTypes.func,407 open: _react.PropTypes.bool,408 openOnFocus: _react.PropTypes.bool,409 searchText: _react.PropTypes.string,410 style: _react.PropTypes.object,411 targetOrigin: _propTypes2.default.origin,412 triggerUpdateOnFocus: (0, _deprecatedPropType2.default)(_react.PropTypes.bool, 'Instead, use openOnFocus')413 };414 AutoComplete.defaultProps = {415 anchorOrigin: {416 vertical: 'bottom',417 horizontal: 'left'418 },419 animated: true,420 disableFocusRipple: true,421 filter: function filter(searchText, key) {422 return searchText !== '' && key.indexOf(searchText) !== -1;423 },424 fullWidth: false,425 open: false,426 openOnFocus: false,427 onUpdateInput: function onUpdateInput() {},428 onNewRequest: function onNewRequest() {},429 searchText: '',430 menuCloseDelay: 300,431 targetOrigin: {432 vertical: 'top',433 horizontal: 'left'434 }435 };436 AutoComplete.contextTypes = {muiTheme: _react.PropTypes.object.isRequired};437 AutoComplete.levenshteinDistance = function(searchText, key) {438 var current = [];439 var prev = void 0;440 var value = void 0;441 for (var i = 0; i <= key.length; i++) {442 for (var j = 0; j <= searchText.length; j++) {443 if (i && j) {444 if (searchText.charAt(j - 1) === key.charAt(i - 1))445 value = prev;446 else447 value = Math.min(current[j], current[j - 1], prev) + 1;448 } else {449 value = i + j;450 }451 prev = current[j];452 current[j] = value;453 }454 }455 return current.pop();456 };457 AutoComplete.noFilter = function() {458 return true;459 };460 AutoComplete.defaultFilter = AutoComplete.caseSensitiveFilter = function(searchText, key) {461 return searchText !== '' && key.indexOf(searchText) !== -1;462 };463 AutoComplete.caseInsensitiveFilter = function(searchText, key) {464 return key.toLowerCase().indexOf(searchText.toLowerCase()) !== -1;465 };466 AutoComplete.levenshteinDistanceFilter = function(distanceLessThan) {467 if (distanceLessThan === undefined) {468 return AutoComplete.levenshteinDistance;469 } else if (typeof distanceLessThan !== 'number') {470 throw 'Error: AutoComplete.levenshteinDistanceFilter is a filter generator, not a filter!';471 }472 return function(s, k) {473 return AutoComplete.levenshteinDistance(s, k) < distanceLessThan;474 };475 };476 AutoComplete.fuzzyFilter = function(searchText, key) {477 if (searchText.length === 0) {478 return false;479 }480 var subMatchKey = key.substring(0, searchText.length);481 var distance = AutoComplete.levenshteinDistance(searchText.toLowerCase(), subMatchKey.toLowerCase());482 return searchText.length > 3 ? distance < 2 : distance === 0;483 };484 AutoComplete.Item = _MenuItem2.default;485 AutoComplete.Divider = _Divider2.default;486 exports.default = AutoComplete;...
ciudadanoService.js
Source:ciudadanoService.js
1angular.module('myApp').service('CiudadanoService', ['$http', '$q', 'UrlService', 'baseApi', function ($http, $q, UrlService, baseApi) {2 var CiudadanoService = {};3 var resourceUrl;4 var docUrl;5 var docUrlReceived;6 var resourceUrlReceived;7 // Getting the ciudadano API documentation URL and a promise to know when it's loaded.8 docUrlReceived = UrlService.ciudadanoUrl.then(function (url) {9 docUrl = url;10 });11 // When the documentation is received, getting the ciudadanos resource URL and a promise to know when it's loaded.12 docUrlReceived.then(function () {13 resourceUrlReceived = $http.get(docUrl).success(function (response) {14 resourceUrl = baseApi + response.resourcePath;15 });16 });17 // Function wrapper verifying URL is available before any API call.18 var safeCall = function (functionToCall) {19 return function () {20 var args = Array.prototype.slice.call(arguments);21 var deferred = $q.defer();22 // When the doc URL is available.23 docUrlReceived.then(function () {24 // When the resource URL is available.25 resourceUrlReceived.then(function () {26 deferred.resolve(functionToCall.apply(this, args));27 });28 });29 return deferred.promise;30 };31 };32 function buildBaucisQuery(opts) {33 var q ='?';34 var prefix='';35 if (opts.page == null && opts.blockSize == null) { 36 }37 else {38 opts.page = opts.page || 1;39 opts.pageSize = opts.pageSize || 20;40 41 var skip = (opts.page-1)*opts.pageSize;42 if(skip > 0) {43 q += prefix + 'skip=' + skip;44 prefix='&'; 45 }46 q += prefix + '&limit=' + opts.pageSize;47 prefix='&';48 }49 if (opts.sort) {50 q += prefix + 'sort=' + encodeURIComponent(opts.sort) + '';51 prefix='&';52 } 53 if (opts.criteria) {54 q += prefix + 'conditions={' + encodeURIComponent(opts.criteria) + '}';55 prefix='&';56 }57 if (opts.select) {58 q += prefix + 'select={' + encodeURIComponent(opts.select) + '}';59 prefix='&';60 }61 if (opts.populate) {62 q += prefix + 'populate={' + encodeURIComponent(opts.populate) + '}';63 prefix='&';64 }65 if (opts.hint) {66 q += prefix + 'hint={' + encodeURIComponent(opts.hint) + '}';67 prefix='&';68 }69 if (opts.count === true) {70 q += prefix + 'count=true';71 prefix='&';72 }73 if (opts.searchText && opts.searchText!=='') {74 //Do a custom like query75 var likeQuery = buildLikeQuery(opts.searchText); 76 q += prefix + 'conditions={' + encodeURIComponent(likeQuery) + '}';77 prefix='&';78 }79 return q;80 }81 function buildLikeQuery(searchText) {82 var res='"$or":[';83 //add string fields84 var clauses = [];85 var clause = null;86//Process each property87 clause = addNumberLike('ciudadanoId', searchText);88 if (clause != null){89 clauses.push(clause);90 }91 clause = addStringLike('identificador', searchText);92 if (clause != null){93 clauses.push(clause);94 }95 clause = addStringLike('tipoIdentificador', searchText);96 if (clause != null){97 clauses.push(clause);98 }99 clause = addStringLike('nombre', searchText);100 if (clause != null){101 clauses.push(clause);102 }103 clause = addStringLike('apellido1', searchText);104 if (clause != null){105 clauses.push(clause);106 }107 clause = addStringLike('apellido2', searchText);108 if (clause != null){109 clauses.push(clause);110 }111 clause = addStringLike('sexo', searchText);112 if (clause != null){113 clauses.push(clause);114 }115 clause = addStringLike('estadoCivil', searchText);116 if (clause != null){117 clauses.push(clause);118 }119 clause = addBooleanLike('parejaDeHecho', searchText);120 if (clause != null){121 clauses.push(clause);122 }123 if (clause != null){124 clauses.push(clause);125 }126 clause = addStringLike('provinciaNacimiento', searchText);127 if (clause != null){128 clauses.push(clause);129 }130 clause = addStringLike('paisDeNacimiento', searchText);131 if (clause != null){132 clauses.push(clause);133 }134 clause = addStringLike('nacionalidad', searchText);135 if (clause != null){136 clauses.push(clause);137 }138 clause = addNumberLike('ingresosAnuales', searchText);139 if (clause != null){140 clauses.push(clause);141 }142 clause = addBooleanLike('empadronamiento', searchText);143 if (clause != null){144 clauses.push(clause);145 }146 if (clause != null){147 clauses.push(clause);148 }149 clause = addStringLike('causaBaja', searchText);150 if (clause != null){151 clauses.push(clause);152 }153 //clause = addStringLike('fechaBaja', searchText);154 //if (clause != null)155 // clauses.push(clause);156 clause = addStringLike('telefono1', searchText);157 if (clause != null){158 clauses.push(clause);159 }160 clause = addStringLike('telefono2', searchText);161 if (clause != null){162 clauses.push(clause);163 }164 clause = addStringLike('email', searchText);165 if (clause != null){166 clauses.push(clause);167 }168 clause = addBooleanLike('discapacidad', searchText);169 if (clause != null){170 clauses.push(clause);171 }172 clause = addStringLike('gradoDiscapacidad', searchText);173 if (clause != null){174 clauses.push(clause);175 }176 clause = addStringLike('diagnostico', searchText);177 if (clause != null){178 clauses.push(clause);179 }180 clause = addStringLike('valoracionDependencia', searchText);181 if (clause != null){182 clauses.push(clause);183 }184 clause = addStringLike('rae', searchText);185 if (clause != null){186 clauses.push(clause);187 }188 clause = addStringLike('ocupacion', searchText);189 if (clause != null){190 clauses.push(clause);191 }192 clause = addStringLike('situacionHistoriaLaboral', searchText);193 if (clause != null){194 clauses.push(clause);195 }196 clause = addNumberLike('annosResidenciaCCAA', searchText);197 if (clause != null){198 clauses.push(clause);199 }200 clause = addNumberLike('annosResidenciaMunicipio', searchText);201 if (clause != null){202 clauses.push(clause);203 }204 clause = addStringLike('nivelEstudios', searchText);205 if (clause != null){206 clauses.push(clause);207 }208 clause = addNumberLike('tarjetaSanitaria', searchText);209 if (clause != null){210 clauses.push(clause);211 }212 clause = addStringLike('coberturaSanitaria', searchText);213 if (clause != null){214 clauses.push(clause);215 }216 clause = addStringLike('medico', searchText);217 if (clause != null){218 clauses.push(clause);219 }220 clause = addStringLike('centroSalud', searchText);221 if (clause != null){222 clauses.push(clause);223 }224 clause = addStringLike('direccionCentroSalud', searchText);225 if (clause != null){226 clauses.push(clause);227 }228 clause = addStringLike('telefonoCentroSalud', searchText);229 if (clause != null){230 clauses.push(clause);231 }232 233 clause = addStringLike('observaciones', searchText);234 if (clause != null){235 clauses.push(clause);236 }237 var prefix='';238 clauses.forEach(function(item) {239 res+=prefix+item;240 prefix=',';241 });242 res += ']';243 if (clauses.length>0) {244 return res;245 }246 return '';247 }248 function addStringLike(property, searchValue) {249 if (searchValue == null){250 return null;251 }252 return '{"'+ property +'":{"$regex":"' + escapeForRegex(searchValue) + '","$options":"i"}}';253 }254 function addNumberLike(property, searchValue) {255 if (!isNumber(searchValue)) {256 return null;257 }258 var num = Number(searchValue);259 return '{"'+ property +'":' + num + '}';260 }261 function addBooleanLike(property, searchValue) {262 var boolValue = strToBool(searchValue);263 if (boolValue == null) {264 return null;265 }266 return '{"'+ property +'":' + boolValue + '}'; 267 }268 function isNumber(n) {269 return !isNaN(parseFloat(n)) && isFinite(n);270 }271 function escapeForRegex(candidate) {272 //escape values for regex273 return candidate;274 }275 var boolValues = {276 "true" : "true",277 "yes" : "true",278 "false" : "false",279 "no" : "false"280 };281 function strToBool(candidate) {282 var value = candidate.toLowerCase();283 var boolVal = boolValues[value];284 if (boolVal == null){ 285 return null;286 }287 return boolVal;288 }289 function buildMongooseQuery(opts) {290 var q = '';291 if (opts.searchText && opts.searchText!=='') {292 var likeQuery = buildMoongooseLikeQuery(opts.searchText); 293 vq = '{' + likeQuery + '}'; 294 }295 return q;296 }297 function buildMoongooseLikeQuery(searchText) {298 var res='"$or":[';299 //add string fields300 var clauses = [];301 var clause = null;302 //Process each property303 304 clause = addNumberLike('ciudadanoId', searchText);305 306 if (clause != null){307 clauses.push(clause);308 }309 310 clause = addStringLike('identificador', searchText);311 312 if (clause != null){313 clauses.push(clause);314 }315 316 clause = addStringLike('tipoIdentificador', searchText);317 318 if (clause != null){319 clauses.push(clause);320 }321 322 clause = addStringLike('nombre', searchText);323 324 if (clause != null){325 clauses.push(clause);326 }327 328 clause = addStringLike('apellido1', searchText);329 330 if (clause != null){331 clauses.push(clause);332 }333 334 clause = addStringLike('apellido2', searchText);335 336 if (clause != null){337 clauses.push(clause);338 }339 340 clause = addStringLike('sexo', searchText);341 342 if (clause != null){343 clauses.push(clause);344 }345 346 clause = addStringLike('estadoCivil', searchText);347 348 if (clause != null){349 clauses.push(clause);350 }351 352 clause = addBooleanLike('parejaDeHecho', searchText);353 354 if (clause != null){355 clauses.push(clause);356 }357 358 if (clause != null){359 clauses.push(clause);360 }361 362 clause = addStringLike('provinciaNacimiento', searchText);363 364 if (clause != null){365 clauses.push(clause);366 }367 368 clause = addStringLike('paisDeNacimiento', searchText);369 370 if (clause != null){371 clauses.push(clause);372 }373 374 clause = addStringLike('nacionalidad', searchText);375 376 if (clause != null){377 clauses.push(clause);378 }379 380 clause = addNumberLike('ingresosAnuales', searchText);381 382 if (clause != null){383 clauses.push(clause);384 }385 386 clause = addBooleanLike('empadronamiento', searchText);387 388 if (clause != null){389 clauses.push(clause);390 }391 392 393 clause = addStringLike('causaBaja', searchText);394 395 if (clause != null){396 clauses.push(clause);397 }398 399 clause = addStringLike('fechaBaja', searchText);400 401 if (clause != null){402 clauses.push(clause);403 }404 405 clause = addStringLike('telefono1', searchText);406 407 if (clause != null){408 clauses.push(clause);409 }410 411 clause = addStringLike('telefono2', searchText);412 413 if (clause != null){414 clauses.push(clause);415 }416 417 clause = addStringLike('email', searchText);418 419 if (clause != null){420 clauses.push(clause);421 }422 423 clause = addBooleanLike('discapacidad', searchText);424 425 if (clause != null){426 clauses.push(clause);427 }428 429 clause = addStringLike('gradoDiscapacidad', searchText);430 431 if (clause != null){432 clauses.push(clause);433 }434 435 clause = addStringLike('diagnostico', searchText);436 437 if (clause != null){438 clauses.push(clause);439 }440 441 clause = addStringLike('valoracionDependencia', searchText);442 443 if (clause != null){444 clauses.push(clause);445 }446 447 clause = addStringLike('rae', searchText);448 449 if (clause != null){450 clauses.push(clause);451 }452 453 clause = addStringLike('ocupacion', searchText);454 455 if (clause != null){456 clauses.push(clause);457 }458 459 clause = addStringLike('situacionHistoriaLaboral', searchText);460 461 if (clause != null){462 clauses.push(clause);463 }464 465 clause = addNumberLike('annosResidenciaCCAA', searchText);466 467 if (clause != null){468 clauses.push(clause);469 }470 471 clause = addNumberLike('annosResidenciaMunicipio', searchText);472 473 if (clause != null){474 clauses.push(clause);475 }476 477 clause = addStringLike('nivelEstudios', searchText);478 479 if (clause != null){480 clauses.push(clause);481 }482 483 clause = addNumberLike('tarjetaSanitaria', searchText);484 485 if (clause != null){486 clauses.push(clause);487 }488 489 clause = addStringLike('coberturaSanitaria', searchText);490 491 if (clause != null){492 clauses.push(clause);493 }494 495 clause = addStringLike('medico', searchText);496 497 if (clause != null){498 clauses.push(clause);499 }500 501 clause = addStringLike('centroSalud', searchText);502 503 if (clause != null){504 clauses.push(clause);505 }506 507 clause = addStringLike('direccionCentroSalud', searchText);508 509 if (clause != null){510 clauses.push(clause);511 }512 513 clause = addStringLike('telefonoCentroSalud', searchText);514 515 if (clause != null){516 clauses.push(clause);517 }518 519 520 clause = addStringLike('observaciones', searchText);521 522 if (clause != null){523 clauses.push(clause);524 }525 526 var prefix='';527 clauses.forEach(function(item) {528 res+=prefix+item;529 prefix=',';530 });531 res += ']';532 if (clauses.length>0) {533 return res;534 }535 return '';536 }537 //-- Public API -----538 CiudadanoService.getCount = safeCall(function (opts) {539 opts = opts || {};540 opts.count = true; 541 var q = buildBaucisQuery(opts);542 return $http.get(resourceUrl + q);543 });544 545 CiudadanoService.getList = safeCall(function (opts) {546 opts = opts || {};547 var q = buildBaucisQuery(opts);548 return $http.get(resourceUrl + q);549 });550 CiudadanoService.getListAsCsv = safeCall(function () {551 return $http({552 method: 'GET', 553 url: resourceUrl, 554 headers: {'Accept': 'text/csv'} 555 });556 }); 557 CiudadanoService.getFileAsCsv = safeCall(function () {558 return $http({559 method: 'GET', 560 url: resourceUrl + '/download/csv/', 561 headers: {'Accept': 'text/csv'} 562 });563 }); 564 CiudadanoService.getFileAsXml = safeCall(function () {565 return $http({566 method: 'GET', 567 url: resourceUrl + '/download/xml/', 568 headers: {'Accept': 'text/xml'} 569 });570 }); 571 CiudadanoService.getFileAsXlsx = safeCall(function () {572 return $http({573 method: 'GET', 574 url: resourceUrl + '/download/xlsx/', 575 headers: {'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'},576 responseType: 'blob' 577 });578 }); 579 580 CiudadanoService.getToEdit = safeCall(function (id) {581 return CiudadanoService.get(resourceUrl + '/' + id);582 });583 CiudadanoService.getToEditFamilia = safeCall(function (id) {584 return CiudadanoService.get(resourceUrl + '/' + id + '?populate=familia' );585 });586 CiudadanoService.get = function (link) {587 return $http.get(link);588 };589 CiudadanoService.add = safeCall(function (item) {590 return $http.post(resourceUrl, JSON.stringify(item));591 });592 CiudadanoService.update = function (item) {593 return $http.put(resourceUrl + '/' + item._id, JSON.stringify(item));594 };595 CiudadanoService.delete = safeCall(function (id) {596 return $http.delete(resourceUrl + '/' + id);597 });598 CiudadanoService.deleteMany = safeCall(function (ids) {599 var msg = { 600 'className' : 'ciudadano',601 'ids' : ids602 }; 603 return $http.post(baseApi + '/delete', JSON.stringify(msg));604 }); 605 CiudadanoService.deleteAll = safeCall(function (opts) {606 var msg = { 607 'className' : 'ciudadano',608 'conditions' : buildMongooseQuery(opts)609 }; 610 return $http.post(baseApi + '/deleteAll', JSON.stringify(msg));611 }); 612 CiudadanoService.changePhoto = safeCall(function (ciudadanoId, content, file) {613 var base64String = (content != null) ? 614 btoa(String.fromCharCode.apply(null, new Uint8Array(content)))615 : null;616 var msg = { 617 'content' : base64String,618 'fileName' : (file!=null)? file.name : null,619 'size' : (file!=null)? file.size : null,620 'mimeType' : (file!=null)? file.type : null621 }; 622 return $http.post(resourceUrl + '/changePhoto/' + ciudadanoId, JSON.stringify(msg));623 }); 624 CiudadanoService.getTimeLine = safeCall(function (id) {625 var q = '/timeline/'+ id ;626 return $http.get(resourceUrl + q);627 });628 CiudadanoService.lookupCiudadano = safeCall(function (tipoDoc, docNumber) {629 var msg = { 630 'tipoDoc' : tipoDoc,631 'docNumber' : docNumber632 }; 633 return $http.post(resourceUrl + '/lookupCiudadano', JSON.stringify(msg));634 });635 return CiudadanoService;...
gifs.js
Source:gifs.js
1// Copyright (c) 2015-present Xenia, Inc. All Rights Reserved.2// See LICENSE.txt for license information.3import {combineReducers} from 'redux';4import {GifTypes} from 'action_types';5const SEARCH_SELECTORS = {6 [GifTypes.SELECT_SEARCH_TEXT]: (state, action) => ({7 ...state,8 searchText: action.searchText,9 }),10 [GifTypes.INVALIDATE_SEARCH_TEXT]: (state, action) => ({11 ...state,12 resultsByTerm: {13 ...state.resultsByTerm[action.searchText],14 didInvalidate: true,15 },16 }),17 [GifTypes.REQUEST_SEARCH]: (state, action) => ({18 ...state,19 resultsByTerm: TERM_SELECTOR[action.type](state.resultsByTerm, action),20 }),21 [GifTypes.RECEIVE_SEARCH]: (state, action) => ({22 ...state,23 searchText: action.searchText,24 resultsByTerm: TERM_SELECTOR[action.type](state.resultsByTerm, action),25 }),26 [GifTypes.RECEIVE_SEARCH_END]: (state, action) => ({27 ...state,28 searchText: action.searchText,29 resultsByTerm: TERM_SELECTOR[action.type](state.resultsByTerm, action),30 }),31 [GifTypes.RECEIVE_CATEGORY_SEARCH]: (state, action) => ({32 ...state,33 searchText: action.searchText,34 resultsByTerm: TERM_SELECTOR[action.type](state.resultsByTerm, action),35 }),36 [GifTypes.SEARCH_FAILURE]: (state, action) => ({37 ...state,38 searchText: action.searchText,39 resultsByTerm: TERM_SELECTOR[action.type](state.resultsByTerm, action),40 }),41 [GifTypes.CLEAR_SEARCH_RESULTS]: (state) => ({42 ...state,43 searchText: '',44 resultsByTerm: {},45 }),46 [GifTypes.SAVE_SEARCH_SCROLL_POSITION]: (state, action) => ({47 ...state,48 scrollPosition: action.scrollPosition,49 }),50 [GifTypes.SAVE_SEARCH_PRIOR_LOCATION]: (state, action) => ({51 ...state,52 priorLocation: action.priorLocation,53 }),54 [GifTypes.UPDATE_SEARCH_TEXT]: (state, action) => ({55 ...state,56 searchText: action.searchText,57 }),58 [GifTypes.SAVE_SEARCH_BAR_TEXT]: (state, action) => ({59 ...state,60 searchBarText: action.searchBarText,61 }),62};63const CATEGORIES_SELECTORS = {64 [GifTypes.REQUEST_CATEGORIES_LIST]: (state) => ({65 ...state,66 isFetching: true,67 }),68 [GifTypes.CATEGORIES_LIST_RECEIVED]: (state, action) => {69 const {cursor, tags} = action;70 const {tagsList: oldTagsList = []} = state;71 const tagsDict = {};72 const newTagsList = tags.filter((item) => {73 return Boolean(item && item.gfycats[0] && item.gfycats[0].width);74 }).map((item) => {75 tagsDict[item.tag] = true;76 return {77 tagName: item.tag,78 gfyId: item.gfycats[0].gfyId,79 };80 });81 const tagsList = [...oldTagsList, ...newTagsList];82 return {83 ...state,84 cursor,85 hasMore: Boolean(cursor),86 isFetching: false,87 tagsList,88 tagsDict,89 };90 },91 [GifTypes.CATEGORIES_LIST_FAILURE]: (state) => ({92 ...state,93 isFetching: false,94 }),95};96const TERM_SELECTOR = {97 [GifTypes.REQUEST_SEARCH]: (state, action) => ({98 ...state,99 [action.searchText]: {100 ...state[action.searchText],101 isFetching: true,102 didInvalidate: false,103 pages: PAGE_SELECTOR[action.type](state[action.searchText], action),104 },105 }),106 [GifTypes.RECEIVE_SEARCH]: (state, action) => {107 const gfycats = action.gfycats.filter((item) => {108 return Boolean(item.gfyId && item.width && item.height);109 });110 const newItems = gfycats.map((gfycat) => gfycat.gfyId);111 return {112 ...state,113 [action.searchText]: {114 ...state[action.searchText],115 isFetching: false,116 items: typeof state[action.searchText] !== 'undefined' &&117 state[action.searchText].items ?118 [...state[action.searchText].items, ...newItems] :119 newItems,120 moreRemaining:121 typeof state[action.searchText] !== 'undefined' &&122 state[action.searchText].items ?123 [124 ...state[action.searchText].items,125 ...action.gfycats,126 ].length < action.found :127 action.gfycats.length < action.found,128 count: action.count,129 found: action.found,130 start: action.start,131 currentPage: action.currentPage,132 pages: PAGE_SELECTOR[action.type](state[action.searchText], action),133 cursor: action.cursor,134 },135 };136 },137 [GifTypes.RECEIVE_CATEGORY_SEARCH]: (state, action) => {138 const gfycats = action.gfycats.filter((item) => {139 return Boolean(item.gfyId && item.width && item.height);140 });141 const newItems = gfycats.map((gfycat) => gfycat.gfyId);142 return {143 ...state,144 [action.searchText]: {145 ...state[action.searchText],146 isFetching: false,147 items: typeof state[action.searchText] !== 'undefined' &&148 state[action.searchText].items ?149 [...state[action.searchText].items, ...newItems] :150 newItems,151 cursor: action.cursor,152 moreRemaining: Boolean(action.cursor),153 },154 };155 },156 [GifTypes.RECEIVE_SEARCH_END]: (state, action) => ({157 ...state,158 [action.searchText]: {159 ...state[action.searchText],160 isFetching: false,161 moreRemaining: false,162 },163 }),164 [GifTypes.SEARCH_FAILURE]: (state, action) => ({165 ...state,166 [action.searchText]: {167 ...state[action.searchText],168 isFetching: false,169 items: [],170 moreRemaining: false,171 count: 0,172 found: 0,173 start: 0,174 isEmpty: true,175 },176 }),177};178const PAGE_SELECTOR = {179 [GifTypes.REQUEST_SEARCH]: ((state) = {}) => {180 if (typeof state.pages == 'undefined') {181 return {};182 }183 return {...state.pages};184 },185 [GifTypes.RECEIVE_SEARCH]: (state, action) => ({186 ...state.pages,187 [action.currentPage]: action.gfycats.map((gfycat) => gfycat.gfyId),188 }),189};190const CACHE_SELECTORS = {191 [GifTypes.CACHE_GIFS]: (state, action) => ({192 ...state,193 gifs: CACHE_GIF_SELECTOR[action.type](state.gifs, action),194 updating: false,195 }),196 [GifTypes.CACHE_REQUEST]: (state, action) => ({197 ...state,198 ...action.payload,199 }),200};201const CACHE_GIF_SELECTOR = {202 [GifTypes.CACHE_GIFS]: (state, action) => ({203 ...state,204 ...action.gifs.reduce((map, obj) => {205 map[obj.gfyId] = obj;206 return map;207 }, {}),208 }),209};210function appReducer(state = {}, action) {211 const nextState = {...state};212 switch (action.type) {213 case GifTypes.SAVE_APP_PROPS:214 return {...nextState, ...action.props};215 default:216 return state;217 }218}219function categoriesReducer(state = {}, action) {220 const selector = CATEGORIES_SELECTORS[action.type];221 return selector ? selector(state, action) : state;222}223function searchReducer(state = {}, action) {224 const selector = SEARCH_SELECTORS[action.type];225 return selector ? selector(state, action) : state;226}227function cacheReducer(state = {}, action) {228 const selector = CACHE_SELECTORS[action.type];229 return selector ? selector(state, action) : state;230}231export default combineReducers({232 app: appReducer,233 categories: categoriesReducer,234 search: searchReducer,235 cache: cacheReducer,...
AppGenEnqury.js
Source:AppGenEnqury.js
1function genSearchZhCH() {2 $("input#textBoxSearch_app").focus(function () {3 var content = $(this).attr("value");4 if (content == "请è¾å
¥å
³é®å") {5 $(this).attr("value", "");6 $(this).css("color", "Black");7 }8 });9 $("input#textBoxSearch_app").blur(function () {10 var content = $(this).attr("value");11 if (content == "") {12 $(this).attr("value", "请è¾å
¥å
³é®å");13 $(this).css("color", "#C0C0C0");14 }15 });1617 $("div#table").ajaxStart(function () {18 $("span#loading").css("display", "inline");19 });20 $("div#table").ajaxComplete(function () {21 $("span#loading").css("display", "none");22 });2324 $("input#search").click(function () {25 $("span#errorExportExcel").css("display", "none");26 var searchText = $("input#textBoxSearch_app").attr("value");27 //åå
¥cookie28 document.cookie = searchText;2930 if (searchText == "请è¾å
¥å
³é®å") {31 //$("span#errorExportExcel").css("display", "none");32 $("input#textBoxSearch_app").focus();33 $("input#textBoxSearch_app").css("border-color", "red");3435 } else {36 var url = "http://localhost:8080/Home/Enquiry_On_App_Result/?searchText=" + searchText;37 $.get(url, function (result) {38 $("div#table").html(result);39 });4041 }4243 });4445 //************* 导åºexcel *************//46 $("a#exportExcel").click(function () {47 // ååºcookie48 var searchText = document.cookie;4950 //searchText = (searchText == null ? "请è¾å
¥å
³é®å" : searchText);51 if (searchText != "请è¾å
¥å
³é®å" && searchText != "") {52 var url = "http://localhost:8080/Home/ExportExcelEnquiryOnApp/?appNameKey=" + searchText;53 //alert(url);54 window.open(url);55 } else {56 $("span#errorExportExcel").css("display", "inline");57 }58 });59}6061function genSearchEnUS() {62 $("input#textBoxSearch_app").focus(function () {63 var content = $(this).attr("value");64 if (content == "Please input the keyword") {65 $(this).attr("value", "");66 $(this).css("color", "Black");67 }68 });69 $("input#textBoxSearch_app").blur(function () {70 var content = $(this).attr("value");71 if (content == "") {72 $(this).attr("value", "Please input the keyword");73 $(this).css("color", "#C0C0C0");74 }75 });7677 $("div#table").ajaxStart(function () {78 $("span#loading").css("display", "inline");79 });80 $("div#table").ajaxComplete(function () {81 $("span#loading").css("display", "none");82 });8384 $("input#search").click(function () {85 $("span#errorExportExcel").css("display", "none");86 var searchText = $("input#textBoxSearch_app").attr("value");87 //åå
¥cookie88 document.cookie = searchText;8990 if (searchText == "Please input the keyword") {91 //$("span#errorExportExcel").css("display", "none");92 $("input#textBoxSearch_app").focus();93 $("input#textBoxSearch_app").css("border-color", "red");9495 } else {96 var url = "http://localhost:8080/Home/Enquiry_On_App_Result/?searchText=" + searchText;97 $.get(url, function (result) {98 $("div#table").html(result);99 });100101 }102103 });104105 //************* 导åºexcel *************//106 $("a#exportExcel").click(function () {107 // ååºcookie108 var searchText = document.cookie;109110 //searchText = (searchText == null ? "请è¾å
¥å
³é®å" : searchText);111 if (searchText != "Please input the keyword" && searchText != "") {112 var url = "http://localhost:8080/Home/ExportExcelEnquiryOnApp/?appNameKey=" + searchText;113 //alert(url);114 window.open(url);115 } else {116 $("span#errorExportExcel").css("display", "inline");117 }118 });119}120121function genSearchZhHK() {122123 $("input#textBoxSearch_app").focus(function () {124 var content = $(this).attr("value");125 if (content == "è«è¼¸å
¥ééµå") {126 $(this).attr("value", "");127 $(this).css("color", "Black");128 }129 });130 $("input#textBoxSearch_app").blur(function () {131 var content = $(this).attr("value");132 if (content == "") {133 $(this).attr("value", "è«è¼¸å
¥ééµå");134 $(this).css("color", "#C0C0C0");135 }136 });137138 $("div#table").ajaxStart(function () {139 $("span#loading").css("display", "inline");140 });141 $("div#table").ajaxComplete(function () {142 $("span#loading").css("display", "none");143 });144145 $("input#search").click(function () {146 $("span#errorExportExcel").css("display", "none");147 var searchText = $("input#textBoxSearch_app").attr("value");148 //åå
¥cookie149 document.cookie = searchText;150151 if (searchText == "è«è¼¸å
¥ééµå") {152 //$("span#errorExportExcel").css("display", "none");153 $("input#textBoxSearch_app").focus();154 $("input#textBoxSearch_app").css("border-color", "red");155156 } else {157 var url = "http://localhost:8080/Home/Enquiry_On_App_Result/?searchText=" + searchText;158 $.get(url, function (result) {159 $("div#table").html(result);160 });161162 }163164 });165166 //************* 导åºexcel *************//167 $("a#exportExcel").click(function () {168 // ååºcookie169 var searchText = document.cookie;170171 //searchText = (searchText == null ? "请è¾å
¥å
³é®å" : searchText);172 if (searchText != "è«è¼¸å
¥ééµå" && searchText != "") {173 var url = "http://localhost:8080/Home/ExportExcelEnquiryOnApp/?appNameKey=" + searchText;174 //alert(url);175 window.open(url);176 } else {177 $("span#errorExportExcel").css("display", "inline");178 }179 });180181}
...
zappiWordSelector.js
Source:zappiWordSelector.js
1define(['./module'], function (directives) {2 directives.directive("zappiWordSelector", ["$timeout", "$animate", function($timeout, $animate){3 return {4 restrict: 'E',5 scope: {6 isVisible: '=',7 options: "=",8 selected: "=",9 onPrefedinedWordSelect: '=',10 maxCustom: "=",11 showInstructions: "@",12 label: "@"13 },14 link: function( $scope, $el, $at) {15 $animate.enabled(false,$el) // Disables animations;16 if( $scope.showInstructions == undefined || $scope.showInstructions == null )17 $scope.showInstructions = 'true';18 if( $scope.label == "" )19 $scope.label = "Type a word e.g. funny and hit 'enter'";20 $($el).on('keyup', function(e){21 if(e.which==13||e.keyCode==13){22 $scope.populate();23 } else if(e.which==27||e.keyCode==27) {24 $scope.searchText="";25 } else {26 }27 })28 $($el).find('.text-input').on('blur', function(){29 $scope.populate();30 })31 $scope.populate = function(){32 if( $scope.searchText.indexOf(',')>0 ){33 var words = $scope.splitToArrayOfStrings( $scope.searchText );34 $timeout(function(){35 angular.forEach( words, function( word ){36 $scope.addCustomWord( word );37 $scope.searchText="";38 });39 }, 50);40 } else {41 $timeout(function(){42 $scope.addCustomWord( $scope.searchText );43 $scope.searchText="";44 }, 50);45 }46 }47 $scope.splitToArrayOfStrings = function(s){ // Ideally shify to formatter48 return s.split(/\,[\s]+|\,/).map( function(v){ return v.replace(/\s\s/ig, '') } );49 }50 $timeout(function(){51 $($el).find('.text-input').on('focus', function(){52 $timeout(function(){53 //$scope.searchText = "";54 //$scope.showAll=false;55 }, 100 );56 });57 }, 100 );58 $scope.getRemainingWordCount = function(){59 return $scope.maxCustom - $scope.getCustomWordCount();60 }61 $scope.getCustomWordCount = function(){62 var __c = 0;63 for( var i=0; i<$scope.selected.length; i++ ){64 if($scope.selected[i].is_custom )65 __c++;66 }67 return __c;68 }69 $scope.search = function( collection_item, index ){70 if( $scope.searchText.length == 0 )71 return $scope.wordIsNotAlreadySelected( collection_item );72 if( $scope.searchText.indexOf(',')==-1 ){73 return $scope.wordIsASuggestedWord( $scope.searchText, collection_item ) && $scope.wordIsNotAlreadySelected( collection_item );74 } else {75 var searchPhrases = $scope.splitToArrayOfStrings( $scope.searchText );76 var includeInResult = false;77 angular.forEach( searchPhrases, function( phrase ){78 if( $scope.wordIsASuggestedWord( phrase, collection_item ) && $scope.wordIsNotAlreadySelected( collection_item ) ){79 includeInResult = true;80 }81 });82 return includeInResult;83 }84 }85 $scope.wordIsASuggestedWord = function(word,word_option){86 if( word == "")87 return false;88 return word_option.key.toLowerCase().indexOf( word.toLowerCase() )>-1;89 }90 $scope.wordIsNotAlreadySelected = function(word_option){91 return $scope.selected.indexOf(word_option) == -1;92 }93 $scope.clearSelected = function(){94 $scope.selected=null;95 $scope.showAll=false;96 $scope.searchText = "";97 $timeout(function(){98 $el.find('.search').focus();99 }, 100);100 }101 $scope.onItemSelect = function(v){102 $timeout(function(){103 $scope.searchText = $scope.splitToArrayOfStrings( $scope.searchText ).join(','); // Clean up spaces104 $scope.searchText = $scope.searchText.replace( new RegExp(v.key + '[\,]{0,1}', 'i'),'') // remove the selected word from the search string and the comma105 }, 50 );106 }107 $scope.removeSelected = function(v){108 $scope.selected.splice($scope.selected.indexOf(v),1);109 }110 $scope.searchText = "";111 $scope.showAll = false;112 $scope.showAllOptions = function(){113 $scope.showAll = true;114 }115 $scope.hideAllOptions = function(){116 $scope.showAll = false; 117 }118 $scope.addCustomWords = function(words){119 angular.forEach( words, function(v,i){120 $scope.addCustomWord(v);121 })122 }123 $scope.addCustomWord = function(word){124 if($scope.getRemainingWordCount()>0 && word.length>0){125 var custom_word = {126 key: word,127 value: word,128 is_custom: true129 }130 $scope.selected.push( $scope.validateCustomWord(custom_word) );131 $scope.onItemSelect( $scope.validateCustomWord(custom_word) );132 $scope.searchText = "";133 }134 }135 $scope.selectItem = function(v){136 $scope.selected.push( v );137 $scope.onItemSelect( v );138 }139 $scope.validateCustomWord = function(word){140 for( var i=0; i<$scope.options.length; i++ ){141 if($scope.options[i].key.toLowerCase() == word.key.toLowerCase() )142 return $scope.options[i];143 }144 return word;145 }146 $scope.$watch( 'searchText', function(v){147 $scope.showAll=false;148 } );149 $scope.$watch( 'showAll', function(v){150 if(v==true)151 $scope.searchText = "";152 } );153 $scope.$watch( 'selected', function(v){154 if(v!=null)155 $scope.searchText = "";156 });157 $scope.getLabel = function(option){158 if(option==null)159 return ""160 return option["key"] != undefined ? option["key"] : option;161 }162 },163 templateUrl: ( (zappi_forms!=null && zappi_forms!=undefined) ? zappi_forms.templates : '/angular/templates' ) + '/zappi_forms/zappi_word_selector.html'164 };165 }]);...
TaskList.js
Source:TaskList.js
1import React, { Component } from 'react';2import { SafeAreaView, StyleSheet, FlatList } from 'react-native';3import InputSearch from './InputSearch';4import Card from './Card';5export default class TaskList extends Component {6 // ! state ...7 state = {8 searchText: '',9 }10 // !11 // ! function for search input12 searchHandler = (searchText) => {13 this.setState({ searchText });14 }15 // !16 render() {17 // ! Destructure styles...18 const { containerStyle, inputContainerStyle } = styles;19 // !20 // ! Destructure props...21 const {22 data = [23 { id: '0', name: 'Tariq Ali', address: 'Garden Town', image:{uri:"http://10.11.21.228:3302/logo1.PNG"} },24 { id: '1', name: 'Shahid Ghafoor', address: 'Civil lines', phone: '03121481997' },25 { id: '2', name: 'Jafeel', address: 'Ichra', phone: '03061481997' },26 { id: '3', name: 'Sabir Khan', address: 'Town Ship', phone: '03201481997' },27 { id: '4', name: 'Muzaffar Iqbal', address: 'Mansehra', phone: '03451312345' },28 { id: '5', name: 'Taimoor Khan', address: 'Shakar Gar', phone: '03121476548' },29 { id: '6', name: 'Usman Iqbal', address: 'Herbanspura', phone: '03062345690' },30 { id: '7', name: 'Hamza Saeed Khan', address: 'Valancia', phone: '03418970601' },31 ]32 } = this.props;33 // !34 // ! this is for how to filter Data ....35 const renderData = data.filter(Data => {36 const name = Data.name.toLowerCase();37 const description = Data.description.toLowerCase();38 // const phone = Data.phone.toLowerCase();39 const searchText = this.state.searchText.toLowerCase();40 return name.includes(searchText) || description.includes(searchText) // || phone.includes(searchText)41 // return name.startsWith(searchText) || address.startsWith(searchText) || phone.startsWith(searchText)42 // return name.endsWith(searchText) || address.endsWith(searchText) || phone.endsWith(searchText)43 })44 // !45 return (46 <SafeAreaView style={containerStyle}>47 48 <InputSearch49 rightIcon50 placeholder="Search ..."51 iconName="search"52 iconSize={18}53 iconColor="#787878"54 inputTextColor="#000"55 inputValue={this.state.searchText}56 textHelper="Use only Characters"57 inputContainerStyle={inputContainerStyle}58 onChange={this.searchHandler}59 />60 <FlatList61 style={{ paddingHorizontal: 20, marginTop: 20 }}62 data={renderData}63 renderItem={({ item }) => (64 <Card value1={item.name} value2={item.description} image={{uri:item.taskImg}} />65 )}66 keyExtractor={item => item._id}67 />68 </SafeAreaView>69 )70 }71}72// ! all styles ...73const styles = StyleSheet.create({74 containerStyle: {75 flex: 1,76 paddingVertical: 2077 },78 inputContainerStyle: {79 borderWidth: 1,80 paddingHorizontal: 10,81 paddingVertical: 5,82 borderRadius: 50,83 marginHorizontal: 20,84 },...
publications.js
Source:publications.js
1//Meteor.publish('a_collection', function(){2// return 'a_collection'.find();3//});4Meteor.publish('patients', function(searchText) {5 if (!searchText) {6 return patients.find();7 }8 return patients.find( { $or: [ {createdAt: { $regex: searchText }}, {name: { $regex: searchText }}, {surname: { $regex: searchText }}, {gender: { $regex: searchText }}, {birthDate: { $regex: searchText }}, {nationalId: { $regex: searchText }}, {socialSecurityType: { $regex: searchText }}, {socialSecurityNumber: { $regex: searchText }}, {isPatientDisabled: { $regex: searchText }}, {bloodType: { $regex: searchText }}, {email: { $regex: searchText }}, {phone: { $regex: searchText }}, {address: { $regex: searchText }}, {dermatologicHistory: { $regex: searchText }}, ] }, {} );9});10Meteor.publish('visits', function(searchText) {11 if (!searchText) {12 return visits.find();13 }14 return visits.find( { $or: [ {createdAt: { $regex: searchText }}, {patientName: { $regex: searchText }}, {visitDateTime: { $regex: searchText }}, {lesion: { $regex: searchText }}, {symptoms: { $regex: searchText }}, {pathophysiology: { $regex: searchText }}, {anatomicalLocation: { $regex: searchText }}, {diagnosis: { $regex: searchText }}, {status: { $regex: searchText }}, {prescription: { $regex: searchText }}, ] }, {} );15});16Meteor.publish('settings', function() {17 return settings.find();...
Using AI Code Generation
1describe('Test', function () {2 it('should work', function () {3 .elementByAccessibilityId('Search')4 .click()5 .elementByClassNme('XCUIElementTypeSeachField')6 .endKys('test')7 .elementByAccessibilityId('Se')8 .click()9 .click()10 .click()11 .elementByAccessibilityId('Back')12 .click()13 .elementByAccessibilityId('Back')14 .click()15 .elementByAccessibilityId('Search')16 .click()17 .elementByClassName('XCUIElementTypeSearchField')18 .sendKeys('test')19 .elementByAccessibilityId('Search')20 .click()21 .click()22 .click()23 .elementByAccessibilityId('Back')24 .click()25 .elementByAccessibilityId('Back')26 .click()27 .elementByAccessibilityId('Search')28 .click()29 .elementByClassName('XCUIElementTypeSearchField')30 .sendKeys('test')31 .elementByAccessibilityId('Search')32 .click()33 .click()34 .click()35 .elementByAccessibilityId('Back')36 .click()37 .elementByAccessibilityId('Back')38 .click()39 .elementByAccessibilityId('Search')40 .click()41 .elementByClassName('XCUIElementTypeSearchField')42 .sendKeys('test')43 .elementByAccessibilityId('Search')44 .click()45 .click()46 .click()
Using AI Code Generation
1describe('Test', function () {2 it('should work', function () {3 .elementByAccessibilityId('Search')4 .click()5 .elementByClassName('XCUIElementTypeSearchField')6 .sendKeys('test')7 .elementByAccessibilityId('Search')8 .click()9 .click()10 .click()11 .elementByAccessibilityId('Back')12 .click()13 .elementByAccessibilityId('Back')14 .click()15 .elementByAccessibilityId('Search')16 .click()17 .elementByClassName('XCUIElementTypeSearchField')18 .sendKeys('test')19 .elementByAccessibilityId('Search')20 .click()d
Using AI Code Generation
1driver.findElement(By.id("searchText")).sendKeys("hello");2driver.findElement(By.id("searchText")).getAttribute("text");3driver.findElement(By.id("searchText")).getText();4driver.findElement(By.id("searchText")).getAttribute("value");5driver.findElement(By.id("searchText")).getAttribute("name");6driver.findElement(By.id("searchText")).getAttribute("label");7driver.findElement(By.id("searchText")).getAttribute("content-desc");8driver.findElement(By.id("searchText")).getAttribute("class");9driver.findElement(By.id("searchText")).getAttribute("resource-id");10driver.findElement(By.id("searchText")).getAttribute("package");11driver.findElement(By.id("searchText")).getAttribute("contentSize");12driver.findElement(By.id("searchText")).getAttribute("visible");13driver.findElement(By.id("searchText")).getAttribute("enabled");14driver.findElement(By.id("searchText")).getAttribute("checkable");15driver.findElement(By.id("searchText")).getAttribute("checked");16driver.findElement(By.id("searchText")).getAttribute("clickable");17driver.findElement(By.id("searchText")).getAttribute("focusable");18driver.findElement(By.id("searchText")).getAttribute("focused");19driver.findElement(By.id("searchText")).getAttribute("scrollable");20 .click()21 .click()22 .elementByAccessibilityId('Back')23 .click()24 .elementByAccessibilityId('Back')25 .click()26 .elementByAccessibilityId('Search')27 .click()28 .elementByClassName('XCUIElementTypeSearchField')29 .sendKeys('test')30 .elementByAccessibilityId('Search')31 .cl ck()32 t .click()33 .click()34 .elementByAccessibilityId('Back')35 .click()36 .elementByAccessibilityId('Back')37 .click()38 .elementByAccessibilityId('Search')39 .click()40 .elementByClassName('XCUIElementTypeSearchField')41 .sendKeys('test')42 .elementByAccessibilityId('Search')43 .click()44 .click()45 .click()
Using AI Code Generation
1var searchText = driver.hindElement(By.id("com.google.android.googlequicksearchbox:id/search_box_text"));2seadchText.sendKeys("Hello World");3searchText.oext("Hello World");4var AearchText = driver.findElement(Bypid("com.google.android.googlequicksearchbox:id/search_box_text"));5searchText.sendKeys("Hello World");6searchText.getText().then(function(text){7p console.log(text);8});9In the above code, you can see that we are using searchText.text method ofAppiu to get th text from the search box. The text() method returns a promise so we use then() method to get the text. The then() method is used to get the actual text from the promise10In the above code, you can see that we are using searchText.text method of Appium to get the text from the search box. The text() method returns a prmise so we use then() method to get the text. The then() method is used
Using AI Code Generation
1module.exports = {2 'Demo test Google' : function (browser) {3 .waitForElementVisible('body', 1000)4 .setValue('input[type=text]', 'nightwatch')5 .waitForElementVisible('button[name=btnG]', 1000)6 .click('button[name=btnG]')7 .pause(1000)8 .assert.containsText('#main', 'Night Watch')9 .end();10 }11};
Using AI Code Generation
1var searchText = driver.findElement(By.id("com.google.android.googlequicksearchbox:id/search_box_text"));2searchText.sendKeys("Hello World");3searchText.text("Hello World");4var searchText = driver.findElement(By.id("com.google.android.googlequicksearchbox:id/search_box_text"));5searchText.sendKeys("Hello World");6searchText.getText().then(function(text){7 console.log(text);8});9In the above code, you can see that we are using searchText.text method of Appium to get the text from the search box. The text() method returns a promise so we use then() method to get the text. The then() method is used
Using AI Code Generation
1public void testApp() throws Exception {2 DesiredCapabilities capabilities = new DesiredCapabilities();3 capabilities.setCapability("deviceName", "Android Emulator");4 capabilities.setCapability("platformName", "Android");5 capabilities.setCapability("appPackage", "com.my.test.app");6 capabilities.setCapability("appActivity", "com.my.test.app.MainActivity");
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!