Explorar el Código

Tests: Added tests for LabeledInputVIew#infoText. Code refactoring in the LabeledInputView class.

Aleksander Nowodzinski hace 7 años
padre
commit
01df5f9950

+ 49 - 31
packages/ckeditor5-ui/src/labeledinput/labeledinputview.js

@@ -28,7 +28,7 @@ export default class LabeledInputView extends View {
 		super( locale );
 
 		const inputUid = `ck-input-${ uid() }`;
-		const errorUid = `ck-error-${ uid() }`;
+		const statusUid = `ck-status-${ uid() }`;
 
 		/**
 		 * The text of the label.
@@ -73,20 +73,19 @@ export default class LabeledInputView extends View {
 		this.set( 'errorText', null );
 
 		/**
-		 * TODO
+		 * The additional information text displayed next to the {@link #inputView} which can
+		 * be used to inform the user about the purpose of the input, provide help or hints.
 		 *
-		 * @observable
-		 * @member {String|null} #tipText
-		 */
-		this.set( 'tipText', null );
-
-		/**
-		 * TODO
+		 * Set it to `null` to hide the message.
+		 *
+		 * **Note:** This text will be displayed in the same place as {@link #errorText} but the
+		 * later always takes precedence: if the {@link #hasError} is `true`, the info text
+		 * is replaced by {@link #errorText} for as long as the value of the input is invalid.
 		 *
 		 * @observable
 		 * @member {String|null} #infoText
 		 */
-		this.bind( 'infoText' ).to( this, 'errorText', this, 'tipText', ( errorText, tipText ) => errorText || tipText );
+		this.set( 'infoText', null );
 
 		/**
 		 * The label view.
@@ -100,14 +99,33 @@ export default class LabeledInputView extends View {
 		 *
 		 * @member {module:ui/inputtext/inputtextview~InputTextView} #inputView
 		 */
-		this.inputView = this._createInputView( InputView, inputUid, errorUid );
+		this.inputView = this._createInputView( InputView, inputUid, statusUid );
 
 		/**
-		 * The info view for the {@link #inputView}.
+		 * The status view for the {@link #inputView}. It displays {@link #errorText} and
+		 * {@link #infoText}.
 		 *
-		 * @member {module:ui/view~View} #infoView
+		 * @member {module:ui/view~View} #statusView
+		 */
+		this.statusView = this._createStatusView( statusUid );
+
+		/**
+		 * The combined status text made of {@link #errorText} and {@link #infoText}.
+		 * Note that when present, {@link #errorText} always takes precedence in the
+		 * status.
+		 *
+		 * @see #errorText
+		 * @see #infoText
+		 * @see #statusView
+		 * @private
+		 * @observable
+		 * @member {String|null} #statusText
 		 */
-		this.infoView = this._createInfoView( errorUid );
+		this.bind( '_statusText' ).to(
+			this, 'errorText',
+			this, 'infoText',
+			( errorText, infoText ) => errorText || infoText
+		);
 
 		const bind = this.bindTemplate;
 
@@ -123,7 +141,7 @@ export default class LabeledInputView extends View {
 			children: [
 				this.labelView,
 				this.inputView,
-				this.infoView
+				this.statusView
 			]
 		} );
 	}
