packages/sql-fixture/tests/Unit/Fixture/FixtureSetTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Fixture;
6
7use LogicException;
8use OutOfBoundsException;
9use PHPUnit\Framework\Attributes\CoversClass;
10use PHPUnit\Framework\Attributes\Test;
11use PHPUnit\Framework\TestCase;
12use SqlFixture\Fixture\FixtureSet;
13
14#[CoversClass(FixtureSet::class)]
15final class FixtureSetTest extends TestCase
16{
17    #[Test]
18    public function testReadsByPositionInThePlansOrder(): void
19    {
20        $set = new FixtureSet(
21            ['order' => [['id' => 1]], 'order_detail' => [['id' => 1], ['id' => 2]]],
22            ['order' => false, 'order_detail' => true],
23            ['order', 'order_detail']
24        );
25
26        self::assertSame(['id' => 1], $set->row(0));
27        self::assertCount(2, $set->rows(1));
28    }
29
30    #[Test]
31    public function testOffsetGetSupportsListAssignment(): void
32    {
33        $set = new FixtureSet(
34            ['order' => [['id' => 1]], 'order_detail' => [['id' => 9]]],
35            ['order' => false, 'order_detail' => true],
36            ['order', 'order_detail']
37        );
38
39        [$order, $details] = $set;
40
41        self::assertSame(['id' => 1], $order);
42        self::assertSame([['id' => 9]], $details);
43    }
44
45    #[Test]
46    public function testReadsByTableName(): void
47    {
48        $set = new FixtureSet(['order' => [['id' => 1]]], ['order' => false], ['order']);
49
50        self::assertSame(['id' => 1], $set['order']);
51    }
52
53    #[Test]
54    public function testATableHoldingAListReadsBackAsAList(): void
55    {
56        $set = new FixtureSet(['order_detail' => [['id' => 1]]], ['order_detail' => true], ['order_detail']);
57
58        self::assertSame([['id' => 1]], $set['order_detail']);
59    }
60
61    #[Test]
62    public function testRowIsNullWhereNothingWasGenerated(): void
63    {
64        $set = new FixtureSet(['order_shipping' => []], ['order_shipping' => false], ['order_shipping']);
65
66        self::assertNull($set->row('order_shipping'));
67        self::assertNull($set['order_shipping']);
68    }
69
70    #[Test]
71    public function testRowRefusesATableHoldingAList(): void
72    {
73        $set = new FixtureSet(['order_detail' => [['id' => 1]]], ['order_detail' => true], ['order_detail']);
74
75        $this->expectException(OutOfBoundsException::class);
76        $this->expectExceptionMessage('holds a list of rows');
77
78        $set->row('order_detail');
79    }
80
81    #[Test]
82    public function testRowsAlwaysReturnsAList(): void
83    {
84        $set = new FixtureSet(
85            ['order' => [['id' => 1]], 'order_detail' => [['id' => 2]], 'shipping' => []],
86            ['order' => false, 'order_detail' => true, 'shipping' => false],
87            ['order', 'order_detail', 'shipping']
88        );
89
90        self::assertSame([['id' => 1]], $set->rows('order'));
91        self::assertSame([['id' => 2]], $set->rows('order_detail'));
92        self::assertSame([], $set->rows('shipping'));
93    }
94
95    #[Test]
96    public function testCountsTheTablesNotTheRows(): void
97    {
98        $set = new FixtureSet(
99            ['order' => [['id' => 1]], 'order_detail' => [['id' => 1], ['id' => 2]]],
100            ['order' => false, 'order_detail' => true],
101            ['order', 'order_detail']
102        );
103
104        self::assertCount(2, $set);
105    }
106
107    #[Test]
108    public function testIteratesInThePlansOrder(): void
109    {
110        $set = new FixtureSet(
111            ['order' => [['id' => 1]], 'order_detail' => [['id' => 2]]],
112            ['order' => false, 'order_detail' => true],
113            ['order', 'order_detail']
114        );
115
116        self::assertSame([['id' => 1], [['id' => 2]]], iterator_to_array($set));
117    }
118
119    #[Test]
120    public function testTablesReportsWhichTablesItHolds(): void
121    {
122        $set = new FixtureSet(['order' => [['id' => 1]]], ['order' => false], ['order']);
123
124        self::assertTrue(isset($set['order']));
125        self::assertFalse(isset($set['nope']));
126        self::assertSame(['order'], $set->tables());
127        self::assertSame(['order' => ['id' => 1]], $set->toArray());
128    }
129
130    #[Test]
131    public function testAnUnknownTableReadsBackAsNothing(): void
132    {
133        $set = new FixtureSet(['order' => [['id' => 1]]], ['order' => false], ['order']);
134
135        self::assertNull($set['nope']);
136        self::assertSame([], $set->rows('nope'));
137    }
138
139    #[Test]
140    public function testGetReadsTheEntryWhicheverShapeItHas(): void
141    {
142        $set = new FixtureSet(
143            ['order' => [['id' => 1]], 'order_detail' => [['id' => 2]]],
144            ['order' => false, 'order_detail' => true],
145            ['order', 'order_detail']
146        );
147
148        self::assertSame(['id' => 1], $set->get('order'));
149        self::assertSame([['id' => 2]], $set->get('order_detail'));
150    }
151
152    #[Test]
153    public function testAnUnknownTableIsNotTreatedAsAList(): void
154    {
155        $set = new FixtureSet(['order' => [['id' => 1]]], ['order' => false], ['order']);
156
157        self::assertNull($set->row('nope'));
158    }
159
160    #[Test]
161    public function testToArrayKeepsEveryTable(): void
162    {
163        $set = new FixtureSet(
164            ['order' => [['id' => 1]], 'order_detail' => [['id' => 2]]],
165            ['order' => false, 'order_detail' => true],
166            ['order', 'order_detail']
167        );
168
169        self::assertSame(
170            ['order' => ['id' => 1], 'order_detail' => [['id' => 2]]],
171            $set->toArray()
172        );
173    }
174
175    #[Test]
176    public function testAPositionPastTheEndReadsAsNothing(): void
177    {
178        $set = new FixtureSet(['order' => [['id' => 1]]], ['order' => false], ['order']);
179
180        self::assertNull($set[7]);
181        self::assertFalse(isset($set[7]));
182    }
183    public function testOffsetExistsTracksNamesAndPositions(): void
184    {
185        $set = new FixtureSet(['a' => []], ['a' => true], ['a']);
186        self::assertTrue(isset($set['a']));
187        self::assertTrue(isset($set[0]));
188        self::assertFalse(isset($set[1]));
189    }
190    public function testGetIteratorPreservesPlanOrder(): void
191    {
192        $set = new FixtureSet(['a' => [['id' => 2]], 'b' => []], ['a' => false, 'b' => true], ['b', 'a']);
193        self::assertSame([[], ['id' => 2]], iterator_to_array($set));
194    }
195    public function testOffsetSetRejectsMutation(): void
196    {
197        $set = new FixtureSet(['order' => [['id' => 1]]], ['order' => false], ['order']);
198        $this->expectException(LogicException::class);
199        $this->expectExceptionMessage('A FixtureSet is read-only.');
200        $set['order'] = ['id' => 2];
201    }
202
203    public function testOffsetUnsetRejectsRemoval(): void
204    {
205        $set = new FixtureSet(['order' => [['id' => 1]]], ['order' => false], ['order']);
206        $this->expectException(LogicException::class);
207        $this->expectExceptionMessage('A FixtureSet is read-only.');
208        unset($set['order']);
209    }
210}
211