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[\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', ''); $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; } }