### 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
```