@@ -150,14 +168,14 @@ export default class LabeledInputView extends View {
 	 * @private
 	 * @param {Function} InputView Input view constructor.
 	 * @param {String} inputUid Unique id to set as inputView#id attribute.
-	 * @param {String} errorUid Unique id of the error for the input's `aria-describedby` attribute.
+	 * @param {String} statusUid Unique id of the status for the input's `aria-describedby` attribute.
 	 * @returns {module:ui/inputtext/inputtextview~InputTextView}
 	 */
-	_createInputView( InputView, inputUid, errorUid ) {
-		const inputView = new InputView( this.locale, errorUid );
+	_createInputView( InputView, inputUid, statusUid ) {
+		const inputView = new InputView( this.locale, statusUid );
 
 		inputView.id = inputUid;
-		inputView.ariaDesribedById = errorUid;
+		inputView.ariaDesribedById = statusUid;
 		inputView.bind( 'value' ).to( this );
 		inputView.bind( 'isReadOnly' ).to( this );
 		inputView.bind( 'hasError' ).to( this, 'errorText', value => !!value );
@@ -172,36 +190,36 @@ export default class LabeledInputView extends View {
 	}
 
 	/**
-	 * Creates the error view instance.
+	 * Creates the status view instance. It displays {@link #errorText} and {@link #infoText}
+	 * next to the {@link #inputView}. See {@link _statusText}.
 	 *
 	 * @private
-	 * @param {String} errorUid Unique id of the error, shared with the input's `aria-describedby` attribute.
+	 * @param {String} statusUid Unique id of the status, shared with the input's `aria-describedby` attribute.
 	 * @returns {module:ui/view~View}
 	 */
-	_createInfoView( errorUid ) {
-		const infoView = new View( this.locale );
+	_createStatusView( statusUid ) {
+		const statusView = new View( this.locale );
 		const bind = this.bindTemplate;
 
-		infoView.setTemplate( {
+		statusView.setTemplate( {
 			tag: 'div',
 			attributes: {
 				class: [
 					'ck',
-					'ck-labeled-input__info',
-					bind.if( 'errorText', 'ck-labeled-input__info_error' ),
-					bind.if( 'tipText', 'ck-labeled-input__info_tip' ),
-					bind.if( 'infoText', 'ck-hidden', value => !value )
+					'ck-labeled-input__status',
+					bind.if( 'errorText', 'ck-labeled-input__status_error' ),
+					bind.if( '_statusText', 'ck-hidden', value => !value )
 				],
-				id: errorUid
+				id: statusUid
 			},
 			children: [
 				{
-					text: bind.to( 'infoText' )
+					text: bind.to( '_statusText' )
 				}
 			]
 		} );
 
-		return infoView;
+		return statusView;
 	}
 
 	/**

+ 35 - 15
packages/ckeditor5-ui/tests/labeledinput/labeledinputview.js

@@ -28,6 +28,10 @@ describe( 'LabeledInputView', () => {
 			expect( view.errorText ).to.be.null;
 		} );
 
+		it( 'should set view#infoText', () => {
+			expect( view.infoText ).to.be.null;
+		} );
+
 		it( 'should create view#inputView', () => {
 			expect( view.inputView ).to.instanceOf( InputView );
 		} );
@@ -36,20 +40,20 @@ describe( 'LabeledInputView', () => {
 			expect( view.labelView ).to.instanceOf( LabelView );
 		} );
 
-		it( 'should create view#errorView', () => {
-			expect( view.errorView ).to.instanceOf( View );
+		it( 'should create view#statusView', () => {
+			expect( view.statusView ).to.instanceOf( View );
 
-			expect( view.errorView.element.tagName ).to.equal( 'DIV' );
-			expect( view.errorView.element.classList.contains( 'ck' ) ).to.be.true;
-			expect( view.errorView.element.classList.contains( 'ck-labeled-input__error' ) ).to.be.true;
+			expect( view.statusView.element.tagName ).to.equal( 'DIV' );
+			expect( view.statusView.element.classList.contains( 'ck' ) ).to.be.true;
+			expect( view.statusView.element.classList.contains( 'ck-labeled-input__status' ) ).to.be.true;
 		} );
 
 		it( 'should pair #inputView and #labelView by unique id', () => {
 			expect( view.labelView.for ).to.equal( view.inputView.id );
 		} );
 
-		it( 'should pair #inputView and #errorView by unique id', () => {
-			expect( view.inputView.ariaDesribedById ).to.equal( view.errorView.element.id );
+		it( 'should pair #inputView and #statusView by unique id', () => {
+			expect( view.inputView.ariaDesribedById ).to.equal( view.statusView.element.id );
 		} );
 	} );
 
@@ -67,8 +71,8 @@ describe( 'LabeledInputView', () => {
 			expect( view.template.children[ 1 ] ).to.equal( view.inputView );
 		} );
 
-		it( 'should have the error container', () => {
-			expect( view.template.children[ 2 ] ).to.equal( view.errorView );
+		it( 'should have the status container', () => {
+			expect( view.template.children[ 2 ] ).to.equal( view.statusView );
 		} );
 
 		describe( 'DOM bindings', () => {
@@ -82,17 +86,33 @@ describe( 'LabeledInputView', () => {
 				} );
 			} );
 
-			describe( 'error container', () => {
+			describe( 'status container', () => {
 				it( 'should react on view#errorText', () => {
-					const errorContainer = view.element.lastChild;
+					const statusElement = view.statusView.element;
 
 					view.errorText = '';
-					expect( errorContainer.classList.contains( 'ck-hidden' ) ).to.be.true;
-					expect( errorContainer.innerHTML ).to.equal( '' );
+					expect( statusElement.classList.contains( 'ck-hidden' ) ).to.be.true;
+					expect( statusElement.classList.contains( 'ck-labeled-input__status_error' ) ).to.be.false;
+					expect( statusElement.innerHTML ).to.equal( '' );
 
 					view.errorText = 'foo';
-					expect( errorContainer.classList.contains( 'ck-hidden' ) ).to.be.false;
-					expect( errorContainer.innerHTML ).to.equal( 'foo' );
+					expect( statusElement.classList.contains( 'ck-hidden' ) ).to.be.false;
+					expect( statusElement.classList.contains( 'ck-labeled-input__status_error' ) ).to.be.true;
+					expect( statusElement.innerHTML ).to.equal( 'foo' );
+				} );
+
+				it( 'should react on view#infoText', () => {
+					const statusElement = view.statusView.element;
+
+					view.infoText = '';
+					expect( statusElement.classList.contains( 'ck-hidden' ) ).to.be.true;
+					expect( statusElement.classList.contains( 'ck-labeled-input__status_error' ) ).to.be.false;
+					expect( statusElement.innerHTML ).to.equal( '' );
+
+					view.infoText = 'foo';
+					expect( statusElement.classList.contains( 'ck-hidden' ) ).to.be.false;
+					expect( statusElement.classList.contains( 'ck-labeled-input__status_error' ) ).to.be.false;
+					expect( statusElement.innerHTML ).to.equal( 'foo' );
 				} );
 			} );
 		} );