### Install and Setup Plugin Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/INDEX.md Install the plugin via Composer and then register it within Craft CMS. Finally, verify the installation by running a basic command. ```bash # Install plugin via Composer composer require markhuot/craft-pest # Install plugin in Craft ./craft plugin/install pest # Verify setup ./craft pest/test ``` -------------------------------- ### Plugin Installation and Setup Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/INDEX.md Commands to install the Craft Pest plugin and perform initial setup. ```bash composer require markhuot/craft-pest ./craft plugin/install pest ``` -------------------------------- ### Run Post-Clone Setup Script Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Manually executes the post-clone setup script. This script handles initial project setup tasks like directory creation, environment configuration, and key generation. ```bash # Run post-clone setup ./bin/post-clone.sh ``` -------------------------------- ### Plugin Discovery Process Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md Illustrates the sequence of steps Craft CMS takes to discover and load a plugin, starting from Composer installation. ```text composer install ↓ Composer writes to vendor/composer/installed.json ↓ Craft scans installed packages ↓ Finds markhuot/craft-pest with type: "craft-plugin" ↓ Reads markhuot\craftpestplugin\Pest class ↓ PSR-4 resolves to src/Pest.php ↓ Plugin class instantiated ↓ init() method called ``` -------------------------------- ### Event Listener Pattern Example Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/INDEX.md Shows how to register an event listener using `Event::on()`. This example specifically hooks into the `EVENT_AFTER_INSTALL_PLUGIN` event for the `Plugins` class. ```php Event::on(Plugins::class, Plugins::EVENT_AFTER_INSTALL_PLUGIN, callback); // Responds to plugin system events ``` -------------------------------- ### Project Configuration Example Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md If a `project.yaml` file exists, craft-pest-core automatically applies it before tests. This example shows basic field and section configurations. ```yaml # project.yaml fields: fields: title: type: craft\fields\PlainText sections: sections: news: handle: news type: single ``` -------------------------------- ### Composer Scripts for Setup Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Defines Composer script hooks for automatic execution of setup scripts during installation and updates. Ensures essential setup tasks are performed when dependencies change. ```json "scripts": { "post-install-cmd": ["bin/post-install.sh"], "post-update-cmd": ["bin/post-install.sh"] } ``` -------------------------------- ### Pest Plugin init() Method Reference Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/api-reference/pest-class.md Illustrates that the init() method is called automatically by Craft CMS during plugin loading. This example is for reference and shows how to get the plugin instance, but manual calling of init() is not required. ```php use markhuot\craftpestplugin\Pest; // The init() method is called automatically by Craft when the plugin is loaded // You do not need to call this manually. It's shown here for reference: $pestPlugin = Pest::getInstance(); // init() has already been called automatically ``` -------------------------------- ### Setup Environment File Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Copies the default '.env.example.dev' to '.env' if a .env file does not already exist. This provides a base configuration for the development environment. ```bash if [ ! -f ".env" ]; then cp vendor/craftcms/craft/.env.example.dev ./.env.example fi ``` -------------------------------- ### Setup Configuration Directory Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Copies the default configuration files from 'stubs/config/' to the 'config/' directory if the config directory does not exist. ```bash if [ ! -d "config" ]; then cp -r stubs/config ./ fi ``` -------------------------------- ### Install and Run Craft Pest Plugin Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/overview.md Install the plugin using Composer, enable it via the Craft console, and then execute tests using the provided command. ```bash composer require markhuot/craft-pest ./craft plugin/install pest ./craft pest/test ``` -------------------------------- ### Setup Bootstrap Script Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Copies the 'bootstrap.php' file from the Craft CMS vendor directory to the project root if it does not exist. ```bash if [ ! -f "bootstrap.php" ]; then cp vendor/craftcms/craft/bootstrap.php ./ fi ``` -------------------------------- ### Pest Configuration File Example Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md An example of a `pest.xml` configuration file used to define test suites and their directories. This file is optional and defaults are applied if it's absent. ```xml tests/Unit tests/Feature ``` -------------------------------- ### Initializing a Default Volume Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md The setup script initializes a default volume named 'Local' with the handle 'local'. This integrates with Craft's volume system. ```php // bin/create-default-fs.php $volume = new \craft\models\Volume; $volume->name = 'Local'; $volume->handle = 'local'; $volume->fs = $fs; $app->volumes->saveVolume($volume); ``` -------------------------------- ### Plugin Database Record Insertion Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md When installed, the plugin creates records in the 'plugins' table. This SQL statement shows an example insertion. ```sql -- plugins table INSERT INTO plugins ( `handle`, `class`, `enabled`, `dateInstalled` ) VALUES ( 'pest', 'markhuot\craftpestplugin\Pest', '1', NOW() ); ``` -------------------------------- ### Initialize Default Filesystem Manually Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Manually initializes the default filesystem. This script is typically not needed as it's handled by other setup processes. ```bash # Initialize filesystem (usually not needed) php ./bin/create-default-fs.php ``` -------------------------------- ### Install Craft Pest Plugin Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/configuration.md Installs the Pest plugin via Composer and registers it with Craft. This command creates database records, triggers the plugin's init method, fires an event, and scaffolds test files. ```bash ./craft plugin/install pest ``` -------------------------------- ### Registering Plugin Installation Event Listener Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/plugin-lifecycle.md This snippet shows how to register an event listener for the `EVENT_AFTER_INSTALL_PLUGIN` event. This listener will be triggered after any plugin is successfully installed. ```php Event::on( Plugins::class, // Event emitter class Plugins::EVENT_AFTER_INSTALL_PLUGIN, // Event name function (PluginEvent $event) { ... } // Listener callback ); ``` -------------------------------- ### Run Craft Application Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Ensures the Craft application fully initializes and persists the filesystem and volume configurations. This is a crucial step after setup scripts have been executed. ```php $app->run(); ``` -------------------------------- ### Configuration Application Example Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/core-features.md If `project.yaml` exists in the project root, its configuration is automatically applied before tests run. This ensures your tests use the same schema and content types as your project. ```php it('uses configuration', function () { // project.yaml has been applied // Content types from YAML are available // Custom fields are configured }); ``` -------------------------------- ### Install Pest Parallel Testing Plugin Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Installs the official Pest plugin for parallel test execution. ```bash # Install parallel testing plugin composer require --dev pestphp/pest-plugin-parallel ``` -------------------------------- ### Install Craft Pest Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/INDEX.md Use Composer to install the Craft Pest plugin. This command should be run in your project's root directory. ```bash composer require markhuot/craft-pest ``` -------------------------------- ### Setup Craft Console Script Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Copies the 'craft' console script from the Craft CMS vendor directory and makes it executable if it does not already exist in the project root. ```bash if [ ! -f "craft" ]; then cp vendor/craftcms/craft/craft ./ chmod +x ./craft fi ``` -------------------------------- ### Event Handler Logic for Pest Plugin Installation Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/plugin-lifecycle.md This is the callback function for the `EVENT_AFTER_INSTALL_PLUGIN` event. It checks if the installed plugin is the Pest plugin and, if so, invokes the `CopyInitialStubs` action. ```php function (PluginEvent $event) { if (is_a($event->plugin, Pest::class)) { service(CopyInitialStubs::class)(); } } ``` -------------------------------- ### List Installed Craft Plugins Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Displays a list of all installed plugins in your Craft CMS project, including the Craft Pest plugin if it has been installed. ```bash ./craft plugin/list ``` -------------------------------- ### Install Pest Plugin Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Command to install the Pest plugin for Craft CMS, resolving 'Unknown command' errors. ```bash Error: Unknown command "pest/test" **Solution:** Ensure plugin is installed: ./craft plugin/install pest ``` -------------------------------- ### Pest Plugin Initialization Logic Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/api-reference/pest-class.md This internal code shows how the Pest plugin initializes itself by calling the parent init() method, registering an event listener for plugin installation, and triggering the CopyInitialStubs action when the Pest plugin is installed. ```php function init() { parent::init(); Event::on( Plugins::class, Plugins::EVENT_AFTER_INSTALL_PLUGIN, function (PluginEvent $event) { if (is_a($event->plugin, Pest::class)) { service(CopyInitialStubs::class)(); } } ); } ``` -------------------------------- ### Install Pest Mutation Plugin Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Install the Pest mutation testing plugin using Composer. This enables mutation testing capabilities for your project. ```bash composer require --dev pestphp/pest-plugin-mutation ``` -------------------------------- ### Setup Web Directory Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Copies the 'web' directory from the Craft CMS vendor package to the project root if it does not exist. This directory contains public-facing assets and the main entry point. ```bash if [ ! -d "web" ]; then cp -r vendor/craftcms/craft/web ./ fi ``` -------------------------------- ### Create Local Filesystem if Not Exists Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Creates a local filesystem with the handle 'local' if it doesn't already exist. This is useful for ensuring consistent filesystem setup in test environments. ```php $fs = $app->fs->getFilesystemByHandle('local'); if (! $fs) { $fs = $app->fs->createFilesystem([ 'type' => \craft\fs\Local::class, 'name' => 'Local', 'handle' => 'local', 'hasUrls' => true, 'url' => 'http://localhost:8080/volumes/local/', 'settings' => ['path' => CRAFT_BASE_PATH.'/web/volumes/local'], ]); $result = $app->fs->saveFilesystem($fs); } ``` -------------------------------- ### Class Resolution Example Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md Demonstrates how Craft CMS resolves class names to file paths based on the PSR-4 configuration. ```php $class = "markhuot\craftpestplugin\Pest"; // Resolves to: src/Pest.php ``` ```php // Would resolve to: src/Services/TestManager.php $class = "markhuot\craftpestplugin\Services\TestManager"; ``` -------------------------------- ### Singleton Pattern Example Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/INDEX.md Illustrates the Singleton pattern by retrieving an instance of the Pest plugin class. It shows that multiple calls to getInstance() return the same object reference. ```php $plugin = Pest::getInstance(); $same = Pest::getInstance(); // Both references point to same instance ``` -------------------------------- ### Creating Assets in Tests with Volume Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md Tests can create assets and specify the volume they belong to, using the 'local' volume initialized by the setup script. ```php $asset = Asset::factory() ->volume('local') ->create(); ``` -------------------------------- ### Querying Entries with Query Builders Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/usage-examples.md This example demonstrates how to query entries using a syntax similar to Craft templates. It allows filtering, ordering, and limiting results. ```php $entries = Entry::all() ->section('news') ->orderBy('postDate desc') ->limit(10) ->collect(); ``` -------------------------------- ### Pest::init() Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/api-reference/pest-class.md Initializes the plugin and registers event listeners. This method is automatically called by Craft CMS during application startup and handles the setup of event handlers, including the one for post-installation actions. ```APIDOC ## init() ### Description Initializes the plugin and registers event listeners. This method is called automatically by Craft CMS during application initialization to set up event handlers and perform initial setup tasks. ### Method `public function init(): void` ### Parameters None ### Return Type `void` ### Description Called by Craft's plugin system during application initialization. This method: 1. Calls the parent `Plugin::init()` to ensure proper parent class initialization 2. Registers an event listener on the `Plugins::EVENT_AFTER_INSTALL_PLUGIN` event 3. When the Pest plugin itself is installed, triggers the `CopyInitialStubs` action from the craft-pest-core package to scaffold initial test files and configuration ### Events Registered: - `craft\services\Plugins::EVENT_AFTER_INSTALL_PLUGIN` - Triggered when any plugin is installed. The listener checks if the installed plugin is the Pest plugin itself, and if so, invokes `CopyInitialStubs` action. ### Example ```php use markhuot\craftpestplugin\Pest; // The init() method is called automatically by Craft when the plugin is loaded // You do not need to call this manually. It's shown here for reference: $pestPlugin = Pest::getInstance(); // init() has already been called automatically ``` ``` -------------------------------- ### Authenticating Users in Tests Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md This example demonstrates how to create a user, authenticate them using `actingAs`, and then make a request to a protected route like the dashboard. This leverages Craft's user and authentication systems. ```php $user = User::factory()->create(); $this->actingAs($user); $this->get('/dashboard'); ``` -------------------------------- ### Accessing Craft Services Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md Within the plugin, Craft services can be accessed using the global `Craft` instance. This example shows how to access plugins, fields, and volumes. ```php use Craft; $plugins = Craft::$app->plugins; $fields = Craft::$app->fields; $volumes = Craft::$app->volumes; ``` -------------------------------- ### Query and Assert DOM Content Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/INDEX.md This example shows how to fetch a page, query for a specific DOM element (h1), and assert that its text content matches an expected value. ```php $response->get('/') ->expectSelector('h1') ->text->toBe('Welcome'); ``` -------------------------------- ### Bootstrap Craft Console Application Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Includes the necessary Craft CMS console bootstrap files and initializes the application instance. This is the starting point for running Craft console commands. ```php require __DIR__.'/../bootstrap.php'; $app = require CRAFT_VENDOR_PATH.'/craftcms/cms/bootstrap/console.php'; ``` -------------------------------- ### Service Locator Pattern Example Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/INDEX.md Demonstrates the Service Locator pattern for dependency injection. The `service()` function automatically resolves and instantiates the required class, handling its dependencies. ```php service(CopyInitialStubs::class)(); // Automatically resolves dependencies ``` -------------------------------- ### Successful Test Run Output Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Example output indicating that all tests in a feature suite passed successfully. ```text PASS tests/Feature/HomeTest.php (3 tests, 12 assertions) ✓ loads the homepage ✓ has a welcoming h1 element ✓ asserts nine list items ────────────────────────────────────────────────────── Tests: 3 passed Time: 1.234s ``` -------------------------------- ### Pest XML Configuration Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Example Pest configuration file (`pest.xml`) defining test suites and coverage settings. ```xml tests/Unit tests/Feature src src ``` -------------------------------- ### Plugin Initialization with Event Listener Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/plugin-lifecycle.md The init() method is called after a plugin class is instantiated. It's used here to register an event listener for plugin installation events. ```php public function init() { parent::init(); // Call parent Plugin::init() // Register event listeners Event::on( Plugins::class, Plugins::EVENT_AFTER_INSTALL_PLUGIN, function (PluginEvent $event) { if (is_a($event->plugin, Pest::class)) { service(CopyInitialStubs::class)(); } } ); } ``` -------------------------------- ### Craft-Specific HTTP Testing Helpers Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Provides examples of using built-in Craft Pest helpers for making HTTP requests and performing assertions. ```php // HTTP testing $this->get('/path'); $this->post('/path', $data); // Assertions ->assertOk(); ->assertStatus(200); ->assertSee('text'); // DOM queries ->expectSelector('h1'); ->querySelector('li'); // Factories Entry::factory()->create(); Asset::factory()->create(); ``` -------------------------------- ### Run Mutation Tests Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Execute mutation tests using the Craft console command. This command leverages the installed Pest mutation plugin. ```bash ./craft pest/test --mutate ``` -------------------------------- ### Craft CMS Plugins Service Workflow Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md Outlines the sequence of operations when a plugin is installed via the console command. ```text craft plugin/install pest ↓ Craft\services\Plugins::installPlugin($plugin) ↓ Plugin initialization code runs ↓ Plugins::EVENT_AFTER_INSTALL_PLUGIN fired ↓ All registered listeners called ``` -------------------------------- ### Execute Create Default Filesystem Script Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Invokes the 'create-default-fs.php' script and suppresses all standard output and error streams. This is used during plugin installation to initialize the filesystem without verbose logging. ```bash php ./bin/create-default-fs.php > /dev/null 2>&1 ``` -------------------------------- ### Create Local Volume if Not Exists Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Creates a volume named 'local' that utilizes the previously configured local filesystem. This completes the asset storage setup for testing purposes. ```php $volume = $app->volumes->getVolumeByHandle('local'); if (! $volume) { $volume = new \craft\models\Volume; $volume->name = 'Local'; $volume->handle = 'local'; $volume->fs = $fs; $app->volumes->saveVolume($volume); } ``` -------------------------------- ### Craft CMS Documentation Navigation Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/DOCUMENTATION-MAP.md Serves as a complete guide to all documentation, offering quick links, project identity, documentation structure, and key sections by use case. ```markdown #### 10. **INDEX.md** (Detailed navigation) - **Size:** ~400 lines - **Purpose:** Complete guide to all documentation - **Contains:** - Quick links and project identity - Documentation structure with descriptions - Key sections by use case - Feature overview - File structure summary - Dependencies table - Version compatibility - Common tasks - Development section - Architecture patterns - Integration points - Troubleshooting reference - Quick start - **Use:** Navigate to the right documentation section ``` -------------------------------- ### Run Tests in Parallel Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Executes tests concurrently using the installed parallel testing plugin for faster feedback. ```bash # Run in parallel ./craft pest/test --parallel ``` -------------------------------- ### Failed Test Run Output Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Example output showing a test failure, including the specific test that failed and the error message. ```text FAIL tests/Feature/HomeTest.php (3 tests, 12 assertions) ✓ loads the homepage ✗ has a welcoming h1 element ✓ asserts nine list items ────────────────────────────────────────────────────── FAILED has a welcoming h1 element Expected 'Welcome' but got 'Hello' at tests/Feature/HomeTest.php:15 ────────────────────────────────────────────────────── Tests: 2 passed, 1 failed Time: 1.456s ``` -------------------------------- ### Composer Plugin Configuration Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/configuration.md Specifies allowed Composer plugins for the project. This ensures necessary plugins for Yii, Pest, and Craft installation are permitted. ```json { "config": { "allow-plugins": { "yiisoft/yii2-composer": true, "pestphp/pest-plugin": true, "craftcms/plugin-installer": true } } } ``` -------------------------------- ### Manual Transaction Management in Craft Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md Demonstrates how to manually manage database transactions using Craft's built-in database service. This is typically used for complex operations within a single test or setup. ```php Craft::$app->db->transaction(function() { ... }); ``` -------------------------------- ### Transaction Pattern in Tests Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/INDEX.md This example highlights the Transaction pattern within tests. It demonstrates creating an entry, and notes that the database transaction is automatically rolled back after the test completes. ```php it('creates entry', function () { Entry::factory()->create(); // Automatic transaction rollback after test }); ``` -------------------------------- ### Perform HTTP Requests Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/core-features.md Make various HTTP requests (GET, POST, PUT, PATCH, DELETE, HEAD) to test application endpoints. POST requests can include data, and all methods accept an options array for headers, cookies, and query parameters. ```php // GET request $response = $this->get('/path'); // POST request with data $response = $this->post('/path', [ 'field' => 'value' ]); // Other HTTP methods $response = $this->put('/path', $data); $response = $this->patch('/path', $data); $response = $this->delete('/path'); $response = $this->head('/path'); ``` ```php $response = $this->get('/path', [ 'headers' => [ 'Authorization' => 'Bearer token' ] ]); ``` -------------------------------- ### Registering an Event Listener Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md Registers a listener for the `EVENT_AFTER_INSTALL_PLUGIN` event on the `Plugins` service. ```php use yii\base\Event; use craft\services\Plugins; use craft\events\PluginEvent; Event::on( Plugins::class, // Emitter Plugins::EVENT_AFTER_INSTALL_PLUGIN, // Event name function (PluginEvent $event) { ... } // Callback ); ``` -------------------------------- ### Generate Craft Keys Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Executes the Craft CMS console command 'setup/keys' to generate necessary encryption keys for the application. ```bash php craft setup/keys ``` -------------------------------- ### Create Volume with Factory Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/usage-examples.md Creates a local filesystem-based volume for assets, automatically configured for testing. ```php $volume = Volume::factory()->create(); ``` -------------------------------- ### Verify Test Database and Environment Variables Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Solution for database connection errors, advising to check the test database existence and correct environment variable configuration. ```text SQLSTATE[HY000]: General error: ... **Solution:** Verify test database exists and environment variables are set correctly. ``` -------------------------------- ### Watch for Changes and Rerun Tests Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Starts Pest tests in watch mode, automatically rerunning tests whenever code files are modified. ```bash # Watch for changes and rerun tests ./craft pest/test --watch ``` -------------------------------- ### Comprehensive Kitchen Sink Test Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/usage-examples.md Demonstrates creating sections, volumes, and entries with nested factories, then tests the entry's public page and content. ```php it('tests the kitchen sink', function () { // Create a section using the factory $section = Section::factory()->create(); // Create a volume for file uploads (uses local filesystem, not S3) $volume = Volume::factory()->create(); // Create an entry with custom fields $entry = Entry::factory() // Access section by handle ->section($section->handle) // Set custom fields as though querying from the template ->isPromoted(true) // Nest factories - related assets are created automatically ->heroImage(Asset::factory()->volume($volume->handle)) ->create(); // Test the entry's public page $this->get($entry->uri) // Assert successful response ->assertOk() // Find specific DOM elements ->expectSelector('h1') // Query the text of selected elements ->text->toBe('Welcome'); }); ``` -------------------------------- ### Run Plugin Tests Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/INDEX.md Commands to execute the plugin's test suite. Includes options for running all tests, a specific file, or watching for changes. ```bash # Run all tests ./craft pest/test # Run specific test file ./craft pest/test tests/Feature/HomeTest.php # Watch for changes and rerun ./craft pest/test --watch ``` -------------------------------- ### Composer Show Tree Command Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/api-reference/imports-and-dependencies.md Use `composer show --tree` to list all project dependencies in a hierarchical tree structure, helping to understand the dependency graph. ```bash # List all dependencies composer show --tree ``` -------------------------------- ### Create Asset with Factory Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/usage-examples.md Generates a test asset within a specified volume, including a default image file. ```php $asset = Asset::factory() ->volume($volume->handle) ->create(); ``` -------------------------------- ### Accessing Field Types in Tests Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md Tests can access field types on elements. This example shows accessing a boolean field 'isPromoted' and a text field 'authorName' on an entry. ```php // In tests $entry->isPromoted; // Boolean field $entry->authorName; // Text field ``` -------------------------------- ### Create Volume Factory Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/core-features.md Instantiate Volume objects for testing using the VolumeFactory. The factory can be configured for local filesystem usage to avoid cluttering production environments. ```php use markhuot\craftpest\factories\VolumeFactory; $volume = Volume::factory()->create(); // Configured for local filesystem (not S3) // Prevents test file clutter in production environments ``` -------------------------------- ### PSR-4 Autoloading Configuration Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/api-reference/imports-and-dependencies.md Configure PSR-4 autoloading in Composer to map namespaces to specific base directories. This example maps the plugin's namespace to the 'src/' directory. ```json { "autoload": { "psr-4": { "markhuot\craftpestplugin\": "src/" } } } ``` -------------------------------- ### Run Tests with Options Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/README.md Execute tests using the './craft pest/test' command. You can run all tests, filter tests by a keyword pattern, or enable watch mode for continuous testing. ```bash ./craft pest/test # All tests ./craft pest/test --filter=keyword # Matching pattern ./craft pest/test --watch # Watch mode ``` -------------------------------- ### Set Storage Directory Permissions Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Command to fix 'Permission denied' errors related to the storage directory by setting appropriate file permissions. ```bash Permission denied: storage/logs/... **Solution:** Ensure `storage/` directory is writable: chmod -R 755 storage/ ``` -------------------------------- ### Accessing Craft Services in Tests Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Demonstrates how to access Craft CMS services, such as retrieving entries or plugin information, within a test environment. ```php use Craft; it('accesses craft services', function () { $entries = Entry::find()->section('news')->all(); $plugins = Craft::$app->plugins->getPlugin('pest'); }); ``` -------------------------------- ### Ensure Test Files Exist Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Troubleshooting step for 'No tests were executed' errors, emphasizing the need for test files in the correct directory and naming convention. ```text No tests were executed **Solution:** Ensure test files exist in `tests/` directory and follow naming convention (`*Test.php`). ``` -------------------------------- ### Get Pest Plugin Instance Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/api-reference/pest-class.md Retrieves the singleton instance of the Pest plugin. This method is inherited from Craft's Plugin base class and is useful for accessing plugin functionality statically. ```php use markhuot\craftpestplugin\Pest; // Get the plugin instance $pestPlugin = Pest::getInstance(); ``` -------------------------------- ### Singleton Pattern Implementation Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/plugin-lifecycle.md Demonstrates the singleton pattern for a plugin class, ensuring only one instance exists per application lifecycle. This is typically inherited from craft\base\Plugin. ```php $pest = Pest::getInstance(); $same = Pest::getInstance(); assert($pest === $same); // Same instance ``` -------------------------------- ### Service Locator Pattern Usage Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/api-reference/imports-and-dependencies.md Utilize the `service()` helper to instantiate classes with automatic dependency resolution, promoting testability and decoupling. ```php service(CopyInitialStubs::class)(); ``` ```php $action = app()->make(CopyInitialStubs::class); $action(); ``` -------------------------------- ### Database Transaction Example Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/core-features.md Tests automatically run within database transactions, ensuring test isolation and fast execution. Database changes made within a test are rolled back upon completion. ```php it('creates an entry', function () { $entry = Entry::factory()->create(); // Database changes are visible within test $this->assertDatabaseHas('entries', [ 'id' => $entry->id ]); }); // Transaction rolls back, changes discarded ``` -------------------------------- ### Run All Test Suites Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Executes all defined test suites, effectively running all tests in the project. ```bash # Run both (all tests) ./craft pest/test ``` -------------------------------- ### Run All Tests and Fail Fast Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Executes all tests in the project and exits immediately if any test fails, suitable for CI environments. ```bash # Run all tests, fail fast ./craft pest/test --bail ``` -------------------------------- ### Asserting Text Content on Homepage Source: https://github.com/markhuot/craft-pest/blob/master/README.md Tests the homepage to ensure the main heading (h1) contains the expected 'Welcome' text. ```php it('has a welcoming h1 element') ->get('/') ->expectSelector('h1') ->text->toBe('Welcome'); ``` -------------------------------- ### Service Resolution for Dependency Injection Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/plugin-lifecycle.md The plugin uses the `service()` helper function for dependency injection. This allows for easy testing and avoids hardcoding dependencies. ```php service(CopyInitialStubs::class)(); ``` -------------------------------- ### Craft Pest Plugin File Structure Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/overview.md Overview of the directory structure for the Craft Pest plugin, highlighting key files and their roles. ```bash craft-pest/ ├── src/ │ └── Pest.php # Main plugin class ├── bin/ │ ├── post-install.sh # Post-install setup script │ ├── post-clone.sh # Post-clone setup script │ └── create-default-fs.php # Filesystem initialization ├── composer.json # Project metadata and dependencies ├── LICENSE.md # Proprietary license terms └── README.md # User documentation ``` -------------------------------- ### Create Entry with Factory and Nested Assets Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/usage-examples.md Creates a Craft CMS entry, setting its section, custom fields, and a nested hero image asset. ```php $entry = Entry::factory() ->section($section->handle) ->isPromoted(true) ->heroImage(Asset::factory()->volume($volume->handle)) ->create(); ``` -------------------------------- ### Basic Homepage Test Source: https://github.com/markhuot/craft-pest/blob/master/README.md A simple test to verify that the homepage loads successfully and returns an OK status. ```php it('loads the homepage') ->get('/') ->assertOk(); ``` -------------------------------- ### Specify Custom Pest Configuration File Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Uses a custom Pest configuration file instead of the default `pest.xml`. This allows for project-specific test suite configurations. ```bash ./craft pest/test --config=pest.xml ``` -------------------------------- ### service() Helper Signature Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/api-reference/imports-and-dependencies.md Provides the inferred signature for the `service()` helper function, used for instantiating classes with dependency injection. ```php use function markhuot\craftpest\helpers\base\service; // Signature (inferred) function service(string $class): mixed; ``` -------------------------------- ### Craft Console Application Integration Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md The command integrates with Craft's console application. It extends the base Command class and defines actions like 'actionIndex'. ```php use craft\console\Application; class PestCommand extends Command { public function actionIndex() { ... } } ``` -------------------------------- ### Create Asset Factory Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/core-features.md Use the Asset factory to create new asset elements. You can specify the volume and filename. By default, it creates a 500x500px gray square image. ```php use markhuot\craftpest\factories\AssetFactory; $asset = Asset::factory() ->volume($volume->handle) ->create(); // Default image: 500x500px gray square // Custom filename $asset = Asset::factory() ->volume($volume->handle) ->filename('test-image.jpg') ->create(); ``` -------------------------------- ### Type Declarations in Functions Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/api-reference/imports-and-dependencies.md Illustrates minimal type declarations in functions, showing a function with no return type and another with a parameter type hint. ```php function init() // No return type { // ... } function (PluginEvent $event) { // Parameter type hint // ... } ``` -------------------------------- ### Craft CMS Console Command Reference Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/DOCUMENTATION-MAP.md Provides a comprehensive reference for all console command options, including pest/test command syntax, basic usage, options, exit codes, and configuration. ```markdown #### 9. **console-commands.md** - **Size:** ~500 lines - **Purpose:** Complete console command reference - **Contains:** - Command overview - pest/test command syntax and usage - Basic usage examples (all tests, specific file, directory) - Options (--filter, --watch, --config, --coverage, --verbose, --quiet, --halt-on-failure, --bail, --seed, --order) - Exit codes - Configuration file (pest.xml) - Related Craft commands (plugin/install, plugin/list, setup/keys) - Project structure requirements - Test file naming conventions - Test functions syntax - Environment during test execution - Available services in tests - Common workflows (TDD, debugging, CI, commits) - Output examples (success and failure) - Pest configuration example - Pest helpers reference - Troubleshooting guide - Advanced usage (multiple suites, parallel, plugins) - Command reference summary table - **Use:** Learn and reference all console command options ``` -------------------------------- ### Pest Test with Closure Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Illustrates creating a test that uses a closure to define its logic, including data creation and assertions. ```php // Test with closure it('creates an entry', function () { $entry = Entry::factory()->create(); expect($entry->id)->toBeGreaterThan(0); }); ``` -------------------------------- ### Craft CMS Imports and Dependencies Reference Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/DOCUMENTATION-MAP.md Lists all external classes and functions used by the plugin, including core PHP classes, Craft framework classes, and helper functions. ```markdown #### 12. **api-reference/imports-and-dependencies.md** - **Size:** ~350 lines - **Purpose:** All external classes and functions used - **Contains:** - Core PHP classes imported - Craft framework classes (Plugin, Event, Plugins, etc.) - craft-pest-core classes (CopyInitialStubs, behaviors) - Yii framework classes (Event) - Helper functions (service()) - Unused imports analysis - Actually used imports table - Namespace structure - Dependency versions and constraints - Composer plugin configuration - Service locator pattern explanation - Event system details - Type system notes - PSR standards compliance - External package exports (CopyInitialStubs, service()) - Testing and compatibility notes - **Use:** Understand all dependencies and imports ``` -------------------------------- ### Stop at First Failure Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Runs tests and stops execution immediately after the first test failure is encountered. ```bash # Stop at first failure ./craft pest/test -x ``` -------------------------------- ### Configure Templates Path Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Sets the CRAFT_TEMPLATES_PATH to './tests/templates' in the .env.example file. This isolates test-specific templates from the main application templates. ```bash if ! grep -q "CRAFT_TEMPLATES_PATH=" .env.example; then echo "" >> .env.example echo "CRAFT_TEMPLATES_PATH=./tests/templates" >> .env.example echo "" >> .env.example fi ``` -------------------------------- ### Configure Queue Processing Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Adds or updates the CRAFT_RUN_QUEUE_AUTOMATICALLY setting to 'false' in the .env.example file. This is crucial for ensuring deterministic test execution by disabling automatic background job processing. ```bash if ! grep -q "CRAFT_RUN_QUEUE_AUTOMATICALLY=" .env.example; then echo "" >> .env.example echo "CRAFT_RUN_QUEUE_AUTOMATICALLY=false" >> .env.example echo "" >> .env.example fi ``` -------------------------------- ### CopyInitialStubs Action Signature Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/api-reference/imports-and-dependencies.md Defines the inferred signature for the `CopyInitialStubs` action, which is responsible for creating initial test files and stubs. ```php use markhuot\craftpest\actions\CopyInitialStubs; // Signature (inferred) class CopyInitialStubs { public function __invoke(): void; } ``` -------------------------------- ### Craft Pest Project Test Directory Structure Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Illustrates the default project structure for tests in a Craft Pest project. It shows the organization of Feature and Unit tests, as well as test templates. ```bash tests/ ├── Feature/ # Integration/browser tests │ ├── HomeTest.php │ └── EntryTest.php ├── Unit/ # Unit tests │ └── CalculatorTest.php └── templates/ # Test templates └── home.html ``` -------------------------------- ### Run All Tests Before Commit Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md A common workflow step to ensure all tests pass before committing code changes. ```bash # Run all tests before commit ./craft pest/test ``` -------------------------------- ### Creating Elements in Tests Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md In tests, elements like Entries and Assets can be created using factory methods provided by craft-pest-core. ```php // In tests (provided by craft-pest-core) $entry = Entry::factory()->create(); $asset = Asset::factory()->create(); ``` -------------------------------- ### Create Section with Factory Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/usage-examples.md Creates a new Craft CMS section using a factory, generating default handle and name. ```php $section = Section::factory()->create(); ``` -------------------------------- ### Create Test Data with Factory Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/README.md Utilize the Entry factory to create test entries for your Craft CMS content. Specify the section, title, and then call 'create' to persist the entry. ```php $entry = Entry::factory() ->section('news') ->title('My Post') ->create(); ``` -------------------------------- ### Pest Test with Expectations Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/console-commands.md Shows a basic test structure using the `test` function, suitable for simple assertions or placeholder tests. ```php // Test with expectations test('does something', function () { // ... }); ``` -------------------------------- ### Count DOM Elements Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/INDEX.md Demonstrates how to query for all list items (li) on a page and assert that the count of these elements matches a specific number. ```php $response->get('/') ->querySelector('li') ->assertCount(9); ``` -------------------------------- ### Comprehensive Kitchen Sink Test Source: https://github.com/markhuot/craft-pest/blob/master/README.md A detailed test demonstrating various Pest for Craft CMS features, including factory usage for sections, volumes, and entries, and making HTTP requests. ```php it('tests the kitchen sink', function () { // Factories can be used to create fields, sections, entries, etc… Realistically, much // of this may come from your project.yaml, but in the event you need to scaffold some // content types while testing a plugin or module, it is absolutely possible. // What's more, if a project.yaml is detected, Craft Pest will automatically check and // apply that config before each run to ensure you are always testing against a clean // schema. $section = Section::factory()->create(); // Volume factories give you a local folder-based volume that ensures // your tests don't clutter your production S3 buckets, for example. $volume = Volume::factory()->create(); $entry = Entry::factory() // Most fields on the entry factory can be defined just like you would' // when querying `craft.entries` in a template. ->section($section->handle) // Even custom fields can be defined while creating an entry. This allows // you to mock/simulate a variety of content elements without needing to // pass around a complex and huge "seeding" database. ->isPromoted(true) // Custom fields can be set to nested factories and will be automatically // created as they are needed. // Most factories can be utilized with as few as one additional field, like // assets here, which only need to know their volume. The contents of the // image will default to a 500x500px gray square. ->heroImage(Asset::factory()->volume($volume->handle)) ->create(); // For simple tests, you can call `->get()` or `->post()` to make simulated // HTTP requests against the Craft site. It will take a site (or CP) URL and // return the rendered response. // For many people, just starting out with testing, their first (and only) // test is simply `$this->get('/')` to ensure the homepage loads. $this->get($entry->uri) // All HTTP tests should probably check the status code of the response and // ensure Craft returned a 200 Ok response. ->assertOk() // A response can be further inspected to check that the exact HTML matches // your expectations. Here the `querySelector` and `expectSelector` methods // allow you to parse over the response using a familiar CSS-based syntax. ->expectSelector('h1') // Querying the HTML allows you to test the text, count, or even HTML of the // DOM to ensure it matches your expectations. ->text->toBe('Welcome'); }); ``` -------------------------------- ### HTTP Methods for Testing Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/usage-examples.md Use these methods to simulate different HTTP requests during your tests. They are available directly within your test methods. ```php $this->get('/path') // GET request $this->post('/path') // POST request $this->put('/path') // PUT request $this->patch('/path') // PATCH request $this->delete('/path') // DELETE request $this->head('/path') // HEAD request ``` -------------------------------- ### Run Tests Matching Pattern Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/usage-examples.md Filters and runs tests whose names or descriptions match a given pattern. ```bash ./craft pest/test --filter=kitchen ``` -------------------------------- ### Configure URL Script Name Omission Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/setup-scripts.md Enables CRAFT_OMIT_SCRIPT_NAME_IN_URLS to 'true' in the .env.example file. This simplifies URLs in the test environment by removing 'index.php'. ```bash if ! grep -q "CRAFT_OMIT_SCRIPT_NAME_IN_URLS=" .env.example; then echo "" >> .env.example echo "CRAFT_OMIT_SCRIPT_NAME_IN_URLS=true" >> .env.example echo "" >> .env.example fi ``` -------------------------------- ### HTTP Testing with craft-pest-core Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/craft-integration.md Tests make HTTP requests through craft-pest-core's `TestableElementBehavior`. This mimics real HTTP requests to Craft's application. ```php $this->get('/') ``` -------------------------------- ### Required Packages Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/configuration.md Lists the essential Composer packages required for the plugin to function. Includes Craft CMS and the core Pest testing functionality. ```json { "require": { "craftcms/cms": "^4.5|^5.0.0-beta.1", "markhuot/craft-pest-core": "^2.0.0" } } ``` -------------------------------- ### Checking HTTP Headers Source: https://github.com/markhuot/craft-pest/blob/master/README.md Asserts that the 'x-powered-by' header on the homepage response is set to 'Craft CMS'. ```php it('promotes craft') ->get('/') ->assertHeader('x-powered-by', 'Craft CMS'); ``` -------------------------------- ### Run Tests with Craft Pest Source: https://github.com/markhuot/craft-pest/blob/master/_autodocs/configuration.md Executes all tests in the project using the Pest framework via the Craft console command. This command is provided by the craft-pest-core package. ```bash ./craft pest/test ```