rest-themes-controller.php 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. <?php
  2. /**
  3. * Unit tests covering WP_REST_Themes_Controller functionality.
  4. *
  5. * @package WordPress
  6. * @subpackage REST API
  7. */
  8. /**
  9. * @group restapi-themes
  10. * @group restapi
  11. */
  12. class WP_Test_REST_Themes_Controller extends WP_Test_REST_Controller_Testcase {
  13. /**
  14. * Subscriber user ID.
  15. *
  16. * @since 5.0.0
  17. *
  18. * @var int $subscriber_id
  19. */
  20. protected static $subscriber_id;
  21. /**
  22. * Contributor user ID.
  23. *
  24. * @since 5.0.0
  25. *
  26. * @var int $contributor_id
  27. */
  28. protected static $contributor_id;
  29. /**
  30. * Admin user ID.
  31. *
  32. * @since 5.7.0
  33. *
  34. * @var int $admin_id
  35. */
  36. protected static $admin_id;
  37. /**
  38. * The current theme object.
  39. *
  40. * @since 5.0.0
  41. *
  42. * @var WP_Theme $current_theme
  43. */
  44. protected static $current_theme;
  45. /**
  46. * The REST API route for themes.
  47. *
  48. * @since 5.0.0
  49. *
  50. * @var string $themes_route
  51. */
  52. protected static $themes_route = '/wp/v2/themes';
  53. /**
  54. * Performs a REST API request for the active theme.
  55. *
  56. * @since 5.0.0
  57. *
  58. * @param string $method Optional. Request method. Default GET.
  59. * @return WP_REST_Response The request's response.
  60. */
  61. protected function perform_active_theme_request( $method = 'GET' ) {
  62. $request = new WP_REST_Request( $method, self::$themes_route );
  63. $request->set_param( 'status', 'active' );
  64. return rest_get_server()->dispatch( $request );
  65. }
  66. /**
  67. * Check that common properties are included in a response.
  68. *
  69. * @since 5.0.0
  70. *
  71. * @param WP_REST_Response $response Current REST API response.
  72. */
  73. protected function check_get_theme_response( $response ) {
  74. if ( $response instanceof WP_REST_Response ) {
  75. $headers = $response->get_headers();
  76. $response = $response->get_data();
  77. } else {
  78. $headers = array();
  79. }
  80. $this->assertArrayHasKey( 'X-WP-Total', $headers );
  81. $this->assertSame( 1, $headers['X-WP-Total'] );
  82. $this->assertArrayHasKey( 'X-WP-TotalPages', $headers );
  83. $this->assertSame( 1, $headers['X-WP-TotalPages'] );
  84. }
  85. /**
  86. * Set up class test fixtures.
  87. *
  88. * @since 5.0.0
  89. *
  90. * @param WP_UnitTest_Factory $factory WordPress unit test factory.
  91. */
  92. public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
  93. self::$admin_id = $factory->user->create(
  94. array(
  95. 'role' => 'administrator',
  96. )
  97. );
  98. self::$subscriber_id = $factory->user->create(
  99. array(
  100. 'role' => 'subscriber',
  101. )
  102. );
  103. self::$contributor_id = $factory->user->create(
  104. array(
  105. 'role' => 'contributor',
  106. )
  107. );
  108. self::$current_theme = wp_get_theme();
  109. wp_set_current_user( self::$contributor_id );
  110. }
  111. /**
  112. * Clean up test fixtures.
  113. *
  114. * @since 5.0.0
  115. */
  116. public static function wpTearDownAfterClass() {
  117. self::delete_user( self::$subscriber_id );
  118. self::delete_user( self::$contributor_id );
  119. self::delete_user( self::$admin_id );
  120. }
  121. /**
  122. * Set up each test method.
  123. *
  124. * @since 5.0.0
  125. */
  126. public function setUp() {
  127. parent::setUp();
  128. wp_set_current_user( self::$contributor_id );
  129. switch_theme( 'rest-api' );
  130. }
  131. /**
  132. * Theme routes should be registered correctly.
  133. *
  134. * @ticket 45016
  135. */
  136. public function test_register_routes() {
  137. $routes = rest_get_server()->get_routes();
  138. $this->assertArrayHasKey( self::$themes_route, $routes );
  139. $this->assertArrayHasKey( self::$themes_route . '/(?P<stylesheet>[\\w-]+)', $routes );
  140. }
  141. /**
  142. * Test retrieving a collection of themes.
  143. *
  144. * @ticket 45016
  145. */
  146. public function test_get_items() {
  147. $response = self::perform_active_theme_request();
  148. $this->assertSame( 200, $response->get_status() );
  149. $data = $response->get_data();
  150. $this->check_get_theme_response( $response );
  151. $fields = array(
  152. '_links',
  153. 'author',
  154. 'author_uri',
  155. 'description',
  156. 'name',
  157. 'requires_php',
  158. 'requires_wp',
  159. 'screenshot',
  160. 'status',
  161. 'stylesheet',
  162. 'tags',
  163. 'template',
  164. 'textdomain',
  165. 'theme_supports',
  166. 'theme_uri',
  167. 'version',
  168. );
  169. $this->assertSameSets( $fields, array_keys( $data[0] ) );
  170. }
  171. /**
  172. * Test retrieving a collection of inactive themes.
  173. *
  174. * @ticket 50152
  175. */
  176. public function test_get_items_inactive() {
  177. wp_set_current_user( self::$admin_id );
  178. $request = new WP_REST_Request( 'GET', self::$themes_route );
  179. $request->set_param( 'status', 'inactive' );
  180. $response = rest_get_server()->dispatch( $request );
  181. $this->assertSame( 200, $response->get_status() );
  182. $data = $response->get_data();
  183. $fields = array(
  184. '_links',
  185. 'author',
  186. 'author_uri',
  187. 'description',
  188. 'name',
  189. 'requires_php',
  190. 'requires_wp',
  191. 'screenshot',
  192. 'status',
  193. 'stylesheet',
  194. 'tags',
  195. 'template',
  196. 'textdomain',
  197. 'theme_uri',
  198. 'version',
  199. );
  200. $this->assertEqualSets( $fields, array_keys( $data[0] ) );
  201. $this->assertContains( 'twentytwenty', wp_list_pluck( $data, 'stylesheet' ) );
  202. $this->assertNotContains( get_stylesheet(), wp_list_pluck( $data, 'stylesheet' ) );
  203. }
  204. /**
  205. * Test retrieving a collection of inactive themes.
  206. *
  207. * @ticket 50152
  208. */
  209. public function test_get_items_active_and_inactive() {
  210. wp_set_current_user( self::$admin_id );
  211. $request = new WP_REST_Request( 'GET', self::$themes_route );
  212. $request->set_param( 'status', array( 'active', 'inactive' ) );
  213. $response = rest_get_server()->dispatch( $request );
  214. $this->assertSame( 200, $response->get_status() );
  215. $data = $response->get_data();
  216. $this->assertContains( 'twentytwenty', wp_list_pluck( $data, 'stylesheet' ) );
  217. $this->assertContains( get_stylesheet(), wp_list_pluck( $data, 'stylesheet' ) );
  218. }
  219. /**
  220. * @ticket 46723
  221. * @ticket 50152
  222. * @dataProvider data_get_items_by_status
  223. */
  224. public function test_get_items_logged_out( $status, $error_code ) {
  225. wp_set_current_user( 0 );
  226. $request = new WP_REST_Request( 'GET', self::$themes_route );
  227. $request->set_param( 'status', $status );
  228. $response = rest_get_server()->dispatch( $request );
  229. $this->assertErrorResponse( $error_code, $response, 401 );
  230. }
  231. /**
  232. * An error should be returned when the user does not have the edit_posts capability.
  233. *
  234. * @ticket 45016
  235. * @ticket 50152
  236. * @dataProvider data_get_items_by_status
  237. */
  238. public function test_get_items_no_permission( $status, $error_code ) {
  239. wp_set_current_user( self::$subscriber_id );
  240. $request = new WP_REST_Request( 'GET', self::$themes_route );
  241. $request->set_param( 'status', $status );
  242. $response = rest_get_server()->dispatch( $request );
  243. $this->assertErrorResponse( $error_code, $response, 403 );
  244. }
  245. public function data_get_items_by_status() {
  246. return array(
  247. array( 'active', 'rest_cannot_view_active_theme' ),
  248. array( 'active, inactive', 'rest_cannot_view_themes' ),
  249. array( 'inactive', 'rest_cannot_view_themes' ),
  250. array( '', 'rest_cannot_view_themes' ),
  251. );
  252. }
  253. /**
  254. * @ticket 50152
  255. * @dataProvider data_get_items_by_status_for_contributor
  256. */
  257. public function test_get_items_contributor( $status, $error_code ) {
  258. wp_set_current_user( self::$contributor_id );
  259. $request = new WP_REST_Request( 'GET', self::$themes_route );
  260. $request->set_param( 'status', $status );
  261. $response = rest_get_server()->dispatch( $request );
  262. if ( $error_code ) {
  263. $this->assertErrorResponse( $error_code, $response, 403 );
  264. } else {
  265. $this->assertSame( 200, $response->get_status() );
  266. }
  267. }
  268. public function data_get_items_by_status_for_contributor() {
  269. return array(
  270. array( 'active', '' ),
  271. array( 'active, inactive', 'rest_cannot_view_themes' ),
  272. array( 'inactive', 'rest_cannot_view_themes' ),
  273. array( '', 'rest_cannot_view_themes' ),
  274. );
  275. }
  276. /**
  277. * @ticket 46723
  278. */
  279. public function test_get_item_single_post_type_cap() {
  280. $user = self::factory()->user->create_and_get();
  281. $user->add_cap( 'edit_pages' );
  282. wp_set_current_user( $user->ID );
  283. $response = self::perform_active_theme_request();
  284. $this->assertSame( 200, $response->get_status() );
  285. }
  286. /**
  287. * Test an item is prepared for the response.
  288. *
  289. * @ticket 45016
  290. */
  291. public function test_prepare_item() {
  292. $response = self::perform_active_theme_request();
  293. $this->assertSame( 200, $response->get_status() );
  294. $this->check_get_theme_response( $response );
  295. }
  296. /**
  297. * Verify the theme schema.
  298. *
  299. * @ticket 45016
  300. */
  301. public function test_get_item_schema() {
  302. $response = self::perform_active_theme_request( 'OPTIONS' );
  303. $data = $response->get_data();
  304. $properties = $data['schema']['properties'];
  305. $this->assertSame( 15, count( $properties ) );
  306. $this->assertArrayHasKey( 'author', $properties );
  307. $this->assertArrayHasKey( 'raw', $properties['author']['properties'] );
  308. $this->assertArrayHasKey( 'rendered', $properties['author']['properties'] );
  309. $this->assertArrayHasKey( 'author_uri', $properties );
  310. $this->assertArrayHasKey( 'raw', $properties['author_uri']['properties'] );
  311. $this->assertArrayHasKey( 'rendered', $properties['author_uri']['properties'] );
  312. $this->assertArrayHasKey( 'description', $properties );
  313. $this->assertArrayHasKey( 'raw', $properties['description']['properties'] );
  314. $this->assertArrayHasKey( 'rendered', $properties['description']['properties'] );
  315. $this->assertArrayHasKey( 'name', $properties );
  316. $this->assertArrayHasKey( 'raw', $properties['name']['properties'] );
  317. $this->assertArrayHasKey( 'rendered', $properties['name']['properties'] );
  318. $this->assertArrayHasKey( 'requires_php', $properties );
  319. $this->assertArrayHasKey( 'requires_wp', $properties );
  320. $this->assertArrayHasKey( 'screenshot', $properties );
  321. $this->assertArrayHasKey( 'status', $properties );
  322. $this->assertArrayHasKey( 'stylesheet', $properties );
  323. $this->assertArrayHasKey( 'tags', $properties );
  324. $this->assertArrayHasKey( 'raw', $properties['tags']['properties'] );
  325. $this->assertArrayHasKey( 'items', $properties['tags']['properties']['raw'] );
  326. $this->assertArrayHasKey( 'rendered', $properties['tags']['properties'] );
  327. $this->assertArrayHasKey( 'template', $properties );
  328. $this->assertArrayHasKey( 'textdomain', $properties );
  329. $this->assertArrayHasKey( 'theme_supports', $properties );
  330. $this->assertArrayHasKey( 'theme_uri', $properties );
  331. $this->assertArrayHasKey( 'raw', $properties['theme_uri']['properties'] );
  332. $this->assertArrayHasKey( 'rendered', $properties['theme_uri']['properties'] );
  333. $this->assertArrayHasKey( 'version', $properties );
  334. $theme_supports = $properties['theme_supports']['properties'];
  335. $this->assertArrayHasKey( 'align-wide', $theme_supports );
  336. $this->assertArrayHasKey( 'automatic-feed-links', $theme_supports );
  337. $this->assertArrayHasKey( 'custom-header', $theme_supports );
  338. $this->assertArrayHasKey( 'custom-background', $theme_supports );
  339. $this->assertArrayHasKey( 'custom-logo', $theme_supports );
  340. $this->assertArrayHasKey( 'customize-selective-refresh-widgets', $theme_supports );
  341. $this->assertArrayHasKey( 'title-tag', $theme_supports );
  342. $this->assertArrayHasKey( 'dark-editor-style', $theme_supports );
  343. $this->assertArrayHasKey( 'disable-custom-font-sizes', $theme_supports );
  344. $this->assertArrayHasKey( 'disable-custom-gradients', $theme_supports );
  345. $this->assertArrayHasKey( 'editor-color-palette', $theme_supports );
  346. $this->assertArrayHasKey( 'editor-font-sizes', $theme_supports );
  347. $this->assertArrayHasKey( 'editor-gradient-presets', $theme_supports );
  348. $this->assertArrayHasKey( 'editor-styles', $theme_supports );
  349. $this->assertArrayHasKey( 'formats', $theme_supports );
  350. $this->assertArrayHasKey( 'html5', $theme_supports );
  351. $this->assertArrayHasKey( 'post-thumbnails', $theme_supports );
  352. $this->assertArrayHasKey( 'responsive-embeds', $theme_supports );
  353. $this->assertArrayHasKey( 'title-tag', $theme_supports );
  354. $this->assertArrayHasKey( 'wp-block-styles', $theme_supports );
  355. $this->assertCount( 20, $theme_supports );
  356. }
  357. /**
  358. * @ticket 49906
  359. */
  360. public function test_theme_author() {
  361. $response = self::perform_active_theme_request();
  362. $result = $response->get_data();
  363. $this->assertArrayHasKey( 'author', $result[0] );
  364. $this->assertSame( 'Michael Heilemann', $result[0]['author']['raw'] );
  365. $this->assertSame(
  366. '<a href="http://binarybonsai.com/?search=1&#038;term=2">Michael Heilemann</a>',
  367. $result[0]['author']['rendered']
  368. );
  369. }
  370. /**
  371. * @ticket 49906
  372. */
  373. public function test_theme_author_uri() {
  374. $response = self::perform_active_theme_request();
  375. $result = $response->get_data();
  376. $this->assertArrayHasKey( 'author_uri', $result[0] );
  377. $this->assertSame( 'http://binarybonsai.com/?search=1&term=2', $result[0]['author_uri']['raw'] );
  378. $this->assertSame( 'http://binarybonsai.com/?search=1&#038;term=2', $result[0]['author_uri']['rendered'] );
  379. }
  380. /**
  381. * @ticket 49906
  382. */
  383. public function test_theme_description() {
  384. $response = self::perform_active_theme_request();
  385. $result = $response->get_data();
  386. $this->assertArrayHasKey( 'description', $result[0] );
  387. $this->assertSame(
  388. 'The 9\' foot tall theme.',
  389. $result[0]['description']['raw']
  390. );
  391. $this->assertSame(
  392. 'The 9&#8242; foot tall theme.',
  393. $result[0]['description']['rendered']
  394. );
  395. }
  396. /**
  397. * @ticket 49906
  398. */
  399. public function test_theme_requires_php() {
  400. $response = self::perform_active_theme_request();
  401. $result = $response->get_data();
  402. $this->assertArrayHasKey( 'requires_php', $result[0] );
  403. $this->assertSame( '5.6', $result[0]['requires_php'] );
  404. }
  405. /**
  406. * @ticket 49906
  407. */
  408. public function test_theme_requires_wp() {
  409. $response = self::perform_active_theme_request();
  410. $result = $response->get_data();
  411. $this->assertArrayHasKey( 'requires_wp', $result[0] );
  412. $this->assertSame( '5.3', $result[0]['requires_wp'] );
  413. }
  414. /**
  415. * @ticket 49906
  416. */
  417. public function test_theme_name() {
  418. $response = self::perform_active_theme_request();
  419. $result = $response->get_data();
  420. $this->assertArrayHasKey( 'name', $result[0] );
  421. $this->assertSame( 'REST Theme', $result[0]['name']['raw'] );
  422. $this->assertSame( 'REST Theme', $result[0]['name']['rendered'] );
  423. }
  424. /**
  425. * @ticket 49906
  426. */
  427. public function test_theme_screenshot() {
  428. $response = self::perform_active_theme_request();
  429. $result = $response->get_data();
  430. $this->assertArrayHasKey( 'screenshot', $result[0] );
  431. $this->assertSame( '', $result[0]['screenshot'] ); // No screenshot for default theme
  432. }
  433. /**
  434. * @ticket 49906
  435. */
  436. public function test_theme_stylesheet() {
  437. $response = self::perform_active_theme_request();
  438. $result = $response->get_data();
  439. $this->assertArrayHasKey( 'stylesheet', $result[0] );
  440. $this->assertSame( 'rest-api', $result[0]['stylesheet'] );
  441. }
  442. /**
  443. * @ticket 49906
  444. */
  445. public function test_theme_tags() {
  446. $response = self::perform_active_theme_request();
  447. $result = $response->get_data();
  448. $this->assertArrayHasKey( 'tags', $result[0] );
  449. $this->assertSame( array( 'holiday', 'custom-menu' ), $result[0]['tags']['raw'] );
  450. $this->assertSame( 'holiday, custom-menu', $result[0]['tags']['rendered'] );
  451. }
  452. /**
  453. * @ticket 49906
  454. */
  455. public function test_theme_template() {
  456. $response = self::perform_active_theme_request();
  457. $result = $response->get_data();
  458. $this->assertArrayHasKey( 'template', $result[0] );
  459. $this->assertSame( 'default', $result[0]['template'] );
  460. }
  461. /**
  462. * @ticket 49906
  463. */
  464. public function test_theme_textdomain() {
  465. $response = self::perform_active_theme_request();
  466. $result = $response->get_data();
  467. $this->assertArrayHasKey( 'textdomain', $result[0] );
  468. $this->assertSame( 'rest-api', $result[0]['textdomain'] );
  469. }
  470. public function test_theme_theme_uri() {
  471. $response = self::perform_active_theme_request();
  472. $result = $response->get_data();
  473. $this->assertArrayHasKey( 'theme_uri', $result[0] );
  474. $this->assertSame( 'http://wordpress.org/?search=1&term=2', $result[0]['theme_uri']['raw'] );
  475. $this->assertSame( 'http://wordpress.org/?search=1&#038;term=2', $result[0]['theme_uri']['rendered'] );
  476. }
  477. /**
  478. * @ticket 49906
  479. */
  480. public function test_theme_version() {
  481. $response = self::perform_active_theme_request();
  482. $result = $response->get_data();
  483. $this->assertArrayHasKey( 'version', $result[0] );
  484. $this->assertSame( '1.6', $result[0]['version'] );
  485. }
  486. /**
  487. * @ticket 49037
  488. */
  489. public function test_theme_supports_disable_custom_colors_false() {
  490. remove_theme_support( 'disable-custom-colors' );
  491. $response = self::perform_active_theme_request();
  492. $result = $response->get_data();
  493. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  494. $this->assertArrayHasKey( 'disable-custom-colors', $result[0]['theme_supports'] );
  495. $this->assertFalse( $result[0]['theme_supports']['disable-custom-colors'] );
  496. }
  497. /**
  498. * @ticket 49037
  499. */
  500. public function test_theme_supports_disable_custom_colors_true() {
  501. remove_theme_support( 'disable-custom-colors' );
  502. add_theme_support( 'disable-custom-colors' );
  503. $response = self::perform_active_theme_request();
  504. $result = $response->get_data();
  505. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  506. $this->assertTrue( $result[0]['theme_supports']['disable-custom-colors'] );
  507. }
  508. /**
  509. * @ticket 49037
  510. */
  511. public function test_theme_supports_disable_custom_font_sizes_false() {
  512. remove_theme_support( 'disable-custom-font-sizes' );
  513. $response = self::perform_active_theme_request();
  514. $result = $response->get_data();
  515. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  516. $this->assertArrayHasKey( 'disable-custom-font-sizes', $result[0]['theme_supports'] );
  517. $this->assertFalse( $result[0]['theme_supports']['disable-custom-font-sizes'] );
  518. }
  519. /**
  520. * @ticket 49037
  521. */
  522. public function test_theme_supports_disable_custom_font_sizes_true() {
  523. remove_theme_support( 'disable-custom-font-sizes' );
  524. add_theme_support( 'disable-custom-font-sizes' );
  525. $response = self::perform_active_theme_request();
  526. $result = $response->get_data();
  527. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  528. $this->assertTrue( $result[0]['theme_supports']['disable-custom-font-sizes'] );
  529. }
  530. /**
  531. * @ticket 49037
  532. */
  533. public function test_theme_supports_editor_font_sizes_false() {
  534. remove_theme_support( 'editor-font-sizes' );
  535. $response = self::perform_active_theme_request();
  536. $result = $response->get_data();
  537. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  538. $this->assertArrayHasKey( 'editor-font-sizes', $result[0]['theme_supports'] );
  539. $this->assertFalse( $result[0]['theme_supports']['editor-font-sizes'] );
  540. }
  541. /**
  542. * @ticket 49037
  543. */
  544. public function test_theme_supports_editor_font_sizes_array() {
  545. remove_theme_support( 'editor-font-sizes' );
  546. $tiny = array(
  547. 'name' => 'Tiny',
  548. 'size' => 8,
  549. 'slug' => 'tiny',
  550. );
  551. add_theme_support( 'editor-font-sizes', array( $tiny ) );
  552. $response = self::perform_active_theme_request();
  553. $result = $response->get_data();
  554. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  555. $this->assertArrayHasKey( 'editor-font-sizes', $result[0]['theme_supports'] );
  556. $this->assertEquals( array( $tiny ), $result[0]['theme_supports']['editor-font-sizes'] );
  557. }
  558. /**
  559. * @ticket 49037
  560. */
  561. public function test_theme_supports_editor_color_palette_false() {
  562. remove_theme_support( 'editor-color-palette' );
  563. $response = self::perform_active_theme_request();
  564. $result = $response->get_data();
  565. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  566. $this->assertArrayHasKey( 'editor-color-palette', $result[0]['theme_supports'] );
  567. $this->assertFalse( $result[0]['theme_supports']['editor-color-palette'] );
  568. }
  569. /**
  570. * @ticket 49037
  571. */
  572. public function test_theme_supports_editor_color_palette_array() {
  573. remove_theme_support( 'editor-color-palette' );
  574. $wordpress_blue = array(
  575. 'name' => 'WordPress Blue',
  576. 'slug' => 'wordpress-blue',
  577. 'color' => '#0073AA',
  578. );
  579. add_theme_support( 'editor-color-palette', array( $wordpress_blue ) );
  580. $response = self::perform_active_theme_request();
  581. $result = $response->get_data();
  582. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  583. $this->assertSame( array( $wordpress_blue ), $result[0]['theme_supports']['editor-color-palette'] );
  584. }
  585. /**
  586. * @ticket 49037
  587. */
  588. public function test_theme_supports_enable_automatic_feed_links() {
  589. remove_theme_support( 'automatic-feed-links' );
  590. add_theme_support( 'automatic-feed-links' );
  591. $response = self::perform_active_theme_request();
  592. $result = $response->get_data();
  593. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  594. $this->assertTrue( $result[0]['theme_supports']['automatic-feed-links'] );
  595. }
  596. /**
  597. * @ticket 49037
  598. */
  599. public function test_theme_supports_does_not_enable_automatic_feed_links() {
  600. remove_theme_support( 'automatic-feed-links' );
  601. $response = self::perform_active_theme_request();
  602. $result = $response->get_data();
  603. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  604. $this->assertArrayHasKey( 'automatic-feed-links', $result[0]['theme_supports'] );
  605. $this->assertFalse( $result[0]['theme_supports']['automatic-feed-links'] );
  606. }
  607. /**
  608. * @ticket 49037
  609. */
  610. public function test_theme_does_not_support_custom_logo() {
  611. remove_theme_support( 'custom-logo' );
  612. $response = self::perform_active_theme_request();
  613. $result = $response->get_data();
  614. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  615. $this->assertArrayHasKey( 'custom-logo', $result[0]['theme_supports'] );
  616. $this->assertFalse( $result[0]['theme_supports']['custom-logo'] );
  617. }
  618. /**
  619. * @ticket 49037
  620. */
  621. public function test_theme_supports_custom_logo() {
  622. remove_theme_support( 'custom-logo' );
  623. $wordpress_logo = array(
  624. 'width' => 400,
  625. 'height' => 100,
  626. 'flex-width' => true,
  627. 'flex-height' => true,
  628. 'header-text' => array( 'site-title', 'site-description' ),
  629. 'unlink-homepage-logo' => false,
  630. );
  631. add_theme_support( 'custom-logo', $wordpress_logo );
  632. $response = self::perform_active_theme_request();
  633. $result = $response->get_data();
  634. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  635. $this->assertSame( $wordpress_logo, $result[0]['theme_supports']['custom-logo'] );
  636. }
  637. /**
  638. * @ticket 49037
  639. */
  640. public function test_theme_does_not_support_custom_header() {
  641. remove_theme_support( 'custom-header' );
  642. $response = self::perform_active_theme_request();
  643. $result = $response->get_data();
  644. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  645. $this->assertArrayHasKey( 'custom-header', $result[0]['theme_supports'] );
  646. $this->assertFalse( $result[0]['theme_supports']['custom-header'] );
  647. }
  648. /**
  649. * @ticket 49037
  650. */
  651. public function test_theme_supports_custom_header() {
  652. remove_theme_support( 'custom-header' );
  653. $wordpress_header = array(
  654. 'default-image' => '',
  655. 'random-default' => false,
  656. 'width' => 0,
  657. 'height' => 0,
  658. 'flex-height' => false,
  659. 'flex-width' => false,
  660. 'default-text-color' => '',
  661. 'header-text' => true,
  662. 'uploads' => true,
  663. 'wp-head-callback' => '',
  664. 'admin-head-callback' => '',
  665. 'admin-preview-callback' => '',
  666. 'video' => false,
  667. 'video-active-callback' => 'is_front_page',
  668. );
  669. $excluded = array(
  670. 'wp-head-callback',
  671. 'admin-head-callback',
  672. 'admin-preview-callback',
  673. 'video-active-callback',
  674. );
  675. add_theme_support( 'custom-header', $wordpress_header );
  676. $response = self::perform_active_theme_request();
  677. $result = $response->get_data();
  678. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  679. $expected = array_diff_key( $wordpress_header, array_flip( $excluded ) );
  680. $this->assertSame( $expected, $result[0]['theme_supports']['custom-header'] );
  681. }
  682. /**
  683. * @ticket 49037
  684. */
  685. public function test_theme_does_not_support_custom_background() {
  686. remove_theme_support( 'custom-background' );
  687. $response = self::perform_active_theme_request();
  688. $result = $response->get_data();
  689. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  690. $this->assertArrayHasKey( 'custom-background', $result[0]['theme_supports'] );
  691. $this->assertFalse( $result[0]['theme_supports']['custom-background'] );
  692. }
  693. /**
  694. * @ticket 49037
  695. */
  696. public function test_theme_supports_custom_background() {
  697. remove_theme_support( 'custom-background' );
  698. $background = array(
  699. 'default-image' => '',
  700. 'default-preset' => 'default',
  701. 'default-position-x' => 'left',
  702. 'default-position-y' => 'top',
  703. 'default-size' => 'auto',
  704. 'default-repeat' => 'repeat',
  705. 'default-attachment' => 'scroll',
  706. 'default-color' => '',
  707. 'wp-head-callback' => '_custom_background_cb',
  708. 'admin-head-callback' => '',
  709. 'admin-preview-callback' => '',
  710. );
  711. $excluded = array(
  712. 'wp-head-callback',
  713. 'admin-head-callback',
  714. 'admin-preview-callback',
  715. );
  716. add_theme_support( 'custom-background', $background );
  717. $response = self::perform_active_theme_request();
  718. $result = $response->get_data();
  719. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  720. $expected = array_diff_key( $background, array_flip( $excluded ) );
  721. $this->assertSame( $expected, $result[0]['theme_supports']['custom-background'] );
  722. }
  723. /**
  724. * @ticket 49037
  725. */
  726. public function test_theme_does_not_support_html5() {
  727. remove_theme_support( 'html5' );
  728. $response = self::perform_active_theme_request();
  729. $result = $response->get_data();
  730. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  731. $this->assertArrayHasKey( 'html5', $result[0]['theme_supports'] );
  732. $this->assertFalse( $result[0]['theme_supports']['html5'] );
  733. }
  734. /**
  735. * @ticket 49037
  736. */
  737. public function test_theme_supports_html5() {
  738. remove_theme_support( 'html5' );
  739. $html5 = array(
  740. 'search-form',
  741. 'comment-form',
  742. 'comment-list',
  743. 'gallery',
  744. 'caption',
  745. 'script',
  746. 'style',
  747. );
  748. add_theme_support( 'html5', $html5 );
  749. $response = self::perform_active_theme_request();
  750. $result = $response->get_data();
  751. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  752. $this->assertSame( $html5, $result[0]['theme_supports']['html5'] );
  753. }
  754. /**
  755. * @ticket 49037
  756. */
  757. public function test_theme_cannot_manage_title_tag() {
  758. remove_theme_support( 'title-tag' );
  759. $response = self::perform_active_theme_request();
  760. $result = $response->get_data();
  761. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  762. $this->assertArrayHasKey( 'title-tag', $result[0]['theme_supports'] );
  763. $this->assertFalse( $result[0]['theme_supports']['title-tag'] );
  764. }
  765. /**
  766. * @ticket 49037
  767. */
  768. public function test_theme_can_manage_title_tag() {
  769. global $_wp_theme_features;
  770. $_wp_theme_features['title-tag'] = true;
  771. $response = self::perform_active_theme_request();
  772. $result = $response->get_data();
  773. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  774. $this->assertTrue( $result[0]['theme_supports']['title-tag'] );
  775. }
  776. /**
  777. * @ticket 49037
  778. */
  779. public function test_theme_cannot_manage_selective_refresh_for_widgets() {
  780. remove_theme_support( 'customize-selective-refresh-widgets' );
  781. $response = self::perform_active_theme_request();
  782. $result = $response->get_data();
  783. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  784. $this->assertArrayHasKey( 'customize-selective-refresh-widgets', $result[0]['theme_supports'] );
  785. $this->assertFalse( $result[0]['theme_supports']['customize-selective-refresh-widgets'] );
  786. }
  787. /**
  788. * @ticket 49037
  789. */
  790. public function test_theme_can_manage_selective_refresh_for_widgets() {
  791. remove_theme_support( 'customize-selective-refresh-widgets' );
  792. add_theme_support( 'customize-selective-refresh-widgets' );
  793. $response = self::perform_active_theme_request();
  794. $result = $response->get_data();
  795. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  796. $this->assertTrue( $result[0]['theme_supports']['customize-selective-refresh-widgets'] );
  797. }
  798. /**
  799. * @ticket 49037
  800. */
  801. public function test_theme_no_wp_block_styles() {
  802. remove_theme_support( 'wp-block-styles' );
  803. $response = self::perform_active_theme_request();
  804. $result = $response->get_data();
  805. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  806. $this->assertArrayHasKey( 'wp-block-styles', $result[0]['theme_supports'] );
  807. $this->assertFalse( $result[0]['theme_supports']['wp-block-styles'] );
  808. }
  809. /**
  810. * @ticket 49037
  811. */
  812. public function test_theme_wp_block_styles_optin() {
  813. remove_theme_support( 'wp-block-styles' );
  814. add_theme_support( 'wp-block-styles' );
  815. $response = self::perform_active_theme_request();
  816. $result = $response->get_data();
  817. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  818. $this->assertTrue( $result[0]['theme_supports']['wp-block-styles'] );
  819. }
  820. /**
  821. * @ticket 49037
  822. */
  823. public function test_theme_no_align_wide() {
  824. remove_theme_support( 'align-wide' );
  825. $response = self::perform_active_theme_request();
  826. $result = $response->get_data();
  827. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  828. $this->assertArrayHasKey( 'align-wide', $result[0]['theme_supports'] );
  829. $this->assertFalse( $result[0]['theme_supports']['align-wide'] );
  830. }
  831. /**
  832. * @ticket 49037
  833. */
  834. public function test_theme_align_wide_optin() {
  835. remove_theme_support( 'align-wide' );
  836. add_theme_support( 'align-wide' );
  837. $response = self::perform_active_theme_request();
  838. $result = $response->get_data();
  839. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  840. $this->assertTrue( $result[0]['theme_supports']['align-wide'] );
  841. }
  842. /**
  843. * @ticket 49037
  844. */
  845. public function test_theme_no_editor_styles() {
  846. remove_theme_support( 'editor-styles' );
  847. $response = self::perform_active_theme_request();
  848. $result = $response->get_data();
  849. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  850. $this->assertArrayHasKey( 'editor-styles', $result[0]['theme_supports'] );
  851. $this->assertFalse( $result[0]['theme_supports']['editor-styles'] );
  852. }
  853. /**
  854. * @ticket 49037
  855. */
  856. public function test_theme_editor_styles_optin() {
  857. remove_theme_support( 'editor-styles' );
  858. add_theme_support( 'editor-styles' );
  859. $response = self::perform_active_theme_request();
  860. $result = $response->get_data();
  861. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  862. $this->assertTrue( $result[0]['theme_supports']['editor-styles'] );
  863. }
  864. /**
  865. * @ticket 49037
  866. */
  867. public function test_theme_no_dark_editor_style() {
  868. remove_theme_support( 'dark-editor-style' );
  869. $response = self::perform_active_theme_request();
  870. $result = $response->get_data();
  871. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  872. $this->assertArrayHasKey( 'dark-editor-style', $result[0]['theme_supports'] );
  873. $this->assertFalse( $result[0]['theme_supports']['dark-editor-style'] );
  874. }
  875. /**
  876. * @ticket 49037
  877. */
  878. public function test_theme_dark_editor_style_optin() {
  879. remove_theme_support( 'dark-editor-style' );
  880. add_theme_support( 'dark-editor-style' );
  881. $response = self::perform_active_theme_request();
  882. $result = $response->get_data();
  883. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  884. $this->assertTrue( $result[0]['theme_supports']['dark-editor-style'] );
  885. }
  886. /**
  887. * @ticket 49037
  888. */
  889. public function test_theme_no_disable_custom_gradients() {
  890. remove_theme_support( 'disable-custom-gradients' );
  891. $response = self::perform_active_theme_request();
  892. $result = $response->get_data();
  893. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  894. $this->assertArrayHasKey( 'disable-custom-gradients', $result[0]['theme_supports'] );
  895. $this->assertFalse( $result[0]['theme_supports']['disable-custom-gradients'] );
  896. }
  897. /**
  898. * @ticket 49037
  899. */
  900. public function test_theme_disable_custom_gradients() {
  901. remove_theme_support( 'disable-custom-gradients' );
  902. add_theme_support( 'disable-custom-gradients' );
  903. $response = self::perform_active_theme_request();
  904. $result = $response->get_data();
  905. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  906. $this->assertTrue( $result[0]['theme_supports']['disable-custom-gradients'] );
  907. }
  908. /**
  909. * @ticket 49037
  910. */
  911. public function test_theme_supports_editor_gradient_presets_array() {
  912. remove_theme_support( 'editor-gradient-presets' );
  913. $gradient = array(
  914. 'name' => __( 'Vivid cyan blue to vivid purple', 'themeLangDomain' ),
  915. 'gradient' => 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
  916. 'slug' => 'vivid-cyan-blue-to-vivid-purple',
  917. );
  918. add_theme_support( 'editor-gradient-presets', array( $gradient ) );
  919. $response = self::perform_active_theme_request();
  920. $result = $response->get_data();
  921. $this->assertArrayHasKey( 'theme_supports', $result[0] );
  922. $this->assertSame( array( $gradient ), $result[0]['theme_supports']['editor-gradient-presets'] );
  923. }
  924. /**
  925. * Should include relevant data in the 'theme_supports' key.
  926. *
  927. * @ticket 45016
  928. */
  929. public function test_theme_supports_formats() {
  930. remove_theme_support( 'post-formats' );
  931. $response = self::perform_active_theme_request();
  932. $result = $response->get_data();
  933. $this->assertTrue( isset( $result[0]['theme_supports'] ) );
  934. $this->assertTrue( isset( $result[0]['theme_supports']['formats'] ) );
  935. $this->assertSame( array( 'standard' ), $result[0]['theme_supports']['formats'] );
  936. }
  937. /**
  938. * Test when a theme only supports some post formats.
  939. *
  940. * @ticket 45016
  941. */
  942. public function test_theme_supports_formats_non_default() {
  943. add_theme_support( 'post-formats', array( 'aside', 'video' ) );
  944. $response = self::perform_active_theme_request();
  945. $result = $response->get_data();
  946. $this->assertTrue( isset( $result[0]['theme_supports'] ) );
  947. $this->assertTrue( isset( $result[0]['theme_supports']['formats'] ) );
  948. $this->assertSame( array( 'standard', 'aside', 'video' ), $result[0]['theme_supports']['formats'] );
  949. }
  950. /**
  951. * Test when a theme does not support responsive embeds.
  952. *
  953. * @ticket 45016
  954. */
  955. public function test_theme_supports_responsive_embeds_false() {
  956. remove_theme_support( 'responsive-embeds' );
  957. $response = self::perform_active_theme_request();
  958. $result = $response->get_data();
  959. $this->assertTrue( isset( $result[0]['theme_supports'] ) );
  960. $this->assertTrue( isset( $result[0]['theme_supports']['responsive-embeds'] ) );
  961. $this->assertFalse( $result[0]['theme_supports']['responsive-embeds'] );
  962. }
  963. /**
  964. * Test when a theme supports responsive embeds.
  965. *
  966. * @ticket 45016
  967. */
  968. public function test_theme_supports_responsive_embeds_true() {
  969. remove_theme_support( 'responsive-embeds' );
  970. add_theme_support( 'responsive-embeds' );
  971. $response = self::perform_active_theme_request();
  972. $result = $response->get_data();
  973. $this->assertTrue( isset( $result[0]['theme_supports'] ) );
  974. $this->assertTrue( $result[0]['theme_supports']['responsive-embeds'] );
  975. }
  976. /**
  977. * Test when a theme does not support post thumbnails.
  978. *
  979. * @ticket 45016
  980. */
  981. public function test_theme_supports_post_thumbnails_false() {
  982. remove_theme_support( 'post-thumbnails' );
  983. $response = self::perform_active_theme_request();
  984. $result = $response->get_data();
  985. $this->assertTrue( isset( $result[0]['theme_supports'] ) );
  986. $this->assertTrue( isset( $result[0]['theme_supports']['post-thumbnails'] ) );
  987. $this->assertFalse( $result[0]['theme_supports']['post-thumbnails'] );
  988. }
  989. /**
  990. * Test when a theme supports all post thumbnails.
  991. *
  992. * @ticket 45016
  993. */
  994. public function test_theme_supports_post_thumbnails_true() {
  995. remove_theme_support( 'post-thumbnails' );
  996. add_theme_support( 'post-thumbnails' );
  997. $response = self::perform_active_theme_request();
  998. $result = $response->get_data();
  999. $this->assertTrue( isset( $result[0]['theme_supports'] ) );
  1000. $this->assertTrue( $result[0]['theme_supports']['post-thumbnails'] );
  1001. }
  1002. /**
  1003. * Test when a theme only supports post thumbnails for certain post types.
  1004. *
  1005. * @ticket 45016
  1006. */
  1007. public function test_theme_supports_post_thumbnails_array() {
  1008. remove_theme_support( 'post-thumbnails' );
  1009. add_theme_support( 'post-thumbnails', array( 'post' ) );
  1010. $response = self::perform_active_theme_request();
  1011. $result = $response->get_data();
  1012. $this->assertTrue( isset( $result[0]['theme_supports'] ) );
  1013. $this->assertSame( array( 'post' ), $result[0]['theme_supports']['post-thumbnails'] );
  1014. }
  1015. /**
  1016. * @ticket 49406
  1017. */
  1018. public function test_variadic_theme_support() {
  1019. register_theme_feature(
  1020. 'test-feature',
  1021. array(
  1022. 'type' => 'array',
  1023. 'variadic' => true,
  1024. 'show_in_rest' => array(
  1025. 'schema' => array(
  1026. 'items' => array(
  1027. 'type' => 'string',
  1028. ),
  1029. ),
  1030. ),
  1031. )
  1032. );
  1033. add_theme_support( 'test-feature', 'a', 'b', 'c' );
  1034. $response = self::perform_active_theme_request();
  1035. $result = $response->get_data();
  1036. $this->assertTrue( isset( $result[0]['theme_supports'] ) );
  1037. $this->assertSame( array( 'a', 'b', 'c' ), $result[0]['theme_supports']['test-feature'] );
  1038. }
  1039. /**
  1040. * It should be possible to register custom fields to the endpoint.
  1041. *
  1042. * @ticket 45016
  1043. */
  1044. public function test_get_additional_field_registration() {
  1045. $schema = array(
  1046. 'type' => 'integer',
  1047. 'description' => 'Some integer of mine',
  1048. 'enum' => array( 1, 2, 3, 4 ),
  1049. );
  1050. register_rest_field(
  1051. 'theme',
  1052. 'my_custom_int',
  1053. array(
  1054. 'schema' => $schema,
  1055. 'get_callback' => array( $this, 'additional_field_get_callback' ),
  1056. )
  1057. );
  1058. $response = self::perform_active_theme_request( 'OPTIONS' );
  1059. $data = $response->get_data();
  1060. $this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] );
  1061. $this->assertSame( $schema, $data['schema']['properties']['my_custom_int'] );
  1062. $response = self::perform_active_theme_request( 'GET' );
  1063. $data = $response->get_data();
  1064. $this->assertArrayHasKey( 'my_custom_int', $data[0] );
  1065. $this->assertSame( 2, $data[0]['my_custom_int'] );
  1066. global $wp_rest_additional_fields;
  1067. $wp_rest_additional_fields = array();
  1068. }
  1069. /**
  1070. * Return a value for the custom field.
  1071. *
  1072. * @since 5.0.0
  1073. *
  1074. * @param array $theme Theme data array.
  1075. * @return int Additional field value.
  1076. */
  1077. public function additional_field_get_callback( $theme ) {
  1078. return 2;
  1079. }
  1080. /**
  1081. * The create_item() method does not exist for themes.
  1082. */
  1083. public function test_create_item() {}
  1084. /**
  1085. * The update_item() method does not exist for themes.
  1086. */
  1087. public function test_update_item() {}
  1088. /**
  1089. * Test single theme.
  1090. *
  1091. * @ticket 50152
  1092. */
  1093. public function test_get_item() {
  1094. wp_set_current_user( self::$admin_id );
  1095. $route = sprintf( '%s/%s', self::$themes_route, WP_DEFAULT_THEME );
  1096. $request = new WP_REST_Request( 'GET', $route );
  1097. $response = rest_get_server()->dispatch( $request );
  1098. $this->assertSame( 200, $response->get_status() );
  1099. $data = $response->get_data();
  1100. $links = $response->get_links();
  1101. $fields = array(
  1102. 'author',
  1103. 'author_uri',
  1104. 'description',
  1105. 'name',
  1106. 'requires_php',
  1107. 'requires_wp',
  1108. 'screenshot',
  1109. 'status',
  1110. 'stylesheet',
  1111. 'tags',
  1112. 'template',
  1113. 'textdomain',
  1114. 'theme_uri',
  1115. 'version',
  1116. );
  1117. $fields_links = array( 'collection', 'self' );
  1118. $this->assertEqualSets( $fields, array_keys( $data ) );
  1119. $this->assertEqualSets( $fields_links, array_keys( $links ) );
  1120. }
  1121. /**
  1122. * @ticket 50152
  1123. */
  1124. public function test_get_item_no_permission() {
  1125. wp_set_current_user( self::$subscriber_id );
  1126. $request = new WP_REST_Request( 'GET', self::$themes_route . '/' . WP_DEFAULT_THEME );
  1127. $response = rest_get_server()->dispatch( $request );
  1128. $this->assertErrorResponse( 'rest_cannot_view_themes', $response, 403 );
  1129. }
  1130. /**
  1131. * @ticket 50152
  1132. */
  1133. public function test_get_active_item_no_permission() {
  1134. wp_set_current_user( self::$subscriber_id );
  1135. $request = new WP_REST_Request( 'GET', self::$themes_route . '/' . get_stylesheet() );
  1136. $response = rest_get_server()->dispatch( $request );
  1137. $this->assertErrorResponse( 'rest_cannot_view_active_theme', $response, 403 );
  1138. }
  1139. /**
  1140. * @ticket 50152
  1141. */
  1142. public function test_get_item_invalid() {
  1143. wp_set_current_user( self::$admin_id );
  1144. $request = new WP_REST_Request( 'GET', self::$themes_route . '/invalid' );
  1145. $response = rest_get_server()->dispatch( $request );
  1146. $this->assertErrorResponse( 'rest_theme_not_found', $response, 404 );
  1147. }
  1148. /**
  1149. * @ticket 50152
  1150. */
  1151. public function test_get_active_item_as_contributor() {
  1152. $route = sprintf( '%s/%s', self::$themes_route, get_stylesheet() );
  1153. $request = new WP_REST_Request( 'GET', $route );
  1154. $response = rest_get_server()->dispatch( $request );
  1155. $this->assertSame( 200, $response->get_status() );
  1156. }
  1157. /**
  1158. * The delete_item() method does not exist for themes.
  1159. */
  1160. public function test_delete_item() {}
  1161. /**
  1162. * Context is not supported for themes.
  1163. */
  1164. public function test_context_param() {}
  1165. }