@@ -12,7 +12,12 @@ import {
12
12
import { NoopAnimationsModule } from '@angular/platform-browser/animations' ;
13
13
import { MdSelectModule } from './index' ;
14
14
import { OverlayContainer } from '../core/overlay/overlay-container' ;
15
- import { MdSelect , MdSelectFloatPlaceholderType } from './select' ;
15
+ import {
16
+ MdSelect ,
17
+ MdSelectFloatPlaceholderType ,
18
+ SELECT_PANEL_EXTRA_WIDTH ,
19
+ SELECT_PANEL_VIEWPORT_PADDING ,
20
+ } from './select' ;
16
21
import { MdSelectDynamicMultipleError , MdSelectNonArrayValueError } from './select-errors' ;
17
22
import { MdOption } from '../core/option/option' ;
18
23
import { Dir } from '../core/rtl/dir' ;
@@ -24,9 +29,22 @@ import {dispatchFakeEvent} from '../core/testing/dispatch-events';
24
29
import { wrappedErrorMessage } from '../core/testing/wrapped-error-message' ;
25
30
26
31
27
- describe ( 'MdSelect' , ( ) => {
32
+ class FakeViewportRuler {
33
+ getViewportRect ( ) {
34
+ return {
35
+ left : 0 , top : 0 , width : 1014 , height : 686 , bottom : 686 , right : 1014
36
+ } ;
37
+ }
38
+
39
+ getViewportScrollPosition ( ) {
40
+ return { top : 0 , left : 0 } ;
41
+ }
42
+ }
43
+
44
+ fdescribe ( 'MdSelect' , ( ) => {
28
45
let overlayContainerElement : HTMLElement ;
29
46
let dir : { value : 'ltr' | 'rtl' } ;
47
+ let fakeViewportRuler = new FakeViewportRuler ( ) ;
30
48
31
49
beforeEach ( async ( ( ) => {
32
50
TestBed . configureTestingModule ( {
@@ -65,7 +83,7 @@ describe('MdSelect', () => {
65
83
{ provide : Dir , useFactory : ( ) => {
66
84
return dir = { value : 'ltr' } ;
67
85
} } ,
68
- { provide : ViewportRuler , useClass : FakeViewportRuler }
86
+ { provide : ViewportRuler , useValue : fakeViewportRuler }
69
87
]
70
88
} ) ;
71
89
@@ -882,6 +900,97 @@ describe('MdSelect', () => {
882
900
883
901
} ) ;
884
902
903
+ describe ( 'limited space to open horizontally' , ( ) => {
904
+ beforeEach ( ( ) => {
905
+ select . style . position = 'absolute' ;
906
+ select . style . top = '200px' ;
907
+ } ) ;
908
+
909
+ it ( 'should stay within the viewport when overflowing on the left in ltr' , async ( ( ) => {
910
+ select . style . left = '-75px' ;
911
+ trigger . click ( ) ;
912
+ fixture . detectChanges ( ) ;
913
+
914
+ fixture . whenStable ( ) . then ( ( ) => {
915
+ const panelLeft = document . querySelector ( '.mat-select-panel' )
916
+ . getBoundingClientRect ( ) . left ;
917
+ expect ( Math . round ( panelLeft ) ) . toBe ( SELECT_PANEL_VIEWPORT_PADDING ,
918
+ `Expected select panel to be inside the viewport in ltr.` ) ;
919
+ } ) ;
920
+ } ) ) ;
921
+
922
+ it ( 'should stay within the viewport when overflowing on the right in rtl' , async ( ( ) => {
923
+ dir . value = 'rtl' ;
924
+ select . style . left = '-75px' ;
925
+ trigger . click ( ) ;
926
+ fixture . detectChanges ( ) ;
927
+
928
+ fixture . whenStable ( ) . then ( ( ) => {
929
+ const panelLeft = document . querySelector ( '.mat-select-panel' )
930
+ . getBoundingClientRect ( ) . left ;
931
+ const targetLeft = SELECT_PANEL_VIEWPORT_PADDING + SELECT_PANEL_EXTRA_WIDTH ;
932
+
933
+ expect ( Math . round ( panelLeft ) ) . toBe ( targetLeft ,
934
+ `Expected select panel to be inside the viewport in rtl.` ) ;
935
+ } ) ;
936
+ } ) ) ;
937
+
938
+ it ( 'should stay within the viewport when overflowing on the right in ltr' , async ( ( ) => {
939
+ select . style . right = '-75px' ;
940
+ trigger . click ( ) ;
941
+ fixture . detectChanges ( ) ;
942
+
943
+ fixture . whenStable ( ) . then ( ( ) => {
944
+ const viewportRect = fakeViewportRuler . getViewportRect ( ) . right ;
945
+ const panelRight = document . querySelector ( '.mat-select-panel' )
946
+ . getBoundingClientRect ( ) . right ;
947
+ const targetRight = SELECT_PANEL_VIEWPORT_PADDING + SELECT_PANEL_EXTRA_WIDTH ;
948
+
949
+ expect ( viewportRect - Math . round ( panelRight ) ) . toBe ( targetRight ,
950
+ `Expected select panel to be inside the viewport in ltr.` ) ;
951
+ } ) ;
952
+ } ) ) ;
953
+
954
+ it ( 'should stay within the viewport when overflowing on the right in rtl' , async ( ( ) => {
955
+ dir . value = 'rtl' ;
956
+ select . style . right = '-75px' ;
957
+ trigger . click ( ) ;
958
+ fixture . detectChanges ( ) ;
959
+
960
+ fixture . whenStable ( ) . then ( ( ) => {
961
+ const viewportRect = fakeViewportRuler . getViewportRect ( ) . right ;
962
+ const panelRight = document . querySelector ( '.mat-select-panel' )
963
+ . getBoundingClientRect ( ) . right ;
964
+
965
+ expect ( viewportRect - Math . round ( panelRight ) ) . toBe ( SELECT_PANEL_VIEWPORT_PADDING ,
966
+ `Expected select panel to be inside the viewport in rtl.` ) ;
967
+ } ) ;
968
+ } ) ) ;
969
+
970
+ it ( 'should keep the position within the viewport on repeat openings' , async ( ( ) => {
971
+ select . style . left = '-75px' ;
972
+ trigger . click ( ) ;
973
+ fixture . detectChanges ( ) ;
974
+
975
+ let panelLeft = document . querySelector ( '.mat-select-panel' ) . getBoundingClientRect ( ) . left ;
976
+
977
+ expect ( Math . round ( panelLeft ) ) . toBe ( SELECT_PANEL_VIEWPORT_PADDING ,
978
+ `Expected select panel to be inside the viewport.` ) ;
979
+
980
+ fixture . componentInstance . select . close ( ) ;
981
+ fixture . detectChanges ( ) ;
982
+
983
+ fixture . whenStable ( ) . then ( ( ) => {
984
+ trigger . click ( ) ;
985
+ fixture . detectChanges ( ) ;
986
+ panelLeft = document . querySelector ( '.mat-select-panel' ) . getBoundingClientRect ( ) . left ;
987
+
988
+ expect ( Math . round ( panelLeft ) ) . toBe ( SELECT_PANEL_VIEWPORT_PADDING ,
989
+ `Expected select panel continue being inside the viewport.` ) ;
990
+ } ) ;
991
+ } ) ) ;
992
+ } ) ;
993
+
885
994
describe ( 'when scrolled' , ( ) => {
886
995
887
996
// Need to set the scrollTop two different ways to support
@@ -1030,8 +1139,8 @@ describe('MdSelect', () => {
1030
1139
trigger = multiFixture . debugElement . query ( By . css ( '.mat-select-trigger' ) ) . nativeElement ;
1031
1140
select = multiFixture . debugElement . query ( By . css ( 'md-select' ) ) . nativeElement ;
1032
1141
1033
- select . style . marginLeft = '20px ' ;
1034
- select . style . marginRight = '20px ' ;
1142
+ select . style . marginLeft = '50px ' ;
1143
+ select . style . marginRight = '50px ' ;
1035
1144
} ) ;
1036
1145
1037
1146
it ( 'should adjust for the checkbox in ltr' , ( ) => {
@@ -1956,16 +2065,3 @@ class SelectWithPlainTabindex { }
1956
2065
`
1957
2066
} )
1958
2067
class SelectEarlyAccessSibling { }
1959
-
1960
-
1961
- class FakeViewportRuler {
1962
- getViewportRect ( ) {
1963
- return {
1964
- left : 0 , top : 0 , width : 1014 , height : 686 , bottom : 686 , right : 1014
1965
- } ;
1966
- }
1967
-
1968
- getViewportScrollPosition ( ) {
1969
- return { top : 0 , left : 0 } ;
1970
- }
1971
- }
0 commit comments