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)]
34#[UsesClass(\SqlFixture\Plan\Choice\ChoiceValidation::class)]
35#[UsesClass(\SqlFixture\Plan\Choice\PlanContents::class)]
36final class PlanStructureExceptionTest extends TestCase
37{
38    #[Test]
39    public function testColumnsBoundTwiceNamesTheColumnAndBothParents(): void
40    {
41        $message = (new \SqlFixture\Plan\Exception\DuplicateColumnBindingException(
42            ColumnRef::of('b', 'x'),
43            ColumnRef::of('a', 'id'),
44            ColumnRef::of('c', 'id')
45        ))->getMessage();
46
47        self::assertSame(
48            'b.x is bound to a.id and to c.id. A column can reference one parent, so one of '
49            . 'the two relations has to go.',
50            $message
51        );
52    }
53
54    #[Test]
55    public function testCycleShowsTheLoopClosingBackOnItself(): void
56    {
57        $message = (new \SqlFixture\Plan\Exception\CyclicDependencyException(['a', 'b', 'c']))->getMessage();
58
59        self::assertSame(
60            'The plan contains cyclic dependencies among: a, b, c. No generation order satisfies them.',
61            $message
62        );
63    }
64
65    #[Test]
66    public function testUnboundedSelfReferenceSuggestsTheOptionalMarker(): void
67    {
68        $message = (new \SqlFixture\Plan\Exception\UnboundedSelfReferenceException(
69            'category',
70            'category.id < category.parent_id'
71        ))->getMessage();
72
73        self::assertSame(
74            'The relation category.id < category.parent_id makes every category row need '
75            . 'another one, without end. Mark the child optional with ? so the chain can stop.',
76            $message
77        );
78    }
79
80}
81