33 * For licensing, see LICENSE.md.
44 */
55
6- /* global document, window */
7-
86import global from '../../src/dom/global' ;
97import { getOptimalPosition } from '../../src/dom/position' ;
10- import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils' ;
11-
12- testUtils . createSinonSandbox ( ) ;
138
14- let element , target , limiter , windowStub ;
9+ let element , target , limiter ;
1510
16- describe ( 'getOptimalPosition' , ( ) => {
11+ describe ( 'getOptimalPosition() ' , ( ) => {
1712 beforeEach ( ( ) => {
18- windowStub = {
13+ stubWindow ( {
1914 innerWidth : 10000 ,
2015 innerHeight : 10000 ,
2116 scrollX : 0 ,
2217 scrollY : 0
23- } ;
24-
25- testUtils . sinon . stub ( global , 'window' , windowStub ) ;
18+ } ) ;
2619 } ) ;
2720
2821 describe ( 'for single position' , ( ) => {
@@ -37,7 +30,7 @@ describe( 'getOptimalPosition', () => {
3730 } ) ;
3831
3932 it ( 'should return coordinates (window scroll)' , ( ) => {
40- Object . assign ( windowStub , {
33+ stubWindow ( {
4134 innerWidth : 10000 ,
4235 innerHeight : 10000 ,
4336 scrollX : 100 ,
@@ -51,41 +44,67 @@ describe( 'getOptimalPosition', () => {
5144 } ) ;
5245 } ) ;
5346
54- it ( 'should return coordinates (positioned element parent)' , ( ) => {
55- const positionedParent = document . createElement ( 'div' ) ;
56-
57- Object . assign ( windowStub , {
58- innerWidth : 10000 ,
59- innerHeight : 10000 ,
60- scrollX : 1000 ,
61- scrollY : 1000 ,
62- getComputedStyle : ( el ) => {
63- return window . getComputedStyle ( el ) ;
64- }
65- } ) ;
66-
67- Object . assign ( positionedParent . style , {
68- position : 'absolute' ,
69- top : '1000px' ,
70- left : '1000px'
47+ describe ( 'positioned element parent' , ( ) => {
48+ let parent ;
49+
50+ it ( 'should return coordinates' , ( ) => {
51+ stubWindow ( {
52+ innerWidth : 10000 ,
53+ innerHeight : 10000 ,
54+ scrollX : 1000 ,
55+ scrollY : 1000
56+ } ) ;
57+
58+ parent = getElement ( {
59+ top : 1000 ,
60+ right : 1010 ,
61+ bottom : 1010 ,
62+ left : 1000 ,
63+ width : 10 ,
64+ height : 10
65+ } , {
66+ position : 'absolute'
67+ } ) ;
68+
69+ element . parentElement = parent ;
70+
71+ assertPosition ( { element, target, positions : [ attachLeft ] } , {
72+ top : - 900 ,
73+ left : - 920 ,
74+ name : 'left'
75+ } ) ;
7176 } ) ;
7277
73- document . body . appendChild ( positionedParent ) ;
74- positionedParent . appendChild ( element ) ;
75-
76- stubElementRect ( positionedParent , {
77- top : 1000 ,
78- right : 1010 ,
79- bottom : 1010 ,
80- left : 1000 ,
81- width : 10 ,
82- height : 10
83- } ) ;
84-
85- assertPosition ( { element, target, positions : [ attachLeft ] } , {
86- top : - 900 ,
87- left : - 920 ,
88- name : 'left'
78+ it ( 'should return coordinates (scroll and border)' , ( ) => {
79+ stubWindow ( {
80+ innerWidth : 10000 ,
81+ innerHeight : 10000 ,
82+ scrollX : 1000 ,
83+ scrollY : 1000
84+ } ) ;
85+
86+ parent = getElement ( {
87+ top : 0 ,
88+ right : 10 ,
89+ bottom : 10 ,
90+ left : 0 ,
91+ width : 10 ,
92+ height : 10 ,
93+ scrollTop : 100 ,
94+ scrollLeft : 200
95+ } , {
96+ position : 'absolute' ,
97+ borderLeftWidth : '20px' ,
98+ borderTopWidth : '40px' ,
99+ } ) ;
100+
101+ element . parentElement = parent ;
102+
103+ assertPosition ( { element, target, positions : [ attachLeft ] } , {
104+ top : 160 ,
105+ left : 260 ,
106+ name : 'left'
107+ } ) ;
89108 } ) ;
90109 } ) ;
91110 } ) ;
@@ -252,7 +271,7 @@ describe( 'getOptimalPosition', () => {
252271 } ) ;
253272
254273 it ( 'should return the very first coordinates if limiter does not fit into the viewport' , ( ) => {
255- stubElementRect ( limiter , {
274+ limiter = getElement ( {
256275 top : - 100 ,
257276 right : - 80 ,
258277 bottom : - 80 ,
@@ -320,12 +339,41 @@ const attachTop = ( targetRect, elementRect ) => ( {
320339 name : 'bottom'
321340} ) ;
322341
323- function stubElementRect ( element , rect ) {
324- if ( element . getBoundingClientRect . restore ) {
325- element . getBoundingClientRect . restore ( ) ;
342+ // Returns a synthetic element.
343+ //
344+ // @private
345+ // @param {Object } properties A set of properties for the element.
346+ // @param {Object } styles A set of styles in `window.getComputedStyle()` format.
347+ function getElement ( properties = { } , styles = { } ) {
348+ const element = {
349+ tagName : 'div' ,
350+ scrollLeft : 0 ,
351+ scrollTop : 0
352+ } ;
353+
354+ Object . assign ( element , properties ) ;
355+
356+ if ( ! styles . borderLeftWidth ) {
357+ styles . borderLeftWidth = '0px' ;
358+ }
359+
360+ if ( ! styles . borderTopWidth ) {
361+ styles . borderTopWidth = '0px' ;
326362 }
327363
328- testUtils . sinon . stub ( element , 'getBoundingClientRect' ) . returns ( rect ) ;
364+ global . window . getComputedStyle . withArgs ( element ) . returns ( styles ) ;
365+
366+ return element ;
367+ }
368+
369+ // Stubs the window.
370+ //
371+ // @private
372+ // @param {Object } properties A set of properties the window should have.
373+ function stubWindow ( properties ) {
374+ global . window = Object . assign ( {
375+ getComputedStyle : sinon . stub ( )
376+ } , properties ) ;
329377}
330378
331379// <-- 100px ->
@@ -343,10 +391,7 @@ function stubElementRect( element, rect ) {
343391// |
344392//
345393function setElementTargetPlayground ( ) {
346- element = document . createElement ( 'div' ) ;
347- target = document . createElement ( 'div' ) ;
348-
349- stubElementRect ( element , {
394+ element = getElement ( {
350395 top : 0 ,
351396 right : 20 ,
352397 bottom : 20 ,
@@ -355,7 +400,7 @@ function setElementTargetPlayground() {
355400 height : 20
356401 } ) ;
357402
358- stubElementRect ( target , {
403+ target = getElement ( {
359404 top : 100 ,
360405 right : 110 ,
361406 bottom : 110 ,
@@ -387,11 +432,7 @@ function setElementTargetPlayground() {
387432//
388433//
389434function setElementTargetLimiterPlayground ( ) {
390- element = document . createElement ( 'div' ) ;
391- target = document . createElement ( 'div' ) ;
392- limiter = document . createElement ( 'div' ) ;
393-
394- stubElementRect ( element , {
435+ element = getElement ( {
395436 top : 0 ,
396437 right : 20 ,
397438 bottom : 20 ,
@@ -400,7 +441,7 @@ function setElementTargetLimiterPlayground() {
400441 height : 20
401442 } ) ;
402443
403- stubElementRect ( limiter , {
444+ limiter = getElement ( {
404445 top : 100 ,
405446 right : 10 ,
406447 bottom : 120 ,
@@ -409,7 +450,7 @@ function setElementTargetLimiterPlayground() {
409450 height : 20
410451 } ) ;
411452
412- stubElementRect ( target , {
453+ target = getElement ( {
413454 top : 100 ,
414455 right : 10 ,
415456 bottom : 110 ,
0 commit comments