Procházet zdrojové kódy

Tests: Added DropdownView panel positioning tests for LTR and RTL languages.

Aleksander Nowodzinski před 6 roky
rodič
revize
c27af5f82f

+ 9 - 1
packages/ckeditor5-ui/src/dropdown/dropdownview.js

@@ -253,7 +253,7 @@ export default class DropdownView extends View {
 			// If "auto", find the best position of the panel to fit into the viewport.
 			// If "auto", find the best position of the panel to fit into the viewport.
 			// Otherwise, simply assign the static position.
 			// Otherwise, simply assign the static position.
 			if ( this.panelPosition === 'auto' ) {
 			if ( this.panelPosition === 'auto' ) {
-				this.panelView.position = getOptimalPosition( {
+				this.panelView.position = DropdownView._getOptimalPosition( {
 					element: this.panelView.element,
 					element: this.panelView.element,
 					target: this.buttonView.element,
 					target: this.buttonView.element,
 					fitInViewport: true,
 					fitInViewport: true,
@@ -403,3 +403,11 @@ DropdownView.defaultPanelPositions = {
 		};
 		};
 	}
 	}
 };
 };
+
+/**
+ * A function used to calculate the optimal position for the dropdown panel.
+ *
+ * @protected
+ * @member {Function} module:ui/dropdown/dropdownview~DropdownView._getOptimalPosition
+ */
+DropdownView._getOptimalPosition = getOptimalPosition;

+ 88 - 82
packages/ckeditor5-ui/tests/dropdown/dropdownview.js

@@ -10,7 +10,6 @@ import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
 import ButtonView from '../../src/button/buttonview';
 import ButtonView from '../../src/button/buttonview';
 import DropdownPanelView from '../../src/dropdown/dropdownpanelview';
 import DropdownPanelView from '../../src/dropdown/dropdownpanelview';
 import global from '@ckeditor/ckeditor5-utils/src/dom/global';
 import global from '@ckeditor/ckeditor5-utils/src/dom/global';
-import Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 
 
 describe( 'DropdownView', () => {
 describe( 'DropdownView', () => {
@@ -19,7 +18,10 @@ describe( 'DropdownView', () => {
 	testUtils.createSinonSandbox();
 	testUtils.createSinonSandbox();
 
 
 	beforeEach( () => {
 	beforeEach( () => {
-		locale = { t() {} };
+		locale = {
+			languageDirection: 'ltr',
+			t() {}
+		};
 
 
 		buttonView = new ButtonView( locale );
 		buttonView = new ButtonView( locale );
 		panelView = new DropdownPanelView( locale );
 		panelView = new DropdownPanelView( locale );
@@ -116,7 +118,7 @@ describe( 'DropdownView', () => {
 			} );
 			} );
 
 
 			describe( 'view.panelView#position to view#panelPosition', () => {
 			describe( 'view.panelView#position to view#panelPosition', () => {
-				it( 'does not update until the dropdown is opened', () => {
+				it( 'does not update until the dropdown is open', () => {
 					view.isOpen = false;
 					view.isOpen = false;
 					view.panelPosition = 'nw';
 					view.panelPosition = 'nw';
 
 
@@ -128,86 +130,37 @@ describe( 'DropdownView', () => {
 				} );
 				} );
 
 
 				describe( 'in "auto" mode', () => {
 				describe( 'in "auto" mode', () => {
-					beforeEach( () => {
-						// Bloat the panel a little to give the positioning algorithm something to
-						// work with. If the panel was empty, any smart positioning is pointless.
-						// Placing an empty element in the viewport isn't that hard, right?
-						panelView.element.style.width = '200px';
-						panelView.element.style.height = '200px';
-					} );
-
-					it( 'defaults to "south-east" when there is a plenty of space around', () => {
-						const windowRect = new Rect( global.window );
-
-						// "Put" the dropdown in the middle of the viewport.
-						stubElementClientRect( view.buttonView.element, {
-							top: windowRect.height / 2,
-							left: windowRect.width / 2,
-							width: 10,
-							height: 10
-						} );
-
-						view.isOpen = true;
-
-						expect( panelView.position ).to.equal( 'se' );
-					} );
-
-					it( 'when the dropdown in the north-west corner of the viewport', () => {
-						stubElementClientRect( view.buttonView.element, {
-							top: 0,
-							left: 0,
-							width: 100,
-							height: 10
-						} );
+					it( 'uses _getOptimalPosition() and a dedicated set of positions (LTR)', () => {
+						const spy = testUtils.sinon.spy( DropdownView, '_getOptimalPosition' );
+						const { southEast, southWest, northEast, northWest } = DropdownView.defaultPanelPositions;
 
 
 						view.isOpen = true;
 						view.isOpen = true;
 
 
-						expect( panelView.position ).to.equal( 'se' );
+						sinon.assert.calledWithExactly( spy, sinon.match( {
+							element: panelView.element,
+							target: buttonView.element,
+							positions: [
+								southEast, southWest, northEast, northWest
+							],
+							fitInViewport: true
+						} ) );
 					} );
 					} );
 
 
-					it( 'when the dropdown in the north-east corner of the viewport', () => {
-						const windowRect = new Rect( global.window );
-
-						stubElementClientRect( view.buttonView.element, {
-							top: 0,
-							left: windowRect.right - 100,
-							width: 100,
-							height: 10
-						} );
+					it( 'uses _getOptimalPosition() and a dedicated set of positions (RTL)', () => {
+						const spy = testUtils.sinon.spy( DropdownView, '_getOptimalPosition' );
+						const { southEast, southWest, northEast, northWest } = DropdownView.defaultPanelPositions;
 
 
+						view.locale.languageDirection = 'rtl';
 						view.isOpen = true;
 						view.isOpen = true;
 
 
-						expect( panelView.position ).to.equal( 'sw' );
-					} );
-
-					it( 'when the dropdown in the south-west corner of the viewport', () => {
-						const windowRect = new Rect( global.window );
-
-						stubElementClientRect( view.buttonView.element, {
-							top: windowRect.bottom - 10,
-							left: 0,
-							width: 100,
-							height: 10
-						} );
-
-						view.isOpen = true;
-
-						expect( panelView.position ).to.equal( 'ne' );
-					} );
-
-					it( 'when the dropdown in the south-east corner of the viewport', () => {
-						const windowRect = new Rect( global.window );
-
-						stubElementClientRect( view.buttonView.element, {
-							top: windowRect.bottom - 10,
-							left: windowRect.right - 100,
-							width: 100,
-							height: 10
-						} );
-
-						view.isOpen = true;
-
-						expect( panelView.position ).to.equal( 'nw' );
+						sinon.assert.calledWithExactly( spy, sinon.match( {
+							element: panelView.element,
+							target: buttonView.element,
+							positions: [
+								southWest, southEast, northWest, northEast
+							],
+							fitInViewport: true
+						} ) );
 					} );
 					} );
 				} );
 				} );
 			} );
 			} );
@@ -372,13 +325,66 @@ describe( 'DropdownView', () => {
 			sinon.assert.calledOnce( spy );
 			sinon.assert.calledOnce( spy );
 		} );
 		} );
 	} );
 	} );
-} );
 
 
-function stubElementClientRect( element, data ) {
-	const clientRect = Object.assign( {}, data );
+	describe( 'DropdownView.defaultPanelPositions', () => {
+		let positions, buttonRect, panelRect;
+
+		beforeEach( () => {
+			positions = DropdownView.defaultPanelPositions;
+
+			buttonRect = {
+				top: 100,
+				bottom: 200,
+				left: 100,
+				right: 200,
+				width: 100,
+				height: 100
+			};
+
+			panelRect = {
+				top: 0,
+				bottom: 0,
+				left: 0,
+				right: 0,
+				width: 50,
+				height: 50
+			};
+		} );
+
+		it( 'should have a proper length', () => {
+			expect( Object.keys( positions ) ).to.have.length( 4 );
+		} );
+
+		it( 'should define the "southEast" position', () => {
+			expect( positions.southEast( buttonRect, panelRect ) ).to.deep.equal( {
+				top: 200,
+				left: 100,
+				name: 'se'
+			} );
+		} );
+
+		it( 'should define the "southWest" position', () => {
+			expect( positions.southWest( buttonRect, panelRect ) ).to.deep.equal( {
+				top: 200,
+				left: 150,
+				name: 'sw'
+			} );
+		} );
 
 
-	clientRect.right = clientRect.left + clientRect.width;
-	clientRect.bottom = clientRect.top + clientRect.height;
+		it( 'should define the "northEast" position', () => {
+			expect( positions.northEast( buttonRect, panelRect ) ).to.deep.equal( {
+				top: 50,
+				left: 100,
+				name: 'ne'
+			} );
+		} );
 
 
-	testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( clientRect );
-}
+		it( 'should define the "northWest" position', () => {
+			expect( positions.northWest( buttonRect, panelRect ) ).to.deep.equal( {
+				top: 150,
+				left: 150,
+				name: 'nw'
+			} );
+		} );
+	} );
+} );