monorepo/native/wordpress/maple-fonts-wp/tests/test-rest-controller.php
2026-01-30 22:33:40 -05:00

387 lines
11 KiB
PHP

<?php
/**
* Tests for MLF_Rest_Controller class.
*
* @package Maple_Local_Fonts
*/
/**
* Class Test_MLF_Rest_Controller
*
* @covers MLF_Rest_Controller
*/
class Test_MLF_Rest_Controller extends WP_Test_REST_Controller_Testcase {
/**
* REST controller instance.
*
* @var MLF_Rest_Controller
*/
private $controller;
/**
* Admin user ID.
*
* @var int
*/
private $admin_id;
/**
* Subscriber user ID.
*
* @var int
*/
private $subscriber_id;
/**
* Set up test fixtures.
*/
public function set_up() {
parent::set_up();
// Register REST routes
$this->controller = new MLF_Rest_Controller();
$this->controller->register_routes();
// Create users
$this->admin_id = $this->factory->user->create(['role' => 'administrator']);
$this->subscriber_id = $this->factory->user->create(['role' => 'subscriber']);
// Clear any existing fonts and cache
delete_transient('mlf_imported_fonts_list');
}
/**
* Clean up after tests.
*/
public function tear_down() {
// Clean up test fonts
$fonts = get_posts([
'post_type' => 'wp_font_family',
'posts_per_page' => -1,
'meta_key' => '_mlf_imported',
'meta_value' => '1',
'fields' => 'ids',
]);
foreach ($fonts as $font_id) {
wp_delete_post($font_id, true);
}
wp_set_current_user(0);
delete_transient('mlf_imported_fonts_list');
parent::tear_down();
}
/**
* Test route registration.
*/
public function test_register_routes() {
$routes = rest_get_server()->get_routes();
$this->assertArrayHasKey('/mlf/v1/fonts', $routes);
$this->assertArrayHasKey('/mlf/v1/fonts/(?P<id>[\d]+)', $routes);
}
/**
* Test get_items without authentication.
*/
public function test_get_items_unauthenticated() {
$request = new WP_REST_Request('GET', '/mlf/v1/fonts');
$response = rest_get_server()->dispatch($request);
$this->assertEquals(401, $response->get_status());
}
/**
* Test get_items with subscriber (insufficient permissions).
*/
public function test_get_items_insufficient_permissions() {
wp_set_current_user($this->subscriber_id);
$request = new WP_REST_Request('GET', '/mlf/v1/fonts');
$response = rest_get_server()->dispatch($request);
$this->assertEquals(403, $response->get_status());
}
/**
* Test get_items with admin.
*/
public function test_get_items_as_admin() {
wp_set_current_user($this->admin_id);
$request = new WP_REST_Request('GET', '/mlf/v1/fonts');
$response = rest_get_server()->dispatch($request);
$this->assertEquals(200, $response->get_status());
$this->assertIsArray($response->get_data());
}
/**
* Test get_items returns installed fonts.
*/
public function test_get_items_returns_fonts() {
wp_set_current_user($this->admin_id);
// Create a test font
$font_id = $this->create_test_font('Test API Font', 'test-api-font');
$request = new WP_REST_Request('GET', '/mlf/v1/fonts');
$response = rest_get_server()->dispatch($request);
$this->assertEquals(200, $response->get_status());
$data = $response->get_data();
$this->assertCount(1, $data);
$this->assertEquals($font_id, $data[0]['id']);
$this->assertEquals('Test API Font', $data[0]['name']);
}
/**
* Test get_item.
*/
public function test_get_item() {
wp_set_current_user($this->admin_id);
$font_id = $this->create_test_font('Single Font', 'single-font');
$request = new WP_REST_Request('GET', '/mlf/v1/fonts/' . $font_id);
$response = rest_get_server()->dispatch($request);
$this->assertEquals(200, $response->get_status());
$data = $response->get_data();
$this->assertEquals($font_id, $data['id']);
$this->assertEquals('Single Font', $data['name']);
}
/**
* Test get_item not found.
*/
public function test_get_item_not_found() {
wp_set_current_user($this->admin_id);
$request = new WP_REST_Request('GET', '/mlf/v1/fonts/99999');
$response = rest_get_server()->dispatch($request);
$this->assertEquals(404, $response->get_status());
}
/**
* Test create_item without authentication.
*/
public function test_create_item_unauthenticated() {
$request = new WP_REST_Request('POST', '/mlf/v1/fonts');
$request->set_param('font_name', 'Open Sans');
$request->set_param('weights', [400, 700]);
$request->set_param('styles', ['normal']);
$response = rest_get_server()->dispatch($request);
$this->assertEquals(401, $response->get_status());
}
/**
* Test create_item with subscriber.
*/
public function test_create_item_insufficient_permissions() {
wp_set_current_user($this->subscriber_id);
$request = new WP_REST_Request('POST', '/mlf/v1/fonts');
$request->set_param('font_name', 'Open Sans');
$request->set_param('weights', [400, 700]);
$request->set_param('styles', ['normal']);
$response = rest_get_server()->dispatch($request);
$this->assertEquals(403, $response->get_status());
}
/**
* Test create_item with invalid font name.
*/
public function test_create_item_invalid_font_name() {
wp_set_current_user($this->admin_id);
$request = new WP_REST_Request('POST', '/mlf/v1/fonts');
$request->set_param('font_name', '<script>alert("xss")</script>');
$request->set_param('weights', [400]);
$request->set_param('styles', ['normal']);
$response = rest_get_server()->dispatch($request);
$this->assertEquals(400, $response->get_status());
}
/**
* Test create_item with no weights.
*/
public function test_create_item_no_weights() {
wp_set_current_user($this->admin_id);
$request = new WP_REST_Request('POST', '/mlf/v1/fonts');
$request->set_param('font_name', 'Test Font');
$request->set_param('weights', []);
$request->set_param('styles', ['normal']);
$response = rest_get_server()->dispatch($request);
$this->assertEquals(400, $response->get_status());
}
/**
* Test create_item with no styles.
*/
public function test_create_item_no_styles() {
wp_set_current_user($this->admin_id);
$request = new WP_REST_Request('POST', '/mlf/v1/fonts');
$request->set_param('font_name', 'Test Font');
$request->set_param('weights', [400]);
$request->set_param('styles', []);
$response = rest_get_server()->dispatch($request);
$this->assertEquals(400, $response->get_status());
}
/**
* Test delete_item without authentication.
*/
public function test_delete_item_unauthenticated() {
$font_id = $this->create_test_font('Delete Font', 'delete-font');
$request = new WP_REST_Request('DELETE', '/mlf/v1/fonts/' . $font_id);
$response = rest_get_server()->dispatch($request);
$this->assertEquals(401, $response->get_status());
}
/**
* Test delete_item with subscriber.
*/
public function test_delete_item_insufficient_permissions() {
$font_id = $this->create_test_font('Delete Font 2', 'delete-font-2');
wp_set_current_user($this->subscriber_id);
$request = new WP_REST_Request('DELETE', '/mlf/v1/fonts/' . $font_id);
$response = rest_get_server()->dispatch($request);
$this->assertEquals(403, $response->get_status());
}
/**
* Test delete_item as admin.
*/
public function test_delete_item_as_admin() {
$font_id = $this->create_test_font('Delete Font 3', 'delete-font-3');
wp_set_current_user($this->admin_id);
$request = new WP_REST_Request('DELETE', '/mlf/v1/fonts/' . $font_id);
$response = rest_get_server()->dispatch($request);
$this->assertEquals(200, $response->get_status());
$data = $response->get_data();
$this->assertTrue($data['deleted']);
}
/**
* Test delete_item not found.
*/
public function test_delete_item_not_found() {
wp_set_current_user($this->admin_id);
$request = new WP_REST_Request('DELETE', '/mlf/v1/fonts/99999');
$response = rest_get_server()->dispatch($request);
$this->assertEquals(404, $response->get_status());
}
/**
* Test delete_item for font not imported by plugin.
*/
public function test_delete_item_not_ours() {
wp_set_current_user($this->admin_id);
// Create a font without our meta
$font_id = wp_insert_post([
'post_type' => 'wp_font_family',
'post_title' => 'Theme Font',
'post_status' => 'publish',
]);
$request = new WP_REST_Request('DELETE', '/mlf/v1/fonts/' . $font_id);
$response = rest_get_server()->dispatch($request);
$this->assertEquals(403, $response->get_status());
// Clean up
wp_delete_post($font_id, true);
}
/**
* Test item schema.
*/
public function test_get_item_schema() {
$request = new WP_REST_Request('OPTIONS', '/mlf/v1/fonts');
$response = rest_get_server()->dispatch($request);
$data = $response->get_data();
$this->assertArrayHasKey('schema', $data);
$this->assertEquals('font', $data['schema']['title']);
}
/**
* Test context parameter.
*/
public function test_context_param() {
// This test is inherited from WP_Test_REST_Controller_Testcase
// We just need to implement it to satisfy the abstract requirement
$this->assertTrue(true);
}
/**
* Helper to create a test font.
*
* @param string $name Font name.
* @param string $slug Font slug.
* @return int Font ID.
*/
private function create_test_font($name, $slug) {
// Create font family post
$font_id = wp_insert_post([
'post_type' => 'wp_font_family',
'post_title' => $name,
'post_name' => $slug,
'post_status' => 'publish',
'post_content' => wp_json_encode([
'fontFamily' => $name,
'slug' => $slug,
]),
]);
// Add our meta marker
update_post_meta($font_id, '_mlf_imported', '1');
// Create a font face
$face_id = wp_insert_post([
'post_type' => 'wp_font_face',
'post_title' => $name . ' 400 normal',
'post_status' => 'publish',
'post_parent' => $font_id,
'post_content' => wp_json_encode([
'fontFamily' => $name,
'fontWeight' => '400',
'fontStyle' => 'normal',
'src' => ['file:./fonts/' . $slug . '_normal_400.woff2'],
]),
]);
// Clear cache
delete_transient('mlf_imported_fonts_list');
return $font_id;
}
}