Index: src/wp-admin/css/dashboard.css
===================================================================
--- src/wp-admin/css/dashboard.css	(revision 39345)
+++ src/wp-admin/css/dashboard.css	(working copy)
@@ -518,6 +518,10 @@
 	resize: none;
 }
 
+#quick-press.is-saving .spinner {
+	visibility: inherit;
+}
+
 /* Dashboard Quick Draft - Drafts list */
 
 .js #dashboard_quick_press .drafts {
@@ -541,9 +545,68 @@
 	margin: 0 12px;
 }
 
+#dashboard_quick_press .drafts ul.is-placeholder li {
+	padding: 3px 0;
+	color: transparent;
+}
+
+@-webkit-keyframes loading-fade {
+
+	0% {
+		opacity: 0.5;
+	}
+
+	50% {
+		opacity: 1;
+	}
+
+	100% {
+		opacity: 0.5;
+	}
+}
+
+@keyframes loading-fade {
+
+	0% {
+		opacity: 0.5;
+	}
+
+	50% {
+		opacity: 1;
+	}
+
+	100% {
+		opacity: 0.5;
+	}
+}
+
+#dashboard_quick_press .drafts ul.is-placeholder li:before,
+#dashboard_quick_press .drafts ul.is-placeholder li:after {
+	content: "";
+	display: block;
+	height: 13px;
+	background: #eee;
+	-webkit-animation: loading-fade 1.6s ease-in-out infinite;
+	animation: loading-fade 1.6s ease-in-out infinite;
+}
+
+#dashboard_quick_press .drafts ul.is-placeholder li:before {
+	margin-bottom: 5px;
+	width: 40%;
+}
+
+#dashboard_quick_press .drafts ul.is-placeholder li:after {
+	width: 80%;
+}
+
 #dashboard_quick_press .drafts li {
 	margin-bottom: 1em;
 }
+
+#dashboard_quick_press .drafts li.is-new {
+	background-color: #fffbe5;
+}
+
 #dashboard_quick_press .drafts li time {
 	color: #72777c;
 }
Index: src/wp-admin/includes/dashboard.php
===================================================================
--- src/wp-admin/includes/dashboard.php	(revision 39345)
+++ src/wp-admin/includes/dashboard.php	(working copy)
@@ -50,6 +50,7 @@
 	if ( is_blog_admin() && current_user_can( get_post_type_object( 'post' )->cap->create_posts ) ) {
 		$quick_draft_title = sprintf( '<span class="hide-if-no-js">%1$s</span> <span class="hide-if-js">%2$s</span>', __( 'Quick Draft' ), __( 'Drafts' ) );
 		wp_add_dashboard_widget( 'dashboard_quick_press', $quick_draft_title, 'wp_dashboard_quick_press' );
+		add_action( 'admin_footer', 'wp_dashboard_print_recent_drafts_template' );
 	}
 
 	// WordPress News
@@ -494,46 +495,47 @@
 	$post_ID = (int) $post->ID;
 ?>
 
-	<form name="post" action="<?php echo esc_url( admin_url( 'post.php' ) ); ?>" method="post" id="quick-press" class="initial-form hide-if-no-js">
-
-		<?php if ( $error_msg ) : ?>
-		<div class="error"><?php echo $error_msg; ?></div>
-		<?php endif; ?>
-
+	<form name="post" method="post" id="quick-press" class="initial-form hide-if-no-js">
+		<div class="notice notice-info notice-alt inline" style="display: none;"><p></p></div>
 		<div class="input-text-wrap" id="title-wrap">
-			<label class="screen-reader-text prompt" for="title" id="title-prompt-text">
+			<label class="prompt" for="title" id="title-prompt-text">
 
 				<?php
 				/** This filter is documented in wp-admin/edit-form-advanced.php */
 				echo apply_filters( 'enter_title_here', __( 'Title' ), $post );
 				?>
 			</label>
-			<input type="text" name="post_title" id="title" autocomplete="off" />
+			<input type="text" name="title" id="title" autocomplete="off" />
 		</div>
 
 		<div class="textarea-wrap" id="description-wrap">
-			<label class="screen-reader-text prompt" for="content" id="content-prompt-text"><?php _e( 'What&#8217;s on your mind?' ); ?></label>
+			<label class="prompt" for="content" id="content-prompt-text"><?php _e( 'What&#8217;s on your mind?' ); ?></label>
 			<textarea name="content" id="content" class="mceEditor" rows="3" cols="15" autocomplete="off"></textarea>
 		</div>
