|
| 1 | +# Local Testing Setup — Jetpack Search AI Answers |
| 2 | + |
| 3 | +A checklist to verify your local environment can run tests and test the AI Answers feature end-to-end, including live calls to a WPcom sandbox. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## 1. Prerequisites |
| 8 | + |
| 9 | +- [x ] Docker Desktop is installed and running (`docker info` returns no error) |
| 10 | +- [x ] `jetpack` CLI is installed and on PATH: |
| 11 | + ```bash |
| 12 | + jetpack --version |
| 13 | + # If missing: npm install -g @automattic/jetpack-cli (or pnpm add -g) |
| 14 | + ``` |
| 15 | +- [x ] Node and pnpm are available: |
| 16 | + ```bash |
| 17 | + node --version # 20+ |
| 18 | + pnpm --version # 9+ |
| 19 | + ``` |
| 20 | +- [x ] PHP and Composer are available: |
| 21 | + ```bash |
| 22 | + php --version # 8.0+ |
| 23 | + composer --version |
| 24 | + ``` |
| 25 | +- [x ] You're on the right branch: |
| 26 | + ```bash |
| 27 | + git branch # should be jps3-answers-plan |
| 28 | + ``` |
| 29 | + |
| 30 | +--- |
| 31 | + |
| 32 | +## 2. Install Monorepo Dependencies |
| 33 | + |
| 34 | +- [x ] Install all JS and PHP dependencies from the monorepo root: |
| 35 | + ```bash |
| 36 | + pnpm install |
| 37 | + composer install |
| 38 | + ``` |
| 39 | + This only needs to be done once (or after a `git pull` that changes lockfiles). |
| 40 | + |
| 41 | +--- |
| 42 | + |
| 43 | +## 3. Run Unit Tests Without Docker |
| 44 | + |
| 45 | +The PHP unit tests for the Search and Sync packages use WorDBless (no WordPress needed) and run locally without Docker. |
| 46 | + |
| 47 | +- [x ] Run Search package PHP tests: |
| 48 | + ```bash |
| 49 | + jetpack test php packages/search -v |
| 50 | + ``` |
| 51 | + Expected: all tests pass (including `AI_Answers_Test` once Task 1 is implemented). |
| 52 | + |
| 53 | +- [x ] Run Sync package PHP tests: |
| 54 | + ```bash |
| 55 | + jetpack test php packages/sync -v |
| 56 | + ``` |
| 57 | + Expected: all tests pass (including the CPT sync tests once Task 2 is implemented). |
| 58 | + |
| 59 | +- [x ] Run Search package JS tests: |
| 60 | + ```bash |
| 61 | + cd projects/packages/search |
| 62 | + pnpm test-scripts |
| 63 | + ``` |
| 64 | + Expected: all tests pass. |
| 65 | + |
| 66 | +--- |
| 67 | + |
| 68 | +## 4. Build the Search Package |
| 69 | + |
| 70 | +Build is required before the Docker site can serve the updated JS bundle. |
| 71 | + |
| 72 | +- [x ] Build all Search JS bundles: |
| 73 | + ```bash |
| 74 | + cd projects/packages/search |
| 75 | + pnpm build |
| 76 | + ``` |
| 77 | + Expected: `build/` directory updated with no errors. |
| 78 | + |
| 79 | +- [ ] For active development, use watch mode instead: |
| 80 | + ```bash |
| 81 | + pnpm watch |
| 82 | + ``` |
| 83 | + Leave this running while you work — it rebuilds on file save. |
| 84 | + |
| 85 | +--- |
| 86 | + |
| 87 | +## 5. Start Docker WordPress Environment |
| 88 | + |
| 89 | +- [x ] Start containers (first time or after `jetpack docker clean`): |
| 90 | + ```bash |
| 91 | + jetpack docker up -d |
| 92 | + jetpack docker install |
| 93 | + ``` |
| 94 | + WordPress is now at [http://localhost](http://localhost). |
| 95 | + Default credentials: `jp_docker_acct` / `jp_docker_pass` |
| 96 | + |
| 97 | +- [x ] If containers were already installed previously, just start them: |
| 98 | + ```bash |
| 99 | + jetpack docker up -d |
| 100 | + ``` |
| 101 | + |
| 102 | +- [x ] Verify WordPress is reachable: |
| 103 | + ```bash |
| 104 | + open http://localhost/wp-admin |
| 105 | + ``` |
| 106 | + You should see the WP login page. |
| 107 | + |
| 108 | +- [x ] Verify Jetpack plugin is active (it's auto-linked from the monorepo): |
| 109 | + ```bash |
| 110 | + jetpack docker wp plugin list | grep jetpack |
| 111 | + ``` |
| 112 | + Expected: `jetpack` shows as `active`. |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +## 6. Connect Jetpack to WordPress.com via Tunnel |
| 117 | + |
| 118 | +Jetpack requires a publicly accessible URL to handshake with WPcom. |
| 119 | + |
| 120 | +**If you're an Automattician**, use Jurassic Tube (preferred): |
| 121 | + |
| 122 | +- [ ] Follow the setup instructions at PCYsg-GJ2-p2 to install and configure Jurassic Tube if you haven't already. |
| 123 | +- [ ] Start the tunnel: |
| 124 | + ```bash |
| 125 | + jetpack docker up --jurassic-tube |
| 126 | + ``` |
| 127 | + Note your assigned domain (e.g. `yourname.jurassictube.example`). |
| 128 | + |
| 129 | +**Alternative**: Use ngrok (requires a paid account for a stable subdomain): |
| 130 | +- [ ] Start with ngrok: |
| 131 | + ```bash |
| 132 | + jetpack docker up --ngrok |
| 133 | + ``` |
| 134 | + |
| 135 | +- [ ] Once the tunnel is running, re-install WordPress with the tunnel domain: |
| 136 | + ```bash |
| 137 | + jetpack docker install |
| 138 | + ``` |
| 139 | + (This updates `WP_SITEURL` and `WP_HOME` to the tunnel domain.) |
| 140 | + |
| 141 | +- [ ] Go to **Jetpack → Dashboard** in wp-admin and complete the WPcom connection flow. Sign in with your WPcom account. |
| 142 | + |
| 143 | +- [ ] Verify connection: |
| 144 | + ```bash |
| 145 | + jetpack docker wp jetpack status |
| 146 | + ``` |
| 147 | + Expected: `Jetpack is connected to WordPress.com`. |
| 148 | + |
| 149 | +--- |
| 150 | + |
| 151 | +## 7. Enable Instant Search |
| 152 | + |
| 153 | +Instant Search must be enabled for the overlay and AI Answers panel to appear. |
| 154 | + |
| 155 | +- [ ] Enable the Search module and Instant Search: |
| 156 | + ```bash |
| 157 | + jetpack docker wp option update jetpack_active_modules '["search"]' --format=json |
| 158 | + jetpack docker wp option update instant_search_enabled 1 |
| 159 | + ``` |
| 160 | + |
| 161 | +- [ ] Verify in wp-admin: **Jetpack → Search** should show the Search dashboard with "Instant Search" toggled on. |
| 162 | + |
| 163 | +--- |
| 164 | + |
| 165 | +## 8. Enable the AI Answers Feature Flag |
| 166 | + |
| 167 | +- [ ] Enable the AI Answers feature: |
| 168 | + ```bash |
| 169 | + jetpack docker wp option update jetpack_search_ai_answers_enabled 1 |
| 170 | + ``` |
| 171 | + |
| 172 | +- [ ] Verify the **Behavior** and **Topics** tabs appear at **Jetpack → Search**. |
| 173 | + |
| 174 | +- [ ] Add a test behavior post via the Behavior tab (type any text, click Save). |
| 175 | + |
| 176 | +- [ ] Add a test topic via **Jetpack → Search → Topics → Add Topic**. |
| 177 | + Use this post content as a starting point: |
| 178 | + ``` |
| 179 | + This topic covers questions about resetting passwords and account access. |
| 180 | +
|
| 181 | + Example questions: |
| 182 | + - How do I reset my password? |
| 183 | + - I forgot my login email. |
| 184 | + - My account is locked. |
| 185 | +
|
| 186 | + Guidelines: |
| 187 | + Direct users to the account recovery page. Do not speculate about lock durations. |
| 188 | + ``` |
| 189 | + |
| 190 | +--- |
| 191 | + |
| 192 | +## 9. Point PHP→WPcom Calls to a Sandbox |
| 193 | + |
| 194 | +This routes Jetpack's server-side API calls (JWT issuance, sync, REST proxy) through your WPcom sandbox instead of production. |
| 195 | + |
| 196 | +- [ ] Create a mu-plugin file for sandbox config: |
| 197 | + ```bash |
| 198 | + cat > tools/docker/mu-plugins/sandbox.php << 'EOF' |
| 199 | + <?php |
| 200 | + // Route Jetpack server-side WPcom calls to sandbox. |
| 201 | + // Replace YOUR_SANDBOX with your actual sandbox hostname (e.g. myname.wordpress.com). |
| 202 | + define( 'JETPACK__SANDBOX_DOMAIN', 'YOUR_SANDBOX.wordpress.com' ); |
| 203 | + EOF |
| 204 | + ``` |
| 205 | +
|
| 206 | +- [ ] Restart containers to pick up the mu-plugin: |
| 207 | + ```bash |
| 208 | + jetpack docker down && jetpack docker up -d |
| 209 | + ``` |
| 210 | +
|
| 211 | +- [ ] Verify the sandbox constant is loaded: |
| 212 | + ```bash |
| 213 | + jetpack docker wp eval "echo JETPACK__SANDBOX_DOMAIN;" |
| 214 | + ``` |
| 215 | + Expected: prints your sandbox hostname. |
| 216 | +
|
| 217 | +**What this affects**: sync calls, JWT token issuance, REST proxy calls made by PHP. It does NOT redirect browser-to-wpcom calls (the overlay search query and the AI answers SSE call). |
| 218 | +
|
| 219 | +--- |
| 220 | +
|
| 221 | +## 10. Point Browser→WPcom Calls to a Sandbox |
| 222 | +
|
| 223 | +The instant-search overlay and AI Answers SSE call go directly from the browser to `public-api.wordpress.com`. To test against a sandbox, you need to intercept these at the network level. |
| 224 | +
|
| 225 | +### Option A: Proxyman (macOS, recommended) |
| 226 | +
|
| 227 | +- [ ] Install [Proxyman](https://proxyman.io) (free tier is sufficient). |
| 228 | +- [ ] Enable SSL proxying for `public-api.wordpress.com`. |
| 229 | +- [ ] Add a **Map Remote** rule: |
| 230 | + - Match: `https://public-api.wordpress.com/*` |
| 231 | + - Replace host with: `YOUR_SANDBOX.wordpress.com` |
| 232 | +- [ ] Enable the rule and keep Proxyman running while testing. |
| 233 | +
|
| 234 | +### Option B: /etc/hosts entry (only works if sandbox has a stable IP) |
| 235 | +
|
| 236 | +- [ ] Add to `/etc/hosts`: |
| 237 | + ``` |
| 238 | + SANDBOX_IP public-api.wordpress.com |
| 239 | + ``` |
| 240 | +- [ ] Flush DNS cache: |
| 241 | + ```bash |
| 242 | + sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder |
| 243 | + ``` |
| 244 | +- [ ] Remove the entry when done to restore normal operation. |
| 245 | +
|
| 246 | +### Option C: Hardcode in mu-plugin (no proxy needed, test only) |
| 247 | +
|
| 248 | +If you just want to test with a different base URL, add an override filter in your sandbox mu-plugin. The search overlay reads `JetpackInstantSearchOptions.apiRoot` for WP REST calls; for the AI answers endpoint you can override via a filter on `generate_initial_javascript_state()`: |
| 249 | +
|
| 250 | +```php |
| 251 | +add_filter( 'jetpack_instant_search_options', function( $options ) { |
| 252 | + // Override the AI answers endpoint base for sandbox testing. |
| 253 | + $options['aiAnswersBaseUrl'] = 'https://YOUR_SANDBOX.wordpress.com/wpcom/v2'; |
| 254 | + return $options; |
| 255 | +} ); |
| 256 | +``` |
| 257 | +
|
| 258 | +This requires a small code change in `answers-panel`'s SSE URL construction to read `aiAnswersBaseUrl` from `JetpackInstantSearchOptions` with a fallback to `https://public-api.wordpress.com/wpcom/v2`. Add that fallback when implementing Task 8. |
| 259 | +
|
| 260 | +--- |
| 261 | +
|
| 262 | +## 11. Verify End-to-End in the Browser |
| 263 | +
|
| 264 | +Once the wpcom AI agent endpoint is live on your sandbox: |
| 265 | +
|
| 266 | +- [ ] Open the site frontend in a browser (via the tunnel URL or localhost). |
| 267 | +- [ ] Click the Search icon or start typing in the search box to open the overlay. |
| 268 | +- [ ] Type a query that matches your test topic (e.g. "reset password") — at least 3 characters. |
| 269 | +- [ ] Verify: **loading spinner** appears above the results ("Finding an answer…"). |
| 270 | +- [ ] Verify: **streamed tokens** appear and the answer text builds up progressively. |
| 271 | +- [ ] Verify: **citations** appear below the answer when the stream completes. |
| 272 | +- [ ] Verify: standard search results still appear below the citations. |
| 273 | +- [ ] Type a query with no matching topic or search results — verify the panel shows a graceful "I couldn't find relevant content" response (or hides silently on error). |
| 274 | +- [ ] Disable the feature flag and verify the panel disappears: |
| 275 | + ```bash |
| 276 | + jetpack docker wp option update jetpack_search_ai_answers_enabled 0 |
| 277 | + ``` |
| 278 | + Refresh the page — no AI panel should appear. |
| 279 | +
|
| 280 | +--- |
| 281 | +
|
| 282 | +## 12. Verify Sync is Wiring Up (Optional — requires WPcom sandbox) |
| 283 | +
|
| 284 | +To verify that CPT posts are reaching the sandbox's shadow replicastore: |
| 285 | +
|
| 286 | +- [ ] Create a topic post via the Topics tab. |
| 287 | +- [ ] Force a sync: |
| 288 | + ```bash |
| 289 | + jetpack docker wp jetpack sync start |
| 290 | + ``` |
| 291 | +- [ ] Check sync queue is draining: |
| 292 | + ```bash |
| 293 | + jetpack docker wp jetpack sync status |
| 294 | + ``` |
| 295 | +- [ ] On your WPcom sandbox, use the Jetpack Debug page (`jptools.wordpress.com/debug`) or the WPcom REST API to verify the `jetpack_search_topic` post arrived. |
| 296 | +
|
| 297 | +--- |
| 298 | +
|
| 299 | +## Troubleshooting |
| 300 | +
|
| 301 | +| Problem | Fix | |
| 302 | +|---------|-----| |
| 303 | +| `jetpack docker up` fails | Make sure Docker Desktop is running and you have at least 4 GB RAM allocated | |
| 304 | +| Jetpack won't connect | Confirm the tunnel is active and the tunnel URL matches `WP_SITEURL` — run `jetpack docker install` after starting the tunnel | |
| 305 | +| Instant Search overlay doesn't appear | Check `instant_search_enabled` is `1` and the Jetpack Search module is active; try a hard refresh | |
| 306 | +| AI panel doesn't appear | Check `jetpack_search_ai_answers_enabled` is `1`; open browser dev tools and look for console errors from the SSE connection | |
| 307 | +| SSE call returns 404 | The wpcom agent isn't deployed yet on that sandbox — confirm with the WPcom side implementation | |
| 308 | +| SSE call returns 401 | HMAC token not generating — check `jetpack_search_ai_answers_enabled` is `1` and the blog token is present (`jetpack docker wp eval "print_r(Automattic\Jetpack\Connection\Tokens::get_access_token(JETPACK_MASTER_USER));"`) | |
| 309 | +| Sync tests fail | Run `jetpack test php packages/sync -v` and check the error message; common cause is a missing WorDBless bootstrap | |
0 commit comments