Skip to content

Commit 0fd92cc

Browse files
committed
chore: completing partial tests
1 parent 8f9faa8 commit 0fd92cc

6 files changed

Lines changed: 470 additions & 172 deletions

clover.xml

Lines changed: 166 additions & 172 deletions
Large diffs are not rendered by default.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
use Html\Trait\ClassResolverTrait;
4+
use Html\Delegator\HTMLDocumentDelegator;
5+
use Html\Delegator\HTMLElementDelegator;
6+
7+
class TestClassResolverExtra
8+
{
9+
use ClassResolverTrait;
10+
11+
public function callGetClassesExtendingClass(string $base): array
12+
{
13+
return $this->getClassesExtendingClass($base);
14+
}
15+
16+
public function callGetClassesImplementingInterface(string $interface): array
17+
{
18+
return $this->getClassesImplementingInterface($interface);
19+
}
20+
21+
public function callGetElementByQualifiedName(string $name): ?string
22+
{
23+
return $this->getElementByQualifiedName($name);
24+
}
25+
26+
public function callGetDelegatorFromElement(\DOM\Element $element): ?HTMLElementDelegator
27+
{
28+
return $this->getDelegatorFromElement($element);
29+
}
30+
}
31+
32+
// Simple classes for testing inheritance/interface discovery
33+
class BaseForResolverTest {}
34+
class SubForResolverTest extends BaseForResolverTest {}
35+
interface InterfaceForResolver {}
36+
class ImplementsResolverTest implements InterfaceForResolver {}
37+
38+
// Test element delegator with Element attribute
39+
#[\Html\Mapping\Element('x-foo')]
40+
class TestElementDelegator extends HTMLElementDelegator {
41+
public static string $QUALIFIED_NAME = 'x-foo';
42+
}
43+
44+
test('getClassesExtendingClass finds subclasses', function () {
45+
$resolver = new TestClassResolverExtra();
46+
47+
$result = $resolver->callGetClassesExtendingClass(BaseForResolverTest::class);
48+
49+
expect(in_array(SubForResolverTest::class, $result))->toBeTrue();
50+
});
51+
52+
test('getClassesImplementingInterface finds implementations', function () {
53+
$resolver = new TestClassResolverExtra();
54+
55+
$result = $resolver->callGetClassesImplementingInterface(InterfaceForResolver::class);
56+
57+
expect(in_array(ImplementsResolverTest::class, $result))->toBeTrue();
58+
});
59+
60+
test('getElementByQualifiedName finds class by attribute', function () {
61+
$resolver = new TestClassResolverExtra();
62+
63+
$class = $resolver->callGetElementByQualifiedName('x-foo');
64+
65+
expect($class)->toBe(TestElementDelegator::class);
66+
});
67+
68+
test('getDelegatorFromElement returns instance of the configured class', function () {
69+
$doc = HTMLDocumentDelegator::createEmpty();
70+
$element = $doc->delegated->createElement('x-foo');
71+
72+
$resolver = new TestClassResolverExtra();
73+
$delegator = $resolver->callGetDelegatorFromElement($element);
74+
75+
expect($delegator)->toBeInstanceOf(TestElementDelegator::class);
76+
});
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
use Html\Trait\ClassResolverTrait;
4+
5+
class TestClassResolverPrivate
6+
{
7+
use ClassResolverTrait;
8+
9+
public function callLoadAllPhpFiles(string $dir): void
10+
{
11+
$this->loadAllPhpFiles($dir);
12+
}
13+
14+
public function callFindComposerRoot(string $start): ?string
15+
{
16+
return $this->findComposerRoot($start);
17+
}
18+
19+
public function callGetPackageRoot(): string
20+
{
21+
return $this->getPackageRoot();
22+
}
23+
}
24+
25+
test('loadAllPhpFiles requires php files and loads classes', function () {
26+
$tmp = sys_get_temp_dir() . '/ehd_test_' . uniqid();
27+
mkdir($tmp . '/src', 0777, true);
28+
$file = $tmp . '/src/TestLoadedClass.php';
29+
file_put_contents($file, "<?php\nclass TempLoadedClass {}\n");
30+
31+
$t = new TestClassResolverPrivate();
32+
33+
expect(class_exists('TempLoadedClass'))->toBeFalse();
34+
$t->callLoadAllPhpFiles($tmp . '/src');
35+
expect(class_exists('TempLoadedClass'))->toBeTrue();
36+
37+
// cleanup
38+
@unlink($file);
39+
@rmdir($tmp . '/src');
40+
@rmdir($tmp);
41+
});
42+
43+
test('findComposerRoot returns autoload path when composer.json and vendor/autoload.php exist', function () {
44+
$tmp = sys_get_temp_dir() . '/ehd_test_comp_' . uniqid();
45+
mkdir($tmp . '/nested/dir', 0777, true);
46+
file_put_contents($tmp . '/composer.json', '{}');
47+
mkdir($tmp . '/vendor', 0777, true);
48+
file_put_contents($tmp . '/vendor/autoload.php', "<?php\n// autoload\n");
49+
50+
$t = new TestClassResolverPrivate();
51+
52+
$found = $t->callFindComposerRoot($tmp . '/nested/dir');
53+
54+
expect($found)->toBe($tmp . '/vendor/autoload.php');
55+
56+
// cleanup
57+
@unlink($tmp . '/vendor/autoload.php');
58+
@rmdir($tmp . '/vendor');
59+
@unlink($tmp . '/composer.json');
60+
@rmdir($tmp . '/nested/dir');
61+
@rmdir($tmp . '/nested');
62+
@rmdir($tmp);
63+
});
64+
65+
test('getPackageRoot returns string and points to package root', function () {
66+
$t = new TestClassResolverPrivate();
67+
68+
$pkg = $t->callGetPackageRoot();
69+
70+
expect(is_string($pkg))->toBeTrue();
71+
expect(is_dir($pkg))->toBeTrue();
72+
});

