docs: consolidate documentation into organized structure

- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
This commit is contained in:
2025-10-05 11:05:04 +02:00
parent 887847dde6
commit 5050c7d73a
36686 changed files with 196456 additions and 12398919 deletions

View File

@@ -0,0 +1,246 @@
<?php
declare(strict_types=1);
namespace Tests\Framework\Http\ValueObjects;
use App\Framework\Http\ValueObjects\ETag;
describe('ETag Value Object', function () {
it('can be created with basic value', function () {
$etag = new ETag('abc123');
expect($etag->getValue())->toBe('abc123');
expect($etag->isStrong())->toBeTrue();
expect($etag->isWeak())->toBeFalse();
expect($etag->toHeaderValue())->toBe('"abc123"');
});
it('can be created as weak ETag', function () {
$etag = new ETag('abc123', true);
expect($etag->getValue())->toBe('abc123');
expect($etag->isWeak())->toBeTrue();
expect($etag->isStrong())->toBeFalse();
expect($etag->toHeaderValue())->toBe('W/"abc123"');
});
it('rejects empty values', function () {
expect(fn () => new ETag(''))->toThrow(\InvalidArgumentException::class);
});
it('supports strong factory method', function () {
$etag = ETag::strong('strong-value');
expect($etag->getValue())->toBe('strong-value');
expect($etag->isStrong())->toBeTrue();
expect($etag->toHeaderValue())->toBe('"strong-value"');
});
it('supports weak factory method', function () {
$etag = ETag::weak('weak-value');
expect($etag->getValue())->toBe('weak-value');
expect($etag->isWeak())->toBeTrue();
expect($etag->toHeaderValue())->toBe('W/"weak-value"');
});
it('can create ETag from content hash', function () {
$content = 'Hello, World!';
$expectedHash = hash('sha256', $content);
$strongETag = ETag::fromContent($content);
expect($strongETag->getValue())->toBe($expectedHash);
expect($strongETag->isStrong())->toBeTrue();
$weakETag = ETag::fromContent($content, true);
expect($weakETag->getValue())->toBe($expectedHash);
expect($weakETag->isWeak())->toBeTrue();
});
it('can create ETag from file', function () {
// Create a temporary test file
$tempFile = '/tmp/claude/etag_test_file.txt';
if (! is_dir('/tmp/claude')) {
mkdir('/tmp/claude', 0755, true);
}
file_put_contents($tempFile, 'Test content');
$etag = ETag::fromFile($tempFile);
expect($etag->getValue())->toBeString();
expect($etag->isStrong())->toBeTrue();
// Cleanup
unlink($tempFile);
});
it('throws exception for non-existent file', function () {
expect(fn () => ETag::fromFile('/nonexistent/file.txt'))
->toThrow(\InvalidArgumentException::class);
});
it('can parse strong ETag from header', function () {
$etag = ETag::parse('"abc123"');
expect($etag->getValue())->toBe('abc123');
expect($etag->isStrong())->toBeTrue();
});
it('can parse weak ETag from header', function () {
$etag = ETag::parse('W/"abc123"');
expect($etag->getValue())->toBe('abc123');
expect($etag->isWeak())->toBeTrue();
});
it('can parse ETag without quotes', function () {
$etag = ETag::parse('abc123');
expect($etag->getValue())->toBe('abc123');
expect($etag->isStrong())->toBeTrue();
});
it('throws exception for empty header value', function () {
expect(fn () => ETag::parse(''))->toThrow(\InvalidArgumentException::class);
expect(fn () => ETag::parse(' '))->toThrow(\InvalidArgumentException::class);
});
it('can parse multiple ETags from header', function () {
$etags = ETag::parseMultiple('"abc123", W/"def456", "ghi789"');
expect($etags)->toHaveCount(3);
expect($etags[0])->toBeInstanceOf(ETag::class);
expect($etags[0]->getValue())->toBe('abc123');
expect($etags[0]->isStrong())->toBeTrue();
expect($etags[1]->getValue())->toBe('def456');
expect($etags[1]->isWeak())->toBeTrue();
expect($etags[2]->getValue())->toBe('ghi789');
expect($etags[2]->isStrong())->toBeTrue();
});
it('handles wildcard in parseMultiple', function () {
$etags = ETag::parseMultiple('*');
expect($etags)->toBe(['*']);
});
it('handles empty parseMultiple', function () {
$etags = ETag::parseMultiple('');
expect($etags)->toBe([]);
});
it('supports strong comparison matching', function () {
$etag1 = ETag::strong('abc123');
$etag2 = ETag::strong('abc123');
$etag3 = ETag::weak('abc123');
$etag4 = ETag::strong('different');
// Strong comparison requires both to be strong
expect($etag1->matches($etag2, true))->toBeTrue();
expect($etag1->matches($etag3, true))->toBeFalse(); // One is weak
expect($etag1->matches($etag4, true))->toBeFalse(); // Different values
});
it('supports weak comparison matching', function () {
$etag1 = ETag::strong('abc123');
$etag2 = ETag::weak('abc123');
$etag3 = ETag::strong('different');
// Weak comparison only checks values
expect($etag1->matches($etag2, false))->toBeTrue();
expect($etag1->matches($etag3, false))->toBeFalse();
});
it('can match against list of ETags', function () {
$etag = ETag::strong('abc123');
$etags = [
ETag::strong('different'),
ETag::weak('abc123'),
ETag::strong('another'),
];
expect($etag->matchesAny($etags, false))->toBeTrue(); // Weak comparison
expect($etag->matchesAny($etags, true))->toBeFalse(); // Strong comparison (target is weak)
// Test with wildcard
expect($etag->matchesAny(['*'], false))->toBeTrue();
expect($etag->matchesAny(['*'], true))->toBeTrue();
});
it('supports withWeak transformation', function () {
$strong = ETag::strong('abc123');
$weak = $strong->withWeak(true);
$strongAgain = $weak->withWeak(false);
expect($strong->isStrong())->toBeTrue();
expect($weak->isWeak())->toBeTrue();
expect($weak->getValue())->toBe('abc123');
expect($strongAgain->isStrong())->toBeTrue();
// Original should be unchanged
expect($strong->isStrong())->toBeTrue();
});
it('supports equality comparison', function () {
$etag1 = ETag::strong('abc123');
$etag2 = ETag::strong('abc123');
$etag3 = ETag::weak('abc123');
$etag4 = ETag::strong('different');
expect($etag1->equals($etag2))->toBeTrue();
expect($etag1->equals($etag3))->toBeFalse(); // Different weak/strong
expect($etag1->equals($etag4))->toBeFalse(); // Different value
});
it('supports string conversion', function () {
$strong = ETag::strong('abc123');
$weak = ETag::weak('def456');
expect($strong->toString())->toBe('"abc123"');
expect($weak->toString())->toBe('W/"def456"');
expect((string) $strong)->toBe('"abc123"');
expect((string) $weak)->toBe('W/"def456"');
});
it('handles same file consistently', function () {
// Create test file
$tempFile = '/tmp/claude/etag_consistency_test.txt';
if (! is_dir('/tmp/claude')) {
mkdir('/tmp/claude', 0755, true);
}
file_put_contents($tempFile, 'Consistent content');
$etag1 = ETag::fromFile($tempFile);
$etag2 = ETag::fromFile($tempFile);
expect($etag1->equals($etag2))->toBeTrue();
// Cleanup
unlink($tempFile);
});
it('handles content changes in file', function () {
// Create test file
$tempFile = '/tmp/claude/etag_change_test.txt';
if (! is_dir('/tmp/claude')) {
mkdir('/tmp/claude', 0755, true);
}
file_put_contents($tempFile, 'Original content');
$etag1 = ETag::fromFile($tempFile);
// Wait a moment and change content
sleep(1);
file_put_contents($tempFile, 'Modified content');
$etag2 = ETag::fromFile($tempFile);
expect($etag1->equals($etag2))->toBeFalse();
// Cleanup
unlink($tempFile);
});
});