Testing

Setup

Install Dev Dependencies

composer install

Run Tests

composer test

Run All Quality Checks

composer qa

Bootstrap

The test bootstrap (tests/bootstrap.php) mocks all WordPress functions used by the notification package:

  • esc_html(), esc_attr(), esc_url(), wp_kses_post()
  • wp_mail(), wp_json_encode(), current_time()
  • get_transient(), set_transient(), delete_transient()
  • add_action(), add_filter(), do_action(), apply_filters()
  • get_current_user_id(), dbDelta()

Testing Notifications

Test a Custom Notification

<?php

declare(strict_types=1);

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;
use App\Notifications\OrderShipped;
use WPZylos\Framework\Notification\MailMessage;

class OrderShippedTest extends TestCase
{
    public function testViaReturnsExpectedChannels(): void
    {
        $order = (object) ['id' => 1, 'tracking_url' => 'https://example.com/track'];
        $notification = new OrderShipped($order);

        $this->assertSame(['mail', 'database'], $notification->via());
    }

    public function testToMailBuildsCorrectMessage(): void
    {
        $order = (object) ['id' => 42, 'tracking_url' => 'https://example.com/track/42'];
        $notification = new OrderShipped($order);
        $notifiable = (object) ['email' => '[email protected]'];

        $message = $notification->toMail($notifiable);

        $this->assertInstanceOf(MailMessage::class, $message);
        $this->assertSame('Order Shipped!', $message->subject);
        $this->assertStringContainsString('42', $message->lines[0]);
    }

    public function testToDatabaseReturnsData(): void
    {
        $order = (object) ['id' => 42, 'tracking_url' => 'https://example.com'];
        $notification = new OrderShipped($order);
        $notifiable = (object) [];

        $data = $notification->toDatabase($notifiable);

        $this->assertArrayHasKey('order_id', $data);
        $this->assertSame(42, $data['order_id']);
    }
}

Test the NotificationManager

<?php

declare(strict_types=1);

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;
use WPZylos\Framework\Notification\Contracts\NotificationChannel;
use WPZylos\Framework\Notification\Notification;
use WPZylos\Framework\Notification\NotificationManager;

class NotificationManagerTest extends TestCase
{
    public function testSendDispatchesToChannels(): void
    {
        $manager = new NotificationManager();

        $channel = $this->createMock(NotificationChannel::class);
        $channel->expects($this->once())->method('send');

        $manager->extend('test', $channel);

        $notification = new class extends Notification {
            public function via(): array { return ['test']; }
        };

        $manager->send(new \stdClass(), $notification);
    }
}

Test Custom Channels

<?php

declare(strict_types=1);

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;
use App\Channels\SlackChannel;
use WPZylos\Framework\Notification\Notification;

class SlackChannelTest extends TestCase
{
    public function testSendSkipsWhenNoToSlackMethod(): void
    {
        $channel = new SlackChannel('https://hooks.slack.com/test');

        $notification = new class extends Notification {
            public function via(): array { return ['slack']; }
        };

        // Should not throw — silently skips
        $channel->send(new \stdClass(), $notification);
        $this->assertTrue(true);
    }
}

Test MailMessage Rendering

public function testMailMessageRenders(): void
{
    $message = (new MailMessage())
        ->subject('Test')
        ->greeting('Hello!')
        ->line('This is a test.')
        ->action('Click', 'https://example.com');

    $html = $message->render();

    $this->assertStringContainsString('<h1>Hello!</h1>', $html);
    $this->assertStringContainsString('This is a test.', $html);
    $this->assertStringContainsString('https://example.com', $html);
}

Mocking the NotificationManager

In integration tests, you can mock the manager to verify notifications were sent:

$mockManager = $this->createMock(NotificationManager::class);
$mockManager->expects($this->once())
    ->method('send')
    ->with(
        $this->callback(fn($n) => $n instanceof User),
        $this->isInstanceOf(OrderShipped::class)
    );

Code Coverage

Generate a coverage report:

XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html coverage/

Open coverage/index.html in your browser to view the report.