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

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Shadow\Mutation\Upsert;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use ZtdQuery\Exception\UnsupportedSqlException;
11use ZtdQuery\Shadow\Mutation\Upsert\UpsertNumber;
12
13#[CoversClass(UpsertNumber::class)]
14#[UsesClass(UnsupportedSqlException::class)]
15final class UpsertNumberTest extends TestCase
16{
17    public function testOfKeepsANumberAsItIs(): void
18    {
19        self::assertSame(7, (new UpsertNumber())->of(7));
20        self::assertSame(1.5, (new UpsertNumber())->of(1.5));
21    }
22
23    public function testOfReadsWholeTextAsAnIntegerRatherThanAFloat(): void
24    {
25        self::assertSame(12, (new UpsertNumber())->of('12'));
26    }
27
28    public function testOfReadsTextWrittenTheWayAFloatIsAsAFloat(): void
29    {
30        self::assertSame(1.5, (new UpsertNumber())->of('1.5'));
31        self::assertSame(1000.0, (new UpsertNumber())->of('1e3'));
32    }
33
34    public function testOfRefusesTextThatIsNotWrittenAsANumber(): void
35    {
36        $this->expectException(UnsupportedSqlException::class);
37
38        (new UpsertNumber())->of('paid');
39    }
40
41    public function testOfRefusesABooleanBecauseArithmeticOnItIsNotSomethingSqlAgreesOn(): void
42    {
43        $this->expectException(UnsupportedSqlException::class);
44
45        (new UpsertNumber())->of(true);
46    }
47
48    public function testIsNumericAnswersForTheValuesArithmeticCanBeDoneOn(): void
49    {
50        self::assertTrue((new UpsertNumber())->isNumeric(7));
51        self::assertTrue((new UpsertNumber())->isNumeric(1.5));
52        self::assertTrue((new UpsertNumber())->isNumeric('12'));
53        self::assertFalse((new UpsertNumber())->isNumeric('paid'));
54        self::assertFalse((new UpsertNumber())->isNumeric(null));
55    }
56
57    public function testPositiveKeepsTheNumberAndItsSign(): void
58    {
59        self::assertSame(-3, (new UpsertNumber())->positive('-3'));
60    }
61
62    public function testPositiveIsUnknownForAnUnknownValue(): void
63    {
64        self::assertNull((new UpsertNumber())->positive(null));
65    }
66
67    public function testNegativeTurnsTheSignAround(): void
68    {
69        self::assertSame(-3, (new UpsertNumber())->negative(3));
70        self::assertSame(3, (new UpsertNumber())->negative(-3));
71    }
72
73    public function testNegativeIsUnknownForAnUnknownValue(): void
74    {
75        self::assertNull((new UpsertNumber())->negative(null));
76    }
77
78    public function testAddSumsBothSides(): void
79    {
80        self::assertSame(5, (new UpsertNumber())->add(2, '3'));
81    }
82
83    public function testAddIsUnknownWhenEitherSideIs(): void
84    {
85        self::assertNull((new UpsertNumber())->add(null, 3));
86        self::assertNull((new UpsertNumber())->add(3, null));
87    }
88
89    public function testSubtractTakesTheRightSideFromTheLeft(): void
90    {
91        self::assertSame(2, (new UpsertNumber())->subtract(5, 3));
92    }
93
94    public function testSubtractIsUnknownWhenEitherSideIs(): void
95    {
96        self::assertNull((new UpsertNumber())->subtract(null, 3));
97        self::assertNull((new UpsertNumber())->subtract(3, null));
98    }
99
100    public function testMultiplyMultipliesBothSides(): void
101    {
102        self::assertSame(6, (new UpsertNumber())->multiply(2, 3));
103    }
104
105    public function testMultiplyIsUnknownWhenEitherSideIs(): void
106    {
107        self::assertNull((new UpsertNumber())->multiply(null, 3));
108        self::assertNull((new UpsertNumber())->multiply(3, null));
109    }
110
111    public function testDivideDividesTheLeftSideByTheRight(): void
112    {
113        self::assertSame(2, (new UpsertNumber())->divide(6, 3));
114    }
115
116    public function testDivideIsUnknownWhenEitherSideIs(): void
117    {
118        self::assertNull((new UpsertNumber())->divide(null, 3));
119        self::assertNull((new UpsertNumber())->divide(3, null));
120    }
121
122    public function testDivideRefusesAZeroDivisor(): void
123    {
124        $this->expectException(UnsupportedSqlException::class);
125
126        (new UpsertNumber())->divide(6, 0);
127    }
128
129    public function testDivideRefusesAZeroDivisorWrittenAsAFloat(): void
130    {
131        $this->expectException(UnsupportedSqlException::class);
132
133        (new UpsertNumber())->divide(6, 0.0);
134    }
135
136    public function testModuloAnswersWhatIsLeftOver(): void
137    {
138        self::assertSame(1, (new UpsertNumber())->modulo(7, 3));
139    }
140
141    public function testModuloTakesBothSidesAsWholeNumbersFirst(): void
142    {
143        self::assertSame(1, (new UpsertNumber())->modulo(7.9, 3.9));
144    }
145
146    public function testModuloIsUnknownWhenEitherSideIs(): void
147    {
148        self::assertNull((new UpsertNumber())->modulo(null, 3));
149        self::assertNull((new UpsertNumber())->modulo(3, null));
150    }
151
152    public function testModuloRefusesADivisorThatIsZeroOnceItIsAWholeNumber(): void
153    {
154        $this->expectException(UnsupportedSqlException::class);
155
156        (new UpsertNumber())->modulo(7, 0.5);
157    }
158}
159