Skip to content

Commit 74e17f8

Browse files
authored
Jetpack Connection Heath tests: Migrate from Jetpack plugin to Connection package (#47837)
* Jetpack Connection Heath tests: Migrate from Jetpack plugin to Connection package
1 parent 662f387 commit 74e17f8

20 files changed

Lines changed: 3391 additions & 1325 deletions

projects/packages/connection/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Package is published in [Packagist](https://packagist.org/packages/automattic/je
1616

1717
## Guides
1818
* [Connection package guide](docs/register-site.md)
19+
* [Connection health tests](docs/connection-health-tests.md)
1920

2021
## Tools
2122

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: changed
3+
4+
Jetpack Connection Health tests: Migrate from Jetpack plugin to Connection package
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
# Connection Health Tests
2+
3+
The connection health testing framework provides a set of diagnostic tests for verifying that a site's Jetpack connection is working correctly. These tests are surfaced in the WordPress **Site Health** screen and can also be run via **WP-CLI**.
4+
5+
## Architecture
6+
7+
The framework is composed of three classes:
8+
9+
### `Connection_Health_Test_Base`
10+
11+
The base framework class. It provides:
12+
13+
- **Test registration** via `add_test()` with support for `direct` and `async` types.
14+
- **Test execution** via `run_test()` (single) and `run_tests()` (all).
15+
- **Result helpers** — static methods for building consistent result arrays: `passing_test()`, `failing_test()`, `skipped_test()`, `informational_test()`, and `connection_failing_test()`.
16+
- **Output methods**`output_results_for_cli()`, `output_results_for_core_async_site_health()`, and `output_fails_as_wp_error()`.
17+
- **Helper methods** for common checks: `helper_is_connected()`, `helper_get_blog_token()`, `helper_retrieve_connection_owner()`, `helper_get_support_url()`, etc.
18+
- **Encryption**`encrypt_string_for_wpcom()` for sending diagnostic data securely.
19+
20+
### `Connection_Health_Tests`
21+
22+
Extends `Connection_Health_Test_Base` with all the connection-specific tests. Its constructor:
23+
24+
1. Auto-discovers all `test__*` methods and registers them as `direct` tests.
25+
2. Fires the `jetpack_connection_tests_loaded` action, passing itself as the argument. This is the extension point for plugins.
26+
3. Optionally includes `last__wpcom_self_test` when the `jetpack_debugger_run_self_test` filter returns `true`.
27+
28+
**Built-in tests:**
29+
30+
| Test | What it checks |
31+
|------|---------------|
32+
| `test__blog_token_if_exists` | Blog token is present |
33+
| `test__check_if_connected` | Site is connected to WordPress.com |
34+
| `test__master_user_exists_on_site` | Connection owner exists locally |
35+
| `test__master_user_can_manage_options` | Connection owner is an administrator |
36+
| `test__outbound_http` | Outbound HTTP requests work |
37+
| `test__outbound_https` | Outbound HTTPS requests work |
38+
| `test__identity_crisis` | No URL mismatch with WordPress.com |
39+
| `test__connection_token_health` | Connection tokens are valid |
40+
| `test__wpcom_connection_test` | WordPress.com can reach the site |
41+
| `test__server_port_value` | Server port is standard |
42+
| `test__xml_parser_available` | PHP XML extension is available |
43+
44+
### `Site_Health`
45+
46+
Integrates the health tests into WordPress Site Health. It:
47+
48+
- Registers each `direct` test as a Site Health direct test (runs on page load).
49+
- Registers an async test suite entry (`jetpack-connection-health`) with a corresponding AJAX handler.
50+
- Defers to the legacy Jetpack debugger when an old Jetpack version is active (detected via `has_filter( 'site_status_tests', 'jetpack_debugger_site_status_tests' )`).
51+
52+
## When tests run
53+
54+
- **Site Health page** (`/wp-admin/site-health.php`): Direct tests run synchronously on page load. The async test suite runs via an AJAX request after the page loads.
55+
- **WP-CLI**: Tests can be run programmatically via `$tests = new Connection_Health_Tests(); $tests->output_results_for_cli();`.
56+
- **REST API / other consumers**: Instantiate `Connection_Health_Tests` and call `run_test()`, `pass()`, or `output_fails_as_wp_error()` as needed.
57+
58+
## Extending with plugin-specific tests
59+
60+
Plugins can add their own tests by hooking into the `jetpack_connection_tests_loaded` action. The Jetpack plugin does this to add a sync health test.
61+
62+
### Step 1: Create a test class
63+
64+
Create a class that extends `Connection_Health_Test_Base`. Define test methods with the `test__` prefix and use the result helpers to return consistent results.
65+
66+
```php
67+
use Automattic\Jetpack\Connection\Connection_Health_Test_Base;
68+
69+
class My_Plugin_Cxn_Tests extends Connection_Health_Test_Base {
70+
71+
/**
72+
* Register this class's tests on a target test suite.
73+
*
74+
* @param Connection_Health_Test_Base $target The test suite to register on.
75+
*/
76+
public function register_tests_on( $target ) {
77+
$methods = get_class_methods( static::class );
78+
foreach ( $methods as $method ) {
79+
if ( ! str_contains( $method, 'test__' ) ) {
80+
continue;
81+
}
82+
$target->add_test( array( $this, $method ), $method, 'direct' );
83+
}
84+
}
85+
86+
/**
87+
* Example: check that sync is healthy.
88+
*/
89+
protected function test__my_feature_health() {
90+
$name = 'test__my_feature_health';
91+
92+
if ( ! $this->helper_is_connected() ) {
93+
return self::skipped_test(
94+
array(
95+
'name' => $name,
96+
'short_description' => 'Not connected.',
97+
)
98+
);
99+
}
100+
101+
if ( my_feature_is_healthy() ) {
102+
return self::passing_test( array( 'name' => $name ) );
103+
}
104+
105+
return self::failing_test(
106+
array(
107+
'name' => $name,
108+
'short_description' => 'My feature is not healthy.',
109+
'severity' => 'recommended',
110+
)
111+
);
112+
}
113+
}
114+
```
115+
116+
### Step 2: Register via the action hook
117+
118+
Hook into `jetpack_connection_tests_loaded` to register your tests on the connection test suite instance.
119+
120+
```php
121+
add_action(
122+
'jetpack_connection_tests_loaded',
123+
function ( $connection_tests ) {
124+
$my_tests = new My_Plugin_Cxn_Tests();
125+
$my_tests->register_tests_on( $connection_tests );
126+
}
127+
);
128+
```
129+
130+
Your tests will now appear in Site Health alongside the built-in connection tests.
131+
132+
### Real-world example: Jetpack plugin
133+
134+
The Jetpack plugin registers its sync health test using this exact pattern in `_inc/lib/debugger.php`:
135+
136+
```php
137+
add_action(
138+
'jetpack_connection_tests_loaded',
139+
function ( $connection_tests ) {
140+
$jetpack_tests = new Jetpack_Cxn_Tests();
141+
$jetpack_tests->register_tests_on( $connection_tests );
142+
}
143+
);
144+
```
145+
146+
It also customizes the support URL for beta versions:
147+
148+
```php
149+
add_filter(
150+
'jetpack_connection_support_url',
151+
function ( $url ) {
152+
if ( Jetpack::is_development_version() ) {
153+
return Redirect::get_url( 'jetpack-contact-support-beta-group' );
154+
}
155+
return $url;
156+
}
157+
);
158+
```
159+
160+
## Available filters
161+
162+
| Filter | Description | Default |
163+
|--------|-------------|---------|
164+
| `jetpack_connection_tests_loaded` | Action. Fires after built-in tests are registered. Receives the `Connection_Health_Tests` instance. ||
165+
| `jetpack_debugger_run_self_test` | Whether to include the WP.com self-test. | `false` |
166+
| `jetpack_connection_support_url` | Support URL shown in failing test results. | Jetpack support contact page |
167+
| `jetpack_connection_reconnect_url` | Reconnect URL shown in connection failure results. | Empty string by default; the Jetpack plugin provides the reconnect URL when available. |
168+
| `jetpack_connection_site_health_badge_label` | Badge label shown in Site Health. | `'Jetpack'` |
169+
170+
## Test result format
171+
172+
All test methods must return an array. Use the static helpers to ensure a consistent structure:
173+
174+
```php
175+
// Passing
176+
return self::passing_test( array( 'name' => 'test__my_test' ) );
177+
178+
// Failing
179+
return self::failing_test( array(
180+
'name' => 'test__my_test',
181+
'short_description' => 'Something is wrong.',
182+
'severity' => 'critical', // or 'recommended'
183+
'action' => 'https://example.com/fix',
184+
'action_label' => 'Fix it',
185+
) );
186+
187+
// Skipped (precondition not met)
188+
return self::skipped_test( array(
189+
'name' => 'test__my_test',
190+
'short_description' => 'Not applicable.',
191+
) );
192+
193+
// Connection-specific failure (includes reconnect action)
194+
return self::connection_failing_test(
195+
'test__my_test',
196+
'Token is invalid.',
197+
'Try reconnecting Jetpack.'
198+
);
199+
```
200+
201+
## Unit tests
202+
203+
The framework and individual tests are covered by PHPUnit tests in `tests/php/`:
204+
205+
- **`Connection_Health_Test_Base_Test.php`** — Tests the base framework: test registration, execution, result helpers, output methods, encryption, filters, and the subclass extension pattern.
206+
- **`Connection_Health_Tests_Test.php`** — Tests individual health test methods: verifies skipped/pass/fail paths for each built-in test using partial mocks for helper methods.
207+
- **`Site_Health_Test.php`** — Tests Site Health integration: registration, legacy Jetpack detection, direct test callback invocation, and AJAX action registration.
208+
209+
Run the tests from the package directory:
210+
211+
```bash
212+
cd projects/packages/connection
213+
composer phpunit
214+
```
215+
216+
To run a specific test file:
217+
218+
```bash
219+
composer phpunit -- --filter Connection_Health_Tests_Test
220+
```

projects/packages/connection/src/class-manager.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ public static function configure() {
192192

193193
// WP 7.0+ Connectors screen card.
194194
Jetpack_Connector::init();
195+
196+
// Site Health integration.
197+
Site_Health::init();
195198
}
196199

197200
/**

0 commit comments

Comments
 (0)