Skip to content

Commit

Permalink
Structure for Webfinger tests
Browse files Browse the repository at this point in the history
  • Loading branch information
obenland committed Jan 9, 2025
1 parent 4a063a4 commit a4dc3be
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 32 deletions.
2 changes: 1 addition & 1 deletion activitypub.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ function rest_init() {
( new Rest\Inbox() )->register_routes();
( new Rest\Followers() )->register_routes();
( new Rest\Following() )->register_routes();
( new Rest\Webfinger() )->register_routes();
( new Rest\Comment() )->register_routes();
( new Rest\Server() )->register_routes();
( new Rest\Collection() )->register_routes();
( new Rest\Interaction() )->register_routes();
( new Rest\Post() )->register_routes();
( new Rest\Webfinger_Controller() )->register_routes();

// Load NodeInfo endpoints only if blog is public.
if ( is_blog_public() ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,33 @@
*
* @see https://webfinger.net/
*/
class Webfinger extends \WP_REST_Controller {
class Webfinger_Controller extends \WP_REST_Controller {
/**
* The namespace of this controller's route.
*
* @var string
*/
protected $namespace = ACTIVITYPUB_REST_NAMESPACE;

/**
* The base of this controller's route.
*
* @var string
*/
protected $rest_base = 'webfinger';

/**
* Register routes.
*/
public function register_routes() {
\register_rest_route(
$this->namespace,
'/webfinger',
'/' . $this->rest_base,
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ),
'permission_callback' => '__return_true',
'args' => array(
'resource' => array(
'description' => 'The WebFinger resource.',
Expand All @@ -41,7 +49,6 @@ public function register_routes() {
'pattern' => '^(acct:)|^(https?://)(.+)$',
),
),
'permission_callback' => '__return_true',
),
'schema' => array( $this, 'get_item_schema' ),
)
Expand Down Expand Up @@ -115,6 +122,7 @@ public function get_item_schema() {
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'webfinger',
'type' => 'object',
'required' => array( 'subject', 'links' ),
'properties' => array(
'subject' => array(
'description' => 'The subject of this WebFinger record.',
Expand All @@ -138,6 +146,7 @@ public function get_item_schema() {
'rel' => array(
'description' => 'The relation type of the link.',
'type' => 'string',
'required' => true,
),
'type' => array(
'description' => 'The content type of the link.',
Expand All @@ -148,6 +157,11 @@ public function get_item_schema() {
'type' => 'string',
'format' => 'uri',
),
'template' => array(
'description' => 'A URI template for the link.',
'type' => 'string',
'format' => 'uri',
),
),
),
),
Expand Down
1 change: 1 addition & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,6 @@ function http_disable_request( $response, $args, $url ) {
// Start up the WP testing environment.
require $_tests_dir . '/includes/bootstrap.php';
require __DIR__ . '/class-activitypub-testcase-cache-http.php';
require __DIR__ . '/class-rest-controller-testcase.php';

\Activitypub\Migration::add_default_settings();
82 changes: 82 additions & 0 deletions tests/class-rest-controller-testcase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
/**
* REST Controller Testcase file.
*
* @package Activitypub
*/

namespace Activitypub\Tests;

/**
* REST Controller Testcase.
*/
abstract class REST_Controller_Testcase extends \WP_Test_REST_TestCase {

/**
* The REST server.
*
* @var \WP_REST_Server
*/
protected $server;

/**
* Set up the test.
*/
public function set_up() {
parent::set_up();
add_filter( 'rest_url', array( $this, 'filter_rest_url_for_leading_slash' ), 10, 2 );

/** @var \WP_REST_Server $wp_rest_server */
global $wp_rest_server;
$wp_rest_server = new \Spy_REST_Server();
do_action( 'rest_api_init', $wp_rest_server );
}

/**
* Tear down the test.
*/
public function tear_down() {
remove_filter( 'rest_url', array( $this, 'test_rest_url_for_leading_slash' ) );

/** @var WP_REST_Server $wp_rest_server */
global $wp_rest_server;
$wp_rest_server = null;

parent::tear_down();
}

/**
* Test get_item.
*/
abstract public function test_get_item();

/**
* Test register_routes.
*/
abstract public function test_get_item_schema();

/**
* Filter REST URL for leading slash.
*
* @param string $url URL.
* @param string $path Path.
* @return string
*/
public function filter_rest_url_for_leading_slash( $url, $path ) {
if ( is_multisite() || get_option( 'permalink_structure' ) ) {
return $url;
}

// Make sure path for rest_url has a leading slash for proper resolution.
if ( 0 !== strpos( $path, '/' ) ) {
$this->fail(
sprintf(
'REST API URL "%s" should have a leading slash.',
$path
)
);
}

return $url;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,16 @@
* @package Activitypub
*/

namespace Activitypub\Tests\Rest;

use Activitypub\Tests\REST_Controller_Testcase;

/**
* Tests for WebFinger REST API endpoint.
*
* @coversDefaultClass \Activitypub\Rest\Webfinger
* @coversDefaultClass \Activitypub\Rest\Webfinger_Controller
*/
class Test_Webfinger extends \WP_UnitTestCase {

/**
* The REST server.
*
* @var \WP_REST_Server
*/
protected $server;
class Test_Webfinger_Controller extends REST_Controller_Testcase {

/**
* Test user.
Expand All @@ -29,9 +26,9 @@ class Test_Webfinger extends \WP_UnitTestCase {
/**
* Set up class test fixtures.
*
* @param WP_UnitTest_Factory $factory WordPress unit test factory.
* @param \WP_UnitTest_Factory $factory WordPress unit test factory.
*/
public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
public static function wpSetUpBeforeClass( \WP_UnitTest_Factory $factory ) {
self::$user = $factory->user->create_and_get(
array(
'user_login' => 'test_user',
Expand All @@ -43,8 +40,6 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {

/**
* Clean up test fixtures.
*
* @since 5.6.0
*/
public static function wpTearDownAfterClass() {
self::delete_user( self::$user->ID );
Expand All @@ -56,13 +51,7 @@ public static function wpTearDownAfterClass() {
public function set_up() {
parent::set_up();

global $wp_rest_server;

$wp_rest_server = new \WP_REST_Server();
$this->server = $wp_rest_server;

\do_action( 'rest_api_init' );
( new \Activitypub\Rest\Webfinger() )->register_routes();

\add_filter( 'webfinger_data', array( '\Activitypub\Integration\Webfinger', 'add_pseudo_user_discovery' ), 1, 2 );
}
Expand All @@ -73,7 +62,7 @@ public function set_up() {
* @covers ::register_routes
*/
public function test_register_routes() {
$routes = $this->server->get_routes();
$routes = rest_get_server()->get_routes();
$this->assertArrayHasKey( '/' . ACTIVITYPUB_REST_NAMESPACE . '/webfinger', $routes );
}

Expand All @@ -83,7 +72,11 @@ public function test_register_routes() {
* @covers ::get_item_schema
*/
public function test_get_item_schema() {
$schema = ( new \Activitypub\Rest\Webfinger() )->get_item_schema();
$request = new \WP_REST_Request( 'OPTIONS', '/' . ACTIVITYPUB_REST_NAMESPACE . '/webfinger' );
$response = rest_get_server()->dispatch( $request )->get_data();

$this->assertArrayHasKey( 'schema', $response );
$schema = $response['schema'];

$this->assertIsArray( $schema );
$this->assertArrayHasKey( 'properties', $schema );
Expand All @@ -97,11 +90,10 @@ public function test_get_item_schema() {
*
* @covers ::get_item
*/
public function test_get_item_with_valid_resource() {
public function test_get_item() {
$request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/webfinger' );
$request->set_param( 'resource', 'acct:[email protected]' );

$response = $this->server->dispatch( $request );
$response = rest_get_server()->dispatch( $request );

$this->assertEquals( 200, $response->get_status() );
$this->assertStringContainsString( 'application/jrd+json', $response->get_headers()['Content-Type'] );
Expand All @@ -116,8 +108,8 @@ public function test_get_item_with_valid_resource() {
public function test_get_item_with_invalid_resource() {
$request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/webfinger' );
$request->set_param( 'resource', 'invalid-resource' );
$response = rest_get_server()->dispatch( $request );

$response = $this->server->dispatch( $request );
$this->assertEquals( 400, $response->get_status() );
}

Expand All @@ -128,7 +120,8 @@ public function test_get_item_with_invalid_resource() {
*/
public function test_get_item_with_missing_resource() {
$request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/webfinger' );
$response = $this->server->dispatch( $request );
$response = rest_get_server()->dispatch( $request );

$this->assertEquals( 400, $response->get_status() );
}

Expand Down Expand Up @@ -163,7 +156,7 @@ function( $data, $resource ) use ( $test_data ) {
$request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/webfinger' );
$request->set_param( 'resource', 'acct:[email protected]' );

$response = $this->server->dispatch( $request );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();

$this->assertEquals( $test_data, $data );
Expand All @@ -179,12 +172,30 @@ public function test_get_item_with_author_url() {
$request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/webfinger' );
$request->set_param( 'resource', $author_url );

$response = $this->server->dispatch( $request );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();

$this->assertEquals( 200, $response->get_status() );
$this->assertStringContainsString( 'application/jrd+json', $response->get_headers()['Content-Type'] );
$this->assertContains( $author_url, $data['aliases'] );
$this->assertArrayHasKey( 'links', $data );
}

/**
* Test that the Webfinger response matches its schema.
*
* @covers ::get_item
* @covers ::get_item_schema
*/
public function test_response_matches_schema() {
$request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/webfinger' );
$request->set_param( 'resource', 'acct:[email protected]' );

$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$schema = ( new \Activitypub\Rest\Webfinger_Controller() )->get_item_schema();

$valid = \rest_validate_value_from_schema( $data, $schema );
$this->assertNotWPError( $valid, 'Response failed schema validation: ' . ( \is_wp_error( $valid ) ? $valid->get_error_message() : '' ) );
}
}

0 comments on commit a4dc3be

Please sign in to comment.