Parcourir la source

Tests: Added unit tests for DropdownView panel positioning (static and 'auto').

Aleksander Nowodzinski il y a 7 ans
Parent
commit
43a26ddc6b

+ 8 - 0
packages/ckeditor5-ui/tests/dropdown/dropdownpanelview.js

@@ -50,6 +50,14 @@ describe( 'DropdownPanelView', () => {
 					view.isVisible = false;
 					expect( view.element.classList.contains( 'ck-dropdown__panel-visible' ) ).to.be.false;
 				} );
+
+				it( 'reacts on view#position', () => {
+					expect( view.element.classList.contains( 'ck-dropdown__panel_se' ) ).to.be.true;
+
+					view.position = 'nw';
+					expect( view.element.classList.contains( 'ck-dropdown__panel_se' ) ).to.be.false;
+					expect( view.element.classList.contains( 'ck-dropdown__panel_nw' ) ).to.be.true;
+				} );
 			} );
 
 			describe( 'listeners', () => {

+ 124 - 0
packages/ckeditor5-ui/tests/dropdown/dropdownview.js

@@ -9,10 +9,15 @@ import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
 import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
 import ButtonView from '../../src/button/buttonview';
 import DropdownPanelView from '../../src/dropdown/dropdownpanelview';
+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';
 
 describe( 'DropdownView', () => {
 	let view, buttonView, panelView, locale;
 
+	testUtils.createSinonSandbox();
+
 	beforeEach( () => {
 		locale = { t() {} };
 
@@ -21,6 +26,15 @@ describe( 'DropdownView', () => {
 
 		view = new DropdownView( locale, buttonView, panelView );
 		view.render();
+
+		// The #panelView positioning depends on the utility that uses DOM Rects.
+		// To avoid an avalanche of warnings (DOM Rects do not work until
+		// the element is in DOM), let's allow the dropdown to render in DOM.
+		global.document.body.appendChild( view.element );
+	} );
+
+	afterEach( () => {
+		view.element.remove();
 	} );
 
 	describe( 'constructor()', () => {
@@ -44,6 +58,10 @@ describe( 'DropdownView', () => {
 			expect( view.isEnabled ).to.be.true;
 		} );
 
+		it( 'sets view#panelPosition "auto"', () => {
+			expect( view.panelPosition ).to.equal( 'auto' );
+		} );
+
 		it( 'creates #focusTracker instance', () => {
 			expect( view.focusTracker ).to.be.instanceOf( FocusTracker );
 		} );
@@ -97,6 +115,103 @@ describe( 'DropdownView', () => {
 				} );
 			} );
 
+			describe( 'view.panelView#position to view#panelPosition', () => {
+				it( 'does not update until the dropdown is opened', () => {
+					view.isOpen = false;
+					view.panelPosition = 'nw';
+
+					expect( panelView.position ).to.equal( 'se' );
+
+					view.isOpen = true;
+
+					expect( panelView.position ).to.equal( 'nw' );
+				} );
+
+				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
+						} );
+
+						view.isOpen = true;
+
+						expect( panelView.position ).to.equal( 'se' );
+					} );
+
+					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
+						} );
+
+						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' );
+					} );
+				} );
+			} );
+
 			describe( 'DOM element bindings', () => {
 				describe( 'class', () => {
 					it( 'reacts on view#isEnabled', () => {
@@ -258,3 +373,12 @@ describe( 'DropdownView', () => {
 		} );
 	} );
 } );
+
+function stubElementClientRect( element, data ) {
+	const clientRect = Object.assign( {}, data );
+
+	clientRect.right = clientRect.left + clientRect.width;
+	clientRect.bottom = clientRect.top + clientRect.height;
+
+	testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( clientRect );
+}