@@ -51,7 +51,8 @@ describe('select', function() {
5151 forEach ( this . actual . find ( 'option' ) , function ( option ) {
5252 optionGroup = option . parentNode . label || '' ;
5353 actualValues [ optionGroup ] = actualValues [ optionGroup ] || [ ] ;
54- actualValues [ optionGroup ] . push ( option . label ) ;
54+ // IE9 doesn't populate the label property from the text property like other browsers
55+ actualValues [ optionGroup ] . push ( option . label || option . text ) ;
5556 } ) ;
5657
5758 this . message = function ( ) {
@@ -433,6 +434,324 @@ describe('select', function() {
433434
434435 } ) ;
435436
437+
438+ describe ( 'selectController.hasOption' , function ( ) {
439+
440+ function compileRepeatedOptions ( ) {
441+ compile ( '<select ng-model="robot">' +
442+ '<option value="{{item.value}}" ng-repeat="item in robots">{{item.label}}</option>' +
443+ '</select>' ) ;
444+ }
445+
446+ function compileGroupedOptions ( ) {
447+ compile (
448+ '<select ng-model="mySelect">' +
449+ '<option ng-repeat="item in values">{{item.name}}</option>' +
450+ '<optgroup ng-repeat="group in groups" label="{{group.name}}">' +
451+ '<option ng-repeat="item in group.values">{{item.name}}</option>' +
452+ '</optgroup>' +
453+ '</select>' ) ;
454+ }
455+
456+ describe ( 'flat options' , function ( ) {
457+ it ( 'should return false for options shifted via ngRepeat' , function ( ) {
458+ scope . robots = [
459+ { value : 1 , label : 'c3p0' } ,
460+ { value : 2 , label : 'r2d2' }
461+ ] ;
462+
463+ compileRepeatedOptions ( ) ;
464+
465+ var selectCtrl = element . controller ( 'select' ) ;
466+
467+ scope . $apply ( function ( ) {
468+ scope . robots . shift ( ) ;
469+ } ) ;
470+
471+ expect ( selectCtrl . hasOption ( '1' ) ) . toBe ( false ) ;
472+ expect ( selectCtrl . hasOption ( '2' ) ) . toBe ( true ) ;
473+ } ) ;
474+
475+
476+ it ( 'should return false for options popped via ngRepeat' , function ( ) {
477+ scope . robots = [
478+ { value : 1 , label : 'c3p0' } ,
479+ { value : 2 , label : 'r2d2' }
480+ ] ;
481+
482+ compileRepeatedOptions ( ) ;
483+
484+ var selectCtrl = element . controller ( 'select' ) ;
485+
486+ scope . $apply ( function ( ) {
487+ scope . robots . pop ( ) ;
488+ } ) ;
489+
490+ expect ( selectCtrl . hasOption ( '1' ) ) . toBe ( true ) ;
491+ expect ( selectCtrl . hasOption ( '2' ) ) . toBe ( false ) ;
492+ } ) ;
493+
494+
495+ it ( 'should return true for options added via ngRepeat' , function ( ) {
496+ scope . robots = [
497+ { value : 2 , label : 'r2d2' }
498+ ] ;
499+
500+ compileRepeatedOptions ( ) ;
501+
502+ var selectCtrl = element . controller ( 'select' ) ;
503+
504+ scope . $apply ( function ( ) {
505+ scope . robots . unshift ( { value : 1 , label : 'c3p0' } ) ;
506+ } ) ;
507+
508+ expect ( selectCtrl . hasOption ( '1' ) ) . toBe ( true ) ;
509+ expect ( selectCtrl . hasOption ( '2' ) ) . toBe ( true ) ;
510+ } ) ;
511+
512+
513+ it ( 'should keep all the options when changing the model' , function ( ) {
514+
515+ compile ( '<select ng-model="mySelect"><option ng-repeat="o in [\'A\',\'B\',\'C\']">{{o}}</option></select>' ) ;
516+
517+ var selectCtrl = element . controller ( 'select' ) ;
518+
519+ scope . $apply ( function ( ) {
520+ scope . mySelect = 'C' ;
521+ } ) ;
522+
523+ expect ( selectCtrl . hasOption ( 'A' ) ) . toBe ( true ) ;
524+ expect ( selectCtrl . hasOption ( 'B' ) ) . toBe ( true ) ;
525+ expect ( selectCtrl . hasOption ( 'C' ) ) . toBe ( true ) ;
526+ expect ( element ) . toEqualSelectWithOptions ( { '' : [ 'A' , 'B' , 'C' ] } ) ;
527+ } ) ;
528+ } ) ;
529+
530+
531+ describe ( 'grouped options' , function ( ) {
532+
533+ it ( 'should be able to detect when elements move from a previous group' , function ( ) {
534+ scope . values = [ { name : 'A' } ] ;
535+ scope . groups = [
536+ {
537+ name : 'first' ,
538+ values : [
539+ { name : 'B' } ,
540+ { name : 'C' } ,
541+ { name : 'D' } ,
542+ ]
543+ } ,
544+ {
545+ name : 'second' ,
546+ values : [
547+ { name : 'E' }
548+ ]
549+ }
550+ ] ;
551+
552+ compileGroupedOptions ( ) ;
553+
554+ var selectCtrl = element . controller ( 'select' ) ;
555+
556+ scope . $apply ( function ( ) {
557+ var itemD = scope . groups [ 0 ] . values . pop ( ) ;
558+ scope . groups [ 1 ] . values . unshift ( itemD ) ;
559+ scope . values . shift ( ) ;
560+ } ) ;
561+
562+ expect ( selectCtrl . hasOption ( 'A' ) ) . toBe ( false ) ;
563+ expect ( selectCtrl . hasOption ( 'B' ) ) . toBe ( true ) ;
564+ expect ( selectCtrl . hasOption ( 'C' ) ) . toBe ( true ) ;
565+ expect ( selectCtrl . hasOption ( 'D' ) ) . toBe ( true ) ;
566+ expect ( selectCtrl . hasOption ( 'E' ) ) . toBe ( true ) ;
567+ expect ( element ) . toEqualSelectWithOptions ( { '' : [ '' ] , 'first' :[ 'B' , 'C' ] , 'second' : [ 'D' , 'E' ] } ) ;
568+ } ) ;
569+
570+
571+ it ( 'should be able to detect when elements move from a following group' , function ( ) {
572+ scope . values = [ { name : 'A' } ] ;
573+ scope . groups = [
574+ {
575+ name : 'first' ,
576+ values : [
577+ { name : 'B' } ,
578+ { name : 'C' } ,
579+ ]
580+ } ,
581+ {
582+ name : 'second' ,
583+ values : [
584+ { name : 'D' } ,
585+ { name : 'E' }
586+ ]
587+ }
588+ ] ;
589+
590+ compileGroupedOptions ( ) ;
591+
592+ var selectCtrl = element . controller ( 'select' ) ;
593+
594+ scope . $apply ( function ( ) {
595+ var itemD = scope . groups [ 1 ] . values . shift ( ) ;
596+ scope . groups [ 0 ] . values . push ( itemD ) ;
597+ scope . values . shift ( ) ;
598+ } ) ;
599+ expect ( selectCtrl . hasOption ( 'A' ) ) . toBe ( false ) ;
600+ expect ( selectCtrl . hasOption ( 'B' ) ) . toBe ( true ) ;
601+ expect ( selectCtrl . hasOption ( 'C' ) ) . toBe ( true ) ;
602+ expect ( selectCtrl . hasOption ( 'D' ) ) . toBe ( true ) ;
603+ expect ( selectCtrl . hasOption ( 'E' ) ) . toBe ( true ) ;
604+ expect ( element ) . toEqualSelectWithOptions ( { '' : [ '' ] , 'first' :[ 'B' , 'C' , 'D' ] , 'second' : [ 'E' ] } ) ;
605+ } ) ;
606+
607+
608+ it ( 'should be able to detect when an element is replaced with an element from a previous group' , function ( ) {
609+ scope . values = [ { name : 'A' } ] ;
610+ scope . groups = [
611+ {
612+ name : 'first' ,
613+ values : [
614+ { name : 'B' } ,
615+ { name : 'C' } ,
616+ { name : 'D' } ,
617+ ]
618+ } ,
619+ {
620+ name : 'second' ,
621+ values : [
622+ { name : 'E' } ,
623+ { name : 'F' }
624+ ]
625+ }
626+ ] ;
627+
628+ compileGroupedOptions ( ) ;
629+
630+ var selectCtrl = element . controller ( 'select' ) ;
631+
632+ scope . $apply ( function ( ) {
633+ var itemD = scope . groups [ 0 ] . values . pop ( ) ;
634+ scope . groups [ 1 ] . values . unshift ( itemD ) ;
635+ scope . groups [ 1 ] . values . pop ( ) ;
636+ } ) ;
637+ expect ( selectCtrl . hasOption ( 'A' ) ) . toBe ( true ) ;
638+ expect ( selectCtrl . hasOption ( 'B' ) ) . toBe ( true ) ;
639+ expect ( selectCtrl . hasOption ( 'C' ) ) . toBe ( true ) ;
640+ expect ( selectCtrl . hasOption ( 'D' ) ) . toBe ( true ) ;
641+ expect ( selectCtrl . hasOption ( 'E' ) ) . toBe ( true ) ;
642+ expect ( selectCtrl . hasOption ( 'F' ) ) . toBe ( false ) ;
643+ expect ( element ) . toEqualSelectWithOptions ( { '' : [ '' , 'A' ] , 'first' :[ 'B' , 'C' ] , 'second' : [ 'D' , 'E' ] } ) ;
644+ } ) ;
645+
646+
647+ it ( 'should be able to detect when element is replaced with an element from a following group' , function ( ) {
648+ scope . values = [ { name : 'A' } ] ;
649+ scope . groups = [
650+ {
651+ name : 'first' ,
652+ values : [
653+ { name : 'B' } ,
654+ { name : 'C' } ,
655+ ]
656+ } ,
657+ {
658+ name : 'second' ,
659+ values : [
660+ { name : 'D' } ,
661+ { name : 'E' }
662+ ]
663+ }
664+ ] ;
665+
666+ compileGroupedOptions ( ) ;
667+
668+ var selectCtrl = element . controller ( 'select' ) ;
669+
670+ scope . $apply ( function ( ) {
671+ scope . groups [ 0 ] . values . pop ( ) ;
672+ var itemD = scope . groups [ 1 ] . values . shift ( ) ;
673+ scope . groups [ 0 ] . values . push ( itemD ) ;
674+ } ) ;
675+ expect ( selectCtrl . hasOption ( 'A' ) ) . toBe ( true ) ;
676+ expect ( selectCtrl . hasOption ( 'B' ) ) . toBe ( true ) ;
677+ expect ( selectCtrl . hasOption ( 'C' ) ) . toBe ( false ) ;
678+ expect ( selectCtrl . hasOption ( 'D' ) ) . toBe ( true ) ;
679+ expect ( selectCtrl . hasOption ( 'E' ) ) . toBe ( true ) ;
680+ expect ( element ) . toEqualSelectWithOptions ( { '' : [ '' , 'A' ] , 'first' :[ 'B' , 'D' ] , 'second' : [ 'E' ] } ) ;
681+ } ) ;
682+
683+
684+ it ( 'should be able to detect when an element is removed' , function ( ) {
685+ scope . values = [ { name : 'A' } ] ;
686+ scope . groups = [
687+ {
688+ name : 'first' ,
689+ values : [
690+ { name : 'B' } ,
691+ { name : 'C' } ,
692+ ]
693+ } ,
694+ {
695+ name : 'second' ,
696+ values : [
697+ { name : 'D' } ,
698+ { name : 'E' }
699+ ]
700+ }
701+ ] ;
702+
703+ compileGroupedOptions ( ) ;
704+
705+ var selectCtrl = element . controller ( 'select' ) ;
706+
707+ scope . $apply ( function ( ) {
708+ scope . groups [ 1 ] . values . shift ( ) ;
709+ } ) ;
710+ expect ( selectCtrl . hasOption ( 'A' ) ) . toBe ( true ) ;
711+ expect ( selectCtrl . hasOption ( 'B' ) ) . toBe ( true ) ;
712+ expect ( selectCtrl . hasOption ( 'C' ) ) . toBe ( true ) ;
713+ expect ( selectCtrl . hasOption ( 'D' ) ) . toBe ( false ) ;
714+ expect ( selectCtrl . hasOption ( 'E' ) ) . toBe ( true ) ;
715+ expect ( element ) . toEqualSelectWithOptions ( { '' : [ '' , 'A' ] , 'first' :[ 'B' , 'C' ] , 'second' : [ 'E' ] } ) ;
716+ } ) ;
717+
718+
719+ it ( 'should be able to detect when a group is removed' , function ( ) {
720+ scope . values = [ { name : 'A' } ] ;
721+ scope . groups = [
722+ {
723+ name : 'first' ,
724+ values : [
725+ { name : 'B' } ,
726+ { name : 'C' } ,
727+ ]
728+ } ,
729+ {
730+ name : 'second' ,
731+ values : [
732+ { name : 'D' } ,
733+ { name : 'E' }
734+ ]
735+ }
736+ ] ;
737+
738+ compileGroupedOptions ( ) ;
739+
740+ var selectCtrl = element . controller ( 'select' ) ;
741+
742+ scope . $apply ( function ( ) {
743+ scope . groups . pop ( ) ;
744+ } ) ;
745+ expect ( selectCtrl . hasOption ( 'A' ) ) . toBe ( true ) ;
746+ expect ( selectCtrl . hasOption ( 'B' ) ) . toBe ( true ) ;
747+ expect ( selectCtrl . hasOption ( 'C' ) ) . toBe ( true ) ;
748+ expect ( selectCtrl . hasOption ( 'D' ) ) . toBe ( false ) ;
749+ expect ( selectCtrl . hasOption ( 'E' ) ) . toBe ( false ) ;
750+ expect ( element ) . toEqualSelectWithOptions ( { '' : [ '' , 'A' ] , 'first' :[ 'B' , 'C' ] } ) ;
751+ } ) ;
752+ } ) ;
753+ } ) ;
754+
436755 describe ( 'select-multiple' , function ( ) {
437756
438757 it ( 'should support type="select-multiple"' , function ( ) {
0 commit comments