-
 		<p class="submit">
-			<input type="hidden" name="action" id="quickpost-action" value="post-quickdraft-save" />
-			<input type="hidden" name="post_ID" value="<?php echo $post_ID; ?>" />
-			<input type="hidden" name="post_type" value="post" />
-			<?php wp_nonce_field( 'add-post' ); ?>
+			<div class="spinner no-float"></div>
 			<?php submit_button( __( 'Save Draft' ), 'primary', 'save', false, array( 'id' => 'save-post' ) ); ?>
 			<br class="clear" />
 		</p>
 
 	</form>
+	<div id="quick-press-drafts" class="drafts">
+		<p class="view-all" style="display: none;">
+			<a href="<?php echo esc_url( admin_url( 'edit.php?post_status=draft' ) ) ?>" aria-label="<?php esc_attr_e( 'View all drafts' ) ?>"><?php _ex( 'View all', 'drafts' ) ?></a>
+		</p>
+		<h2 class="hide-if-no-js"><?php _e( 'Drafts' ) ?></h2>
+		<ul class="drafts-list is-placeholder">
+			<li><span class="screen-reader-text"><?php _e( 'Loading&hellip;' ) ?></span></li>
+		</ul>
+	</div>
 	<?php
-	wp_dashboard_recent_drafts();
 }
 
 /**
  * Show recent drafts of the user on the dashboard.
  *
  * @since 2.7.0
+ * @deprecated 4.7
  *
  * @param array $drafts
  */
@@ -548,13 +550,7 @@
 			'order'          => 'DESC'
 		);
 
-		/**
-		 * Filters the post query arguments for the 'Recent Drafts' dashboard widget.
-		 *
-		 * @since 4.4.0
-		 *
-		 * @param array $query_args The query arguments for the 'Recent Drafts' dashboard widget.
-		 */
+		/** This filter is documented in wp-includes/rest-api.php */
 		$query_args = apply_filters( 'dashboard_recent_drafts_query_args', $query_args );
 
 		$drafts = get_posts( $query_args );
@@ -586,6 +582,25 @@
 }
 
 /**
+ * Get the HTML template for the Quick Draft recent posts.
+ *
+ * @since 4.7.0
+ *
+ * @return string The template HTML.
+ */
+function wp_dashboard_print_recent_drafts_template() {
+	?>
+	<script id="tmpl-item-quick-press-draft" type="text/template">
+		<div class="draft-title">
+			<a href="post.php?post={{ data.id }}&action=edit" aria-label="<?php esc_attr_e( 'Edit Post' ) ?>">{{ data.formattedTitle }}</a>
+			<time datetime="{{ data.date }}">{{ data.formattedDate }}</time>
+		</div>
+		{{{ data.formattedContent }}}
+	</script>
+	<?php
+}
+
+/**
  * Outputs a row for the Recent Comments widget.
  *
  * @access private
Index: src/wp-admin/js/dashboard.js
===================================================================
--- src/wp-admin/js/dashboard.js	(revision 39345)
+++ src/wp-admin/js/dashboard.js	(working copy)
@@ -1,5 +1,5 @@
-/* global pagenow, ajaxurl, postboxes, wpActiveEditor:true */
-var ajaxWidgets, ajaxPopulateWidgets, quickPressLoad;
+/* global _, wp, quickPress, pagenow, ajaxurl, postboxes, wpActiveEditor:true */
+var ajaxWidgets, ajaxPopulateWidgets, QuickPress = {};
 
 jQuery(document).ready( function($) {
 	var welcomePanel = $( '#welcome-panel' ),
@@ -59,69 +59,13 @@
 	};
 	ajaxPopulateWidgets();
 
-	postboxes.add_postbox_toggles(pagenow, { pbshow: ajaxPopulateWidgets } );
+	postboxes.add_postbox_toggles(pagenow, { pbshow: function( id ) {
+		ajaxPopulateWidgets();
 
-	/* QuickPress */
-	quickPressLoad = function() {
-		var act = $('#quickpost-action'), t;
-
-		$( '#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]' ).prop( 'disabled' , false );
-
-		t = $('#quick-press').submit( function( e ) {
-			e.preventDefault();
-			$('#dashboard_quick_press #publishing-action .spinner').show();
-			$('#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]').prop('disabled', true);
-
-			$.post( t.attr( 'action' ), t.serializeArray(), function( data ) {
-				// Replace the form, and prepend the published post.
-				$('#dashboard_quick_press .inside').html( data );
-				$('#quick-press').removeClass('initial-form');
-				quickPressLoad();
-				highlightLatestPost();
-				$('#title').focus();
-			});
-
-			function highlightLatestPost () {
-				var latestPost = $('.drafts ul li').first();
-				latestPost.css('background', '#fffbe5');
-				setTimeout(function () {
-					latestPost.css('background', 'none');
-				}, 1000);
-			}
-		} );
-
-		$('#publish').click( function() { act.val( 'post-quickpress-publish' ); } );
-
-		$('#title, #tags-input, #content').each( function() {
-			var input = $(this), prompt = $('#' + this.id + '-prompt-text');
-
-			if ( '' === this.value ) {
-				prompt.removeClass('screen-reader-text');
-			}
-
-			prompt.click( function() {
-				$(this).addClass('screen-reader-text');
-				input.focus();
-			});
-
-			input.blur( function() {
-				if ( '' === this.value ) {
-					prompt.removeClass('screen-reader-text');
-				}
-			});
-
-			input.focus( function() {
-				prompt.addClass('screen-reader-text');
-			});
-		});
-
-		$('#quick-press').on( 'click focusin', function() {
-			wpActiveEditor = 'content';
-		});
-
-		autoResizeTextarea();
-	};
-	quickPressLoad();
+		if ( 'dashboard_quick_press' === id ) {
+			QuickPress.init();
+		}
+	} } );
 
 	$( '.meta-box-sortables' ).sortable( 'option', 'containment', '#wpwrap' );
 
@@ -186,4 +130,229 @@
 		});
 	}
 
