Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ composer.lock
*.swp
*.swo
*~

/.phpunit.cache/
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,20 @@ Some ideas for future classes:

## Development

This project uses PHP CodeSniffer with PSR-12 standard for code quality.
This project uses PHP CodeSniffer with PSR-12 standard for code quality and PHPUnit for testing.

```bash
# Run tests
composer test

# Check code style
composer check

# Auto-fix code style issues
composer fix

# Or use vendor binaries directly
vendor/bin/phpunit
vendor/bin/phpcs --standard=PSR12 src/
vendor/bin/phpcbf --standard=PSR12 src/
```
Expand Down
11 changes: 9 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,23 @@
"php": "^8.1"
},
"require-dev": {
"squizlabs/php_codesniffer": "^4.0"
"squizlabs/php_codesniffer": "^4.0",
"phpunit/phpunit": "^10.0"
},
"autoload": {
"psr-4": {
"Calvert\\DndErrors\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Calvert\\DndErrors\\Tests\\": "tests/"
}
},
"scripts": {
"check": "phpcs --standard=PSR12 src/",
"fix": "phpcbf --standard=PSR12 src/"
"fix": "phpcbf --standard=PSR12 src/",
"test": "phpunit"
},
"minimum-stability": "stable"
}
24 changes: 24 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
cacheDirectory=".phpunit.cache"
executionOrder="depends,defects"
requireCoverageMetadata="false"
beStrictAboutCoverageMetadata="true"
beStrictAboutOutputDuringTests="true"
failOnRisky="true"
failOnWarning="true">
<testsuites>
<testsuite name="default">
<directory>tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">src</directory>
</include>
</source>
</phpunit>

93 changes: 93 additions & 0 deletions tests/Archetype/PaladinTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace Calvert\DndErrors\Tests\Archetype;

use Calvert\DndErrors\Archetype\Paladin;
use Calvert\DndErrors\ErrorContext;
use PHPUnit\Framework\TestCase;

final class PaladinTest extends TestCase
{
private Paladin $paladin;

protected function setUp(): void
{
$this->paladin = new Paladin();
}

public function testGetSlugReturnsPaladin(): void
{
$this->assertSame('paladin', $this->paladin->getSlug());
}

public function testRenderContainsMessage(): void
{
$context = new ErrorContext(
type: 'Error',
message: 'Test error message',
file: '/path/to/file.php',
line: 42
);

$output = $this->paladin->render($context);

$this->assertStringContainsString('Test error message', $output);
$this->assertStringContainsString('/path/to/file.php:42', $output);
}

public function testRenderContainsPaladinEmoji(): void
{
$context = new ErrorContext(
type: 'Error',
message: 'Test error',
);

$output = $this->paladin->render($context);

// Should contain paladin emoji (✨ or ⚔️)
$this->assertTrue(
str_contains($output, '✨') || str_contains($output, '⚔️'),
'Output should contain paladin emoji'
);
}

public function testRenderIncludesLocationWhenProvided(): void
{
$context = new ErrorContext(
type: 'Error',
message: 'Test error',
file: 'test.php',
line: 10
);

$output = $this->paladin->render($context);

$this->assertStringContainsString('test.php:10', $output);
}

public function testRenderShowsUnknownLocationWhenFileOrLineMissing(): void
{
$context = new ErrorContext(
type: 'Error',
message: 'Test error',
);

$output = $this->paladin->render($context);

$this->assertStringContainsString('Unknown location', $output);
}

public function testRenderForFatalError(): void
{
$context = new ErrorContext(
type: 'fatal',
message: 'Fatal error occurred',
);

$output = $this->paladin->render($context);

// Fatal errors should have special headers
$this->assertStringContainsString('Fatal error occurred', $output);
}
}

51 changes: 51 additions & 0 deletions tests/Archetype/RangerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Calvert\DndErrors\Tests\Archetype;

use Calvert\DndErrors\Archetype\Ranger;
use Calvert\DndErrors\ErrorContext;
use PHPUnit\Framework\TestCase;

final class RangerTest extends TestCase
{
private Ranger $ranger;

protected function setUp(): void
{
$this->ranger = new Ranger();
}

public function testGetSlugReturnsRanger(): void
{
$this->assertSame('ranger', $this->ranger->getSlug());
}

public function testRenderContainsMessage(): void
{
$context = new ErrorContext(
type: 'Error',
message: 'Trail lost',
file: '/forest/path.php',
line: 15
);

$output = $this->ranger->render($context);

$this->assertStringContainsString('Trail lost', $output);
$this->assertStringContainsString('/forest/path.php:15', $output);
}

public function testRenderContainsRangerEmoji(): void
{
$context = new ErrorContext(
type: 'Error',
message: 'Test error',
);

$output = $this->ranger->render($context);

// Should contain ranger emoji 🏹
$this->assertStringContainsString('🏹', $output);
}
}

51 changes: 51 additions & 0 deletions tests/Archetype/WizardTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Calvert\DndErrors\Tests\Archetype;

use Calvert\DndErrors\Archetype\Wizard;
use Calvert\DndErrors\ErrorContext;
use PHPUnit\Framework\TestCase;

final class WizardTest extends TestCase
{
private Wizard $wizard;

protected function setUp(): void
{
$this->wizard = new Wizard();
}

public function testGetSlugReturnsWizard(): void
{
$this->assertSame('wizard', $this->wizard->getSlug());
}

public function testRenderContainsMessage(): void
{
$context = new ErrorContext(
type: 'Error',
message: 'Arcane failure',
file: '/spellbook/incantation.php',
line: 7
);

$output = $this->wizard->render($context);

$this->assertStringContainsString('Arcane failure', $output);
$this->assertStringContainsString('/spellbook/incantation.php:7', $output);
}

public function testRenderContainsWizardEmoji(): void
{
$context = new ErrorContext(
type: 'Error',
message: 'Test error',
);

$output = $this->wizard->render($context);

// Should contain wizard emoji 🧙
$this->assertStringContainsString('🧙', $output);
}
}

44 changes: 44 additions & 0 deletions tests/ErrorContextTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Calvert\DndErrors\Tests;

use Calvert\DndErrors\ErrorContext;
use PHPUnit\Framework\TestCase;

final class ErrorContextTest extends TestCase
{
public function testCanCreateErrorContextWithAllProperties(): void
{
$context = new ErrorContext(
type: 'RuntimeException',
message: 'Test error message',
file: '/path/to/file.php',
line: 42,
trace: array('trace' => 'data'),
phpVersion: '8.1.0'
);

$this->assertSame('RuntimeException', $context->type);
$this->assertSame('Test error message', $context->message);
$this->assertSame('/path/to/file.php', $context->file);
$this->assertSame(42, $context->line);
$this->assertSame(array('trace' => 'data'), $context->trace);
$this->assertSame('8.1.0', $context->phpVersion);
}

public function testCanCreateErrorContextWithMinimalProperties(): void
{
$context = new ErrorContext(
type: 'Error',
message: 'Test message'
);

$this->assertSame('Error', $context->type);
$this->assertSame('Test message', $context->message);
$this->assertNull($context->file);
$this->assertNull($context->line);
$this->assertSame(array(), $context->trace);
$this->assertNull($context->phpVersion);
}
}