From 24ee04a77d078a156554693ccd91be78dcf5300f Mon Sep 17 00:00:00 2001 From: Fellyph Cintra Date: Tue, 28 Oct 2025 10:16:34 +0000 Subject: [PATCH 01/10] applying docs guidelines --- .../04-wp-playground-cli.md | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/packages/docs/site/docs/developers/05-local-development/04-wp-playground-cli.md b/packages/docs/site/docs/developers/05-local-development/04-wp-playground-cli.md index f5def5f246..8c77971594 100644 --- a/packages/docs/site/docs/developers/05-local-development/04-wp-playground-cli.md +++ b/packages/docs/site/docs/developers/05-local-development/04-wp-playground-cli.md @@ -5,20 +5,19 @@ slug: /developers/local-development/wp-playground-cli # Playground CLI -[@wp-playground/cli](https://www.npmjs.com/package/@wp-playground/cli) is a command-line tool that simplifies the WordPress development and testing flow. -Playground CLI supports auto-mounting a directory with a plugin, theme, or WordPress installation. But if you need flexibility, the CLI supports mounting commands to personalize your local environment. +[@wp-playground/cli](https://www.npmjs.com/package/@wp-playground/cli) is a command-line tool that simplifies the WordPress development and testing flow. You can use Playground CLI to auto-mount a directory with a plugin, theme, or WordPress installation. If you need flexibility, you can use mounting commands to personalize your local environment. **Key features:** -- **Quick Setup**: Set up a local WordPress environment in seconds. +- **Quick setup**: Set up a local WordPress environment in seconds. - **Flexibility**: Allows for configuration to adapt to different scenarios. -- **Simple Environment**: No extra configuration, just a compatible Node version, and you are ready to use it. +- **Simple environment**: No extra configuration, just a compatible Node version, and you are ready to use it. ## Requirements The Playground CLI requires Node.js 20.18 or higher, which is the recommended Long-Term Support (LTS) version. You can download it from the [Node.js website](https://nodejs.org/en/download). -## Quickstart +## Quick start To run the Playground CLI, open a command line and use the following command: @@ -35,7 +34,7 @@ cd my-plugin-or-theme-directory npx @wp-playground/cli@latest server --auto-mount ``` -### Choosing a WordPress and PHP Version +### Choosing a WordPress and PHP version By default, the CLI loads the latest stable version of WordPress and PHP 8.3 due to its improved performance. To specify your preferred versions, you can use the flag `--wp=` and `--php=`: @@ -43,11 +42,11 @@ By default, the CLI loads the latest stable version of WordPress and PHP 8.3 due npx @wp-playground/cli@latest server --wp=6.8 --php=8.3 ``` -### Loading Blueprints +### Loading blueprints One way to take your Playground CLI development experience to the next level is to integrate with [Blueprints](/blueprints/getting-started/). For those unfamiliar with this technology, it allows developers to configure the initial state for their WordPress Playground instances. -Using the `--blueprint=` flag, developers can run a Playground with a custom initial state. We’ll use the example below to do this. +Using the `--blueprint=` flag, developers can run a Playground with a custom initial state. We'll use the example below to do this. **(my-blueprint.json)** @@ -88,7 +87,7 @@ npx @wp-playground/cli@latest server --mount-before-install=.:/wordpress/ On Windows, the path format `/host/path:/vfs/path` can cause issues. To resolve this, use the flags `--mount-dir` and `--mount-dir-before-install`. These flags let you specify host and virtual file system paths in an alternative format`"/host/path"` `"/vfs/path"`. ::: -### Understanding Data Persistence and SQLite Location +### Understanding data persistence and SQLite location By default, Playground CLI stores WordPress files and the SQLite database in **temporary directories on your operating system**: @@ -99,7 +98,7 @@ By default, Playground CLI stores WordPress files and the SQLite database in **t └── tmp/ # Temporary PHP files ``` -**Finding Your Temp Directory:** +**Finding your temp directory:** The actual location depends on your OS (these are examples or common possibilities): @@ -125,7 +124,7 @@ Mount before WP install: /wordpress -> /private/var/folders/c8/mwz12ycx4s509056kby3hk180000gn/T/node-playground-cli-site-62926--62926-yQNOdvJVIgYC/wordpress ``` -**Where is the SQLite Database Stored?** +**Where is the SQLite database stored?** The database location depends on what you mount: @@ -141,10 +140,10 @@ The database location depends on what you mount: - **Custom mounts**: Database location follows your mount configuration -**Automatic Cleanup:** +**Automatic cleanup:** Playground CLI automatically removes temp directories that are: -- Older than 2 days +- Older than two days - No longer associated with a running process **Recommendation:** To persist both your code and database when developing plugins or themes, mount the entire `wp-content` directory instead of just the plugin/theme folder. @@ -157,9 +156,9 @@ cd my-wordpress-project npx @wp-playground/cli@latest server --mount=./wp-content:/wordpress/wp-content ``` -## Command and Arguments +## Commands and arguments -Playground CLI is simple, configurable, and unopinionated. You can set it up according +The Playground CLI is simple, configurable, and unopinionated. You can set it up according to your unique WordPress setup. With the Playground CLI, you can use the following top-level commands: - **`server`**: (Default) Starts a local WordPress server. @@ -190,7 +189,7 @@ The `server` command supports the following optional arguments: - `--internal-cookie-store`: Enable internal cookie handling. When enabled, Playground will manage cookies internally using an HttpCookieStore that persists cookies across requests. When disabled, cookies are handled externally (e.g., by a browser in Node.js environments). Defaults to false. - `--xdebug`: Enable Xdebug. Defaults to false. - `--experimental-devtools`: Enable experimental browser development tools. Defaults to false. -- `--experimental-multi-worker=`: Enable experimental multi-worker support which requires a `/wordpress` directory backed by a real filesystem. Pass a positive number to specify the number of workers to use. Otherwise, defaults to the number of CPUs minus 1. +- `--experimental-multi-worker=`: Enable experimental multi-worker support which requires a `/wordpress` directory backed by a real file system. Pass a positive number to specify the number of workers to use. Otherwise, defaults to the number of CPUs minus one. :::caution With the flag `--follow-symlinks`, the following symlinks will expose files outside mounted directories to Playground and could be a security risk. @@ -204,7 +203,7 @@ With the Playground CLI, you can use the `--help` flag to get the full list of a npx @wp-playground/cli@latest --help ``` -## Programmatic Usage with JavaScript +## Programmatic usage with JavaScript The Playground CLI can also be controlled programmatically from your JavaScript/TypeScript code using the `runCLI` function. This gives you direct access to all CLI functionalities within your code, which is useful for automating end-to-end tests. Let's cover the basics of using `runCLI`. @@ -225,9 +224,9 @@ cliServer = await runCLI({ } as RunCLIArgs); ``` -To execute the code above, the developer can set their preferred method. A simple way to execute this code is to save it as a `.ts` file and run it with a tool like `tsx`. For example: `tsx my-script.ts` +To execute the code above, you can set your preferred method. A simple way to execute this code is to save it as a `.ts` file and run it with a tool like `tsx`. For example: `tsx my-script.ts` -### Setting a Blueprint +### Setting a blueprint You can provide a blueprint in two ways: either as an object literal directly passed to the `blueprint` property, or as a string containing the path to an external `.json` file. @@ -277,7 +276,7 @@ const myBlueprint: BlueprintDeclaration = { ### Mounting a plugin programmatically -It is possible to mount local directories programmatically using `runCLI`. The options `mount` and `mount-before-install` are available. The `hostPath` property expects a path to a directory on your local machine. This path should be relative to where your script is being executed. +You can mount local directories programmatically using `runCLI`. The options `mount` and `mount-before-install` are available. The `hostPath` property expects a path to a directory on your local machine. This path should be relative to where your script is being executed. ```TypeScript cliServer = await runCLI({ @@ -292,7 +291,7 @@ It is possible to mount local directories programmatically using `runCLI`. The o }); ``` -With those options we can combine mounting parts of the project with blueprints, for example: +You can combine mounting parts of the project with blueprints, for example: ```TypeScript From d31581a67c3ca427630e22a36a554bbe179eee83 Mon Sep 17 00:00:00 2001 From: Fellyph Cintra Date: Tue, 28 Oct 2025 10:38:30 +0000 Subject: [PATCH 02/10] Adding more examples for run CLI and new flags --- .../04-wp-playground-cli.md | 525 +++++++++++++++++- 1 file changed, 503 insertions(+), 22 deletions(-) diff --git a/packages/docs/site/docs/developers/05-local-development/04-wp-playground-cli.md b/packages/docs/site/docs/developers/05-local-development/04-wp-playground-cli.md index 8c77971594..2d6996377c 100644 --- a/packages/docs/site/docs/developers/05-local-development/04-wp-playground-cli.md +++ b/packages/docs/site/docs/developers/05-local-development/04-wp-playground-cli.md @@ -34,6 +34,45 @@ cd my-plugin-or-theme-directory npx @wp-playground/cli@latest server --auto-mount ``` +### Auto-mounting different project types + +The `--auto-mount` flag intelligently detects your project type and mounts it appropriately: + +**Plugin directory:** + +```bash +cd my-plugin +npx @wp-playground/cli@latest server --auto-mount +``` + +**Theme directory:** + +```bash +cd my-theme +npx @wp-playground/cli@latest server --auto-mount +``` + +**wp-content directory:** + +```bash +cd my-site/wp-content +npx @wp-playground/cli@latest server --auto-mount +``` + +**Full WordPress installation:** + +```bash +cd my-wordpress +npx @wp-playground/cli@latest server --auto-mount +``` + +**Static HTML/PHP project:** + +```bash +cd my-static-site +npx @wp-playground/cli@latest server --auto-mount +``` + ### Choosing a WordPress and PHP version By default, the CLI loads the latest stable version of WordPress and PHP 8.3 due to its improved performance. To specify your preferred versions, you can use the flag `--wp=` and `--php=`: @@ -42,6 +81,20 @@ By default, the CLI loads the latest stable version of WordPress and PHP 8.3 due npx @wp-playground/cli@latest server --wp=6.8 --php=8.3 ``` +### Setting a custom site URL + +You can configure a custom site URL for your development environment, which is useful for testing domain-specific functionality or simulating production environments: + +```bash +npx @wp-playground/cli@latest server --site-url=https://my-local-dev.test +``` + +You can also specify a custom port: + +```bash +npx @wp-playground/cli@latest server --port=3000 --site-url=http://localhost:3000 +``` + ### Loading blueprints One way to take your Playground CLI development experience to the next level is to integrate with [Blueprints](/blueprints/getting-started/). For those unfamiliar with this technology, it allows developers to configure the initial state for their WordPress Playground instances. @@ -50,14 +103,11 @@ Using the `--blueprint=` flag, developers can run a Playgroun **(my-blueprint.json)** -```bash +```json { - "landingPage": "/wp-admin/options-general.php?page=akismet-key-config", - "login": true, - "plugins": [ - "hello-dolly", - "https://raw.githubusercontent.com/adamziel/blueprints/trunk/docs/assets/hello-from-the-dashboard.zip" - ] + "landingPage": "/wp-admin/options-general.php?page=akismet-key-config", + "login": true, + "plugins": ["hello-dolly", "https://raw.githubusercontent.com/adamziel/blueprints/trunk/docs/assets/hello-from-the-dashboard.zip"] } ``` @@ -75,6 +125,16 @@ Some projects have a specific structure that requires a custom configuration; fo npx @wp-playground/cli@latest server --mount=.:/wordpress/wp-content/plugins/MY-PLUGIN-DIRECTORY ``` +**Multiple mounts:** + +You can mount multiple directories at once: + +```bash +npx @wp-playground/cli@latest server \ + --mount=./my-plugin:/wordpress/wp-content/plugins/my-plugin \ + --mount=./my-theme:/wordpress/wp-content/themes/my-theme +``` + ### Mounting before WordPress installation Consider mounting your WordPress project files before the WordPress installation begins. This approach is beneficial if you want to override the Playground boot process, as it can help connect Playground with `WP-CLI`. The `--mount-before-install` flag supports this process. @@ -83,8 +143,18 @@ Consider mounting your WordPress project files before the WordPress installation npx @wp-playground/cli@latest server --mount-before-install=.:/wordpress/ ``` -:::info -On Windows, the path format `/host/path:/vfs/path` can cause issues. To resolve this, use the flags `--mount-dir` and `--mount-dir-before-install`. These flags let you specify host and virtual file system paths in an alternative format`"/host/path"` `"/vfs/path"`. +### Symlink support for monorepos + +If you're working in a monorepo or complex project structure where packages are symlinked, you can enable symlink following: + +```bash +npx @wp-playground/cli@latest server \ + --follow-symlinks \ + --mount-before-install=./packages/my-plugin:/wordpress/wp-content/plugins/my-plugin +``` + +:::caution +Using `--follow-symlinks` can expose files outside mounted directories to Playground and could be a security risk. Only use this flag when you trust the symlink targets. ::: ### Understanding data persistence and SQLite location @@ -156,6 +226,20 @@ cd my-wordpress-project npx @wp-playground/cli@latest server --mount=./wp-content:/wordpress/wp-content ``` +## Verbosity and debugging + +The CLI supports different verbosity levels to control output, for `quiet`, `normal` and `debug` mode. The default mode is `normal`. For quiet mode, run the server with no output (useful for scripts and automation): + +```bash +npx @wp-playground/cli@latest server --verbosity=quiet +``` + +Get detailed logging information for troubleshooting, with `debug` mode: + +```bash +npx @wp-playground/cli@latest server --verbosity=debug +``` + ## Commands and arguments The Playground CLI is simple, configurable, and unopinionated. You can set it up according @@ -191,8 +275,8 @@ The `server` command supports the following optional arguments: - `--experimental-devtools`: Enable experimental browser development tools. Defaults to false. - `--experimental-multi-worker=`: Enable experimental multi-worker support which requires a `/wordpress` directory backed by a real file system. Pass a positive number to specify the number of workers to use. Otherwise, defaults to the number of CPUs minus one. -:::caution -With the flag `--follow-symlinks`, the following symlinks will expose files outside mounted directories to Playground and could be a security risk. +:::info +On Windows, the path format `/host/path:/vfs/path` can cause issues. To resolve this, use the flags `--mount-dir` and `--mount-dir-before-install`. These flags let you specify host and virtual file system paths in an alternative format`"/host/path"` `"/vfs/path"`. ::: ## Need some help with the CLI? @@ -226,6 +310,65 @@ cliServer = await runCLI({ To execute the code above, you can set your preferred method. A simple way to execute this code is to save it as a `.ts` file and run it with a tool like `tsx`. For example: `tsx my-script.ts` +**Testing with specific PHP versions:** + +```TypeScript +import { runCLI } from "@wp-playground/cli"; + +const cliServer = await runCLI({ + command: 'server', + php: '8.0', + skipWordPressSetup: true, + skipSqliteSetup: true, +}); + +// Test PHP version +await cliServer.playground.writeFile( + '/wordpress/version.php', + '' +); + +const versionUrl = new URL('/version.php', cliServer.serverUrl); +const response = await fetch(versionUrl); +const version = await response.text(); +console.log('PHP Version:', version); // Outputs: 8.0.x +``` + +### Setting a custom site URL programmatically + +```TypeScript +const cliServer = await runCLI({ + command: 'server', + 'site-url': 'https://my-staging.example.com', + port: 9500 +}); + +// Verify site URL is set correctly +await cliServer.playground.writeFile( + '/wordpress/check-url.php', + '' +); + +const checkUrl = new URL('/check-url.php', cliServer.serverUrl); +const response = await fetch(checkUrl); +console.log('Site URL:', await response.text()); +``` + +### Controlling verbosity programmatically + +```TypeScript +import { runCLI } from "@wp-playground/cli"; +import { logger } from '@php-wasm/logger'; + +const cliServer = await runCLI({ + command: 'server', + verbosity: 'debug' // or 'quiet' or 'normal' +}); + +// Add custom logging +logger.debug('Custom debug message'); +``` + ### Setting a blueprint You can provide a blueprint in two ways: either as an object literal directly passed to the `blueprint` property, or as a string containing the path to an external `.json` file. @@ -279,22 +422,38 @@ const myBlueprint: BlueprintDeclaration = { You can mount local directories programmatically using `runCLI`. The options `mount` and `mount-before-install` are available. The `hostPath` property expects a path to a directory on your local machine. This path should be relative to where your script is being executed. ```TypeScript - cliServer = await runCLI({ - command: 'server', - login: true, - 'mount-before-install': [ - { - hostPath: './[my-plugin-local-path]', - vfsPath: '/wordpress/wp-content/plugins/my-plugin', - }, - ], - }); +cliServer = await runCLI({ + command: 'server', + login: true, + 'mount-before-install': [ + { + hostPath: './[my-plugin-local-path]', + vfsPath: '/wordpress/wp-content/plugins/my-plugin', + }, + ], +}); ``` -You can combine mounting parts of the project with blueprints, for example: +**Auto-mounting programmatically:** ```TypeScript +import { runCLI } from "@wp-playground/cli"; +import process from 'node:process'; + +// Change to your project directory +process.chdir('./my-plugin'); + +const cliServer = await runCLI({ + command: 'server', + autoMount: '' // Empty string triggers auto-detection +}); +``` + +### Combining mounts with blueprints + +You can combine mounting parts of the project with blueprints, for example: +```TypeScript import { runCLI, RunCLIArgs, RunCLIServer } from "@wp-playground/cli"; let cliServer: RunCLIServer; @@ -320,3 +479,325 @@ cliServer = await runCLI({ } } as RunCLIArgs); ``` + +**Multiple mounts with blueprints:** + +```TypeScript +const cliServer = await runCLI({ + command: 'server', + mount: [ + { + hostPath: './my-plugin', + vfsPath: '/wordpress/wp-content/plugins/my-plugin' + }, + { + hostPath: './my-theme', + vfsPath: '/wordpress/wp-content/themes/my-theme' + } + ], + blueprint: { + steps: [ + { + step: 'activatePlugin', + pluginPath: '/wordpress/wp-content/plugins/my-plugin/plugin.php' + }, + { + step: 'activateTheme', + themeFolderName: 'my-theme' + } + ] + } +}); +``` + +**Complex blueprint with multiple configurations:** + +```TypeScript +const cliServer = await runCLI({ + command: 'server', + php: '8.3', + wp: 'latest', + login: true, + mount: [ + { + hostPath: './my-plugin', + vfsPath: '/wordpress/wp-content/plugins/my-plugin' + } + ], + blueprint: { + landingPage: '/wp-admin/plugins.php', + steps: [ + { + step: 'activatePlugin', + pluginPath: '/wordpress/wp-content/plugins/my-plugin/plugin.php' + }, + { + step: 'setSiteOptions', + options: { + blogname: 'Plugin Test Site', + permalink_structure: '/%postname%/' + } + }, + { + step: 'runPHP', + code: '' + } + ] + } +}); +``` + +### Mode selection (Blueprint v2) + +You can specify different modes when working with Blueprint v2: + +**Creating a new site:** + +```TypeScript +import { runCLI } from "@wp-playground/cli"; + +const cliServer = await runCLI({ + command: 'server', + 'experimental-blueprints-v2-runner': true, + mode: 'create-new-site', + 'mount-before-install': [ + { + hostPath: './my-new-site', + vfsPath: '/wordpress' + } + ] +}); +``` + +**Applying to an existing site:** + +```TypeScript +const cliServer = await runCLI({ + command: 'server', + 'experimental-blueprints-v2-runner': true, + mode: 'apply-to-existing-site', + 'mount-before-install': [ + { + hostPath: './existing-wordpress', + vfsPath: '/wordpress' + } + ], + blueprint: { + steps: [ + { + step: 'setSiteOptions', + options: { + blogname: 'Updated Site Name' + } + } + ] + } +}); +``` + +## Automated testing + +### Integration testing with Vitest + +The programmatic API is excellent for automated testing. Here's a complete example using Vitest: + +```TypeScript +import { describe, test, expect, afterEach } from 'vitest'; +import { runCLI, RunCLIServer } from "@wp-playground/cli"; + +describe('My Plugin Tests', () => { + let cliServer: RunCLIServer; + + afterEach(async () => { + if (cliServer) { + await cliServer[Symbol.asyncDispose](); + } + }); + + test('plugin activates successfully', async () => { + cliServer = await runCLI({ + command: 'server', + mount: [ + { + hostPath: './my-plugin', + vfsPath: '/wordpress/wp-content/plugins/my-plugin' + } + ], + blueprint: { + steps: [ + { + step: 'activatePlugin', + pluginPath: '/wordpress/wp-content/plugins/my-plugin/plugin.php' + } + ] + } + }); + + const homeUrl = new URL('/', cliServer.serverUrl); + const response = await fetch(homeUrl); + + expect(response.status).toBe(200); + const html = await response.text(); + expect(html).toContain('My Plugin'); + }); + + test('plugin settings page loads', async () => { + cliServer = await runCLI({ + command: 'server', + login: true, // Auto-login as admin + mount: [ + { + hostPath: './my-plugin', + vfsPath: '/wordpress/wp-content/plugins/my-plugin' + } + ], + blueprint: { + steps: [ + { + step: 'activatePlugin', + pluginPath: '/wordpress/wp-content/plugins/my-plugin/plugin.php' + } + ] + } + }); + + const settingsUrl = new URL( + '/wp-admin/options-general.php?page=my-plugin', + cliServer.serverUrl + ); + const response = await fetch(settingsUrl); + + expect(response.status).toBe(200); + }); +}); +``` + +### Testing theme customizations + +```TypeScript +test('theme displays custom header', async () => { + cliServer = await runCLI({ + command: 'server', + mount: [ + { + hostPath: './my-theme', + vfsPath: '/wordpress/wp-content/themes/my-theme' + } + ], + blueprint: { + steps: [ + { + step: 'installTheme', + themeData: { + resource: 'vfs', + path: '/wordpress/wp-content/themes/my-theme' + } + }, + { + step: 'activateTheme', + themeFolderName: 'my-theme' + } + ] + } + }); + + const homeUrl = new URL('/', cliServer.serverUrl); + const response = await fetch(homeUrl); + const html = await response.text(); + + expect(html).toContain('