tests/Trait/DelegatorTraitTest.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
use Html\Trait\DelegatorTrait;
4+
use BadMethodCallException;
5+
use InvalidArgumentException;
6+
7+
class DummyDelegated {
8+
public string $fooProp = 'bar';
9+
10+
public function sum(int $a, int $b): int {
11+
return $a + $b;
12+
}
13+
14+
public function methodTakesObject(\stdClass $obj): string {
15+
return $obj->name ?? 'none';
16+
}
17+
18+
public function typeStrict(int $x): int {
19+
return $x * 2;
20+
}
21+
}
22+
23+
class TestDelegator
24+
{
25+
use DelegatorTrait;
26+
27+
public object $delegated;
28+
29+
public function __construct()
30+
{
31+
$this->delegated = new DummyDelegated();
32+
}
33+
}
34+
35+
test('__call delegates method calls and returns result', function () {
36+
$t = new TestDelegator();
37+
38+
$result = $t->sum(2, 3);
39+
40+
expect($result)->toBe(5);
41+
});
42+
43+
test('__call replaces delegator arg with delegated object when passed', function () {
44+
$t = new TestDelegator();
45+
46+
$other = new TestDelegator();
47+
$other->delegated = new \stdClass();
48+
$other->delegated->name = 'abc';
49+
50+
$res = $t->methodTakesObject($other);
51+
52+
expect($res)->toBe('abc');
53+
});
54+
55+
test('__call throws BadMethodCallException when call fails due to type error', function () {
56+
$t = new TestDelegator();
57+
58+
expect(fn () => $t->typeStrict('not-int'))
59+
->toThrow(BadMethodCallException::class);
60+
});
61+
62+
test('__get returns delegated property value and throws when missing', function () {
63+
$t = new TestDelegator();
64+
65+
expect($t->fooProp)->toBe('bar');
66+
expect(fn () => $t->missingProp)->toThrow(InvalidArgumentException::class);
67+
});
68+
69+
test('__set sets delegated property and throws when missing', function () {
70+
$t = new TestDelegator();
71+
72+
$t->fooProp = 'changed';
73+
expect($t->fooProp)->toBe('changed');
74+
75+
expect(fn () => ($t->unknown = 'x'))->toThrow(InvalidArgumentException::class);
76+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
use Html\Trait\GeneratorResolverTrait;
4+
use Html\Trait\ClassResolverTrait;
5+
use Html\Mapping\TemplateGenerator;
6+
use Html\Interface\TemplateGeneratorInterface;
7+
8+
#[TemplateGenerator('testgen')]
9+
class TestGeneratorImplementation implements TemplateGeneratorInterface {
10+
public function getExtension(): string { return 'x'; }
11+
public function getNamePattern(): string { return 'x'; }
12+
public function canRenderElements(): bool { return false; }
13+
public function canRenderDocuments(): bool { return false; }
14+
public function isTemplated(): bool { return false; }
15+
public function render($elementOrDocument): ?string { return null; }
16+
}
17+
18+
class TestGeneratorResolver {
19+
use GeneratorResolverTrait;
20+
use ClassResolverTrait; // supplies getClassesImplementingInterface used by GeneratorResolver
21+
22+
public function callGetGenerators(array $names): array
23+
{
24+
return $this->getGenerators($names);
25+
}
26+
}
27+
28+
test('getGenerators returns instances of annotated generators by name', function () {
29+
$r = new TestGeneratorResolver();
30+
31+
$result = $r->callGetGenerators(['testgen']);
32+
33+
expect(array_key_exists('testgen', $result))->toBeTrue();
34+
expect($result['testgen'])->toBeInstanceOf(TestGeneratorImplementation::class);
35+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
use Html\Trait\NativePropertiesTrait;
4+
5+
class TestNativeProperties {
6+
use NativePropertiesTrait;
7+
8+
// define properties that trait expects to exist
9+
public ?string $textContent = null;
10+
public string $innerHTML = '';
11+
public string $nodeValue = '';
12+
public string $substitutedNodeValue = '';
13+
}
14+
15+
test('textContent setter and getter', function () {
16+
$t = new TestNativeProperties();
17+
18+
$t->setTextContent('hello');
19+
20+
expect($t->getTextContent())->toBe('hello');
21+
});
22+
23+
test('innerHTML setter and getter', function () {
24+
$t = new TestNativeProperties();
25+
26+
$t->setInnerHTML('<b>bold</b>');
27+
28+
expect($t->getInnerHTML())->toBe('<b>bold</b>');
29+
});
30+
31+
test('nodeValue setter and getter', function () {
32+
$t = new TestNativeProperties();
33+
34+
$t->setNodeValue('node');
35+
36+
expect($t->getNodeValue())->toBe('node');
37+
});
38+
39+
test('substitutedNodeValue setter and getter', function () {
40+
$t = new TestNativeProperties();
41+
42+
$t->setSubstitutedNodeValue('sub');
43+
44+
expect($t->getSubstitutedNodeValue())->toBe('sub');
45+
});

0 commit comments

Comments
 (0)