packages/ztd-query-core/tests/Unit/Shadow/Mutation/ConflictSearchTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Shadow\Mutation;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use ZtdQuery\Schema\Key\CandidateKeyConflict;
11use ZtdQuery\Schema\Key\CandidateKeyMatch;
12use ZtdQuery\Schema\Key\CandidateKeySet;
13use ZtdQuery\Shadow\Mutation\ConflictSearch;
14use ZtdQuery\Shadow\Mutation\Upsert\UpsertOperator;
15use ZtdQuery\Shadow\Mutation\UpsertColumnSource;
16use ZtdQuery\Shadow\Mutation\UpsertExpression;
17use ZtdQuery\Shadow\Mutation\UpsertExpressionKind;
18
19#[CoversClass(ConflictSearch::class)]
20#[UsesClass(CandidateKeySet::class)]
21#[UsesClass(CandidateKeyMatch::class)]
22#[UsesClass(CandidateKeyConflict::class)]
23#[UsesClass(UpsertExpression::class)]
24#[UsesClass(\ZtdQuery\Shadow\Mutation\Upsert\UpsertColumn::class)]
25#[UsesClass(\ZtdQuery\Shadow\Mutation\Upsert\UpsertComparison::class)]
26#[UsesClass(\ZtdQuery\Shadow\Mutation\Upsert\UpsertNumber::class)]
27#[UsesClass(\ZtdQuery\Shadow\Mutation\Upsert\UpsertTruth::class)]
28#[UsesClass(UpsertOperator::class)]
29#[UsesClass(\ZtdQuery\Shadow\Mutation\Upsert\UpsertLiteral::class)]
30final class ConflictSearchTest extends TestCase
31{
32    public function testOfAnswersTheRowTheIncomingRowWouldCollideWith(): void
33    {
34        $search = new ConflictSearch(CandidateKeySet::fromSchema(['id']), null, 'users');
35
36        self::assertSame(1, $search->of(['id' => 2], [['id' => 1], ['id' => 2]])?->rowIndex);
37    }
38
39    public function testOfIsNothingWhereNoRowAlreadyThereCarriesTheSameKey(): void
40    {
41        $search = new ConflictSearch(CandidateKeySet::fromSchema(['id']), null, 'users');
42
43        self::assertNull($search->of(['id' => 3], [['id' => 1], ['id' => 2]]));
44    }
45
46    public function testOfIsNothingWhereTheIncomingRowTakesNoPartInTheNarrowedKey(): void
47    {
48        $search = new ConflictSearch(
49            CandidateKeySet::fromSchema(['id']),
50            UpsertExpression::binary(
51                UpsertExpressionKind::Equal,
52                UpsertExpression::column(UpsertColumnSource::Existing, 'active'),
53                UpsertExpression::literal(true),
54            ),
55            'users',
56        );
57
58        self::assertNull($search->of(['id' => 1, 'active' => false], [['id' => 1, 'active' => true]]));
59    }
60
61    public function testOfLeavesOutTheRowsAlreadyThereThatTakeNoPart(): void
62    {
63        $search = new ConflictSearch(
64            CandidateKeySet::fromSchema(['id']),
65            UpsertExpression::binary(
66                UpsertExpressionKind::Equal,
67                UpsertExpression::column(UpsertColumnSource::Existing, 'active'),
68                UpsertExpression::literal(true),
69            ),
70            'users',
71        );
72
73        self::assertNull($search->of(['id' => 1, 'active' => true], [['id' => 1, 'active' => false]]));
74    }
75
76    public function testOfReportsTheRowUnderTheKeyTheCallerKnowsItBy(): void
77    {
78        $search = new ConflictSearch(
79            CandidateKeySet::fromSchema(['id']),
80            UpsertExpression::binary(
81                UpsertExpressionKind::Equal,
82                UpsertExpression::column(UpsertColumnSource::Existing, 'active'),
83                UpsertExpression::literal(true),
84            ),
85            'users',
86        );
87
88        $conflict = $search->of(
89            ['id' => 2, 'active' => true],
90            [['id' => 1, 'active' => false], ['id' => 2, 'active' => true]],
91        );
92
93        self::assertSame(1, $conflict?->rowIndex);
94    }
95}
96