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