diff --git a/src/wp-admin/css/widgets.css b/src/wp-admin/css/widgets.css index 99039d3c7c66a..915adb24918f3 100644 --- a/src/wp-admin/css/widgets.css +++ b/src/wp-admin/css/widgets.css @@ -559,6 +559,12 @@ div#widgets-right .closed .widgets-sortables { border-left: 1px solid #dcdcde; } +/* Sit next to the JS expand/collapse button rather than stacking below it. */ +.widget-title-action .widget-control-edit { + display: inline-block; + vertical-align: top; +} + #widgets-left .widget-control-edit:hover, #widgets-right .widget-control-edit:hover { color: #fff; diff --git a/src/wp-admin/includes/widgets.php b/src/wp-admin/includes/widgets.php index e751602866b0d..53422c8c3254c 100644 --- a/src/wp-admin/includes/widgets.php +++ b/src/wp-admin/includes/widgets.php @@ -259,7 +259,7 @@ function wp_widget_control( $sidebar_args ) { - + diff --git a/tests/phpunit/tests/widgets.php b/tests/phpunit/tests/widgets.php index 8eb5914c9400d..cd4eeb921d9ba 100644 --- a/tests/phpunit/tests/widgets.php +++ b/tests/phpunit/tests/widgets.php @@ -789,6 +789,57 @@ public function test_wp_widget_save_settings_delete() { * @see wp_widget_control() */ public function test_wp_widget_control() { + $control = $this->render_search_widget_control(); + $this->assertNotEmpty( $control ); + + $this->assertStringContainsString( '
', $control ); + $this->assertStringContainsString( '
', $control ); + $this->assertStringContainsString( '
', $control ); + $this->assertStringContainsString( '
', $control ); + $this->assertStringContainsString( '
', $control ); + $this->assertStringContainsString( 'assertStringContainsString( 'assertStringContainsString( '
', $control ); + $this->assertStringContainsString( '
', $control ); + $this->assertStringContainsString( 'widget-control-remove', $control ); + $this->assertStringContainsString( 'widget-control-close', $control ); + $this->assertStringContainsString( '
', $control ); + $this->assertStringContainsString( ' '', + 'after_form' => '', + 'before_widget_content' => '', + 'after_widget_content' => '', + ); + $control = $this->render_search_widget_control( $param_overrides ); + $this->assertNotEmpty( $control ); + $this->assertStringNotContainsString( '', $control ); + $this->assertStringNotContainsString( '
', $control ); + + foreach ( $param_overrides as $contained ) { + $this->assertStringContainsString( $contained, $control ); + } + } + + /** + * @ticket 52399 + * @see wp_widget_control() + */ + public function test_wp_widget_control_edit_link_is_not_hidden_from_js() { + $control = $this->render_search_widget_control(); + + $this->assertStringContainsString( 'class="widget-control-edit"', $control, 'The Edit/Add text link should remain visible when JavaScript is available, as a plain-text path to the accessible single-widget edit screen.' ); + $this->assertStringNotContainsString( 'widget-control-edit hide-if-js', $control ); + } + + /** + * Registers a `search-2` widget in `sidebar-1` and renders its control markup via wp_widget_control(). + * + * @param array $param_overrides Optional. Extra values merged into the sidebar params passed to wp_widget_control(). + * @return string The rendered control markup. + */ + private function render_search_widget_control( array $param_overrides = array() ) { global $wp_registered_widgets; update_option( @@ -810,11 +861,13 @@ public function test_wp_widget_control() { wp_widgets_init(); require_once ABSPATH . 'wp-admin/includes/widgets.php'; - $widget_id = 'search-2'; - $widget = $wp_registered_widgets[ $widget_id ]; - $params = array( - 'widget_id' => $widget['id'], - 'widget_name' => $widget['name'], + $widget = $wp_registered_widgets['search-2']; + $params = array_merge( + array( + 'widget_id' => $widget['id'], + 'widget_name' => $widget['name'], + ), + $param_overrides ); $control_args = array( 0 => $params, @@ -824,46 +877,7 @@ public function test_wp_widget_control() { ob_start(); wp_widget_control( ...$sidebar_args ); - $control = ob_get_clean(); - $this->assertNotEmpty( $control ); - - $this->assertStringContainsString( '
', $control ); - $this->assertStringContainsString( '
', $control ); - $this->assertStringContainsString( '
', $control ); - $this->assertStringContainsString( '', $control ); - $this->assertStringContainsString( '
', $control ); - $this->assertStringContainsString( 'assertStringContainsString( 'assertStringContainsString( '
', $control ); - $this->assertStringContainsString( '
', $control ); - $this->assertStringContainsString( 'widget-control-remove', $control ); - $this->assertStringContainsString( 'widget-control-close', $control ); - $this->assertStringContainsString( '
', $control ); - $this->assertStringContainsString( ' '', - 'after_form' => '', - 'before_widget_content' => '', - 'after_widget_content' => '', - ); - $params = array_merge( $params, $param_overrides ); - $control_args = array( - 0 => $params, - 1 => $widget['params'][0], - ); - $sidebar_args = wp_list_widget_controls_dynamic_sidebar( $control_args ); - - ob_start(); - wp_widget_control( ...$sidebar_args ); - $control = ob_get_clean(); - $this->assertNotEmpty( $control ); - $this->assertStringNotContainsString( '', $control ); - $this->assertStringNotContainsString( '
', $control ); - - foreach ( $param_overrides as $contained ) { - $this->assertStringContainsString( $contained, $control ); - } + return ob_get_clean(); } public function test_the_widget_custom_before_title_arg() {