diff --git a/src/wp-admin/css/dashboard.css b/src/wp-admin/css/dashboard.css
index ab73f828f7067..fc5d83bef6dc8 100644
--- a/src/wp-admin/css/dashboard.css
+++ b/src/wp-admin/css/dashboard.css
@@ -854,7 +854,7 @@ body #dashboard-widgets .postbox form .submit {
color: #646970;
}
-#dashboard_quick_press .drafts p {
+#dashboard_quick_press .drafts .draft-content {
margin: 0;
word-wrap: break-word;
}
diff --git a/src/wp-admin/includes/dashboard.php b/src/wp-admin/includes/dashboard.php
index 778e3de40326b..761e85f640ccd 100644
--- a/src/wp-admin/includes/dashboard.php
+++ b/src/wp-admin/includes/dashboard.php
@@ -586,6 +586,9 @@ function wp_dashboard_quick_press( $error_msg = false ) {
$error_msg,
array(
'additional_classes' => array( 'error' ),
+ 'attributes' => array(
+ 'role' => 'alert',
+ ),
)
);
}
@@ -688,7 +691,7 @@ function wp_dashboard_recent_drafts( $drafts = false ) {
$the_content = wp_trim_words( $draft->post_content, $draft_length );
if ( $the_content ) {
- echo '
' . $the_content . '
';
+ echo '' . $the_content . '
';
}
echo "\n";
}
diff --git a/src/wp-admin/post.php b/src/wp-admin/post.php
index dd7bad1bb3830..8341ac969559b 100644
--- a/src/wp-admin/post.php
+++ b/src/wp-admin/post.php
@@ -96,11 +96,23 @@
$_POST['comment_status'] = get_default_comment_status( $post->post_type );
$_POST['ping_status'] = get_default_comment_status( $post->post_type, 'pingback' );
- // Wrap Quick Draft content in the Paragraph block.
- if ( ! str_contains( $_POST['content'], '' ) ) {
+ $quickdraft_post_title = trim( $_POST['post_title'] );
+ $quickdraft_post_content = trim( $_POST['content'] );
+
+ if ( empty( $quickdraft_post_title ) && empty( $quickdraft_post_content ) ) {
+ return wp_dashboard_quick_press( __( 'Cannot create a draft post with empty title and content.' ) );
+ }
+
+ // Wrap Quick Draft content in a Paragraph block.
+ if (
+ use_block_editor_for_post_type( 'post' ) &&
+ ! empty( $quickdraft_post_content ) &&
+ ! str_contains( $quickdraft_post_content, '' )
+ ) {
+ // Note that `edit_post()` reads from the $_POST superglobal by reference.
$_POST['content'] = sprintf(
'%s',
- str_replace( array( "\r\n", "\r", "\n" ), '
', $_POST['content'] )
+ str_replace( array( "\r\n", "\r", "\n" ), '
', $quickdraft_post_content )
);
}
diff --git a/tests/e2e/specs/dashboard.test.js b/tests/e2e/specs/dashboard.test.js
index 90459ac83ae6f..09508f6622299 100644
--- a/tests/e2e/specs/dashboard.test.js
+++ b/tests/e2e/specs/dashboard.test.js
@@ -8,13 +8,13 @@ test.describe( 'Quick Draft', () => {
await requestUtils.deleteAllPosts();
} );
- test( 'Allows draft to be created with Title and Content', async ( {
+ test( 'should allow Quick Draft to be created with Title and Content', async ( {
admin,
page
} ) => {
await admin.visitAdminPage( '/' );
- // Wait for Quick Draft title field to appear.
+ // Wait for the Quick Draft title field to appear.
const draftTitleField = page.locator(
'#quick-press'
).getByRole( 'textbox', { name: 'Title' } );
@@ -22,36 +22,51 @@ test.describe( 'Quick Draft', () => {
await expect( draftTitleField ).toBeVisible();
// Focus and fill in a title.
- await draftTitleField.fill( 'Test Draft Title' );
+ await draftTitleField.fill( 'Quick Draft test title' );
- // Navigate to content field and type in some content
- await page.keyboard.press( 'Tab' );
- await page.keyboard.type( 'Test Draft Content' );
+ // Wait for the Quick Draft content textarea to appear.
+ const quickDraftContentTextarea = page.locator(
+ '#quick-press'
+ ).getByRole( 'textbox', { name: 'Content' } );
+
+ await expect( quickDraftContentTextarea ).toBeVisible();
+
+ // Focus and fill in some content.
+ await quickDraftContentTextarea.fill( 'Quick Draft test content' );
+
+ // Wait for the Save Draft button to appear and click it.
+ const saveDraftButton = page.locator(
+ '#quick-press'
+ ).getByRole( 'button', { name: 'Save Draft' } );
- // Navigate to Save Draft button and press it.
- await page.keyboard.press( 'Tab' );
- await page.keyboard.press( 'Enter' );
+ await expect( saveDraftButton ).toBeVisible();
+ await saveDraftButton.click();
- // Check that new draft appears in Your Recent Drafts section
+ // Check that the new draft title appears in the 'Your Recent Drafts' section.
await expect(
page.locator( '.drafts .draft-title' ).first().getByRole( 'link' )
- ).toHaveText( 'Test Draft Title' );
+ ).toHaveText( 'Quick Draft test title' );
+
+ // Check that the new draft content appears in the 'Your Recent Drafts' section.
+ await expect(
+ page.locator( '.drafts .draft-content' ).first()
+ ).toHaveText( 'Quick Draft test content' );
- // Check that new draft appears in Posts page
+ // Check that the new draft appears in the Posts page.
await admin.visitAdminPage( '/edit.php' );
await expect(
page.locator( '.type-post.status-draft .title' ).first()
- ).toContainText( 'Test Draft Title' );
+ ).toContainText( 'Quick Draft test title' );
} );
- test( 'Allows draft to be created without Title or Content', async ( {
+ test( 'should prevent Quick Draft from being created without Title or Content', async ( {
admin,
page
} ) => {
await admin.visitAdminPage( '/' );
- // Wait for Save Draft button to appear and click it
+ // Wait for the Save Draft button to appear and click it.
const saveDraftButton = page.locator(
'#quick-press'
).getByRole( 'button', { name: 'Save Draft' } );
@@ -59,12 +74,92 @@ test.describe( 'Quick Draft', () => {
await expect( saveDraftButton ).toBeVisible();
await saveDraftButton.click();
- // Check that new draft appears in Your Recent Drafts section
+ // Check that an admin notice with ARIA role 'alert' appears.
+ await expect(
+ page.locator( '#quick-press' ).getByRole( 'alert' )
+ ).toHaveText( 'Cannot create a draft post with empty title and content.' );
+
+ // Check that no new draft appears in the Posts page.
+ await admin.visitAdminPage( '/edit.php' );
+
+ await expect(
+ page.locator( '#the-list .no-items .colspanchange' )
+ ).toContainText( 'No posts found.' );
+ } );
+
+ test( 'should allow Quick Draft to be created with only the Title', async ( {
+ admin,
+ page
+ } ) => {
+ await admin.visitAdminPage( '/' );
+
+ // Wait for the Quick Draft title field to appear.
+ const quickDraftTitleField = page.locator(
+ '#quick-press'
+ ).getByRole( 'textbox', { name: 'Title' } );
+
+ await expect( quickDraftTitleField ).toBeVisible();
+
+ // Focus and fill in a title.
+ await quickDraftTitleField.fill( 'Quick Draft test title' );
+
+ // Wait for the Save Draft button to appear and click it.
+ const saveDraftButton = page.locator(
+ '#quick-press'
+ ).getByRole( 'button', { name: 'Save Draft' } );
+
+ await expect( saveDraftButton ).toBeVisible();
+ await saveDraftButton.click();
+
+ // Check that the new draft title appears in the 'Your Recent Drafts' section.
+ await expect(
+ page.locator( '.drafts .draft-title' ).first().getByRole( 'link' )
+ ).toHaveText( 'Quick Draft test title' );
+
+ // Check that the new draft appears in the Posts page.
+ await admin.visitAdminPage( '/edit.php' );
+
+ await expect(
+ page.locator( '.type-post.status-draft .title' ).first()
+ ).toContainText( 'Quick Draft test title' );
+ } );
+
+ test( 'should allow Quick Draft to be created with only the Content', async ( {
+ admin,
+ page
+ } ) => {
+ await admin.visitAdminPage( '/' );
+
+ // Wait for the Quick Draft content textarea to appear.
+ const quickDraftContentTextarea = page.locator(
+ '#quick-press'
+ ).getByRole( 'textbox', { name: 'Content' } );
+
+ await expect( quickDraftContentTextarea ).toBeVisible();
+
+ // Focus and fill in some content.
+ await quickDraftContentTextarea.fill( 'Quick Draft test content' );
+
+ // Wait for the Save Draft button to appear and click it.
+ const saveDraftButton = page.locator(
+ '#quick-press'
+ ).getByRole( 'button', { name: 'Save Draft' } );
+
+ await expect( saveDraftButton ).toBeVisible();
+ await saveDraftButton.click();
+
+ // Check that the new draft title appears in the 'Your Recent Drafts' section.
+ // This test relies on Twenty Twenty-One being the active theme.
+ // Twenty Twenty-One alters the default post title from "(no title)" to "Untitled".
await expect(
page.locator( '.drafts .draft-title' ).first().getByRole( 'link' )
).toHaveText( 'Untitled' );
- // Check that new draft appears in Posts page
+ await expect(
+ page.locator( '.drafts .draft-content' ).first()
+ ).toHaveText( 'Quick Draft test content' );
+
+ // Check that the new draft appears in the Posts page.
await admin.visitAdminPage( '/edit.php' );
await expect(