Răsfoiți Sursa

Merge pull request #111 from ckeditor/t/108a

t/108a: 	Implemented global module to create stubbable access to global DOM objects.
Piotrek Koszuliński 9 ani în urmă
părinte
comite
f735ce0564

+ 3 - 3
packages/ckeditor5-utils/src/dom/getpositionedancestor.js

@@ -3,12 +3,12 @@
  * For licensing, see LICENSE.md.
  */
 
-/* globals window */
-
 /**
  * @module utils/dom/getpositionedancestor
  */
 
+import global from './global.js';
+
 /**
  * For a given element, returns the nearest ancestor element which CSS position is not "static".
  *
@@ -17,7 +17,7 @@
  */
 export default function getPositionedAncestor( element ) {
 	while ( element && element.tagName.toLowerCase() != 'html' ) {
-		if ( window.getComputedStyle( element ).position != 'static' ) {
+		if ( global.window.getComputedStyle( element ).position != 'static' ) {
 			return element;
 		}
 

+ 26 - 0
packages/ckeditor5-utils/src/dom/global.js

@@ -0,0 +1,26 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals window, document */
+
+/**
+ * @module utils/dom/global
+ */
+
+/**
+ * A helper (module) giving an access to the global DOM objects such as `window` and
+ * `document`. Accessing these objects using this helper allows easy and bulletproof
+ * testing, i.e. stubbing native properties:
+ *
+ *		import global from 'ckeditor5/utils/dom/global.js';
+ *
+ *		// This stub will work for any code using global module.
+ *		testUtils.sinon.stub( global, 'window', {
+ *			innerWidth: 10000
+ *		} );
+ *
+ *		console.log( global.window.innerWidth );
+ */
+export default { window, document };

+ 5 - 4
packages/ckeditor5-utils/src/dom/position.js

@@ -3,12 +3,11 @@
  * For licensing, see LICENSE.md.
  */
 
-/* globals window */
-
 /**
  * @module utils/dom/position
  */
 
+import global from './global.js';
 import Rect from './rect.js';
 import getPositionedAncestor from './getpositionedancestor.js';
 
@@ -215,9 +214,11 @@ function getBestPosition( positions, targetRect, elementRect, limiterRect, viewp
 // @param {utils/dom/rect~Rect} rect A rect to be converted.
 // @returns {Object} Object containing `left` and `top` properties, in absolute coordinates.
 function getAbsoluteRectCoordinates( { left, top } ) {
+	const { scrollX, scrollY } = global.window;
+
 	return {
-		left: left + window.scrollX,
-		top: top + window.scrollY,
+		left: left + scrollX,
+		top: top + scrollY,
 	};
 }
 

+ 2 - 3
packages/ckeditor5-utils/src/dom/rect.js

@@ -3,12 +3,11 @@
  * For licensing, see LICENSE.md.
  */
 
-/* global window */
-
 /**
  * @module utils/dom/rect
  */
 
+import global from './global.js';
 import isRange from './isrange.js';
 import isElement from '../../utils/lib/lodash/isElement.js';
 
@@ -186,7 +185,7 @@ export default class Rect {
 	 * @returns {module:utils/dom/rect~Rect} A viewport rect.
 	 */
 	static getViewportRect() {
-		const { innerWidth, innerHeight } = window;
+		const { innerWidth, innerHeight } = global.window;
 
 		return new Rect( {
 			top: 0,

+ 47 - 0
packages/ckeditor5-utils/tests/dom/global.js

@@ -0,0 +1,47 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* global window, document */
+
+import global from 'ckeditor5/utils/dom/global.js';
+import testUtils from 'tests/core/_utils/utils.js';
+
+testUtils.createSinonSandbox();
+
+describe( 'global', () => {
+	describe( 'global', () => {
+		describe( 'window', () => {
+			it( 'equals native DOM window', () => {
+				expect( global.window ).to.equal( window );
+			} );
+
+			it( 'stubs', () => {
+				testUtils.sinon.stub( global, 'window', {
+					scrollX: 100
+				} );
+
+				expect( global.window ).to.deep.equal( {
+					scrollX: 100
+				} );
+			} );
+		} );
+
+		describe( 'document', () => {
+			it( 'equals native DOM document', () => {
+				expect( global.document ).to.equal( document );
+			} );
+
+			it( 'stubs', () => {
+				testUtils.sinon.stub( global, 'document', {
+					foo: 'abc'
+				} );
+
+				expect( global.document ).to.deep.equal( {
+					foo: 'abc'
+				} );
+			} );
+		} );
+	} );
+} );

+ 26 - 33
packages/ckeditor5-utils/tests/dom/position.js

@@ -5,31 +5,24 @@
 
 /* global document, window */
 
+import global from 'ckeditor5/utils/dom/global.js';
 import { getOptimalPosition } from 'ckeditor5/utils/dom/position.js';
-import Rect from 'ckeditor5/utils/dom/rect.js';
 import testUtils from 'tests/core/_utils/utils.js';
 
 testUtils.createSinonSandbox();
 
-let element, target, limiter, revertWindowScroll;
+let element, target, limiter, windowStub;
 
 describe( 'getOptimalPosition', () => {
 	beforeEach( () => {
-		// Give us a lot of space.
-		testUtils.sinon.stub( Rect, 'getViewportRect' ).returns( new Rect( {
-			top: 0,
-			right: 10000,
-			bottom: 10000,
-			left: 0,
-			width: 10000,
-			height: 10000
-		} ) );
-	} );
-
-	afterEach( () => {
-		if ( revertWindowScroll ) {
-			revertWindowScroll();
-		}
+		windowStub = {
+			innerWidth: 10000,
+			innerHeight: 10000,
+			scrollX: 0,
+			scrollY: 0
+		};
+
+		testUtils.sinon.stub( global, 'window', windowStub );
 	} );
 
 	describe( 'for single position', () => {
@@ -44,7 +37,12 @@ describe( 'getOptimalPosition', () => {
 		} );
 
 		it( 'should return coordinates (window scroll)', () => {
-			stubWindowScroll( 100, 100 );
+			Object.assign( windowStub, {
+				innerWidth: 10000,
+				innerHeight: 10000,
+				scrollX: 100,
+				scrollY: 100,
+			} );
 
 			assertPosition( { element, target, positions: [ attachLeft ] }, {
 				top: 200,
@@ -55,7 +53,16 @@ describe( 'getOptimalPosition', () => {
 
 		it( 'should return coordinates (positioned element parent)', () => {
 			const positionedParent = document.createElement( 'div' );
-			stubWindowScroll( 1000, 1000 );
+
+			Object.assign( windowStub, {
+				innerWidth: 10000,
+				innerHeight: 10000,
+				scrollX: 1000,
+				scrollY: 1000,
+				getComputedStyle: ( el ) => {
+					return window.getComputedStyle( el );
+				}
+			} );
 
 			Object.assign( positionedParent.style, {
 				position: 'absolute',
@@ -313,20 +320,6 @@ const attachTop = ( targetRect, elementRect ) => ( {
 	name: 'bottom'
 } );
 
-function stubWindowScroll( x, y ) {
-	const { scrollX: savedX, scrollY: savedY } = window;
-
-	window.scrollX = x;
-	window.scrollY = y;
-
-	revertWindowScroll = () => {
-		window.scrollX = savedX;
-		window.scrollY = savedY;
-
-		revertWindowScroll = null;
-	};
-}
-
 function stubElementRect( element, rect ) {
 	if ( element.getBoundingClientRect.restore ) {
 		element.getBoundingClientRect.restore();

+ 8 - 5
packages/ckeditor5-utils/tests/dom/rect.js

@@ -3,8 +3,9 @@
  * For licensing, see LICENSE.md.
  */
 
-/* global document, window */
+/* global document */
 
+import global from 'ckeditor5/utils/dom/global.js';
 import Rect from 'ckeditor5/utils/dom/rect.js';
 import testUtils from 'tests/core/_utils/utils.js';
 
@@ -325,10 +326,12 @@ describe( 'Rect', () => {
 		} );
 
 		it( 'should return the viewport\'s rect', () => {
-			window.scrollX = 100;
-			window.scrollY = 200;
-			window.innerWidth = 1000;
-			window.innerHeight = 500;
+			testUtils.sinon.stub( global, 'window', {
+				innerWidth: 1000,
+				innerHeight: 500,
+				scrollX: 100,
+				scrollY: 200
+			} );
 
 			assertRect( Rect.getViewportRect(), {
 				top: 0,