@@ -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,94 @@ describe('MdSelect', () => {
918
931
919
932
} ) ;
920
933
934
+ describe ( 'limited space to open horizontally' , ( ) => {
935
+ beforeEach ( async ( ( ) => {
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' , async ( ( ) => {
941
+ select . style . left = '-100px' ;
942
+ trigger . click ( ) ;
943
+ fixture . detectChanges ( ) ;
944
+
945
+ fixture . whenStable ( ) . then ( ( ) => {
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
+
953
+ it ( 'should stay within the viewport when overflowing on the right in rtl' , async ( ( ) => {
954
+ dir . value = 'rtl' ;
955
+ select . style . left = '-100px' ;
956
+ trigger . click ( ) ;
957
+ fixture . detectChanges ( ) ;
958
+
959
+ fixture . whenStable ( ) . then ( ( ) => {
960
+ const panelLeft = document . querySelector ( '.mat-select-panel' )
961
+ . getBoundingClientRect ( ) . left ;
962
+
963
+ expect ( panelLeft ) . toBeGreaterThan ( 0 ,
964
+ `Expected select panel to be inside the viewport in rtl.` ) ;
965
+ } ) ;
966
+ } ) ) ;
967
+
968
+ it ( 'should stay within the viewport when overflowing on the right in ltr' , async ( ( ) => {
969
+ select . style . right = '-100px' ;
970
+ trigger . click ( ) ;
971
+ fixture . detectChanges ( ) ;
972
+
973
+ fixture . whenStable ( ) . then ( ( ) => {
974
+ const viewportRect = fakeViewportRuler . getViewportRect ( ) . right ;
975
+ const panelRight = document . querySelector ( '.mat-select-panel' )
976
+ . getBoundingClientRect ( ) . right ;
977
+
978
+ expect ( viewportRect - panelRight ) . toBeGreaterThan ( 0 ,
979
+ `Expected select panel to be inside the viewport in ltr.` ) ;
980
+ } ) ;
981
+ } ) ) ;
982
+
983
+ it ( 'should stay within the viewport when overflowing on the right in rtl' , async ( ( ) => {
984
+ dir . value = 'rtl' ;
985
+ select . style . right = '-100px' ;
986
+ trigger . click ( ) ;
987
+ fixture . detectChanges ( ) ;
988
+
989
+ fixture . whenStable ( ) . then ( ( ) => {
990
+ const viewportRect = fakeViewportRuler . getViewportRect ( ) . right ;
991
+ const panelRight = document . querySelector ( '.mat-select-panel' )
992
+ . getBoundingClientRect ( ) . right ;
993
+
994
+ expect ( viewportRect - panelRight ) . toBeGreaterThan ( 0 ,
995
+ `Expected select panel to be inside the viewport in rtl.` ) ;
996
+ } ) ;
997
+ } ) ) ;
998
+
999
+ it ( 'should keep the position within the viewport on repeat openings' , async ( ( ) => {
1000
+ select . style . left = '-100px' ;
1001
+ trigger . click ( ) ;
1002
+ fixture . detectChanges ( ) ;
1003
+
1004
+ let panelLeft = document . querySelector ( '.mat-select-panel' ) . getBoundingClientRect ( ) . left ;
1005
+
1006
+ expect ( panelLeft ) . toBeGreaterThan ( 0 , `Expected select panel to be inside the viewport.` ) ;
1007
+
1008
+ fixture . componentInstance . select . close ( ) ;
1009
+ fixture . detectChanges ( ) ;
1010
+
1011
+ fixture . whenStable ( ) . then ( ( ) => {
1012
+ trigger . click ( ) ;
1013
+ fixture . detectChanges ( ) ;
1014
+ panelLeft = document . querySelector ( '.mat-select-panel' ) . getBoundingClientRect ( ) . left ;
1015
+
1016
+ expect ( panelLeft ) . toBeGreaterThan ( 0 ,
1017
+ `Expected select panel continue being inside the viewport.` ) ;
1018
+ } ) ;
1019
+ } ) ) ;
1020
+ } ) ;
1021
+
921
1022
describe ( 'when scrolled' , ( ) => {
922
1023
923
1024
// Need to set the scrollTop two different ways to support
@@ -1072,8 +1173,8 @@ describe('MdSelect', () => {
1072
1173
trigger = multiFixture . debugElement . query ( By . css ( '.mat-select-trigger' ) ) . nativeElement ;
1073
1174
select = multiFixture . debugElement . query ( By . css ( 'md-select' ) ) . nativeElement ;
1074
1175
1075
- select . style . marginLeft = '20px ' ;
1076
- select . style . marginRight = '20px ' ;
1176
+ select . style . marginLeft = '60px ' ;
1177
+ select . style . marginRight = '60px ' ;
1077
1178
} ) ;
1078
1179
1079
1180
it ( 'should adjust for the checkbox in ltr' , async ( ( ) => {
@@ -2024,15 +2125,3 @@ class BasicSelectInitiallyHidden {
2024
2125
`
2025
2126
} )
2026
2127
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