controller(); $controller->register(); self::assertSame( array( $controller, 'registerRoutes' ), $GLOBALS['wpcs_test_actions']['rest_api_init'][0] ); } public function test_it_registers_status_and_package_routes(): void { $controller = $this->controller(); $controller->registerRoutes(); self::assertArrayHasKey( 'wp-content-sync/v1/status', $GLOBALS['wpcs_rest_routes'] ); self::assertArrayHasKey( 'wp-content-sync/v1/package', $GLOBALS['wpcs_rest_routes'] ); } public function test_it_requires_manage_options_permission(): void { $GLOBALS['wpcs_current_user_can']['manage_options'] = false; $controller = $this->controller(); self::assertFalse( $controller->canReceivePackage() ); } public function test_it_returns_status_payload(): void { $controller = $this->controller(); self::assertSame( array( 'ok' => true, 'plugin' => 'wp-content-sync', 'version' => WPCS_VERSION, ), $controller->status() ); } public function test_it_accepts_valid_packages(): void { $controller = $this->controller(); self::assertSame( $this->acceptedResponse(), $controller->receivePackage( array( 'package' => $this->validPackage(), ) ) ); } public function test_it_accepts_rest_request_like_objects(): void { $controller = $this->controller(); $request = new class( array( 'package' => $this->validPackage(), ) ) { /** @var array */ private array $params; /** * @param array $params Request params. */ public function __construct( array $params ) { $this->params = $params; } /** * @return array */ public function get_json_params(): array { return $this->params; } }; self::assertSame( $this->acceptedResponse(), $controller->receivePackage( $request ) ); } public function test_it_rejects_invalid_package_shapes(): void { $controller = $this->controller(); self::assertSame( array( 'accepted' => false, 'errors' => array( 'package is required and must be an object.' ), ), $controller->receivePackage( array() ) ); } public function test_it_returns_rejected_response_when_sync_import_fails(): void { $controller = $this->controller( SyncResult::failure( array( 'Posts failed.' ) ) ); self::assertSame( array( 'accepted' => false, 'schema_version' => '1.0', 'manifest' => array( 'posts' => 0, 'terms' => 0, 'media' => 0, 'custom_post_types' => 0, ), 'import' => array( 'successful' => false, 'created' => 0, 'updated' => 0, 'skipped' => 0, 'conflicts' => 0, 'errors' => array( 'Posts failed.' ), ), ), $controller->receivePackage( array( 'package' => $this->validPackage(), ) ) ); } /** * @return array */ private function acceptedResponse(): array { return array( 'accepted' => true, 'schema_version' => '1.0', 'manifest' => array( 'posts' => 0, 'terms' => 0, 'media' => 0, 'custom_post_types' => 0, ), 'import' => array( 'successful' => true, 'created' => 0, 'updated' => 0, 'skipped' => 0, 'conflicts' => 0, 'errors' => array(), ), ); } private function controller( ?SyncResult $result = null ): RestPackageController { return new RestPackageController( new PackageValidator(), $this->syncEngine( $result ?? SyncResult::success() ) ); } private function syncEngine( SyncResult $result ): SyncEngine { return new SyncEngine( new ContentHandlerRegistry( array( $this->handler( $result ) ) ), new SyncStateRepository(), new SettingsRepository(), $this->logger() ); } private function handler( SyncResult $result ): ContentHandlerInterface { return new class( $result ) implements ContentHandlerInterface { private SyncResult $result; public function __construct( SyncResult $result ) { $this->result = $result; } public function bucket(): string { return 'posts'; } public function importRecords( array $records, SyncContext $context ): SyncResult { return $this->result; } }; } private function logger(): LoggerInterface { return new class() implements LoggerInterface { public function error( string $message, array $context = array() ): void {} public function warning( string $message, array $context = array() ): void {} public function info( string $message, array $context = array() ): void {} public function debug( string $message, array $context = array() ): void {} }; } /** * @return array */ private function validPackage(): array { $records = array( 'posts' => array(), 'terms' => array(), 'media' => array(), 'custom_post_types' => array(), ); return array( 'schema_version' => '1.0', 'generated_at' => '2026-04-28T12:00:00+00:00', 'source' => array( 'site_url' => 'https://example.test', 'name' => 'Example', ), 'destination' => array( 'site_url' => 'https://destination.test', 'name' => 'Destination', ), 'manifest' => array( 'posts' => 0, 'terms' => 0, 'media' => 0, 'custom_post_types' => 0, ), 'records' => $records, 'checksums' => array( 'records' => PackageChecksum::records( $records ), ), ); } }