@@ -24,9 +24,22 @@ import {dispatchFakeEvent} from '../core/testing/dispatch-events';
24
24
import { wrappedErrorMessage } from '../core/testing/wrapped-error-message' ;
25
25
26
26
27
+ class FakeViewportRuler {
28
+ getViewportRect ( ) {
29
+ return {
30
+ left : 0 , top : 0 , width : 1014 , height : 686 , bottom : 686 , right : 1014
31
+ } ;
32
+ }
33
+
34
+ getViewportScrollPosition ( ) {
35
+ return { top : 0 , left : 0 } ;
36
+ }
37
+ }
38
+
27
39
describe ( 'MdSelect' , ( ) => {
28
40
let overlayContainerElement : HTMLElement ;
29
41
let dir : { value : 'ltr' | 'rtl' } ;
42
+ let fakeViewportRuler = new FakeViewportRuler ( ) ;
30
43
31
44
beforeEach ( async ( ( ) => {
32
45
TestBed . configureTestingModule ( {
@@ -67,7 +80,7 @@ describe('MdSelect', () => {
67
80
{ provide : Dir , useFactory : ( ) => {
68
81
return dir = { value : 'ltr' } ;
69
82
} } ,
70
- { provide : ViewportRuler , useClass : FakeViewportRuler }
83
+ { provide : ViewportRuler , useValue : fakeViewportRuler }
71
84
]
72
85
} ) ;
73
86
@@ -918,6 +931,91 @@ describe('MdSelect', () => {
918
931
919
932
} ) ;
920
933
934
+ describe ( 'limited space to open horizontally' , ( ) => {
935
+ beforeEach ( ( ) => {
936
+ select . style . position = 'absolute' ;
937
+ select . style . top = '200px' ;
938
+ } ) ;
939
+
940
+ it ( 'should stay within the viewport when overflowing on the left in ltr' , fakeAsync ( ( ) => {
941
+ select . style . left = '-100px' ;
942
+ trigger . click ( ) ;
943
+ tick ( 400 ) ;
944
+ fixture . detectChanges ( ) ;
945
+
946
+ const panelLeft = document . querySelector ( '.mat-select-panel' )
947
+ . getBoundingClientRect ( ) . left ;
948
+ expect ( panelLeft ) . toBeGreaterThan ( 0 ,
949
+ `Expected select panel to be inside the viewport in ltr.` ) ;
950
+ } ) ) ;
951
+
952
+ it ( 'should stay within the viewport when overflowing on the left in rtl' , fakeAsync ( ( ) => {
953
+ dir . value = 'rtl' ;
954
+ select . style . left = '-100px' ;
955
+ trigger . click ( ) ;
956
+ tick ( 400 ) ;
957
+ fixture . detectChanges ( ) ;
958
+
959
+ const panelLeft = document . querySelector ( '.mat-select-panel' )
960
+ . getBoundingClientRect ( ) . left ;
961
+
962
+ expect ( panelLeft ) . toBeGreaterThan ( 0 ,
963
+ `Expected select panel to be inside the viewport in rtl.` ) ;
964
+ } ) ) ;
965
+
966
+ it ( 'should stay within the viewport when overflowing on the right in ltr' , fakeAsync ( ( ) => {
967
+ select . style . right = '-100px' ;
968
+ trigger . click ( ) ;
969
+ tick ( 400 ) ;
970
+ fixture . detectChanges ( ) ;
971
+
972
+ const viewportRect = fakeViewportRuler . getViewportRect ( ) . right ;
973
+ const panelRight = document . querySelector ( '.mat-select-panel' )
974
+ . getBoundingClientRect ( ) . right ;
975
+
976
+ expect ( viewportRect - panelRight ) . toBeGreaterThan ( 0 ,
977
+ `Expected select panel to be inside the viewport in ltr.` ) ;
978
+ } ) ) ;
979
+
980
+ it ( 'should stay within the viewport when overflowing on the right in rtl' , fakeAsync ( ( ) => {
981
+ dir . value = 'rtl' ;
982
+ select . style . right = '-100px' ;
983
+ trigger . click ( ) ;
984
+ tick ( 400 ) ;
985
+ fixture . detectChanges ( ) ;
986
+
987
+ const viewportRect = fakeViewportRuler . getViewportRect ( ) . right ;
988
+ const panelRight = document . querySelector ( '.mat-select-panel' )
989
+ . getBoundingClientRect ( ) . right ;
990
+
991
+ expect ( viewportRect - panelRight ) . toBeGreaterThan ( 0 ,
992
+ `Expected select panel to be inside the viewport in rtl.` ) ;
993
+ } ) ) ;
994
+
995
+ it ( 'should keep the position within the viewport on repeat openings' , async ( ( ) => {
996
+ select . style . left = '-100px' ;
997
+ trigger . click ( ) ;
998
+ fixture . detectChanges ( ) ;
999
+
1000
+ let panelLeft = document . querySelector ( '.mat-select-panel' ) . getBoundingClientRect ( ) . left ;
1001
+
1002
+ expect ( panelLeft ) . toBeGreaterThan ( 0 , `Expected select panel to be inside the viewport.` ) ;
1003
+
1004
+ fixture . componentInstance . select . close ( ) ;
1005
+ fixture . detectChanges ( ) ;
1006
+
1007
+ fixture . whenStable ( ) . then ( ( ) => {
1008
+ trigger . click ( ) ;
1009
+ fixture . detectChanges ( ) ;
1010
+ panelLeft = document . querySelector ( '.mat-select-panel' ) . getBoundingClientRect ( ) . left ;
1011
+
1012
+ expect ( panelLeft ) . toBeGreaterThan ( 0 ,
1013
+ `Expected select panel continue being inside the viewport.` ) ;
1014
+ } ) ;
1015
+ } ) ) ;
1016
+
1017
+ } ) ;
1018
+
921
1019
describe ( 'when scrolled' , ( ) => {
922
1020
923
1021
// Need to set the scrollTop two different ways to support
@@ -1024,42 +1122,38 @@ describe('MdSelect', () => {
1024
1122
select . style . marginRight = '30px' ;
1025
1123
} ) ;
1026
1124
1027
- it ( 'should align the trigger and the selected option on the x-axis in ltr' , async ( ( ) => {
1125
+ it ( 'should align the trigger and the selected option on the x-axis in ltr' , fakeAsync ( ( ) => {
1028
1126
trigger . click ( ) ;
1127
+ tick ( 400 ) ;
1029
1128
fixture . detectChanges ( ) ;
1030
1129
1031
- fixture . whenStable ( ) . then ( ( ) => {
1032
- const triggerLeft = trigger . getBoundingClientRect ( ) . left ;
1033
- const firstOptionLeft = document . querySelector ( '.cdk-overlay-pane md-option' )
1034
- . getBoundingClientRect ( ) . left ;
1130
+ const triggerLeft = trigger . getBoundingClientRect ( ) . left ;
1131
+ const firstOptionLeft = document . querySelector ( '.cdk-overlay-pane md-option' )
1132
+ . getBoundingClientRect ( ) . left ;
1035
1133
1036
- // Each option is 32px wider than the trigger, so it must be adjusted 16px
1037
- // to ensure the text overlaps correctly.
1038
- expect ( firstOptionLeft . toFixed ( 2 ) ) . toEqual ( ( triggerLeft - 16 ) . toFixed ( 2 ) ,
1039
- `Expected trigger to align with the selected option on the x-axis in LTR.` ) ;
1040
- } ) ;
1134
+ // Each option is 32px wider than the trigger, so it must be adjusted 16px
1135
+ // to ensure the text overlaps correctly.
1136
+ expect ( firstOptionLeft . toFixed ( 2 ) ) . toEqual ( ( triggerLeft - 16 ) . toFixed ( 2 ) ,
1137
+ `Expected trigger to align with the selected option on the x-axis in LTR.` ) ;
1041
1138
} ) ) ;
1042
1139
1043
- it ( 'should align the trigger and the selected option on the x-axis in rtl' , async ( ( ) => {
1140
+ it ( 'should align the trigger and the selected option on the x-axis in rtl' , fakeAsync ( ( ) => {
1044
1141
dir . value = 'rtl' ;
1045
- fixture . whenStable ( ) . then ( ( ) => {
1046
- fixture . detectChanges ( ) ;
1142
+ fixture . detectChanges ( ) ;
1047
1143
1048
- trigger . click ( ) ;
1049
- fixture . detectChanges ( ) ;
1144
+ trigger . click ( ) ;
1145
+ tick ( 400 ) ;
1146
+ fixture . detectChanges ( ) ;
1050
1147
1051
- fixture . whenStable ( ) . then ( ( ) => {
1052
- const triggerRight = trigger . getBoundingClientRect ( ) . right ;
1053
- const firstOptionRight =
1054
- document . querySelector ( '.cdk-overlay-pane md-option' ) . getBoundingClientRect ( ) . right ;
1055
-
1056
- // Each option is 32px wider than the trigger, so it must be adjusted 16px
1057
- // to ensure the text overlaps correctly.
1058
- expect ( firstOptionRight . toFixed ( 2 ) )
1059
- . toEqual ( ( triggerRight + 16 ) . toFixed ( 2 ) ,
1060
- `Expected trigger to align with the selected option on the x-axis in RTL.` ) ;
1061
- } ) ;
1062
- } ) ;
1148
+ const triggerRight = trigger . getBoundingClientRect ( ) . right ;
1149
+ const firstOptionRight =
1150
+ document . querySelector ( '.cdk-overlay-pane md-option' ) . getBoundingClientRect ( ) . right ;
1151
+
1152
+ // Each option is 32px wider than the trigger, so it must be adjusted 16px
1153
+ // to ensure the text overlaps correctly.
1154
+ expect ( firstOptionRight . toFixed ( 2 ) )
1155
+ . toEqual ( ( triggerRight + 16 ) . toFixed ( 2 ) ,
1156
+ `Expected trigger to align with the selected option on the x-axis in RTL.` ) ;
1063
1157
} ) ) ;
1064
1158
} ) ;
1065
1159
@@ -1072,8 +1166,8 @@ describe('MdSelect', () => {
1072
1166
trigger = multiFixture . debugElement . query ( By . css ( '.mat-select-trigger' ) ) . nativeElement ;
1073
1167
select = multiFixture . debugElement . query ( By . css ( 'md-select' ) ) . nativeElement ;
1074
1168
1075
- select . style . marginLeft = '20px ' ;
1076
- select . style . marginRight = '20px ' ;
1169
+ select . style . marginLeft = '60px ' ;
1170
+ select . style . marginRight = '60px ' ;
1077
1171
} ) ;
1078
1172
1079
1173
it ( 'should adjust for the checkbox in ltr' , async ( ( ) => {
@@ -1092,21 +1186,20 @@ describe('MdSelect', () => {
1092
1186
} ) ;
1093
1187
} ) ) ;
1094
1188
1095
- it ( 'should adjust for the checkbox in rtl' , async ( ( ) => {
1189
+ it ( 'should adjust for the checkbox in rtl' , fakeAsync ( ( ) => {
1096
1190
dir . value = 'rtl' ;
1097
1191
trigger . click ( ) ;
1192
+ tick ( 400 ) ;
1098
1193
multiFixture . detectChanges ( ) ;
1099
1194
1100
- multiFixture . whenStable ( ) . then ( ( ) => {
1101
- const triggerRight = trigger . getBoundingClientRect ( ) . right ;
1102
- const firstOptionRight =
1103
- document . querySelector ( '.cdk-overlay-pane md-option' ) . getBoundingClientRect ( ) . right ;
1195
+ const triggerRight = trigger . getBoundingClientRect ( ) . right ;
1196
+ const firstOptionRight =
1197
+ document . querySelector ( '.cdk-overlay-pane md-option' ) . getBoundingClientRect ( ) . right ;
1104
1198
1105
- // 48px accounts for the checkbox size, margin and the panel's padding.
1106
- expect ( firstOptionRight . toFixed ( 2 ) )
1107
- . toEqual ( ( triggerRight + 48 ) . toFixed ( 2 ) ,
1108
- `Expected trigger label to align along x-axis, accounting for the checkbox.` ) ;
1109
- } ) ;
1199
+ // 48px accounts for the checkbox size, margin and the panel's padding.
1200
+ expect ( firstOptionRight . toFixed ( 2 ) )
1201
+ . toEqual ( ( triggerRight + 48 ) . toFixed ( 2 ) ,
1202
+ `Expected trigger label to align along x-axis, accounting for the checkbox.` ) ;
1110
1203
} ) ) ;
1111
1204
} ) ;
1112
1205
@@ -2024,15 +2117,3 @@ class BasicSelectInitiallyHidden {
2024
2117
`
2025
2118
} )
2026
2119
class BasicSelectNoPlaceholder { }
2027
-
2028
- class FakeViewportRuler {
2029
- getViewportRect ( ) {
2030
- return {
2031
- left : 0 , top : 0 , width : 1014 , height : 686 , bottom : 686 , right : 1014
2032
- } ;
2033
- }
2034
-
2035
- getViewportScrollPosition ( ) {
2036
- return { top : 0 , left : 0 } ;
2037
- }
2038
- }
0 commit comments