packages/ztd-query-pdo-adapter/tests/Unit/Session/BufferedRowTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Session;
6
7use PDO;
8use PHPUnit\Framework\Attributes\CoversClass;
9use PHPUnit\Framework\TestCase;
10use ReflectionException;
11use stdClass;
12use ZtdQuery\Adapter\Pdo\Session\BufferedRow;
13
14#[CoversClass(BufferedRow::class)]
15final class BufferedRowTest extends TestCase
16{
17    public function testInModeAnswersTheRowKeyedByColumnWhereThatIsAsked(): void
18    {
19        self::assertSame(
20            ['id' => 1, 'name' => 'ada'],
21            (new BufferedRow())->inMode(['id' => 1, 'name' => 'ada'], PDO::FETCH_ASSOC),
22        );
23    }
24
25    public function testInModeAnswersANamedFetchTheSameWayAsAKeyedOne(): void
26    {
27        self::assertSame(
28            ['id' => 1],
29            (new BufferedRow())->inMode(['id' => 1], PDO::FETCH_NAMED),
30        );
31    }
32
33    public function testInModeAnswersTheValuesAloneWhereOnlyPositionsAreAsked(): void
34    {
35        self::assertSame(
36            [1, 'ada'],
37            (new BufferedRow())->inMode(['id' => 1, 'name' => 'ada'], PDO::FETCH_NUM),
38        );
39    }
40
41    public function testInModeAnswersAnObjectWhereOneIsAsked(): void
42    {
43        $object = (new BufferedRow())->inMode(['id' => 1], PDO::FETCH_OBJ);
44
45        self::assertSame(['id' => 1], is_object($object) ? get_object_vars($object) : []);
46    }
47
48    public function testInModeAnswersTheFirstValueWhereOneColumnIsAsked(): void
49    {
50        self::assertSame(1, (new BufferedRow())->inMode(['id' => 1, 'name' => 'ada'], PDO::FETCH_COLUMN));
51    }
52
53    public function testInModeAnswersFalseWhereOneColumnIsAskedOfAnEmptyRow(): void
54    {
55        self::assertFalse((new BufferedRow())->inMode([], PDO::FETCH_COLUMN));
56    }
57
58    public function testInModeAnswersAModeItDoesNotKnowBothWaysAtOnce(): void
59    {
60        self::assertSame(
61            ['id' => 1, 0 => 1],
62            (new BufferedRow())->inMode(['id' => 1], PDO::FETCH_BOTH),
63        );
64    }
65
66    public function testKeyedBothWaysReachesEveryValueUnderEitherKey(): void
67    {
68        self::assertSame(
69            ['id' => 1, 0 => 1, 'name' => 'ada', 1 => 'ada'],
70            (new BufferedRow())->keyedBothWays(['id' => 1, 'name' => 'ada']),
71        );
72    }
73
74    public function testKeyedBothWaysAnswersNothingForARowWithNoColumns(): void
75    {
76        self::assertSame([], (new BufferedRow())->keyedBothWays([]));
77    }
78    public function testResolveModeUsesExplicitThenStatementThenConnectionMode(): void
79    {
80        $row = new BufferedRow();
81        self::assertSame(PDO::FETCH_NUM, $row->resolveMode(PDO::FETCH_NUM, PDO::FETCH_ASSOC, PDO::FETCH_OBJ));
82        self::assertSame(PDO::FETCH_OBJ, $row->resolveMode(PDO::FETCH_DEFAULT, PDO::FETCH_ASSOC, PDO::FETCH_OBJ));
83        self::assertSame(PDO::FETCH_ASSOC, $row->resolveMode(PDO::FETCH_DEFAULT, PDO::FETCH_ASSOC, null));
84    }
85
86
87    public function testFetchPreservesValues(): void
88    {
89        $rows = new BufferedRow();
90        self::assertSame(['id' => 7, 'name' => null], $rows->fetch(['id' => 7, 'name' => null], PDO::FETCH_ASSOC));
91    }
92
93    public function testAllShapesRowsAndSelectsTheRequestedColumn(): void
94    {
95        $rows = new BufferedRow();
96        self::assertSame(['Ada', 'Grace'], $rows->all([['id' => 7, 'name' => 'Ada'], ['id' => 9, 'name' => 'Grace']], PDO::FETCH_COLUMN, [1]));
97        self::assertSame([7], $rows->all([['id' => 7]], PDO::FETCH_COLUMN, ['invalid column']));
98        self::assertSame([[7, 'Ada']], $rows->all([['id' => 7, 'name' => 'Ada']], PDO::FETCH_NUM, []));
99    }
100
101    public function testColumnPreservesNullAndMissingColumnBehavior(): void
102    {
103        $rows = new BufferedRow();
104        self::assertSame('Ada', $rows->column(['id' => 7, 'name' => 'Ada'], 1));
105        self::assertFalse($rows->column(['id' => 7], 1));
106        self::assertFalse($rows->column(['name' => null], 0));
107    }
108
109    /**
110     * @throws ReflectionException
111     */
112    public function testObjectPreservesAnonymousRowsAndEndOfCursor(): void
113    {
114        $rows = new BufferedRow();
115        $object = $rows->object(['id' => 7, 'name' => null], null, []);
116        self::assertInstanceOf(stdClass::class, $object);
117        self::assertSame(['id' => 7, 'name' => null], get_object_vars($object));
118        self::assertFalse($rows->object(false, null, []));
119    }
120
121    /**
122     * @throws ReflectionException
123     */
124    public function testObjectHydratesDeclaredPropertiesAfterConstruction(): void
125    {
126        $prototype = new class ('initial') {
127            public function __construct(public string $name)
128            {
129            }
130        };
131        $object = (new BufferedRow())->object(['name' => 'Ada', 'unknown' => 7], $prototype::class, ['constructor']);
132        self::assertInstanceOf($prototype::class, $object);
133        self::assertSame(['name' => 'Ada'], get_object_vars($object));
134    }
135}
136