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)]
42#[UsesClass(\SqlFixture\Plan\Choice\ChoiceValidation::class)]
43#[UsesClass(\SqlFixture\Plan\Choice\PlanContents::class)]
44final class ColumnRefTest extends TestCase
45{
46 #[Test]
47 public function testNamesATableAndItsColumns(): void
48 {
49 $ref = new ColumnRef('order', ['id']);
50
51 self::assertSame('order', $ref->table);
52 self::assertSame(['id'], $ref->columns);
53 }
54
55 #[Test]
56 public function testOfBuildsFromVariadicColumns(): void
57 {
58 $ref = ColumnRef::of('order', 'shop_id', 'no');
59
60 self::assertSame(['shop_id', 'no'], $ref->columns);
61 }
62
63 #[Test]
64 public function testIsCompositeASingleColumnIsNotComposite(): void
65 {
66 self::assertFalse(ColumnRef::of('order', 'id')->isComposite());
67 }
68
69 #[Test]
70 public function testSeveralColumnsAreComposite(): void
71 {
72 self::assertTrue(ColumnRef::of('order', 'shop_id', 'no')->isComposite());
73 }
74
75 #[Test]
76 public function testToStringPrintsASingleColumnWithADot(): void
77 {
78 self::assertSame('order.id', ColumnRef::of('order', 'id')->toString());
79 }
80
81 #[Test]
82 public function testPrintsCompositeColumnsInParentheses(): void
83 {
84 self::assertSame('order.(shop_id, no)', ColumnRef::of('order', 'shop_id', 'no')->toString());
85 }
86
87 #[Test]
88 public function testCastsToItsWrittenForm(): void
89 {
90 self::assertSame('order.id', (string) ColumnRef::of('order', 'id'));
91 }
92
93 #[Test]
94 public function testEqualsComparesTableAndColumns(): void
95 {
96 self::assertTrue(ColumnRef::of('order', 'id')->equals(ColumnRef::of('order', 'id')));
97 self::assertFalse(ColumnRef::of('order', 'id')->equals(ColumnRef::of('order', 'no')));
98 self::assertFalse(ColumnRef::of('order', 'id')->equals(ColumnRef::of('shipment', 'id')));
99 }
100
101 #[Test]
102 public function testFromReadsASingleColumnEndpoint(): void
103 {
104 $ref = ColumnRef::from('order.id');
105
106 self::assertSame('order', $ref->table);
107 self::assertSame(['id'], $ref->columns);
108 }
109
110 #[Test]
111 public function testFromReadsACompositeEndpoint(): void
112 {
113 $ref = ColumnRef::from('order.(shop_id, no)');
114
115 self::assertSame(['shop_id', 'no'], $ref->columns);
116 }
117
118 #[Test]
119 public function testFromStripsQuoting(): void
120 {
121 self::assertSame('order.id', ColumnRef::from('`order`."id"')->toString());
122 }
123
124 #[Test]
125 public function testFromIgnoresSpaceAroundACompositeList(): void
126 {
127 self::assertSame(['shop_id', 'no'], ColumnRef::from('order. (shop_id, no) ')->columns);
128 }
129
130 #[Test]
131 public function testFromDropsEmptyEntriesWithoutLeavingGapsInTheList(): void
132 {
133 self::assertSame(['a', 'b'], ColumnRef::from('order.(a, , b)')->columns);
134 }
135
136 #[Test]
137 public function testOfKeepsColumnsInTheOrderGiven(): void
138 {
139 self::assertSame(['shop_id', 'no'], ColumnRef::of('order', 'shop_id', 'no')->columns);
140 }
141
142 #[Test]
143 public function testOfReindexesColumnsSpreadFromAKeyedArray(): void
144 {
145 self::assertSame(['shop_id', 'no'], ColumnRef::of('order', ...['a' => 'shop_id', 'b' => 'no'])->columns);
146 }
147}
148