Completed
Pull Request — master (#4)
by Timóteo
05:46
created

RepositoryTest::setUpDatabase()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 29
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 20
nc 4
nop 0
dl 0
loc 29
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace TZachi\PhalconRepository\Tests\Functional;
6
7
use Faker\Factory;
8
use Phalcon\Mvc\Model\Resultset\Simple as SimpleResultset;
9
use TZachi\PhalconRepository\ModelWrapper;
10
use TZachi\PhalconRepository\Repository;
11
use TZachi\PhalconRepository\Tests\Mock\Model\Payment;
12
use TZachi\PhalconRepository\Tests\Mock\Model\User;
13
use function array_reduce;
14
use function current;
15
use function next;
16
use function range;
17
use function reset;
18
19
/**
20
 * @coversDefaultClass Repository
21
 */
22
final class RepositoryTest extends TestCase
23
{
24
    /**
25
     * @var User[] $users
26
     */
27
    private static $users;
28
29
    /**
30
     * @var Payment[] $users
31
     */
32
    private static $payments;
33
34
    /**
35
     * @var Repository
36
     */
37
    private $userRepository;
38
39
    /**
40
     * @var Repository
41
     */
42
    private $paymentRepository;
43
44
    /**
45
     * @beforeClass
46
     */
47
    public static function setUpDatabase(): void
48
    {
49
        self::setUpDi();
50
51
        self::resetTable('users');
52
        self::resetTable('payments');
53
54
        $faker = Factory::create();
55
56
        for ($i = 1; $i <= 30; $i++) {
57
            $user            = new User();
58
            $user->id        = $i;
59
            $user->name      = $faker->unique()->name;
60
            $user->email     = $faker->unique()->email;
61
            $user->createdAt = $faker->dateTimeBetween('-1 month')->format('Y-m-d H:i:s');
62
            $user->save();
63
64
            self::$users[$i] = $user;
65
        }
66
67
        for ($i = 1; $i < 10; $i++) {
68
            $payment            = new Payment();
69
            $payment->id        = $i;
70
            $payment->value     = 1.15 * $i;
71
            $payment->count     = $i % 5;
72
            $payment->createdAt = $faker->dateTimeBetween('-1 month')->format('Y-m-d H:i:s');
73
            $payment->save();
74
75
            self::$payments[$i] = $payment;
76
        }
77
    }
78
79
    /**
80
     * @before
81
     */
82
    public function setUpDependencies(): void
83
    {
84
        self::resetModelsMetadata();
85
86
        $this->userRepository    = new Repository(new ModelWrapper(User::class));
87
        $this->paymentRepository = new Repository(new ModelWrapper(Payment::class));
88
    }
89
90
    /**
91
     * @test
92
     */
93
    public function findFirstShouldReturnModel(): void
94
    {
95
        $user = $this->userRepository->findFirst(1);
96
        self::assertInstanceOf(User::class, $user);
97
        self::assertSame(self::$users[1]->toArray(), $user->toArray());
98
    }
99
100
    /**
101
     * @test
102
     */
103
    public function findFirstShouldReturnNullWhenIdNotFound(): void
104
    {
105
        self::assertNull($this->userRepository->findFirst(100));
106
    }
107
108
    /**
109
     * @test
110
     */
111
    public function findFirstByShouldReturnModel(): void
112
    {
113
        $user = $this->userRepository->findFirstBy('email', self::$users[10]->email);
114
        self::assertInstanceOf(User::class, $user);
115
        self::assertSame(self::$users[10]->toArray(), $user->toArray());
116
117
        $user = $this->userRepository->findFirstBy('id', [3, 4, 5], ['id' => 'DESC']);
118
        self::assertInstanceOf(User::class, $user);
119
        self::assertSame(self::$users[5]->toArray(), $user->toArray());
120
    }
121
122
    /**
123
     * @test
124
     */
125
    public function findFirstWhereShouldReturnModel(): void
126
    {
127
        $conditions = [
128
            '@type' => Repository::TYPE_OR,
129
            'name' => self::$users[26]->name,
130
            'email' => self::$users[28]->email,
131
        ];
132
133
        $user = $this->userRepository->findFirstWhere($conditions, ['id']);
134
        self::assertInstanceOf(User::class, $user);
135
        self::assertSame(self::$users[26]->toArray(), $user->toArray());
136
137
        $user = $this->userRepository->findFirstWhere($conditions, ['id' => 'DESC']);
138
        self::assertInstanceOf(User::class, $user);
139
        self::assertSame(self::$users[28]->toArray(), $user->toArray());
140
    }
141
142
    /**
143
     * @test
144
     */
145
    public function findFirstWhereShouldReturnNullWithInvalidWhere(): void
146
    {
147
        $conditions = [
148
            '@type' => Repository::TYPE_AND,
149
            'name' => self::$users[26]->name,
150
            'email' => self::$users[28]->email,
151
        ];
152
153
        self::assertNull($this->userRepository->findFirstWhere($conditions));
154
    }
155
156
    /**
157
     * @test
158
     */
159
    public function findAllShouldReturnAllRows(): void
160
    {
161
        $this->compareResultSet($this->userRepository->findAll(), self::$users);
162
    }
163
164
    /**
165
     * @test
166
     */
167
    public function findByShouldReturnCorrectResultSet(): void
168
    {
169
        $emails    = [
170
            self::$users[12]->email,
171
            self::$users[22]->email,
172
            self::$users[25]->email,
173
        ];
174
        $resultSet = $this->userRepository->findBy('email', $emails, ['id' => 'DESC'], 2);
175
176
        $this->compareResultSet($resultSet, $this->getUsersSlice([25, 22]));
177
    }
178
179
    /**
180
     * @test
181
     */
182
    public function findWhereShouldReturnCorrectResultSetWithComplexCondition(): void
183
    {
184
        $resultSet = $this->userRepository->findWhere(
185
            [
186
                '@type' => Repository::TYPE_OR,
187
                [
188
                    '@operator' => 'BETWEEN',
189
                    'id' => [15, 21],
190
                ],
191
                'id' => range(5, 9),
192
                'name' => self::$users[11]->name,
193
            ],
194
            ['id' => 'DESC'],
195
            7,
196
            4
197
        );
198
199
        $this->compareResultSet($resultSet, $this->getUsersSlice([17, 16, 15, 11, 9, 8, 7]));
200
    }
201
202
    /**
203
     * @test
204
     */
205
    public function countShouldReturnNumberOfRows(): void
206
    {
207
        self::assertSame(30, $this->userRepository->count());
208
        self::assertSame(
209
            10,
210
            $this->userRepository->count(null, ['id' => [11, 20], '@operator' => 'BETWEEN'])
211
        );
212
    }
213
214
    /**
215
     * @test
216
     */
217
    public function sumShouldReturnSumOnColumn(): void
218
    {
219
        self::assertSame(20., $this->paymentRepository->sum('count'));
220
        self::assertSame(
221
            6.9,
222
            $this->paymentRepository->sum('value', ['id' => [1, 3], '@operator' => 'BETWEEN'])
223
        );
224
    }
225
226
    /**
227
     * @test
228
     */
229
    public function averageShouldReturnAverageOnColumn(): void
230
    {
231
        self::assertSame(
232
            8.05,
233
            $this->paymentRepository->average('value', ['id' => [5, 9], '@operator' => 'BETWEEN'])
234
        );
235
    }
236
237
    /**
238
     * @test
239
     */
240
    public function minimumShouldReturnMinimumOnColumn(): void
241
    {
242
        self::assertSame('1.15', $this->paymentRepository->minimum('value'));
243
        self::assertSame('0', $this->paymentRepository->minimum('count'));
244
245
        $users            = $this->getUsersSlice(range(1, 10));
246
        $minimumCreatedAt = array_reduce(
247
            $users,
248
            static function (?string $carry, User $user): string {
249
                if ($carry === null || $user->createdAt < $carry) {
250
                    return $user->createdAt;
251
                }
252
253
                return $carry;
254
            }
255
        );
256
        self::assertSame(
257
            $minimumCreatedAt,
258
            $this->userRepository->minimum('createdAt', ['id' => [1, 10], '@operator' => 'BETWEEN'])
259
        );
260
    }
261
262
    /**
263
     * @test
264
     */
265
    public function maximumShouldReturnMaximumOnColumn(): void
266
    {
267
        self::assertSame('10.35', $this->paymentRepository->maximum('value'));
268
        self::assertSame('4', $this->paymentRepository->maximum('count'));
269
270
        $users            = $this->getUsersSlice(range(8, 21));
271
        $maximumCreatedAt = array_reduce(
272
            $users,
273
            static function (?string $carry, User $user): string {
274
                if ($carry === null || $user->createdAt > $carry) {
275
                    return $user->createdAt;
276
                }
277
278
                return $carry;
279
            }
280
        );
281
        self::assertSame(
282
            $maximumCreatedAt,
283
            $this->userRepository->maximum('createdAt', ['id' => [8, 21], '@operator' => 'BETWEEN'])
284
        );
285
    }
286
287
    /**
288
     * @param int[] $ids
289
     *
290
     * @return User[]
291
     */
292
    protected function getUsersSlice(array $ids): array
293
    {
294
        $slice = [];
295
        foreach ($ids as $id) {
296
            $slice[$id] = self::$users[$id];
297
        }
298
299
        return $slice;
300
    }
301
302
    /**
303
     * @param User[] $expectedUsers
304
     */
305
    protected function compareResultSet(SimpleResultset $resultSet, array $expectedUsers): void
306
    {
307
        reset($expectedUsers);
308
        $resultSet->rewind();
309
        while ($resultSet->valid()) {
310
            /**
311
             * @var User $user
312
             */
313
            $user = $resultSet->current();
314
            self::assertInstanceOf(User::class, $user);
315
            self::assertSame(current($expectedUsers)->toArray(), $user->toArray());
316
317
            next($expectedUsers);
318
            $resultSet->next();
319
        }
320
    }
321
}
322