Testing

Running the Test Suite

# Run all tests
composer test

# Run with coverage
vendor/bin/phpunit --coverage-html coverage/

# Run a specific test class
vendor/bin/phpunit tests/Unit/MailableTest.php

# Run a specific test method
vendor/bin/phpunit --filter test_basic_email_can_be_built

Test Setup

The test bootstrap (tests/bootstrap.php) mocks these WordPress functions:

FunctionMock Behavior
wp_mail()Records arguments to $wpzylos_test_last_mail global, returns true
esc_url()Uses filter_var() with FILTER_SANITIZE_URL
esc_html()Uses htmlspecialchars()
get_option()Returns [email protected] for admin_email, Test Blog for blogname

Testing Your Own Code

Testing Emails Are Sent

Use the build() method to inspect emails without sending:

use PHPUnit\Framework\TestCase;
use WPZylos\Framework\Mail\Mailable;

class MyFeatureTest extends TestCase
{
    public function test_welcome_email_has_correct_content(): void
    {
        $mail = new Mailable();
        $mail->to('[email protected]')
            ->subject('Welcome')
            ->greeting('Hello!')
            ->line('Welcome aboard.');

        $built = $mail->build();

        $this->assertSame(['[email protected]'], $built['to']);
        $this->assertSame('Welcome', $built['subject']);
        $this->assertStringContainsString('Hello!', $built['message']);
        $this->assertStringContainsString('Welcome aboard.', $built['message']);
    }
}

Testing wp_mail() Was Called

Use the global $wpzylos_test_last_mail set by the mock:

public function test_send_invokes_wp_mail(): void
{
    global $wpzylos_test_last_mail;
    $wpzylos_test_last_mail = null;

    $mail = new Mailable();
    $mail->to('[email protected]')
        ->subject('Test')
        ->line('Body')
        ->send();

    $this->assertNotNull($wpzylos_test_last_mail);
    $this->assertSame(['[email protected]'], $wpzylos_test_last_mail['to']);
    $this->assertSame('Test', $wpzylos_test_last_mail['subject']);
}

Testing MailManager

Create a mock context for MailManager tests:

use WPZylos\Framework\Mail\MailManager;

$context = new class {
    public function path(string $subPath = ''): string
    {
        return sys_get_temp_dir() . '/' . $subPath;
    }
};

$manager = new MailManager($context);
$manager->setFrom('[email protected]', 'Test App');

$mailable = $manager->to('[email protected]');
$this->assertInstanceOf(Mailable::class, $mailable);

Testing View Templates

Create a temporary template file for view rendering tests:

public function test_view_template_renders(): void
{
    $tmpDir = sys_get_temp_dir();
    file_put_contents($tmpDir . '/test-template.php', '<p>Hello <?= $name ?></p>');

    $mail = new Mailable();
    $result = $mail->to('[email protected]')
        ->subject('View Test')
        ->templatePath($tmpDir)
        ->view('test-template', ['name' => 'John'])
        ->build();

    $this->assertStringContainsString('Hello John', $result['message']);

    unlink($tmpDir . '/test-template.php');
}

Quality Assurance

Run the full QA suite:

# All checks: tests, PHPStan, code style
composer qa

# Individual checks
composer test      # PHPUnit
composer analyze   # PHPStan level 5
composer cs        # PHPCS PSR-12
composer cs-fix    # Auto-fix code style