+	autoResizeTextarea();
+
+	if ( jQuery( '#dashboard_quick_press' ).is( ':visible' ) ) {
+		QuickPress.init();
+	}
+});
+
+/**
+ * Collections
+ */
+
+QuickPress.Views = {};
+
+QuickPress.Views.Form = wp.Backbone.View.extend( {
+	events: {
+		'click :input': 'hidePromptAndFocus',
+		'focus :input': 'hidePrompt',
+		'blur :input': 'showPrompt',
+		reset: 'showAllPrompts',
+		click: 'setActiveEditor',
+		focusin: 'setActiveEditor',
+		submit: 'submit'
+	},
+
+	initialize: function() {
+		this.showAllPrompts();
+
+		this.model.on( 'invalid', _.bind( this.render, this ) );
+		this.model.on( 'error',   _.bind( this.showSyncError, this ) );
+	},
+
+	togglePrompt: function( element, visible ) {
+		var $input = jQuery( element ),
+			hasContent = $input.val().length > 0;
+
+		jQuery( element ).siblings( '.prompt' ).toggleClass( 'screen-reader-text', ! visible || hasContent );
+	},
+
+	showAllPrompts: function() {
+		this.$el.find( ':input' ).each( _.bind( function( i, input ) {
+			// Prompt toggling must be deferred because the reset event is
+			// fired before the input values have been cleared
+			_.defer( _.bind( this.togglePrompt, this, input, true ) );
+		}, this ) );
+	},
+
+	showPrompt: function( event ) {
+		this.togglePrompt( event.target, true );
+	},
+
+	hidePrompt: function( event ) {
+		this.togglePrompt( event.target, false );
+	},
+
+	hidePromptAndFocus: function( event ) {
+		this.togglePrompt( event.target, false );
+		jQuery( ':input', event.target ).focus();
+	},
+
+	setActiveEditor: function() {
+		wpActiveEditor = 'content';
+	},
+
+	showSyncError: function( model, error ) {
+		try {
+			this.syncError = JSON.parse( error.responseText ).message;
+		} catch( e ) {
+			this.syncError = quickPress.l10n.error;
+		}
+
+		// Alert screen readers that an error occurred.
+		wp.a11y.speak( quickPress.l10n.error );
+
+		this.render();
+	},
+
+	submit: function( event ) {
+		var values;
+
+		delete this.syncError;
+		event.preventDefault();
+
+		// jQuery's serializeArray returns an array of field tuples, which
+		// we need to transform into an object before sending to API
+		values = _.reduce( this.$el.serializeArray(), function( memo, field ) {
+			memo[ field.name ] = field.value;
+			return memo;
+		}, {} );
+
+		// Ensure that by setting these fields on model that it is valid
+		// before proceeding with save
+		this.model.set( values );
+		if ( ! this.model.isValid() ) {
+			return;
+		}
+
+		// Show a spinner during the callback.
+		this.$el.addClass( 'is-saving' );
+
+		this.model.save()
+			.always( _.bind( function() {
+				this.$el.removeClass( 'is-saving' );
+			}, this ) )
+			.success( _.bind( function() {
+				this.collection.add( this.model, { at: 0 } );
+				this.model = new wp.api.models.Post();
+				this.el.reset();
+			}, this ) );
+	},
+
+	render: function() {
+		var $error = this.$el.find( '.notice-alt' ),
+			errorText;
+
+		if ( this.syncError ) {
+			// Error via API save failure
+			errorText = this.syncError;
+		}
+
+		// Error notice is only visible if error text determined
+		$error.toggle( !! errorText );
+		if ( errorText ) {
+			$error.html( jQuery( '<p />', { text: errorText } ) );
+		}
+	}
+} );
+
+QuickPress.Views.DraftList = wp.Backbone.View.extend( {
+
+	initialize: function() {
+		this.listenTo( this.collection, 'sync', this.onDraftsLoaded );
+	},
+
+	onDraftsLoaded: function() {
+		this.listenTo( this.collection, 'add', this.renderNew );
+		this.render();
+	},
+
+	renderNew: function() {
+
+		// Display highlight effect to first (added) item for one second
+		var $newEl = this.render().$el.find( 'li:first' ).addClass( 'is-new' );
+		setTimeout( function() {
+			$newEl.removeClass( 'is-new' );
+		}, 1000 );
+
+		// Alert screen readers that a new draft has been added.
+		wp.a11y.speak( quickPress.l10n.newDraftCreated );
+	},
+
+	render: function() {
+
+		// Hide drafts list if no drafts exist
+		this.$el.toggle( this.collection.length > 0 );
+
+		// Display a 'View All' link if there are more drafts available.
+		this.$el.find( '.view-all' ).toggle( this.collection.hasMore() );
+
+		// Remove the placeholder class and render the models.
+		this.$el.find( '.drafts-list' )
+			.removeClass( 'is-placeholder' )
+			.html( _.map( this.collection.models, function( draft ) {
+				return new QuickPress.Views.DraftListItem( {
+					model: draft
+				} ).render().el;
+			} ) );
+
+		return this;
+	}
 } );
