Testing

This guide covers testing WPZylos CLI Core and generators built with it.

Running Package Tests

# Run all tests
composer test

# Run specific test
./vendor/bin/phpunit tests/StubCompilerTest.php

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

Testing StubCompiler

<?php

namespace WPZylos\Framework\Cli\Core\Tests;

use PHPUnit\Framework\TestCase;
use WPZylos\Framework\Cli\Core\StubCompiler;

class StubCompilerTest extends TestCase
{
    private string $stubsPath;

    protected function setUp(): void
    {
        $this->stubsPath = __DIR__ . '/fixtures/stubs';

        // Create test stub
        if (!is_dir($this->stubsPath)) {
            mkdir($this->stubsPath, 0755, true);
        }

        file_put_contents(
            $this->stubsPath . '/test.stub',
            'namespace {{namespace}}; class {{class}} {}'
        );
    }

    public function testCompileReplacesTokens(): void
    {
        $compiler = new StubCompiler($this->stubsPath);

        $result = $compiler->compile('test', [
            'namespace' => 'App',
            'class' => 'MyClass',
        ]);

        $this->assertEquals(
            'namespace App; class MyClass {}',
            $result
        );
    }

    public function testCompileWithDefaults(): void
    {
        $compiler = new StubCompiler($this->stubsPath);
        $compiler->setDefaults(['namespace' => 'DefaultNs']);

        $result = $compiler->compile('test', [
            'class' => 'MyClass',
        ]);

        $this->assertStringContainsString('DefaultNs', $result);
    }

    public function testCompileThrowsForMissingStub(): void
    {
        $this->expectException(\InvalidArgumentException::class);

        $compiler = new StubCompiler($this->stubsPath);
        $compiler->compile('nonexistent', []);
    }

    public function testGetAvailable(): void
    {
        $compiler = new StubCompiler($this->stubsPath);
        $stubs = $compiler->getAvailable();

        $this->assertContains('test', $stubs);
    }
}

Testing FileWriter

<?php

namespace WPZylos\Framework\Cli\Core\Tests;

use PHPUnit\Framework\TestCase;
use WPZylos\Framework\Cli\Core\FileWriter;

class FileWriterTest extends TestCase
{
    private string $tempDir;

    protected function setUp(): void
    {
        $this->tempDir = sys_get_temp_dir() . '/cli-core-test-' . uniqid();
        mkdir($this->tempDir);
    }

    protected function tearDown(): void
    {
        $this->recursiveDelete($this->tempDir);
    }

    public function testWriteCreatesFile(): void
    {
        $writer = new FileWriter();
        $path = $this->tempDir . '/test.php';

        $writer->write($path, '<?php echo "test";');

        $this->assertFileExists($path);
        $this->assertEquals('<?php echo "test";', file_get_contents($path));
    }

    public function testWriteCreatesDirectories(): void
    {
        $writer = new FileWriter();
        $path = $this->tempDir . '/deep/nested/dir/test.php';

        $writer->write($path, 'content');

        $this->assertFileExists($path);
    }

    public function testWriteThrowsOnExistingFile(): void
    {
        $this->expectException(\RuntimeException::class);

        $writer = new FileWriter(overwrite: false);
        $path = $this->tempDir . '/existing.php';

        file_put_contents($path, 'original');
        $writer->write($path, 'new content');
    }

    public function testWriteOverwritesWhenEnabled(): void
    {
        $writer = new FileWriter(overwrite: true);
        $path = $this->tempDir . '/existing.php';

        file_put_contents($path, 'original');
        $writer->write($path, 'new content');

        $this->assertEquals('new content', file_get_contents($path));
    }

    public function testWriteIfNotExistsSkipsExisting(): void
    {
        $writer = new FileWriter();
        $path = $this->tempDir . '/existing.php';

        file_put_contents($path, 'original');
        $result = $writer->writeIfNotExists($path, 'new content');

        $this->assertFalse($result);
        $this->assertEquals('original', file_get_contents($path));
    }

    private function recursiveDelete(string $dir): void
    {
        if (!is_dir($dir)) return;

        foreach (scandir($dir) as $item) {
            if ($item === '.' || $item === '..') continue;

            $path = $dir . '/' . $item;
            is_dir($path) ? $this->recursiveDelete($path) : unlink($path);
        }

        rmdir($dir);
    }
}

Testing Custom Generators

<?php

namespace MyPlugin\Tests;

use PHPUnit\Framework\TestCase;
use WPZylos\Framework\Cli\Core\StubCompiler;
use WPZylos\Framework\Cli\Core\FileWriter;
use MyPlugin\Generators\ControllerGenerator;

class ControllerGeneratorTest extends TestCase
{
    private string $tempDir;
    private ControllerGenerator $generator;

    protected function setUp(): void
    {
        $this->tempDir = sys_get_temp_dir() . '/generator-test-' . uniqid();
        mkdir($this->tempDir);
        mkdir($this->tempDir . '/stubs');

        // Create test stub
        file_put_contents(
            $this->tempDir . '/stubs/controller.stub',
            '<?php namespace {{namespace}}; class {{class}}Controller {}'
        );

        $compiler = new StubCompiler($this->tempDir . '/stubs');
        $writer = new FileWriter();
        $this->generator = new ControllerGenerator($compiler, $writer, $this->tempDir);
    }

    public function testGenerateCreatesController(): void
    {
        $files = $this->generator->generate('product');

        $this->assertCount(1, $files);
        $this->assertFileExists($files[0]);
        $this->assertStringContainsString('ProductController', file_get_contents($files[0]));
    }

    public function testGenerateUsesCustomNamespace(): void
    {
        $files = $this->generator->generate('product', [
            'namespace' => 'Custom\\Controllers',
        ]);

        $this->assertStringContainsString(
            'Custom\\Controllers',
            file_get_contents($files[0])
        );
    }
}