Skip to content

Commit e91d6a5

Browse files
committed
Improve tests
1 parent 97c2f99 commit e91d6a5

6 files changed

Lines changed: 236 additions & 30 deletions

File tree

libs/phpdoc/tests/DocBlock/Grammar/DescriptionGrammarRuleTest.php

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,29 @@
1414
use TypeLang\PhpDoc\Parser\Grammar\Cursor;
1515
use TypeLang\PhpDoc\Parser\Grammar\Exception\NoMatchException;
1616
use TypeLang\PhpDoc\Parser\Tag\StringTagParser;
17-
use TypeLang\PhpDoc\Tests\TestCase;
1817

19-
final class DescriptionGrammarRuleTest extends TestCase
18+
final class DescriptionGrammarRuleTest extends GrammarRuleTestCase
2019
{
21-
private function rule(): DescriptionGrammarRule
20+
protected function rule(): DescriptionGrammarRule
2221
{
23-
return new DescriptionGrammarRule(
24-
new BalancedBraceAwareParser(new StringTagParser(new TagFactory())),
25-
);
22+
return new \ReflectionClass(DescriptionGrammarRule::class)
23+
->newLazyProxy(function (DescriptionGrammarRule $proxy) {
24+
return new DescriptionGrammarRule(
25+
descriptionParser: new BalancedBraceAwareParser(
26+
tagParser: new StringTagParser(
27+
tagFactory: new TagFactory(rules: [
28+
DescriptionGrammarRule::NAME => $proxy,
29+
]),
30+
),
31+
),
32+
);
33+
});
2634
}
2735

2836
#[Test]
2937
public function readsThePlainTrailingText(): void
3038
{
31-
$description = $this->rule()(new Cursor('Some description text'));
39+
$description = $this->matchText('Some description text');
3240

3341
self::assertInstanceOf(Description::class, $description);
3442
self::assertSame('Some description text', (string) $description);
@@ -41,7 +49,7 @@ public function readsThePlainTrailingText(): void
4149
#[Test]
4250
public function keepsInlineTags(): void
4351
{
44-
$description = $this->rule()(new Cursor('see {@link X}'));
52+
$description = $this->matchText('see {@link X}');
4553

4654
self::assertInstanceOf(TaggedDescription::class, $description);
4755
self::assertSame('see {@link X}', (string) $description);
@@ -54,8 +62,9 @@ public function keepsInlineTags(): void
5462
public function consumesTheEntireRemainder(): void
5563
{
5664
$cursor = new Cursor('a b c');
57-
$description = $this->rule()($cursor);
65+
$description = $this->matchCursor($cursor);
5866

67+
self::assertInstanceOf(Description::class, $description);
5968
self::assertSame('a b c', (string) $description);
6069
self::assertTrue($cursor->isEof);
6170
}
@@ -75,6 +84,6 @@ public function rejectsAnEmptyDescription(string $input): void
7584
{
7685
$this->expectException(NoMatchException::class);
7786

78-
$this->rule()(new Cursor($input));
87+
$this->matchText($input);
7988
}
8089
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\PhpDoc\Tests\DocBlock\Grammar;
6+
7+
use TypeLang\PhpDoc\Parser\Grammar\Cursor;
8+
use TypeLang\PhpDoc\Parser\Grammar\Grammar;
9+
use TypeLang\PhpDoc\Parser\Grammar\RuleInterface;
10+
use TypeLang\PhpDoc\Tests\TestCase;
11+
12+
/**
13+
* @phpstan-import-type RuleType from Grammar
14+
*/
15+
abstract class GrammarRuleTestCase extends TestCase
16+
{
17+
/**
18+
* @return RuleType
19+
*/
20+
abstract protected function rule(): RuleInterface;
21+
22+
protected function matchCursor(Cursor $cursor): mixed
23+
{
24+
$rule = $this->rule();
25+
26+
return $rule($cursor);
27+
}
28+
29+
protected function matchText(string $text): mixed
30+
{
31+
return $this->matchCursor(new Cursor($text));
32+
}
33+
}

libs/phpdoc/tests/DocBlock/Grammar/ReferenceGrammarRuleTest.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@
1616
use TypeLang\PhpDoc\DocBlock\Reference\VariableReference;
1717
use TypeLang\PhpDoc\Parser\Grammar\Cursor;
1818
use TypeLang\PhpDoc\Parser\Grammar\Exception\NoMatchException;
19-
use TypeLang\PhpDoc\Tests\TestCase;
2019

21-
final class ReferenceGrammarRuleTest extends TestCase
20+
final class ReferenceGrammarRuleTest extends GrammarRuleTestCase
2221
{
22+
protected function rule(): ReferenceGrammarRule
23+
{
24+
return new ReferenceGrammarRule();
25+
}
26+
2327
/**
2428
* Each reference, mapped to the expected reference class and the string it
2529
* stringifies back to.
@@ -44,7 +48,7 @@ public static function referenceDataProvider(): iterable
4448
#[DataProvider('referenceDataProvider')]
4549
public function producesTheExpectedReference(string $input, string $expected, string $stringified): void
4650
{
47-
$reference = new ReferenceGrammarRule()(new Cursor($input));
51+
$reference = $this->matchText($input);
4852

4953
self::assertInstanceOf($expected, $reference);
5054
self::assertSame($stringified, (string) $reference);
@@ -53,7 +57,7 @@ public function producesTheExpectedReference(string $input, string $expected, st
5357
#[Test]
5458
public function classMethodExposesClassAndName(): void
5559
{
56-
$reference = new ReferenceGrammarRule()(new Cursor('Some\Any\Ololo::foo()'));
60+
$reference = $this->matchText('Some\Any\Ololo::foo()');
5761

5862
self::assertInstanceOf(ClassMethodReference::class, $reference);
5963
self::assertSame('Some\Any\Ololo', $reference->class);
@@ -67,7 +71,7 @@ public function classMethodExposesClassAndName(): void
6771
public function stopsAtTheFirstWhitespace(): void
6872
{
6973
$cursor = new Cursor('$var and the rest');
70-
$reference = new ReferenceGrammarRule()($cursor);
74+
$reference = $this->matchCursor($cursor);
7175

7276
self::assertInstanceOf(VariableReference::class, $reference);
7377
self::assertSame('var', $reference->name);
@@ -91,6 +95,6 @@ public function rejectsAnInvalidReference(string $input): void
9195
{
9296
$this->expectException(NoMatchException::class);
9397

94-
new ReferenceGrammarRule()(new Cursor($input));
98+
$this->matchText($input);
9599
}
96100
}

libs/phpdoc/tests/DocBlock/Grammar/TypeGrammarRuleTest.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,22 @@
99
use TypeLang\PhpDoc\DocBlock\Grammar\TypeGrammarRule;
1010
use TypeLang\PhpDoc\Parser\Grammar\Cursor;
1111
use TypeLang\PhpDoc\Parser\Grammar\Exception\NoMatchException;
12-
use TypeLang\PhpDoc\Tests\TestCase;
1312
use TypeLang\Type\NamedTypeNode;
1413
use TypeLang\Type\NullableTypeNode;
1514
use TypeLang\Type\TypeNode;
1615
use TypeLang\Type\UnionTypeNode;
1716

18-
final class TypeGrammarRuleTest extends TestCase
17+
final class TypeGrammarRuleTest extends GrammarRuleTestCase
1918
{
20-
private function rule(): TypeGrammarRule
19+
protected function rule(): TypeGrammarRule
2120
{
2221
return new TypeGrammarRule(new TypeParser());
2322
}
2423

2524
#[Test]
2625
public function producesANamedType(): void
2726
{
28-
$type = $this->rule()(new Cursor('array<int, string>'));
27+
$type = $this->matchText('array<int, string>');
2928

3029
self::assertInstanceOf(NamedTypeNode::class, $type);
3130
self::assertSame('array', (string) $type->name);
@@ -34,15 +33,15 @@ public function producesANamedType(): void
3433
#[Test]
3534
public function producesANullableType(): void
3635
{
37-
$type = $this->rule()(new Cursor('?string'));
36+
$type = $this->matchText('?string');
3837

3938
self::assertInstanceOf(NullableTypeNode::class, $type);
4039
}
4140

4241
#[Test]
4342
public function producesAUnionType(): void
4443
{
45-
$type = $this->rule()(new Cursor('int|string'));
44+
$type = $this->matchText('int|string');
4645

4746
self::assertInstanceOf(UnionTypeNode::class, $type);
4847
}
@@ -55,7 +54,7 @@ public function producesAUnionType(): void
5554
public function stopsAfterTheType(): void
5655
{
5756
$cursor = new Cursor('int|string and the rest');
58-
$type = $this->rule()($cursor);
57+
$type = $this->matchCursor($cursor);
5958

6059
self::assertInstanceOf(UnionTypeNode::class, $type);
6160
self::assertSame(11, $cursor->offset);
@@ -69,7 +68,7 @@ public function stopsAfterTheType(): void
6968
public function respectsTheCursorBase(): void
7069
{
7170
$cursor = new Cursor('int rest', base: 100);
72-
$type = $this->rule()($cursor);
71+
$type = $this->matchCursor($cursor);
7372

7473
self::assertInstanceOf(TypeNode::class, $type);
7574
self::assertSame(104, $cursor->offset);
@@ -80,6 +79,6 @@ public function rejectsAnEmptyInput(): void
8079
{
8180
$this->expectException(NoMatchException::class);
8281

83-
$this->rule()(new Cursor(''));
82+
$this->matchText('');
8483
}
8584
}

libs/phpdoc/tests/DocBlock/Grammar/VariableGrammarRuleTest.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@
99
use TypeLang\PhpDoc\DocBlock\Grammar\VariableGrammarRule;
1010
use TypeLang\PhpDoc\Parser\Grammar\Cursor;
1111
use TypeLang\PhpDoc\Parser\Grammar\Exception\NoMatchException;
12-
use TypeLang\PhpDoc\Tests\TestCase;
1312

14-
final class VariableGrammarRuleTest extends TestCase
13+
final class VariableGrammarRuleTest extends GrammarRuleTestCase
1514
{
15+
protected function rule(): VariableGrammarRule
16+
{
17+
return new VariableGrammarRule();
18+
}
19+
1620
/**
1721
* @return iterable<string, array{string, string}>
1822
*/
@@ -27,7 +31,7 @@ public static function variableDataProvider(): iterable
2731
#[DataProvider('variableDataProvider')]
2832
public function returnsTheNameWithoutTheDollar(string $input, string $expected): void
2933
{
30-
$name = new VariableGrammarRule()(new Cursor($input));
34+
$name = $this->matchText($input);
3135

3236
self::assertSame($expected, $name);
3337
}
@@ -39,7 +43,7 @@ public function returnsTheNameWithoutTheDollar(string $input, string $expected):
3943
public function stopsAtTheFirstWhitespace(): void
4044
{
4145
$cursor = new Cursor('$var and the rest');
42-
$name = new VariableGrammarRule()($cursor);
46+
$name = $this->matchCursor($cursor);
4347

4448
self::assertSame('var', $name);
4549
self::assertSame(4, $cursor->offset);
@@ -64,6 +68,6 @@ public function rejectsAnInvalidVariable(string $input): void
6468
{
6569
$this->expectException(NoMatchException::class);
6670

67-
new VariableGrammarRule()(new Cursor($input));
71+
$this->matchText($input);
6872
}
6973
}

0 commit comments

Comments
 (0)