+
+QuickPress.Views.DraftListItem = wp.Backbone.View.extend( {
+	tagName: 'li',
+
+	template: wp.template( 'item-quick-press-draft' ),
+
+	render: function() {
+		var attributes = _.clone( this.model.attributes );
+		attributes.formattedContent = wp.formatting.trimWords( attributes.content.rendered, 10 );
+		attributes.formattedTitle = attributes.title.rendered.length > 0 ? attributes.title.rendered : quickPress.l10n.noTitle;
+		// We can format dates using newer browser i18n features, but also
+		// provide a fallback to the not-as-nice Date#toLocaleDateString
+		var date = new Date( wp.api.utils.parseISO8601( attributes.date + quickPress.timezoneOffset ) );
+		if ( 'undefined' !== typeof Intl && Intl.DateTimeFormat ) {
+			attributes.formattedDate = new Intl.DateTimeFormat( undefined, {
+				month: 'long',
+				day: 'numeric',
+				year: 'numeric'
+			} ).format( date );
+		} else {
+			attributes.formattedDate = date.toLocaleDateString();
+		}
+
+		this.$el.html( this.template( attributes ) );
+
+		return this;
+	}
+} );
+
+QuickPress.init = function() {
+	wp.api.loadPromise.done( function() {
+		// Fetch drafts
+		var draftsCollection = new wp.api.collections.Posts();
+		draftsCollection.fetch( {
+			data: {
+				status: 'draft',
+				author: quickPress.currentUserId,
+				per_page: 4,
+				order_by: 'date',
+				'quick-draft-post-list': true
+			}
+		} );
+
+		// Drafts list is initialized but not rendered until drafts load
+		new QuickPress.Views.DraftList( {
+			el: '#quick-press-drafts',
+			collection: draftsCollection
+		} );
+
+		new QuickPress.Views.Form( {
+			el: '#quick-press',
+			model: new wp.api.models.Post(),
+			collection: draftsCollection
+		} ).render();
+	});
+};
Index: src/wp-includes/js/wp-util.js
===================================================================
--- src/wp-includes/js/wp-util.js	(revision 39345)
+++ src/wp-includes/js/wp-util.js	(working copy)
@@ -121,4 +121,50 @@
 		}
 	};
 
