packages/sql-fixture/tests/Unit/Plan/PlanStructureExceptionTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Plan;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\Test;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlFixture\Plan\ColumnRef;
12use SqlFixture\Plan\PlanStructureException;
13
14#[CoversClass(PlanStructureException::class)]
15#[UsesClass(ColumnRef::class)]
16#[UsesClass(\SqlFixture\Plan\FixturePlan::class)]
17#[UsesClass(\SqlFixture\Plan\PlanParser::class)]
18#[UsesClass(\SqlFixture\Plan\PlanPrinter::class)]
19#[UsesClass(\SqlFixture\Plan\PlanSyntaxException::class)]
20#[UsesClass(\SqlFixture\Plan\Relation::class)]
21#[UsesClass(\SqlFixture\Plan\RelationKind::class)]
22#[UsesClass(\SqlFixture\Plan\RelationSide::class)]
23#[UsesClass(\SqlFixture\Plan\Parsing\PlanStatements::class)]
24#[UsesClass(\SqlFixture\Plan\Parsing\RelationCursor::class)]
25#[UsesClass(\SqlFixture\Plan\Parsing\RelationReader::class)]
26#[UsesClass(\SqlFixture\Plan\Printing\PlanTables::class)]
27#[UsesClass(\SqlFixture\Plan\Printing\RelationGroups::class)]
28#[UsesClass(\SqlFixture\Plan\Printing\StatementPrinter::class)]
29#[UsesClass(\SqlFixture\Plan\Validation\PlanValidation::class)]
30#[UsesClass(\SqlFixture\Plan\Validation\TableName::class)]
31#[UsesClass(\SqlFixture\Plan\Exception\DuplicateColumnBindingException::class)]
32#[UsesClass(\SqlFixture\Plan\Exception\CyclicDependencyException::class)]
33#[UsesClass(\SqlFixture\Plan\Exception\UnboundedSelfReferenceException::class)]
34final class PlanStructureExceptionTest extends TestCase
35{
36 #[Test]
37 public function testColumnsBoundTwiceNamesTheColumnAndBothParents(): void
38 {
39 $message = (new \SqlFixture\Plan\Exception\DuplicateColumnBindingException(
40 ColumnRef::of('b', 'x'),
41 ColumnRef::of('a', 'id'),
42 ColumnRef::of('c', 'id')
43 ))->getMessage();
44
45 self::assertSame(
46 'b.x is bound to a.id and to c.id. A column can reference one parent, so one of '
47 . 'the two relations has to go.',
48 $message
49 );
50 }
51
52 #[Test]
53 public function testCycleShowsTheLoopClosingBackOnItself(): void
54 {
55 $message = (new \SqlFixture\Plan\Exception\CyclicDependencyException(['a', 'b', 'c']))->getMessage();
56
57 self::assertSame(
58 'The plan contains cyclic dependencies among: a, b, c. No generation order satisfies them.',
59 $message
60 );
61 }
62
63 #[Test]
64 public function testUnboundedSelfReferenceSuggestsTheOptionalMarker(): void
65 {
66 $message = (new \SqlFixture\Plan\Exception\UnboundedSelfReferenceException(
67 'category',
68 'category.id < category.parent_id'
69 ))->getMessage();
70
71 self::assertSame(
72 'The relation category.id < category.parent_id makes every category row need '
73 . 'another one, without end. Mark the child optional with ? so the chain can stop.',
74 $message
75 );
76 }
77
78}
79