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