+	// wp.formatting
+	// ------
+	//
+	// Tools for formatting strings
+	wp.formatting = {
+		settings: settings.formatting || {},
+
+		/**
+		 * Trims text to a certain number of words.
+		 *
+		 * @see wp_trim_words
+		 *
+		 * @param  {string} text     Text to trim.
+		 * @param  {number} numWords Number of words. Optional, default is 55.
+		 * @param  {string} more     What to append if text needs to be trimmed. Optional, default is '…'.
+		 * @return {string}          Trimmed text.
+		 */
+		trimWords: function( text, numWords, more ) {
+			var words, separator;
+
+			if ( 'undefined' === typeof numWords ) {
+				numWords = 55;
+			}
+
+			if ( 'undefined' === typeof more ) {
+				more = wp.formatting.settings.trimWordsMore;
+			}
+
+			text = text.replace( /[\n\r\t ]+/g, ' ' ).replace( /^ | $/g, '' );
+
+			if ( wp.formatting.settings.trimWordsByCharacter ) {
+				separator = '';
+			} else {
+				separator = ' ';
+			}
+
+			words = text.split( separator );
+
+			if ( words.length <= numWords ) {
+				return words.join( separator );
+			}
+
+			return words.slice( 0, numWords ).join( separator ) + more;
+		}
+	};
+
 }(jQuery));
Index: src/wp-includes/rest-api.php
===================================================================
--- src/wp-includes/rest-api.php	(revision 39345)
+++ src/wp-includes/rest-api.php	(working copy)
@@ -164,6 +164,37 @@
 	add_filter( 'rest_post_dispatch', 'rest_send_allow_header', 10, 3 );
 
 	add_filter( 'rest_pre_dispatch', 'rest_handle_options_request', 10, 3 );
+
+	// Legacy filter for Quick Draft recent posts.
+	add_filter( 'rest_post_query', 'rest_filter_quick_draft_query', 10, 2 );
+}
+
+/**
+ * Filter query args used by he Quick Draft recent posts list.
+ *
+ * @param array           $args    Key value array of query var to query value.
+ * @param WP_REST_Request $request The request used.
+ */
+function rest_filter_quick_draft_query( $query_args, $request ) {
+
+	// Only modify Quick Draft queries.
+	$params = $request->get_query_params();
+
+	if ( ! isset( $params['quick-draft-post-list'] ) ) {
+		return $query_args;
+	}
+
+	/**
+	 * Filters the post query arguments for the 'Recent Drafts' dashboard widget.
+	 *
+	 * @since 4.4.0
+	 *
+	 * @param array $query_args The query arguments for the 'Recent Drafts' dashboard widget.
+	 */
+	$query_args = apply_filters( 'dashboard_recent_drafts_query_args', $query_args );
+
+	return $query_args;
+
 }
 
 /**
Index: src/wp-includes/script-loader.php
===================================================================
--- src/wp-includes/script-loader.php	(revision 39345)
+++ src/wp-includes/script-loader.php	(working copy)
@@ -336,6 +336,15 @@
 		'ajax' => array(
 			'url' => admin_url( 'admin-ajax.php', 'relative' ),
 		),
+		'formatting' => array(
+			'trimWordsMore'  => __( '&hellip;' ),
+			/*
+			 * translators: If your word count is based on single characters (e.g. East Asian characters),
+			 * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'.
+			 * Do not translate into your own language.
+			 */
+			'trimWordsByCharacter' => strpos( _x( 'words', 'Word count type. Do not translate!' ), 'characters' ) === 0 && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ),
+		),
 	) );
 
 	$scripts->add( 'wp-backbone', "/wp-includes/js/wp-backbone$suffix.js", array('backbone', 'wp-util'), false, 1 );
