packages/sql-fixture/tests/Unit/Plan/ColumnRefTest.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\PlanSyntaxException;
13
14#[CoversClass(ColumnRef::class)]
15#[UsesClass(PlanSyntaxException::class)]
16#[UsesClass(\SqlFixture\Plan\FixturePlan::class)]
17#[UsesClass(\SqlFixture\Plan\PlanParser::class)]
18#[UsesClass(\SqlFixture\Plan\PlanPrinter::class)]
19#[UsesClass(\SqlFixture\Plan\Relation::class)]
20#[UsesClass(\SqlFixture\Plan\RelationKind::class)]
21#[UsesClass(\SqlFixture\Plan\RelationSide::class)]
22#[UsesClass(\SqlFixture\Plan\Parsing\PlanStatements::class)]
23#[UsesClass(\SqlFixture\Plan\Parsing\RelationCursor::class)]
24#[UsesClass(\SqlFixture\Plan\Parsing\RelationReader::class)]
25#[UsesClass(\SqlFixture\Plan\PlanStructureException::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\EmptyPlanException::class)]
32#[UsesClass(\SqlFixture\Plan\Exception\EmptyTableNameException::class)]
33#[UsesClass(\SqlFixture\Plan\Exception\MissingEndpointColumnsException::class)]
34#[UsesClass(\SqlFixture\Plan\Exception\InvalidTableNameException::class)]
35#[UsesClass(\SqlFixture\Plan\Exception\UnbalancedBracketsException::class)]
36#[UsesClass(\SqlFixture\Plan\Exception\UnexpectedPlanTokenException::class)]
37#[UsesClass(\SqlFixture\Plan\Exception\UnsupportedManyToManyException::class)]
38#[UsesClass(\SqlFixture\Plan\Exception\CompositeArityMismatchException::class)]
39#[UsesClass(\SqlFixture\Plan\Exception\DuplicateColumnBindingException::class)]
40#[UsesClass(\SqlFixture\Plan\Exception\CyclicDependencyException::class)]
41#[UsesClass(\SqlFixture\Plan\Exception\UnboundedSelfReferenceException::class)]
42final class ColumnRefTest extends TestCase
43{
44    #[Test]
45    public function testNamesATableAndItsColumns(): void
46    {
47        $ref = new ColumnRef('order', ['id']);
48
49        self::assertSame('order', $ref->table);
50        self::assertSame(['id'], $ref->columns);
51    }
52
53    #[Test]
54    public function testOfBuildsFromVariadicColumns(): void
55    {
56        $ref = ColumnRef::of('order', 'shop_id', 'no');
57
58        self::assertSame(['shop_id', 'no'], $ref->columns);
59    }
60
61    #[Test]
62    public function testIsCompositeASingleColumnIsNotComposite(): void
63    {
64        self::assertFalse(ColumnRef::of('order', 'id')->isComposite());
65    }
66
67    #[Test]
68    public function testSeveralColumnsAreComposite(): void
69    {
70        self::assertTrue(ColumnRef::of('order', 'shop_id', 'no')->isComposite());
71    }
72
73    #[Test]
74    public function testToStringPrintsASingleColumnWithADot(): void
75    {
76        self::assertSame('order.id', ColumnRef::of('order', 'id')->toString());
77    }
78
79    #[Test]
80    public function testPrintsCompositeColumnsInParentheses(): void
81    {
82        self::assertSame('order.(shop_id, no)', ColumnRef::of('order', 'shop_id', 'no')->toString());
83    }
84
85    #[Test]
86    public function testCastsToItsWrittenForm(): void
87    {
88        self::assertSame('order.id', (string) ColumnRef::of('order', 'id'));
89    }
90
91    #[Test]
92    public function testEqualsComparesTableAndColumns(): void
93    {
94        self::assertTrue(ColumnRef::of('order', 'id')->equals(ColumnRef::of('order', 'id')));
95        self::assertFalse(ColumnRef::of('order', 'id')->equals(ColumnRef::of('order', 'no')));
96        self::assertFalse(ColumnRef::of('order', 'id')->equals(ColumnRef::of('shipment', 'id')));
97    }
98
99    #[Test]
100    public function testFromReadsASingleColumnEndpoint(): void
101    {
102        $ref = ColumnRef::from('order.id');
103
104        self::assertSame('order', $ref->table);
105        self::assertSame(['id'], $ref->columns);
106    }
107
108    #[Test]
109    public function testFromReadsACompositeEndpoint(): void
110    {
111        $ref = ColumnRef::from('order.(shop_id, no)');
112
113        self::assertSame(['shop_id', 'no'], $ref->columns);
114    }
115
116    #[Test]
117    public function testFromStripsQuoting(): void
118    {
119        self::assertSame('order.id', ColumnRef::from('`order`."id"')->toString());
120    }
121
122    #[Test]
123    public function testFromIgnoresSpaceAroundACompositeList(): void
124    {
125        self::assertSame(['shop_id', 'no'], ColumnRef::from('order. (shop_id, no) ')->columns);
126    }
127
128    #[Test]
129    public function testFromDropsEmptyEntriesWithoutLeavingGapsInTheList(): void
130    {
131        self::assertSame(['a', 'b'], ColumnRef::from('order.(a, , b)')->columns);
132    }
133
134    #[Test]
135    public function testOfKeepsColumnsInTheOrderGiven(): void
136    {
137        self::assertSame(['shop_id', 'no'], ColumnRef::of('order', 'shop_id', 'no')->columns);
138    }
139
140    #[Test]
141    public function testOfReindexesColumnsSpreadFromAKeyedArray(): void
142    {
143        self::assertSame(['shop_id', 'no'], ColumnRef::of('order', ...['a' => 'shop_id', 'b' => 'no'])->columns);
144    }
145}
146