widgets.php 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220
  1. <?php
  2. /**
  3. * Test functions and classes for widgets and sidebars.
  4. *
  5. * @group widgets
  6. */
  7. class Tests_Widgets extends WP_UnitTestCase {
  8. public $sidebar_index;
  9. public $valid_sidebar;
  10. function clean_up_global_scope() {
  11. global $wp_widget_factory, $wp_registered_sidebars, $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates;
  12. $wp_registered_sidebars = array();
  13. $wp_registered_widgets = array();
  14. $wp_registered_widget_controls = array();
  15. $wp_registered_widget_updates = array();
  16. $wp_widget_factory->widgets = array();
  17. parent::clean_up_global_scope();
  18. }
  19. function tearDown() {
  20. global $wp_customize;
  21. $wp_customize = null;
  22. parent::tearDown();
  23. }
  24. /**
  25. * @see register_widget()
  26. * @see unregister_widget()
  27. */
  28. function test_register_and_unregister_widget_core_widget() {
  29. global $wp_widget_factory;
  30. $widget_class = 'WP_Widget_Search';
  31. register_widget( $widget_class );
  32. $this->assertArrayHasKey( $widget_class, $wp_widget_factory->widgets );
  33. unregister_widget( $widget_class );
  34. $this->assertArrayNotHasKey( $widget_class, $wp_widget_factory->widgets );
  35. }
  36. /**
  37. * Test that registering a widget class and registering a widget instance work together.
  38. *
  39. * @see register_widget()
  40. * @see unregister_widget()
  41. * @ticket 28216
  42. */
  43. function test_register_and_unregister_widget_instance() {
  44. global $wp_widget_factory, $wp_registered_widgets;
  45. $this->assertEmpty( $wp_widget_factory->widgets );
  46. $this->assertEmpty( $wp_registered_widgets );
  47. update_option(
  48. 'widget_search',
  49. array(
  50. 2 => array( 'title' => '' ),
  51. '_multiwidget' => 1,
  52. )
  53. );
  54. update_option(
  55. 'widget_better_search',
  56. array(
  57. 3 => array( 'title' => '' ),
  58. '_multiwidget' => 1,
  59. )
  60. );
  61. update_option(
  62. 'widget_best_search',
  63. array(
  64. 4 => array( 'title' => '' ),
  65. '_multiwidget' => 1,
  66. )
  67. );
  68. register_widget( 'WP_Widget_Search' );
  69. $this->assertArrayHasKey( 'WP_Widget_Search', $wp_widget_factory->widgets );
  70. $widget_better_search = new WP_Widget_Search();
  71. $widget_better_search->id_base = 'better_search';
  72. $widget_better_search->name = 'Better Search';
  73. $widget_better_search->option_name = 'widget_' . $widget_better_search->id_base;
  74. $widget_better_search->widget_options['classname'] = 'widget_' . $widget_better_search->id_base;
  75. $widget_better_search->control_options['id_base'] = $widget_better_search->id_base;
  76. register_widget( $widget_better_search );
  77. $this->assertContains( $widget_better_search, $wp_widget_factory->widgets );
  78. $widget_best_search = new WP_Widget_Search();
  79. $widget_best_search->id_base = 'best_search';
  80. $widget_best_search->name = 'Best Search';
  81. $widget_best_search->option_name = 'widget_' . $widget_best_search->id_base;
  82. $widget_best_search->widget_options['classname'] = 'widget_' . $widget_best_search->id_base;
  83. $widget_best_search->control_options['id_base'] = $widget_best_search->id_base;
  84. register_widget( $widget_best_search );
  85. $this->assertContains( $widget_best_search, $wp_widget_factory->widgets );
  86. $this->assertCount( 3, $wp_widget_factory->widgets );
  87. $this->assertArrayHasKey( 'WP_Widget_Search', $wp_widget_factory->widgets );
  88. $this->assertContains( $widget_better_search, $wp_widget_factory->widgets );
  89. $this->assertContains( $widget_best_search, $wp_widget_factory->widgets );
  90. $wp_widget_factory->_register_widgets();
  91. $this->assertArrayHasKey( 'search-2', $wp_registered_widgets );
  92. $this->assertArrayHasKey( 'better_search-3', $wp_registered_widgets );
  93. $this->assertArrayHasKey( 'best_search-4', $wp_registered_widgets );
  94. $this->assertInstanceOf( 'WP_Widget_Search', $wp_registered_widgets['search-2']['callback'][0] );
  95. $this->assertSame( $widget_better_search, $wp_registered_widgets['better_search-3']['callback'][0] );
  96. $this->assertSame( $widget_best_search, $wp_registered_widgets['best_search-4']['callback'][0] );
  97. $this->assertContains( $widget_better_search, $wp_widget_factory->widgets );
  98. $this->assertContains( $widget_best_search, $wp_widget_factory->widgets );
  99. $this->assertArrayHasKey( 'WP_Widget_Search', $wp_widget_factory->widgets );
  100. unregister_widget( 'WP_Widget_Search' );
  101. unregister_widget( $widget_better_search );
  102. unregister_widget( $widget_best_search );
  103. $this->assertNotContains( $widget_better_search, $wp_widget_factory->widgets );
  104. $this->assertNotContains( $widget_best_search, $wp_widget_factory->widgets );
  105. $this->assertArrayNotHasKey( 'WP_Widget_Search', $wp_widget_factory->widgets );
  106. }
  107. /**
  108. * @group sidebar
  109. */
  110. function test_register_sidebars_single() {
  111. global $wp_registered_sidebars;
  112. register_sidebars( 1, array( 'id' => 'wp-unit-test' ) );
  113. $this->assertTrue( isset( $wp_registered_sidebars['wp-unit-test'] ) );
  114. }
  115. /**
  116. * @group sidebar
  117. */
  118. function test_register_sidebars_multiple() {
  119. global $wp_registered_sidebars;
  120. $result = array();
  121. $num = 3;
  122. $id_base = 'WP Unit Test';
  123. register_sidebars( $num, array( 'name' => $id_base . ' %d' ) );
  124. $names = wp_list_pluck( $wp_registered_sidebars, 'name' );
  125. for ( $i = 1; $i <= $num; $i++ ) {
  126. if ( in_array( "$id_base $i", $names, true ) ) {
  127. $result[] = true;
  128. }
  129. }
  130. $this->assertSame( $num, count( $result ) );
  131. }
  132. /**
  133. * @group sidebar
  134. */
  135. function test_register_sidebar_with_no_id() {
  136. global $wp_registered_sidebars;
  137. $this->setExpectedIncorrectUsage( 'register_sidebar' );
  138. // Incorrectly register a couple of sidebars for fun.
  139. register_sidebar();
  140. register_sidebar();
  141. $derived_sidebar_id = 'sidebar-2'; // Number of sidebars in the global + 1.
  142. $this->assertArrayHasKey( $derived_sidebar_id, $wp_registered_sidebars );
  143. }
  144. /**
  145. * @group sidebar
  146. */
  147. function test_unregister_sidebar_registered_with_no_id() {
  148. global $wp_registered_sidebars;
  149. $this->setExpectedIncorrectUsage( 'register_sidebar' );
  150. // Incorrectly register a couple of sidebars for fun.
  151. register_sidebar();
  152. register_sidebar();
  153. $derived_sidebar_id = 'sidebar-2'; // Number of sidebars in the global + 1.
  154. unregister_sidebar( $derived_sidebar_id );
  155. $this->assertArrayNotHasKey( $derived_sidebar_id, $wp_registered_sidebars );
  156. }
  157. /**
  158. * @group sidebar
  159. */
  160. function test_register_sidebar_with_string_id() {
  161. global $wp_registered_sidebars;
  162. $sidebar_id = 'wp-unit-test';
  163. register_sidebar( array( 'id' => $sidebar_id ) );
  164. $this->assertArrayHasKey( $sidebar_id, $wp_registered_sidebars );
  165. }
  166. /**
  167. * @group sidebar
  168. */
  169. function test_unregister_sidebar_with_string_id() {
  170. global $wp_registered_sidebars;
  171. $sidebar_id = 'wp-unit-tests';
  172. register_sidebar( array( 'id' => $sidebar_id ) );
  173. unregister_sidebar( $sidebar_id );
  174. $this->assertArrayNotHasKey( $sidebar_id, $wp_registered_sidebars );
  175. }
  176. /**
  177. * @group sidebar
  178. */
  179. function test_register_sidebar_with_numeric_id() {
  180. global $wp_registered_sidebars;
  181. $sidebar_id = 2;
  182. register_sidebar( array( 'id' => $sidebar_id ) );
  183. $this->assertArrayHasKey( $sidebar_id, $wp_registered_sidebars );
  184. }
  185. /**
  186. * @group sidebar
  187. */
  188. function test_unregister_sidebar_with_numeric_id() {
  189. global $wp_registered_sidebars;
  190. $sidebar_id = 2;
  191. register_sidebar( array( 'id' => $sidebar_id ) );
  192. unregister_sidebar( $sidebar_id );
  193. $this->assertArrayNotHasKey( $sidebar_id, $wp_registered_sidebars );
  194. }
  195. /**
  196. * @group sidebar
  197. * @ticket 19709
  198. */
  199. public function test_register_sidebar_with_after_and_before_sidebar() {
  200. global $wp_registered_sidebars;
  201. $sidebar_id = 'test-sidebar';
  202. register_sidebar(
  203. array(
  204. 'id' => $sidebar_id,
  205. 'before_sidebar' => '<div id="%1$s" class="before-sidebar %2$s">',
  206. 'after_sidebar' => '</div> <!-- .before-sidebar -->',
  207. 'class' => 'test-sidebar',
  208. )
  209. );
  210. $this->assertArrayHasKey( $sidebar_id, $wp_registered_sidebars );
  211. $this->assertContains( '<div id="%1$s" class="before-sidebar %2$s">', $wp_registered_sidebars[ $sidebar_id ]['before_sidebar'] );
  212. $this->assertContains( '</div> <!-- .before-sidebar -->', $wp_registered_sidebars[ $sidebar_id ]['after_sidebar'] );
  213. }
  214. /**
  215. * @group sidebar
  216. * @ticket 19709
  217. */
  218. public function test_register_sidebar_without_after_and_before_sidebar() {
  219. global $wp_registered_sidebars;
  220. $sidebar_id = 'test-sidebar-2';
  221. register_sidebar(
  222. array(
  223. 'id' => $sidebar_id,
  224. )
  225. );
  226. $this->assertArrayHasKey( $sidebar_id, $wp_registered_sidebars );
  227. $this->assertEmpty( $wp_registered_sidebars[ $sidebar_id ]['before_sidebar'] );
  228. $this->assertEmpty( $wp_registered_sidebars[ $sidebar_id ]['after_sidebar'] );
  229. }
  230. /**
  231. * Utility hook callback used to store a sidebar ID mid-function.
  232. */
  233. function retrieve_sidebar_id( $index, $valid_sidebar ) {
  234. $this->sidebar_index = $index;
  235. $this->valid_sidebar = $valid_sidebar;
  236. }
  237. /**
  238. * @group sidebar
  239. */
  240. function test_dynamic_sidebar_using_sidebar_registered_with_no_id() {
  241. $this->setExpectedIncorrectUsage( 'register_sidebar' );
  242. // Incorrectly register a couple of sidebars for fun.
  243. register_sidebar();
  244. register_sidebar();
  245. $derived_sidebar_id = 'sidebar-2'; // Number of sidebars in the global + 1.
  246. add_action( 'dynamic_sidebar_before', array( $this, 'retrieve_sidebar_id' ), 10, 2 );
  247. dynamic_sidebar( 2 );
  248. $this->assertSame( $derived_sidebar_id, $this->sidebar_index );
  249. }
  250. /**
  251. * @group sidebar
  252. */
  253. function test_dynamic_sidebar_using_invalid_sidebar_id() {
  254. register_sidebar( array( 'id' => 'wp-unit-text' ) );
  255. add_action( 'dynamic_sidebar_before', array( $this, 'retrieve_sidebar_id' ), 10, 2 );
  256. // 5 is a fake sidebar ID.
  257. dynamic_sidebar( 5 );
  258. /*
  259. * If the sidebar ID is invalid, the second argument passed to
  260. * the 'dynamic_sidebar_before' hook will be false.
  261. */
  262. $this->assertFalse( $this->valid_sidebar );
  263. }
  264. /**
  265. * @group sidebar
  266. */
  267. function test_dynamic_sidebar_numeric_id() {
  268. $sidebar_id = 2;
  269. register_sidebar( array( 'id' => $sidebar_id ) );
  270. add_action( 'dynamic_sidebar_before', array( $this, 'retrieve_sidebar_id' ), 10, 2 );
  271. dynamic_sidebar( $sidebar_id );
  272. $this->assertSame( "sidebar-{$sidebar_id}", $this->sidebar_index );
  273. }
  274. /**
  275. * @group sidebar
  276. */
  277. function test_dynamic_sidebar_string_id() {
  278. $sidebar_id = 'wp-unit-tests';
  279. register_sidebar( array( 'id' => $sidebar_id ) );
  280. add_action( 'dynamic_sidebar_before', array( $this, 'retrieve_sidebar_id' ), 10, 2 );
  281. dynamic_sidebar( $sidebar_id );
  282. $this->assertSame( $sidebar_id, $this->sidebar_index );
  283. }
  284. /**
  285. * @see WP_Widget_Search::form()
  286. */
  287. function test_wp_widget_search_form() {
  288. $widget = new WP_Widget_Search( 'foo', 'Foo' );
  289. ob_start();
  290. $args = array(
  291. 'before_widget' => '<section>',
  292. 'after_widget' => "</section>\n",
  293. 'before_title' => '<h2>',
  294. 'after_title' => "</h2>\n",
  295. );
  296. $instance = array( 'title' => 'Buscar' );
  297. $widget->_set( 2 );
  298. $widget->widget( $args, $instance );
  299. $output = ob_get_clean();
  300. $this->assertNotContains( 'no-options-widget', $output );
  301. $this->assertContains( '<h2>Buscar</h2>', $output );
  302. $this->assertContains( '<section>', $output );
  303. $this->assertContains( '</section>', $output );
  304. }
  305. /**
  306. * @see WP_Widget::form()
  307. */
  308. function test_wp_widget_form() {
  309. $widget = new WP_Widget( 'foo', 'Foo' );
  310. ob_start();
  311. $retval = $widget->form( array() );
  312. $output = ob_get_clean();
  313. $this->assertSame( 'noform', $retval );
  314. $this->assertContains( 'no-options-widget', $output );
  315. }
  316. /**
  317. * @see WP_Widget::__construct()
  318. */
  319. function test_wp_widget_constructor() {
  320. $id_base = 'foo';
  321. $name = 'Foo';
  322. $foo_widget = new WP_Widget( $id_base, $name );
  323. $this->assertSame( $id_base, $foo_widget->id_base );
  324. $this->assertSame( $name, $foo_widget->name );
  325. $this->assertSame( "widget_{$id_base}", $foo_widget->option_name );
  326. $this->assertArrayHasKey( 'classname', $foo_widget->widget_options );
  327. $this->assertSame( "widget_{$id_base}", $foo_widget->widget_options['classname'] );
  328. $this->assertArrayHasKey( 'id_base', $foo_widget->control_options );
  329. $this->assertSame( $id_base, $foo_widget->control_options['id_base'] );
  330. $id_base = 'bar';
  331. $name = 'Bar';
  332. $widget_options = array(
  333. 'classname' => 'bar_classname',
  334. );
  335. $control_options = array(
  336. 'id_base' => 'bar_id_base',
  337. );
  338. $bar_widget = new WP_Widget( $id_base, $name, $widget_options, $control_options );
  339. $this->assertSame( $widget_options['classname'], $bar_widget->widget_options['classname'] );
  340. $this->assertSame( $control_options['id_base'], $bar_widget->control_options['id_base'] );
  341. }
  342. /**
  343. * @see WP_Widget::get_field_name()
  344. * @dataProvider data_wp_widget_get_field_name
  345. */
  346. function test_wp_widget_get_field_name( $expected, $value_to_test ) {
  347. $widget = new WP_Widget( 'foo', 'Foo' );
  348. $widget->_set( 2 );
  349. $this->assertSame( $expected, $widget->get_field_name( $value_to_test ) );
  350. }
  351. /**
  352. * Data provider.
  353. *
  354. * Passes the expected field name and the value to test.
  355. *
  356. * @since 4.4.0
  357. *
  358. * @return array {
  359. * @type array {
  360. * @type string $expected The expected field id to be returned.
  361. * @type string $value_to_test The value being passed to the get_field_name method.
  362. * }
  363. * }
  364. */
  365. function data_wp_widget_get_field_name() {
  366. return array(
  367. array(
  368. 'widget-foo[2][title]',
  369. 'title',
  370. ),
  371. array(
  372. 'widget-foo[2][posttypes][]',
  373. 'posttypes[]',
  374. ),
  375. array(
  376. 'widget-foo[2][posttypes][4]',
  377. 'posttypes[4]',
  378. ),
  379. array(
  380. 'widget-foo[2][posttypes][4][]',
  381. 'posttypes[4][]',
  382. ),
  383. array(
  384. 'widget-foo[2][posttypes][4][][6]',
  385. 'posttypes[4][][6]',
  386. ),
  387. );
  388. }
  389. /**
  390. * @see WP_Widget::get_field_id()
  391. * @dataProvider data_wp_widget_get_field_id
  392. */
  393. function test_wp_widget_get_field_id( $expected, $value_to_test ) {
  394. $widget = new WP_Widget( 'foo', 'Foo' );
  395. $widget->_set( 2 );
  396. $this->assertSame( $expected, $widget->get_field_id( $value_to_test ) );
  397. }
  398. /**
  399. * Data provider.
  400. *
  401. * Passes the expected field id and the value to be used in the tests.
  402. *
  403. * @since 4.4.0
  404. *
  405. * @return array {
  406. * @type array {
  407. * @type string $expected The expected field id to be returned.
  408. * @type string $value_to_test The value being passed to the get_field_id method.
  409. * }
  410. * }
  411. */
  412. function data_wp_widget_get_field_id() {
  413. return array(
  414. array(
  415. 'widget-foo-2-title',
  416. 'title',
  417. ),
  418. array(
  419. 'widget-foo-2-posttypes',
  420. 'posttypes[]',
  421. ),
  422. array(
  423. 'widget-foo-2-posttypes-4',
  424. 'posttypes[4]',
  425. ),
  426. array(
  427. 'widget-foo-2-posttypes-4',
  428. 'posttypes[4][]',
  429. ),
  430. array(
  431. 'widget-foo-2-posttypes-4-6',
  432. 'posttypes[4][][6]',
  433. ),
  434. );
  435. }
  436. /**
  437. * @see WP_Widget::_register()
  438. */
  439. function test_wp_widget__register() {
  440. global $wp_registered_widgets;
  441. $settings = get_option( 'widget_search' );
  442. unset( $settings['_multiwidget'] );
  443. $this->assertArrayHasKey( 2, $settings );
  444. $this->assertEmpty( $wp_registered_widgets );
  445. wp_widgets_init();
  446. // Note: We cannot use array_keys() here because $settings could be an ArrayIterator.
  447. foreach ( $settings as $widget_number => $instance ) {
  448. $widget_id = "search-$widget_number";
  449. $this->assertArrayHasKey( $widget_id, $wp_registered_widgets );
  450. }
  451. }
  452. // @todo Test WP_Widget::display_callback().
  453. /**
  454. * @see WP_Widget::is_preview()
  455. */
  456. function test_wp_widget_is_preview() {
  457. global $wp_customize;
  458. $widget = new WP_Widget( 'foo', 'Foo' );
  459. $this->assertEmpty( $wp_customize );
  460. $this->assertFalse( $widget->is_preview() );
  461. wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
  462. require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
  463. $wp_customize = new WP_Customize_Manager();
  464. $wp_customize->start_previewing_theme();
  465. $this->assertTrue( $widget->is_preview() );
  466. }
  467. // @todo Test WP_Widget::update_callback().
  468. // @todo Test WP_Widget::form_callback().
  469. // @todo Test WP_Widget::_register_one().
  470. /**
  471. * @see WP_Widget::get_settings()
  472. */
  473. function test_wp_widget_get_settings() {
  474. global $wp_registered_widgets;
  475. $option_value = get_option( 'widget_search' );
  476. $this->assertArrayHasKey( '_multiwidget', $option_value );
  477. $this->assertSame( 1, $option_value['_multiwidget'] );
  478. $this->assertArrayHasKey( 2, $option_value );
  479. $instance = $option_value[2];
  480. $this->assertInternalType( 'array', $instance );
  481. $this->assertArrayHasKey( 'title', $instance );
  482. unset( $option_value['_multiwidget'] );
  483. // Pretend this widget is new.
  484. delete_option( 'widget_nav_menu' );
  485. $never_used = get_option( 'widget_nav_menu', array() );
  486. $this->assertSame( array(), (array) $never_used );
  487. wp_widgets_init();
  488. $wp_widget_search = $wp_registered_widgets['search-2']['callback'][0];
  489. $settings = $wp_widget_search->get_settings();
  490. // @todo $this->assertArrayNotHasKey( '_multiwidget', $settings ); ?
  491. $this->assertArrayHasKey( 2, $settings );
  492. foreach ( $option_value as $widget_number => $instance ) {
  493. $this->assertSame( $settings[ $widget_number ], $option_value[ $widget_number ] );
  494. }
  495. // After widgets_init(), get_settings() should create the widget option.
  496. $never_used = get_option( 'widget_nav_menu' );
  497. $this->assertSame( 1, $never_used['_multiwidget'] );
  498. $this->assertArrayNotHasKey( 0, $never_used );
  499. }
  500. /**
  501. * @see WP_Widget::save_settings()
  502. */
  503. function test_wp_widget_save_settings() {
  504. global $wp_registered_widgets;
  505. wp_widgets_init();
  506. $wp_widget_search = $wp_registered_widgets['search-2']['callback'][0];
  507. $settings = $wp_widget_search->get_settings();
  508. $overridden_title = 'Unit Tested';
  509. /*
  510. * Note that if a plugin is filtering $settings to be an ArrayIterator,
  511. * then doing this:
  512. * $settings[2]['title'] = $overridden_title;
  513. * Will fail with this:
  514. * > Indirect modification of overloaded element of X has no effect.
  515. * So this is why the value must be obtained.
  516. */
  517. $instance = $settings[2];
  518. $instance['title'] = $overridden_title;
  519. $settings[2] = $instance;
  520. $wp_widget_search->save_settings( $settings );
  521. $option_value = get_option( $wp_widget_search->option_name );
  522. $this->assertArrayHasKey( '_multiwidget', $option_value );
  523. $this->assertSame( $overridden_title, $option_value[2]['title'] );
  524. }
  525. /**
  526. * @see WP_Widget::save_settings()
  527. */
  528. function test_wp_widget_save_settings_delete() {
  529. global $wp_registered_widgets;
  530. wp_widgets_init();
  531. $wp_widget_search = $wp_registered_widgets['search-2']['callback'][0];
  532. $settings = $wp_widget_search->get_settings();
  533. $this->assertArrayHasKey( 2, $settings );
  534. unset( $settings[2] );
  535. $wp_widget_search->save_settings( $settings );
  536. $option_value = get_option( $wp_widget_search->option_name );
  537. $this->assertArrayNotHasKey( 2, $option_value );
  538. }
  539. /**
  540. * @see wp_widget_control()
  541. */
  542. function test_wp_widget_control() {
  543. global $wp_registered_widgets;
  544. wp_widgets_init();
  545. require_once ABSPATH . '/wp-admin/includes/widgets.php';
  546. $widget_id = 'search-2';
  547. $widget = $wp_registered_widgets[ $widget_id ];
  548. $params = array(
  549. 'widget_id' => $widget['id'],
  550. 'widget_name' => $widget['name'],
  551. );
  552. $control_args = array(
  553. 0 => $params,
  554. 1 => $widget['params'][0],
  555. );
  556. $sidebar_args = wp_list_widget_controls_dynamic_sidebar( $control_args );
  557. ob_start();
  558. wp_widget_control( ...$sidebar_args );
  559. $control = ob_get_clean();
  560. $this->assertNotEmpty( $control );
  561. $this->assertContains( '<div class="widget-top">', $control );
  562. $this->assertContains( '<div class="widget-title-action">', $control );
  563. $this->assertContains( '<div class="widget-title">', $control );
  564. $this->assertContains( '<form method="post">', $control );
  565. $this->assertContains( '<div class="widget-content">', $control );
  566. $this->assertContains( '<input class="widefat"', $control );
  567. $this->assertContains( '<input type="hidden" name="id_base" class="id_base" value="search"', $control );
  568. $this->assertContains( '<div class="widget-control-actions">', $control );
  569. $this->assertContains( '<div class="alignleft">', $control );
  570. $this->assertContains( 'widget-control-remove', $control );
  571. $this->assertContains( 'widget-control-close', $control );
  572. $this->assertContains( '<div class="alignright">', $control );
  573. $this->assertContains( '<input type="submit" name="savewidget"', $control );
  574. $param_overrides = array(
  575. 'before_form' => '<!-- before_form -->',
  576. 'after_form' => '<!-- after_form -->',
  577. 'before_widget_content' => '<!-- before_widget_content -->',
  578. 'after_widget_content' => '<!-- after_widget_content -->',
  579. );
  580. $params = array_merge( $params, $param_overrides );
  581. $control_args = array(
  582. 0 => $params,
  583. 1 => $widget['params'][0],
  584. );
  585. $sidebar_args = wp_list_widget_controls_dynamic_sidebar( $control_args );
  586. ob_start();
  587. wp_widget_control( ...$sidebar_args );
  588. $control = ob_get_clean();
  589. $this->assertNotEmpty( $control );
  590. $this->assertNotContains( '<form method="post">', $control );
  591. $this->assertNotContains( '<div class="widget-content">', $control );
  592. foreach ( $param_overrides as $contained ) {
  593. $this->assertContains( $contained, $control );
  594. }
  595. }
  596. function test_the_widget_custom_before_title_arg() {
  597. register_widget( 'WP_Widget_Text' );
  598. ob_start();
  599. the_widget(
  600. 'WP_Widget_Text',
  601. array(
  602. 'title' => 'Notes',
  603. 'text' => 'Sample text',
  604. ),
  605. array(
  606. 'before_widget' => '<span class="special %s">',
  607. 'after_widget' => '</span>',
  608. )
  609. );
  610. $actual = ob_get_clean();
  611. unregister_widget( 'WP_Widget_Text' );
  612. $this->assertRegExp( '/<span class="special widget_text">/', $actual );
  613. }
  614. /**
  615. * Tests that no 'Undefined index' exception is thrown when trying to
  616. * display an unregistered widget.
  617. *
  618. * @see \the_widget()
  619. */
  620. function test_the_widget_with_unregistered_widget() {
  621. $this->setExpectedIncorrectUsage( 'the_widget' );
  622. the_widget( 'Widget_Class' );
  623. }
  624. /**
  625. * @ticket 34226
  626. */
  627. public function test_the_widget_should_short_circuit_with_widget_display_callback() {
  628. add_filter( 'widget_display_callback', '__return_false' );
  629. register_widget( 'WP_Widget_Text' );
  630. ob_start();
  631. the_widget( 'WP_Widget_Text' );
  632. $widget_content = ob_get_clean();
  633. unregister_widget( 'WP_Widget_Text' );
  634. $this->assertEmpty( $widget_content );
  635. }
  636. /**
  637. * Register nav menu sidebars.
  638. *
  639. * @param array $sidebars Sidebar slugs.
  640. */
  641. function register_sidebars( $sidebars ) {
  642. foreach ( $sidebars as $sidebar ) {
  643. register_sidebar( array( 'id' => $sidebar ) );
  644. }
  645. }
  646. /**
  647. * Tests for when 'sidebars_widgets' theme mod is populated.
  648. *
  649. * @covers ::retrieve_widgets
  650. */
  651. function test_retrieve_widgets_with_theme_mod() {
  652. global $sidebars_widgets, $_wp_sidebars_widgets;
  653. wp_widgets_init();
  654. $this->register_sidebars( array( 'sidebar-1', 'sidebar-2', 'sidebar-3', 'sidebar-4', 'wp_inactive_widgets' ) );
  655. // Test restoring sidebars widgets when previously activated.
  656. set_theme_mod(
  657. 'sidebars_widgets',
  658. array(
  659. 'time' => time(),
  660. 'data' => array(
  661. 'sidebar-1' => array( 'tag_cloud-1' ),
  662. 'sidebar-2' => array(),
  663. 'sidebar-3' => array( 'unregistered_widget-1', 'text-1', 'media_image-1' ),
  664. 'sidebar-4' => null, // Should be converted to array.
  665. 'orphaned_widgets_1' => array( 'media_video-2' ),
  666. ),
  667. )
  668. );
  669. $sidebars_widgets = array(
  670. 'sidebar-1' => array( 'tag_cloud-1' ),
  671. 'sidebar-2' => array( 'text-1' ),
  672. 'fantasy' => array( 'archives-2' ),
  673. 'wp_inactive_widgets' => array(),
  674. );
  675. $result = retrieve_widgets( true );
  676. $this->assertInternalType( 'array', $result );
  677. $this->assertSame( $result, $sidebars_widgets );
  678. foreach ( $sidebars_widgets as $widgets ) {
  679. $this->assertInternalType( 'array', $widgets );
  680. }
  681. $this->assertContains( 'tag_cloud-1', $sidebars_widgets['sidebar-1'] );
  682. $this->assertContains( 'text-1', $sidebars_widgets['sidebar-2'] );
  683. $this->assertContains( 'media_image-1', $sidebars_widgets['sidebar-3'] );
  684. $this->assertArrayNotHasKey( 'orphaned_widgets_1', $sidebars_widgets );
  685. // Unregistered widget should be filtered out.
  686. $this->assertNotContains( 'unregistered_widget-1', $sidebars_widgets['sidebar-3'] );
  687. // 6 default widgets - 1 active text widget + 1 orphaned widget = 6.
  688. $this->assertCount( 6, $sidebars_widgets['wp_inactive_widgets'] );
  689. $this->assertContains( 'meta-2', $sidebars_widgets['wp_inactive_widgets'] );
  690. $this->assertContains( 'search-2', $sidebars_widgets['wp_inactive_widgets'] );
  691. $this->assertContains( 'archives-2', $sidebars_widgets['wp_inactive_widgets'] );
  692. $this->assertContains( 'categories-2', $sidebars_widgets['wp_inactive_widgets'] );
  693. $this->assertContains( 'recent-posts-2', $sidebars_widgets['wp_inactive_widgets'] );
  694. $this->assertContains( 'recent-comments-2', $sidebars_widgets['wp_inactive_widgets'] );
  695. // Sidebar_widgets option was updated.
  696. $this->assertSame( $sidebars_widgets, wp_get_sidebars_widgets() );
  697. }
  698. /**
  699. * Tests for when sidebars widgets matches registered sidebars.
  700. *
  701. * @covers ::retrieve_widgets
  702. */
  703. function test_retrieve_widgets_with_sidebars_widgets_matching_registered_sidebars() {
  704. global $sidebars_widgets;
  705. wp_widgets_init();
  706. $this->register_sidebars( array( 'sidebar-1', 'sidebar-2', 'sidebar-3', 'wp_inactive_widgets' ) );
  707. $sidebars_widgets = array(
  708. 'sidebar-1' => array( 'tag_cloud-1' ),
  709. 'sidebar-2' => array( 'text-1' ),
  710. 'sidebar-3' => array( 'custom_widget-1' ),
  711. 'wp_inactive_widgets' => array(),
  712. );
  713. $result = retrieve_widgets( true );
  714. // $sidebars_widgets matches registered sidebars.
  715. $this->assertInternalType( 'array', $result );
  716. $this->assertSame( $result, $sidebars_widgets );
  717. foreach ( $sidebars_widgets as $widgets ) {
  718. $this->assertInternalType( 'array', $widgets );
  719. }
  720. $this->assertContains( 'tag_cloud-1', $sidebars_widgets['sidebar-1'] );
  721. $this->assertContains( 'text-1', $sidebars_widgets['sidebar-2'] );
  722. // Invalid widget removed, even when $sidebars_widgets matches registered sidebars.
  723. $this->assertEmpty( $sidebars_widgets['sidebar-3'] );
  724. // No lost widgets when $sidebars_widgets matches registered sidebars.
  725. $this->assertEmpty( $sidebars_widgets['wp_inactive_widgets'] );
  726. }
  727. /**
  728. * Tests for when sidebars widgets doesn't match registered sidebars.
  729. *
  730. * @covers ::retrieve_widgets
  731. */
  732. function test_retrieve_widgets_with_sidebars_widgets_not_matching_registered_sidebars() {
  733. global $sidebars_widgets, $_wp_sidebars_widgets;
  734. wp_widgets_init();
  735. $this->register_sidebars( array( 'sidebar-1', 'sidebar-2', 'sidebar-3', 'wp_inactive_widgets' ) );
  736. $sidebars_widgets = array(
  737. 'sidebar-1' => array( 'tag_cloud-1' ),
  738. 'sidebar-2' => array( 'text-1' ),
  739. 'fantasy' => array( 'unregistered_widget-1' ),
  740. 'wp_inactive_widgets' => array(),
  741. );
  742. // Theme changed.
  743. $result = retrieve_widgets( true );
  744. $_wp_sidebars_widgets = array();
  745. $this->assertInternalType( 'array', $result );
  746. $this->assertSame( $result, $sidebars_widgets );
  747. foreach ( $sidebars_widgets as $widgets ) {
  748. $this->assertInternalType( 'array', $widgets );
  749. }
  750. // Current theme doesn't have a fantasy-sidebar.
  751. $this->assertArrayNotHasKey( 'fantasy', $sidebars_widgets );
  752. $this->assertArrayHasKey( 'sidebar-3', $sidebars_widgets );
  753. $this->assertContains( 'tag_cloud-1', $sidebars_widgets['sidebar-1'] );
  754. $this->assertContains( 'text-1', $sidebars_widgets['sidebar-2'] );
  755. $this->assertEmpty( $sidebars_widgets['sidebar-3'] );
  756. // We should not have orphaned widgets, because widget was not registered.
  757. $this->assertArrayNotHasKey( 'orphaned_widgets_1', $sidebars_widgets );
  758. // 6 default widgets.
  759. $this->assertCount( 6, $sidebars_widgets['wp_inactive_widgets'] );
  760. $this->assertContains( 'archives-2', $sidebars_widgets['wp_inactive_widgets'] );
  761. $this->assertContains( 'meta-2', $sidebars_widgets['wp_inactive_widgets'] );
  762. $this->assertContains( 'search-2', $sidebars_widgets['wp_inactive_widgets'] );
  763. $this->assertContains( 'categories-2', $sidebars_widgets['wp_inactive_widgets'] );
  764. $this->assertContains( 'recent-posts-2', $sidebars_widgets['wp_inactive_widgets'] );
  765. $this->assertContains( 'recent-comments-2', $sidebars_widgets['wp_inactive_widgets'] );
  766. // Sidebar_widgets option was updated.
  767. $this->assertSame( $sidebars_widgets, wp_get_sidebars_widgets() );
  768. // Reset.
  769. $sidebars_widgets = array(
  770. 'sidebar-1' => array( 'tag_cloud-1' ),
  771. 'sidebar-2' => array( 'text-1' ),
  772. 'fantasy' => array( 'archives-2' ),
  773. 'wp_inactive_widgets' => array(),
  774. );
  775. // Theme did not change.
  776. $result = retrieve_widgets();
  777. $_wp_sidebars_widgets = array();
  778. $this->assertInternalType( 'array', $result );
  779. $this->assertSame( $result, $sidebars_widgets );
  780. foreach ( $sidebars_widgets as $widgets ) {
  781. $this->assertInternalType( 'array', $widgets );
  782. }
  783. // This sidebar is not registered anymore.
  784. $this->assertArrayNotHasKey( 'fantasy', $sidebars_widgets );
  785. $this->assertArrayHasKey( 'sidebar-3', $sidebars_widgets );
  786. $this->assertContains( 'tag_cloud-1', $sidebars_widgets['sidebar-1'] );
  787. $this->assertContains( 'text-1', $sidebars_widgets['sidebar-2'] );
  788. // 6 default widgets - 1 active text widget = 5.
  789. $this->assertCount( 6, $sidebars_widgets['wp_inactive_widgets'] );
  790. $this->assertContains( 'meta-2', $sidebars_widgets['wp_inactive_widgets'] );
  791. $this->assertContains( 'search-2', $sidebars_widgets['wp_inactive_widgets'] );
  792. // archives-2 ends up as inactive because fantasy sidebar doesn't exist.
  793. $this->assertContains( 'archives-2', $sidebars_widgets['wp_inactive_widgets'] );
  794. $this->assertContains( 'categories-2', $sidebars_widgets['wp_inactive_widgets'] );
  795. $this->assertContains( 'recent-posts-2', $sidebars_widgets['wp_inactive_widgets'] );
  796. $this->assertContains( 'recent-comments-2', $sidebars_widgets['wp_inactive_widgets'] );
  797. // Sidebar_widgets option was updated.
  798. $this->assertSame( $sidebars_widgets, wp_get_sidebars_widgets() );
  799. }
  800. /**
  801. * Tests for Customizer mode.
  802. *
  803. * @covers ::retrieve_widgets
  804. */
  805. function test_retrieve_widgets_for_customizer() {
  806. global $sidebars_widgets, $_wp_sidebars_widgets;
  807. wp_widgets_init();
  808. $this->register_sidebars( array( 'sidebar-1', 'sidebar-2', 'sidebar-3', 'wp_inactive_widgets' ) );
  809. $old_sidebars_widgets = array(
  810. 'sidebar-1' => array( 'tag_cloud-1' ),
  811. 'sidebar-2' => array( 'text-1' ),
  812. 'sidebar-3' => array( 'unregistered_widget-1' ),
  813. 'fantasy' => array( 'archives-2' ),
  814. 'wp_inactive_widgets' => array(),
  815. );
  816. set_theme_mod( 'sidebars_widgets', $old_sidebars_widgets );
  817. $result = retrieve_widgets( 'customize' );
  818. $_wp_sidebars_widgets = array();
  819. $this->assertInternalType( 'array', $result );
  820. $this->assertSame( $result, $sidebars_widgets );
  821. foreach ( $sidebars_widgets as $widgets ) {
  822. $this->assertInternalType( 'array', $widgets );
  823. }
  824. $this->assertContains( 'tag_cloud-1', $sidebars_widgets['sidebar-1'] );
  825. $this->assertContains( 'text-1', $sidebars_widgets['sidebar-2'] );
  826. $this->assertArrayHasKey( 'sidebar-3', $sidebars_widgets );
  827. $this->assertEmpty( $sidebars_widgets['sidebar-3'] );
  828. $this->assertCount( 6, $sidebars_widgets['wp_inactive_widgets'] );
  829. $this->assertContains( 'meta-2', $sidebars_widgets['wp_inactive_widgets'] );
  830. $this->assertContains( 'search-2', $sidebars_widgets['wp_inactive_widgets'] );
  831. $this->assertContains( 'archives-2', $sidebars_widgets['wp_inactive_widgets'] );
  832. $this->assertContains( 'categories-2', $sidebars_widgets['wp_inactive_widgets'] );
  833. $this->assertContains( 'recent-posts-2', $sidebars_widgets['wp_inactive_widgets'] );
  834. $this->assertContains( 'recent-comments-2', $sidebars_widgets['wp_inactive_widgets'] );
  835. // Theme mod with previous widgets was not removed.
  836. $this->assertSameSets( $old_sidebars_widgets, get_theme_mod( 'sidebars_widgets' ) );
  837. // Sidebar_widgets option was not updated.
  838. $this->assertNotEquals( $sidebars_widgets, wp_get_sidebars_widgets() );
  839. }
  840. function test_retreive_widgets_with_single_widget() {
  841. global $sidebars_widgets;
  842. wp_widgets_init();
  843. // Register single-dimension widget.
  844. wp_register_sidebar_widget( 'single', 'Single', '__return_false', array(), array() );
  845. wp_register_widget_control( 'single', 'Single', '__return_false', array(), array() );
  846. $this->register_sidebars( array( 'sidebar-1', 'sidebar-2', 'wp_inactive_widgets' ) );
  847. $sidebars_widgets = array(
  848. 'sidebar-1' => array( 'tag_cloud-1' ),
  849. 'wp_inactive_widgets' => array(),
  850. );
  851. // Theme changed.
  852. $result = retrieve_widgets( true );
  853. $this->assertContains( 'single', $result['wp_inactive_widgets'] );
  854. }
  855. /**
  856. * Tests for orphaned widgets being moved into inactive widgets.
  857. *
  858. * @covers ::retrieve_widgets
  859. */
  860. function test_retrieve_widgets_move_orphaned_widgets_to_inactive() {
  861. global $sidebars_widgets;
  862. wp_widgets_init();
  863. $this->register_sidebars( array( 'sidebar-1', 'sidebar-2', 'sidebar-3', 'wp_inactive_widgets' ) );
  864. $sidebars_widgets = array(
  865. 'sidebar-1' => array( 'tag_cloud-1' ),
  866. 'sidebar-2' => array( 'text-1' ),
  867. 'wp_inactive_widgets' => array( 'search-2', 'archives-2' ),
  868. 'orphaned_widgets_1' => array( 'calendar-1' ),
  869. );
  870. retrieve_widgets();
  871. $this->assertInternalType( 'array', $sidebars_widgets );
  872. foreach ( $sidebars_widgets as $widgets ) {
  873. $this->assertInternalType( 'array', $widgets );
  874. }
  875. // 6 default widgets + 1 orphaned calendar widget = 7.
  876. $this->assertCount( 7, $sidebars_widgets['wp_inactive_widgets'] );
  877. $this->assertContains( 'calendar-1', $sidebars_widgets['wp_inactive_widgets'] );
  878. $this->assertArrayNotHasKey( 'orphaned_widgets_1', $sidebars_widgets );
  879. // Sidebar_widgets option was updated.
  880. $this->assertSame( $sidebars_widgets, wp_get_sidebars_widgets() );
  881. }
  882. /**
  883. * Test _wp_remove_unregistered_widgets.
  884. *
  885. * @covers ::_wp_remove_unregistered_widgets
  886. */
  887. public function test__wp_remove_unregistered_widgets() {
  888. $widgets = array(
  889. 'sidebar-1' => array( 'tag_cloud-1' ),
  890. 'sidebar-2' => array( 'text-1' ),
  891. 'fantasy' => array( 'archives-2' ),
  892. 'wp_inactive_widgets' => array(),
  893. 'array_version' => 3,
  894. );
  895. $allowed_widgets = array( 'tag_cloud-1', 'text-1' );
  896. $filtered_widgets = _wp_remove_unregistered_widgets( $widgets, $allowed_widgets );
  897. $this->assertInternalType( 'array', $filtered_widgets );
  898. $this->assertArrayHasKey( 'fantasy', $filtered_widgets );
  899. $this->assertEmpty( $filtered_widgets['fantasy'] );
  900. $this->assertArrayHasKey( 'array_version', $filtered_widgets );
  901. $this->assertSame( 3, $filtered_widgets['array_version'] );
  902. $this->assertInternalType( 'integer', $filtered_widgets['array_version'] );
  903. }
  904. /**
  905. * wp_map_sidebars_widgets Tests.
  906. */
  907. /**
  908. * Two themes with one sidebar each should just map, switching to a theme not previously-active.
  909. *
  910. * @covers ::wp_map_sidebars_widgets
  911. */
  912. public function test_one_sidebar_each() {
  913. $this->register_sidebars( array( 'primary' ) );
  914. $prev_theme_sidebars = array(
  915. 'unique-slug' => 1,
  916. );
  917. $new_next_theme_sidebars = wp_map_sidebars_widgets( $prev_theme_sidebars );
  918. $expected_sidebars = array(
  919. 'primary' => 1,
  920. 'wp_inactive_widgets' => array(),
  921. );
  922. $this->assertEquals( $expected_sidebars, $new_next_theme_sidebars );
  923. }
  924. /**
  925. * Sidebars with the same name should map, switching to a theme not previously-active.
  926. *
  927. * @covers ::wp_map_sidebars_widgets
  928. */
  929. public function test_sidebars_with_same_slug() {
  930. $this->register_sidebars( array( 'primary', 'secondary' ) );
  931. $prev_theme_sidebars = array(
  932. 'primary' => 1,
  933. 'secondary' => 2,
  934. 'wp_inactive_widgets' => array(),
  935. );
  936. $new_next_theme_sidebars = wp_map_sidebars_widgets( $prev_theme_sidebars );
  937. $this->assertEquals( $prev_theme_sidebars, $new_next_theme_sidebars );
  938. }
  939. /**
  940. * Make educated guesses on theme sidebars.
  941. *
  942. * @covers ::wp_map_sidebars_widgets
  943. */
  944. public function test_sidebar_guessing() {
  945. $this->register_sidebars( array( 'primary', 'secondary' ) );
  946. $prev_theme_sidebars = array(
  947. 'header' => array(),
  948. 'footer' => array(),
  949. );
  950. $new_next_theme_sidebars = wp_map_sidebars_widgets( $prev_theme_sidebars );
  951. $expected_sidebars = array(
  952. 'primary' => array(),
  953. 'secondary' => array(),
  954. 'wp_inactive_widgets' => array(),
  955. );
  956. $this->assertEquals( $expected_sidebars, $new_next_theme_sidebars );
  957. }
  958. /**
  959. * Make sure two sidebars that fall in the same group don't get the same menu assigned.
  960. *
  961. * @covers ::wp_map_sidebars_widgets
  962. */
  963. public function test_sidebar_guessing_one_menu_per_group() {
  964. $this->register_sidebars( array( 'primary' ) );
  965. $prev_theme_sidebars = array(
  966. 'top-menu' => array(),
  967. 'secondary' => array(),
  968. );
  969. $new_next_theme_sidebars = wp_map_sidebars_widgets( $prev_theme_sidebars );
  970. $expected_sidebars = array(
  971. 'main' => array(),
  972. 'wp_inactive_widgets' => array(),
  973. );
  974. $this->assertSameSets( $expected_sidebars, $new_next_theme_sidebars );
  975. }
  976. /**
  977. * Make sure two sidebars that fall in the same group get menus assigned from the same group.
  978. *
  979. * @covers ::wp_map_sidebars_widgets
  980. */
  981. public function test_sidebar_guessing_one_menu_per_sidebar() {
  982. $this->register_sidebars( array( 'primary', 'main' ) );
  983. $prev_theme_sidebars = array(
  984. 'navigation-menu' => array(),
  985. 'top-menu' => array(),
  986. );
  987. $new_next_theme_sidebars = wp_map_sidebars_widgets( $prev_theme_sidebars );
  988. $expected_sidebars = array(
  989. 'main' => array(),
  990. 'primary' => array(),
  991. 'wp_inactive_widgets' => array(),
  992. );
  993. $this->assertEquals( $expected_sidebars, $new_next_theme_sidebars );
  994. }
  995. }