Skip to content

Commit ab18a9b

Browse files
committed
Add macro test
1 parent 0a5d552 commit ab18a9b

11 files changed

+386
-3
lines changed

Diff for: .gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
.phpdoc
33
phpdoc.xml
44

5+
# PHPUbit
6+
phpunit.xml
7+
.phpunit*
8+
59
# IDE
610
.idea
711

Diff for: composer.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,21 @@
1818
],
1919
"require": {
2020
"php": ">=7.4",
21-
"phpdocumentor/phpdocumentor": ">=3.0",
22-
"twig/twig": "2.*"
21+
"phpdocumentor/phpdocumentor": ">=3.0"
2322
},
2423
"require-dev": {
25-
"phpunit/phpunit": "^9.5"
24+
"phpunit/phpunit": "^9.5",
25+
"twig/twig": "2.*"
2626
},
2727
"autoload": {
2828
"psr-4": {
2929
"PhpDocumentorMarkdown\\": "src/"
3030
}
3131
},
3232
"autoload-dev": {
33+
"psr-4": {
34+
"PhpDocumentorMarkdown\\Test\\": "tests/"
35+
}
3336
},
3437
"scripts": {
3538
"phpdoc": "phpdoc run -d . -t ./docs"

Diff for: phpunit.dist.xml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<phpunit backupGlobals="false" colors="true">
2+
<testsuites>
3+
<testsuite name="Twig">
4+
<directory suffix="Test.php">./tests/Twig</directory>
5+
</testsuite>
6+
</testsuites>
7+
<extensions>
8+
<extension class="\PhpDocumentorMarkdown\Test\Twig\Extension"/>
9+
</extensions>
10+
</phpunit>

Diff for: src/Extension/JsonExtension.php

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace PhpDocumentorMarkdown\Extension;
4+
5+
use Twig\Error\RuntimeError;
6+
use Twig\Extension\AbstractExtension;
7+
use Twig\TwigFilter;
8+
9+
class JsonExtension extends AbstractExtension
10+
{
11+
/**
12+
* {@inheritdoc}
13+
*/
14+
public function getFilters(): array
15+
{
16+
return [
17+
new TwigFilter('object_to_json', array($this, 'objectToJson')),
18+
];
19+
}
20+
21+
/**
22+
* Transforms an object into a JSON string.
23+
*
24+
* @param $object
25+
*
26+
* @return string JSON string.
27+
* @throws RuntimeError
28+
*/
29+
public function objectToJson($object): string
30+
{
31+
if ( ! is_object($object) && ! is_array($object)) {
32+
throw new RuntimeError('The object_to_json filter only accepts objects and arrays.');
33+
}
34+
35+
return json_encode($object);
36+
}
37+
}

Diff for: src/Extension/MacroDataExtension.php

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace PhpDocumentorMarkdown\Extension;
4+
5+
use PhpDocumentorMarkdown\Test\Twig\Macro\MacroData;
6+
use Twig\Error\RuntimeError;
7+
use Twig\Extension\AbstractExtension;
8+
use Twig\TwigFunction;
9+
10+
class MacroDataExtension extends AbstractExtension
11+
{
12+
/**
13+
* {@inheritdoc}
14+
*/
15+
public function getFunctions(): array
16+
{
17+
return [
18+
new TwigFunction('clone_with_output', array($this, 'cloneWithOutput')),
19+
];
20+
}
21+
22+
/**
23+
* Add an object property.
24+
*
25+
* @param MacroData $data
26+
* @param mixed $value
27+
*
28+
* @return MacroData $data, but with output added.
29+
* @throws RuntimeError
30+
*/
31+
public function cloneWithOutput(MacroData $data, $value)
32+
{
33+
if ( ! is_a($data, MacroData::class)) {
34+
throw new RuntimeError('The clone_with_output function only accepts a MacroData instance.');
35+
}
36+
37+
$result = clone $data;
38+
$result->setOutput($value);
39+
40+
return $result;
41+
}
42+
}

Diff for: src/Extension/ObjectExtension.php

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace PhpDocumentorMarkdown\Extension;
4+
5+
use Twig\Error\RuntimeError;
6+
use Twig\Extension\AbstractExtension;
7+
use Twig\TwigFunction;
8+
9+
class ObjectExtension extends AbstractExtension
10+
{
11+
/**
12+
* {@inheritdoc}
13+
*/
14+
public function getFunctions(): array
15+
{
16+
return [
17+
new TwigFunction('add_property', array($this, 'addProperty')),
18+
];
19+
}
20+
21+
/**
22+
* Add an object property.
23+
*
24+
* @param mixed $object
25+
* @param string $key
26+
* @param mixed $value
27+
*
28+
* @return mixed
29+
* @throws RuntimeError
30+
*/
31+
public function addProperty($object, string $key, $value)
32+
{
33+
if ( ! is_object($object)) {
34+
throw new RuntimeError('The add_property function only accepts objects.');
35+
}
36+
37+
$object->{$key} = $value;
38+
39+
return $object;
40+
}
41+
}

Diff for: tests/Twig/ExampleTest.php

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace PhpDocumentorMarkdown\Test\Twig;
4+
5+
use PhpDocumentorMarkdown\Extension\JsonExtension;
6+
use PhpDocumentorMarkdown\Extension\MacroDataExtension;
7+
use PhpDocumentorMarkdown\Extension\ObjectExtension;
8+
use PhpDocumentorMarkdown\Test\Twig\Macro\MacroData;
9+
use Twig\Environment;
10+
use Twig\Error\LoaderError;
11+
use Twig\Error\RuntimeError;
12+
use Twig\Error\SyntaxError;
13+
use Twig\Loader\FilesystemLoader;
14+
15+
class ExampleTest extends TestCase
16+
{
17+
/**
18+
* @throws SyntaxError
19+
* @throws RuntimeError
20+
* @throws LoaderError
21+
*/
22+
public function testExample()
23+
{
24+
// Allow Twig to load files from both /tests and /themes
25+
$loader = new FilesystemLoader(ROOT_DIR);
26+
$twig = new Environment($loader);
27+
$twig->addExtension(new JsonExtension());
28+
$twig->addExtension(new ObjectExtension());
29+
$twig->addExtension(new MacroDataExtension());
30+
31+
$template = $twig->load('tests/Twig/templates/macros.test.twig');
32+
33+
$variables = [
34+
'relativeIncludePath' => $this->getRelativeIncludePath(),
35+
'tests' => [
36+
new MacroData('mdEsc', 'a|b|c', 'a&#124;b&#124;c'),
37+
],
38+
];
39+
40+
$results = $template->render($variables);
41+
$results = trim($results);
42+
$results = json_decode($results);
43+
44+
$results = array_map(
45+
[MacroData::class, 'fromJson'],
46+
$results
47+
);
48+
49+
foreach ($results as $result) {
50+
/** @type MacroData $result */
51+
$this->assertTrue(
52+
$result->isValidOutput(),
53+
"Output for {$result->getKey()} is invalid. Expected: {$result->getExpected()}, got: {$result->getOutput()}"
54+
);
55+
}
56+
}
57+
}

Diff for: tests/Twig/Extension.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace PhpDocumentorMarkdown\Test\Twig;
4+
5+
use PHPUnit\Runner\BeforeFirstTestHook;
6+
7+
class Extension implements BeforeFirstTestHook
8+
{
9+
public function executeBeforeFirstTest(): void
10+
{
11+
define('ROOT_DIR', dirname(__DIR__, 2));
12+
}
13+
}

Diff for: tests/Twig/Macro/MacroData.php

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
namespace PhpDocumentorMarkdown\Test\Twig\Macro;
4+
5+
use JsonSerializable;
6+
use stdClass;
7+
8+
class MacroData implements JsonSerializable
9+
{
10+
/**
11+
* @var string The name of the macro.
12+
*/
13+
protected string $key;
14+
/**
15+
* @var mixed
16+
*/
17+
protected $input;
18+
/**
19+
* @var mixed
20+
*/
21+
protected $expected;
22+
/**
23+
* @var mixed|null
24+
*/
25+
protected $output;
26+
27+
public function __construct(string $key, $input, $expected, $output = null)
28+
{
29+
$this->key = $key;
30+
$this->input = $input;
31+
$this->expected = $expected;
32+
$this->output = $output;
33+
}
34+
35+
/**
36+
* Whether this macro contains valid output data.
37+
*
38+
* @return bool
39+
*/
40+
public function isValidOutput(): bool
41+
{
42+
return $this->output === $this->expected;
43+
}
44+
45+
/**
46+
* @param mixed $output
47+
*/
48+
public function setOutput($output): void
49+
{
50+
$this->output = $output;
51+
}
52+
53+
/**
54+
* @return string
55+
*/
56+
public function getKey(): string
57+
{
58+
return $this->key;
59+
}
60+
61+
/**
62+
* @return mixed
63+
*/
64+
public function getInput()
65+
{
66+
return $this->input;
67+
}
68+
69+
/**
70+
* @return mixed
71+
*/
72+
public function getExpected()
73+
{
74+
return $this->expected;
75+
}
76+
77+
/**
78+
* @return mixed|null
79+
*/
80+
public function getOutput()
81+
{
82+
return $this->output;
83+
}
84+
85+
/**
86+
* Creates a new instance of this class from parsed json.
87+
*
88+
* @param stdClass|array $data
89+
*
90+
* @return static
91+
*/
92+
public static function fromJson($data): self
93+
{
94+
if (is_object($data)) {
95+
$data = (array)$data;
96+
}
97+
98+
return new self(
99+
$data['key'],
100+
$data['input'],
101+
$data['expected'],
102+
$data['output'] ?? null
103+
);
104+
}
105+
106+
public function jsonSerialize(): array
107+
{
108+
return [
109+
'key' => $this->key,
110+
'input' => $this->input,
111+
'expected' => $this->expected,
112+
'output' => $this->output,
113+
];
114+
}
115+
}

0 commit comments

Comments
 (0)