@@ -815,6 +815,242 @@ describe("General", () => {
815815 . should ( "have.text" , resourceBundle . getText ( MULTIINPUT_SHOW_MORE_TOKENS . defaultText , 1 ) ) ;
816816 } )
817817 } ) ;
818+
819+ it ( "preselects items based on selectedValues property" , ( ) => {
820+ cy . mount (
821+ < MultiComboBox style = "width: 300px" selectedValues = { [ "al" , "en" ] } >
822+ < MultiComboBoxItem text = "Albania" value = "al" > </ MultiComboBoxItem >
823+ < MultiComboBoxItem text = "Denmark" value = "dk" > </ MultiComboBoxItem >
824+ < MultiComboBoxItem text = "England" value = "en" > </ MultiComboBoxItem >
825+ </ MultiComboBox >
826+ ) ;
827+
828+ cy . get ( "ui5-multi-combobox" )
829+ . should ( "have.attr" , "selected-values" , '["al","en"]' ) ;
830+
831+ cy . get ( "[ui5-mcb-item]" )
832+ . eq ( 0 )
833+ . should ( "be.selected" ) ;
834+
835+ cy . get ( "[ui5-mcb-item]" )
836+ . eq ( 2 )
837+ . should ( "be.selected" ) ;
838+
839+ cy . get ( "[ui5-multi-combobox]" )
840+ . as ( "mcb" )
841+ . shadow ( )
842+ . find ( "[ui5-tokenizer]" )
843+ . as ( "tokenizer" ) ;
844+
845+ cy . get ( "@tokenizer" )
846+ . find ( "[ui5-token]" )
847+ . should ( "have.length" , "2" ) ;
848+ } ) ;
849+
850+ it ( "updates selectedValues when a token is deleted" , ( ) => {
851+ cy . mount (
852+ < MultiComboBox style = "width: 300px" selectedValues = { [ "dk" , "en" ] } >
853+ < MultiComboBoxItem text = "Albania" value = "al" > </ MultiComboBoxItem >
854+ < MultiComboBoxItem text = "Denmark" value = "dk" > </ MultiComboBoxItem >
855+ < MultiComboBoxItem text = "England" value = "en" > </ MultiComboBoxItem >
856+ </ MultiComboBox >
857+ ) ;
858+
859+ cy . get ( "[ui5-mcb-item]" )
860+ . eq ( 1 )
861+ . should ( "be.selected" ) ;
862+
863+ cy . get ( "[ui5-mcb-item]" )
864+ . eq ( 2 )
865+ . should ( "be.selected" ) ;
866+
867+ cy . get ( "[ui5-multi-combobox]" )
868+ . as ( "mcb" )
869+ . shadow ( )
870+ . find ( "[ui5-tokenizer]" )
871+ . as ( "tokenizer" ) ;
872+
873+ cy . get ( "@tokenizer" )
874+ . find ( "[ui5-token]" )
875+ . eq ( 1 )
876+ . realClick ( ) ;
877+
878+ cy . realPress ( "Backspace" ) ;
879+
880+ cy . get ( "@tokenizer" )
881+ . find ( "[ui5-token]" )
882+ . should ( "have.length" , "1" ) ;
883+
884+ cy . get ( "[ui5-multi-combobox]" )
885+ . should ( "have.attr" , "selected-values" , '["dk"]' ) ;
886+ } ) ;
887+
888+ it ( "updates selectedValues when selecting items via checkbox" , ( ) => {
889+ cy . mount (
890+ < MultiComboBox style = "width: 300px" >
891+ < MultiComboBoxItem text = "Germany" value = "DE" > </ MultiComboBoxItem >
892+ < MultiComboBoxItem text = "France" value = "FR" > </ MultiComboBoxItem >
893+ < MultiComboBoxItem text = "Italy" value = "IT" > </ MultiComboBoxItem >
894+ < MultiComboBoxItem text = "United States" value = "US" > </ MultiComboBoxItem >
895+ </ MultiComboBox >
896+ ) ;
897+
898+ cy . get ( "[ui5-multi-combobox]" )
899+ . as ( "mcb" )
900+ . should ( "have.attr" , "selected-values" , '[]' ) ;
901+
902+ // Open the dropdown
903+ cy . get ( "@mcb" )
904+ . shadow ( )
905+ . find ( "[ui5-icon][name='slim-arrow-down']" )
906+ . realClick ( ) ;
907+
908+ // Select first item via checkbox
909+ cy . get ( "[ui5-mcb-item]" )
910+ . eq ( 0 )
911+ . shadow ( )
912+ . find ( "[ui5-checkbox]" )
913+ . realClick ( ) ;
914+
915+ cy . get ( "@mcb" )
916+ . should ( "have.attr" , "selected-values" , '["DE"]' ) ;
917+
918+ // Select second item via checkbox
919+ cy . get ( "[ui5-mcb-item]" )
920+ . eq ( 1 )
921+ . shadow ( )
922+ . find ( "[ui5-checkbox]" )
923+ . realClick ( ) ;
924+
925+ cy . get ( "@mcb" )
926+ . should ( "have.attr" , "selected-values" , '["DE","FR"]' ) ;
927+
928+ // Select third and fourth items
929+ cy . get ( "[ui5-mcb-item]" )
930+ . eq ( 2 )
931+ . shadow ( )
932+ . find ( "[ui5-checkbox]" )
933+ . realClick ( ) ;
934+
935+ cy . get ( "[ui5-mcb-item]" )
936+ . eq ( 3 )
937+ . shadow ( )
938+ . find ( "[ui5-checkbox]" )
939+ . realClick ( ) ;
940+
941+ cy . get ( "@mcb" )
942+ . should ( "have.attr" , "selected-values" , '["DE","FR","IT","US"]' ) ;
943+ } ) ;
944+
945+ it ( "selects correct items when selectedValues is set before items are added" , ( ) => {
946+ // First mount with selectedValues but no items
947+ cy . mount (
948+ < MultiComboBox id = "mcb-late-items" style = "width: 300px" selectedValues = { [ "FR" , "US" ] } />
949+ ) ;
950+
951+ cy . get ( "[ui5-multi-combobox]" )
952+ . as ( "mcb" )
953+ . should ( "have.attr" , "selected-values" , '["FR","US"]' ) ;
954+
955+ // No tokens yet since no items
956+ cy . get ( "@mcb" )
957+ . shadow ( )
958+ . find ( "[ui5-tokenizer]" )
959+ . find ( "[ui5-token]" )
960+ . should ( "have.length" , 0 ) ;
961+
962+ // Now add items dynamically
963+ cy . get ( "@mcb" ) . then ( $mcb => {
964+ const mcb = $mcb [ 0 ] ;
965+
966+ const items = [
967+ { text : "Germany" , value : "DE" } ,
968+ { text : "France" , value : "FR" } ,
969+ { text : "Italy" , value : "IT" } ,
970+ { text : "United States" , value : "US" } ,
971+ ] ;
972+
973+ items . forEach ( item => {
974+ const mcbItem = document . createElement ( "ui5-mcb-item" ) ;
975+ mcbItem . setAttribute ( "text" , item . text ) ;
976+ mcbItem . setAttribute ( "value" , item . value ) ;
977+ mcb . appendChild ( mcbItem ) ;
978+ } ) ;
979+ } ) ;
980+
981+ // Verify items with matching values are now selected
982+ cy . get ( "[ui5-mcb-item]" )
983+ . eq ( 1 ) // France
984+ . should ( "have.attr" , "selected" ) ;
985+
986+ cy . get ( "[ui5-mcb-item]" )
987+ . eq ( 3 ) // United States
988+ . should ( "have.attr" , "selected" ) ;
989+
990+ // Verify non-matching items are not selected
991+ cy . get ( "[ui5-mcb-item]" )
992+ . eq ( 0 ) // Germany
993+ . should ( "not.have.attr" , "selected" ) ;
994+
995+ cy . get ( "[ui5-mcb-item]" )
996+ . eq ( 2 ) // Italy
997+ . should ( "not.have.attr" , "selected" ) ;
998+
999+ // Verify tokens are created
1000+ cy . get ( "@mcb" )
1001+ . shadow ( )
1002+ . find ( "[ui5-tokenizer]" )
1003+ . find ( "[ui5-token]" )
1004+ . should ( "have.length" , 2 ) ;
1005+ } ) ;
1006+
1007+ it ( "updates selectedValues when selecting item via Enter key (typeahead)" , ( ) => {
1008+ cy . mount (
1009+ < MultiComboBox style = "width: 300px" >
1010+ < MultiComboBoxItem text = "Germany" value = "DE" > </ MultiComboBoxItem >
1011+ < MultiComboBoxItem text = "France" value = "FR" > </ MultiComboBoxItem >
1012+ < MultiComboBoxItem text = "Canada" value = "CA" > </ MultiComboBoxItem >
1013+ < MultiComboBoxItem text = "Japan" value = "JP" > </ MultiComboBoxItem >
1014+ </ MultiComboBox >
1015+ ) ;
1016+
1017+ cy . get ( "[ui5-multi-combobox]" )
1018+ . as ( "mcb" )
1019+ . should ( "have.attr" , "selected-values" , "[]" ) ;
1020+
1021+ // Type "Ca" to trigger typeahead for Canada
1022+ cy . get ( "@mcb" )
1023+ . shadow ( )
1024+ . find ( "input" )
1025+ . realClick ( )
1026+ . realType ( "Ca" ) ;
1027+
1028+ // Press Enter to select the autocompleted item
1029+ cy . realPress ( "Enter" ) ;
1030+
1031+ // Verify selectedValues is updated
1032+ cy . get ( "@mcb" )
1033+ . should ( "have.attr" , "selected-values" , '["CA"]' ) ;
1034+
1035+ // Verify token is created
1036+ cy . get ( "@mcb" )
1037+ . shadow ( )
1038+ . find ( "[ui5-tokenizer]" )
1039+ . find ( "[ui5-token]" )
1040+ . should ( "have.length" , 1 ) ;
1041+
1042+ // Type "Ja" to select Japan
1043+ cy . get ( "@mcb" )
1044+ . shadow ( )
1045+ . find ( "input" )
1046+ . realType ( "Ja" ) ;
1047+
1048+ cy . realPress ( "Enter" ) ;
1049+
1050+ // Verify selectedValues now has both values
1051+ cy . get ( "@mcb" )
1052+ . should ( "have.attr" , "selected-values" , '["CA","JP"]' ) ;
1053+ } ) ;
8181054} ) ;
8191055
8201056describe ( "MultiComboBox Truncated Tokens" , ( ) => {
@@ -2225,6 +2461,48 @@ describe("Event firing", () => {
22252461 cy . get ( "@valueStateChangeEvent" )
22262462 . should ( "have.been.calledTwice" ) ;
22272463 } ) ;
2464+
2465+ it ( "fires selection-change and updates selectedValues on token deletion" , ( ) => {
2466+ const selectionChangeSpy = cy . stub ( ) . as ( "selectionChangeSpy" ) ;
2467+ cy . mount (
2468+ < MultiComboBox style = "width: 300px" selectedValues = { [ "1" , "3" ] } onSelectionChange = { selectionChangeSpy } >
2469+ < MultiComboBoxItem text = "Item 1" value = "1" > </ MultiComboBoxItem >
2470+ < MultiComboBoxItem text = "Item 1" value = "2" > </ MultiComboBoxItem >
2471+ < MultiComboBoxItem text = "Item 1" value = "3" > </ MultiComboBoxItem >
2472+ </ MultiComboBox >
2473+ ) ;
2474+
2475+ cy . get ( "[ui5-multi-combobox]" )
2476+ . as ( "mcb" )
2477+ . shadow ( )
2478+ . find ( "[ui5-tokenizer]" )
2479+ . as ( "tokenizer" ) ;
2480+
2481+ cy . get ( "@tokenizer" )
2482+ . find ( "[ui5-token]" )
2483+ . eq ( 0 )
2484+ . realClick ( ) ;
2485+
2486+ cy . realPress ( "ArrowRight" ) ;
2487+ cy . get ( "@tokenizer" )
2488+ . find ( "[ui5-token]" )
2489+ . eq ( 1 )
2490+ . should ( "be.focused" ) ;
2491+
2492+ cy . realPress ( "Space" ) ;
2493+ cy . realPress ( "Backspace" ) ;
2494+
2495+ cy . get ( "@tokenizer" )
2496+ . should ( "be.empty" ) ;
2497+
2498+ cy . get ( "@selectionChangeSpy" )
2499+ . should ( "have.been.calledOnce" ) ;
2500+ cy . get ( "@selectionChangeSpy" ) . should ( 'have.been.calledWithMatch' , Cypress . sinon . match ( event => {
2501+ return event . detail . item === undefined ;
2502+ } ) ) ;
2503+ cy . get ( "[ui5-multi-combobox]" )
2504+ . should ( "have.attr" , "selected-values" , '[]' ) ;
2505+ } ) ;
22282506} ) ;
22292507
22302508describe ( "MultiComboBox RTL/LTR Arrow Navigation" , ( ) => {
0 commit comments