@@ -721,7 +730,16 @@
 			'current' => __( 'Current Color' ),
 		) );
 
-		$scripts->add( 'dashboard', "/wp-admin/js/dashboard$suffix.js", array( 'jquery', 'admin-comments', 'postbox' ), false, 1 );
+		$scripts->add( 'dashboard', "/wp-admin/js/dashboard$suffix.js", array( 'jquery', 'admin-comments', 'postbox', 'wp-api', 'wp-backbone', 'wp-a11y', 'wp-util' ), false, 1 );
+		did_action( 'init' ) && $scripts->localize( 'dashboard', 'quickPress', array(
+			'currentUserId'  => get_current_user_id(),
+			'l10n' => array(
+				'error'           => __( 'An error has occurred. Please reload the page and try again.' ),
+				'newDraftCreated' => __( 'Success. A new draft was created.' ),
+				'noTitle'         => __( '(no title)' ),
+			),
+			'timezoneOffset' => ( get_option( 'gmt_offset' ) >= 0 ? '+' : '-' ) . date( 'H:i', abs( get_option( 'gmt_offset' ) * 3600 ) ),
+		) );
 
 		$scripts->add( 'list-revisions', "/wp-includes/js/wp-list-revisions$suffix.js" );
 
Index: tests/qunit/index.html
===================================================================
--- tests/qunit/index.html	(revision 39345)
+++ tests/qunit/index.html	(working copy)
@@ -61,6 +61,7 @@
 		<script src="wp-admin/js/customize-base.js"></script>
 		<script src="wp-admin/js/customize-header.js"></script>
 		<script src="wp-includes/js/shortcode.js"></script>
+		<script src="wp-includes/js/wp-util.js"></script>
 		<script src="wp-admin/js/customize-controls.js"></script>
 		<script src="wp-admin/js/customize-controls-utils.js"></script>
 		<script src="wp-admin/js/customize-nav-menus.js"></script>
Index: tests/qunit/wp-includes/js/wp-util.js
===================================================================
--- tests/qunit/wp-includes/js/wp-util.js	(nonexistent)
+++ tests/qunit/wp-includes/js/wp-util.js	(working copy)
@@ -0,0 +1,40 @@
+( function( QUnit ) {
+	wp.formatting.settings.trimWordsMore = '&hellip;';
+	QUnit.module( 'wp-util' );
+	var longText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce varius lacinia vehicula. Etiam sapien risus, ultricies ac posuere eu, convallis sit amet augue. Pellentesque urna massa, lacinia vel iaculis eget, bibendum in mauris. Aenean eleifend pulvinar ligula, a convallis eros gravida non. Suspendisse potenti. Pellentesque et odio tortor. In vulputate pellentesque libero, sed dapibus velit mollis viverra. Pellentesque id urna euismod dolor cursus sagittis.';
+
+	QUnit.test( 'wp.formatting.trimWords', function( assert ) {
+		_.each( [
+			{
+				'trimmed': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce varius lacinia vehicula. Etiam sapien risus, ultricies ac posuere eu, convallis sit amet augue. Pellentesque urna massa, lacinia vel iaculis eget, bibendum in mauris. Aenean eleifend pulvinar ligula, a convallis eros gravida non. Suspendisse potenti. Pellentesque et odio tortor. In vulputate pellentesque libero, sed dapibus velit&hellip;',
+				'text': longText,
+				'description': 'Trims to 55 by default.'
+			},
+			{
+				'trimmed': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce varius&hellip;',
+				'text': longText,
+				'length': 10,
+				'description': 'Trims to 10.'
+			},
+			{
+				'trimmed': 'Lorem ipsum dolor sit amet,[...] Read on!',
+				'text': longText,
+				'description': 'Trims to 5 and uses custom more.',
+				'length': 5,
+				'more': '[...] Read on!'
+			},
+			{
+				'trimmed': 'This is some short text.',
+				'text': 'This is some short text.',
+				'description': 'Doesn\'t strip short text.',
+			}
+
+		], function( test ) {
+			assert.equal(
+				wp.formatting.trimWords( test.text, test.length, test.more ),
+				test.trimmed,
+				test.description
+			);
+		} );
+	} );
+} )( window.QUnit );
