Completed
Push — master ( cda546...72ee7f )
by Jacob
03:25
created

MysqlSeriesRepositoryTest   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 397
Duplicated Lines 29.47 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 3
Bugs 0 Features 1
Metric Value
wmc 21
c 3
b 0
f 1
lcom 1
cbo 5
dl 117
loc 397
rs 10

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Jacobemerick\Web\Domain\Blog\Series;
4
5
use Aura\Sql\ConnectionLocator;
6
use Aura\Sql\ExtendedPdo;
7
use PHPUnit_Framework_TestCase;
8
9
class MysqlSeriesRepositoryTest extends PHPUnit_Framework_TestCase
10
{
11
12
    protected static $connection;
13
14
    public static function setUpBeforeClass()
15
    {
16
        $extendedPdo = new ExtendedPdo('sqlite::memory:');
17
        $extendedPdo->exec("ATTACH DATABASE `jpemeric_blog.db` AS `jpemeric_blog`");
18
19
        $extendedPdo->exec("
20
            CREATE TABLE IF NOT EXISTS `jpemeric_blog`.`post` (
21
                `id` integer PRIMARY KEY AUTOINCREMENT,
22
                `title` varchar(60) NOT NULL,
23
                `path` varchar(60) NOT NULL,
24
                `category` varchar(15) NOT NULL,
25
                `date` datetime,
26
                `body` text,
27
                `display` integer(1) NOT NULL
28
            )"
29
        );
30
        $extendedPdo->exec("
31
            CREATE TABLE IF NOT EXISTS `jpemeric_blog`.`series` (
32
                `id` integer PRIMARY KEY AUTOINCREMENT,
33
                `title` text NOT NULL,
34
                `description` text NOT NULL
35
            )"
36
        );
37
        $extendedPdo->exec("
38
            CREATE TABLE IF NOT EXISTS `jpemeric_blog`.`series_post` (
39
                `series` integer NOT NULL,
40
                `post` integer NOT NULL,
41
                `order` integer(1) NOT NULL
42
            )"
43
        );
44
45
        self::$connection = new ConnectionLocator(function () use ($extendedPdo) {
46
            return $extendedPdo;
47
        });
48
    }
49
50
    public function testIsInstanceOfSeriesRepository()
51
    {
52
        $repository = new MysqlSeriesRepository(self::$connection);
53
54
        $this->assertInstanceOf(
55
            'Jacobemerick\Web\Domain\Blog\Series\MysqlSeriesRepository',
56
            $repository
57
        );
58
    }
59
60
    public function testImplementsSeriesInterface()
61
    {
62
        $repository = new MysqlSeriesRepository(self::$connection);
63
64
        $this->assertInstanceOf(
65
            'Jacobemerick\Web\Domain\Blog\Series\SeriesRepositoryInterface',
66
            $repository
67
        );
68
    }
69
70
    public function testConstructSetsConnections()
71
    {
72
        $respository = new MysqlSeriesRepository(self::$connection);
73
74
        $this->assertAttributeSame(
75
            self::$connection,
76
            'connections',
77
            $respository
78
        );
79
    }
80
81
    public function testGetSeriesForPost()
82
    {
83
        $testPostData = [
84
            [
85
                'id' => rand(1, 100),
86
                'title' => 'test one',
87
                'category' => 'test category',
88
                'path' => 'test-one',
89
                'display' => 1,
90
            ],
91
            [
92
                'id' => rand(101, 200),
93
                'title' => 'test two',
94
                'category' => 'test category',
95
                'path' => 'test-two',
96
                'display' => 1,
97
            ],
98
        ];
99
100
        $testSeriesData = [
101
            [
102
                'id' => rand(1, 100),
103
                'title' => 'test one',
104
                'description' => 'test description',
105
            ],
106
        ];
107
108
        $testSeriesPostData = [];
109
        foreach ($testPostData as $testPostDataRow) {
110
            array_push($testSeriesPostData, [
111
                'series' => reset($testSeriesData)['id'],
112
                'post' => $testPostDataRow['id'],
113
            ]);
114
        }
115
116
        array_walk($testPostData, [$this, 'insertPostData']);
117
        array_walk($testSeriesData, [$this, 'insertSeriesData']);
118
        array_walk($testSeriesPostData, [$this, 'insertSeriesPostData']);
119
120
        $repository = new MysqlSeriesRepository(self::$connection);
121
        $data = $repository->getSeriesForPost(reset($testPostData)['id']);
122
123
        $this->assertNotFalse($data);
124
        $this->assertInternalType('array', $data);
125
        foreach ($testPostData as $key => $testPostRow) {
126
            $this->assertInternalType('array', $data[$key]);
127
            $this->assertArrayHasKey('series_title', $data[$key]);
128
            $this->assertEquals(reset($testSeriesData)['title'], $data[$key]['series_title']);
129
            $this->assertArrayHasKey('series_description', $data[$key]);
130
            $this->assertEquals(reset($testSeriesData)['description'], $data[$key]['series_description']);
131
            $this->assertArrayHasKey('post', $data[$key]);
132
            $this->assertEquals($testPostRow['id'], $data[$key]['post']);
133
            $this->assertArrayHasKey('title', $data[$key]);
134
            $this->assertEquals($testPostRow['title'], $data[$key]['title']);
135
            $this->assertArrayHasKey('category', $data[$key]);
136
            $this->assertEquals($testPostRow['category'], $data[$key]['category']);
137
            $this->assertArrayHasKey('path', $data[$key]);
138
            $this->assertEquals($testPostRow['path'], $data[$key]['path']);
139
        }
140
    }
141
142
    public function testGetSeriesForPostOrder()
143
    {
144
        $testPostData = [
145
            [
146
                'id' => rand(1, 100),
147
                'display' => 1,
148
            ],
149
            [
150
                'id' => rand(101, 200),
151
                'display' => 1,
152
            ],
153
            [
154
                'id' => rand(201, 300),
155
                'display' => 1,
156
            ],
157
        ];
158
159
        $testSeriesData = [
160
            [
161
                'id' => rand(1, 100),
162
            ],
163
        ];
164
165
        $order = [1, 2, 3];
166
        shuffle($order);
167
        $testSeriesPostData = [];
168
        foreach ($testPostData as $key => $testPostDataRow) {
169
            array_push($testSeriesPostData, [
170
                'series' => reset($testSeriesData)['id'],
171
                'post' => $testPostDataRow['id'],
172
                'order' => $order[$key],
173
            ]);
174
        }
175
176
        array_walk($testPostData, [$this, 'insertPostData']);
177
        array_walk($testSeriesData, [$this, 'insertSeriesData']);
178
        array_walk($testSeriesPostData, [$this, 'insertSeriesPostData']);
179
180
        $repository = new MysqlSeriesRepository(self::$connection);
181
        $data = $repository->getSeriesForPost(reset($testPostData)['id']);
182
183
        usort($testPostData, function ($rowA, $rowB) use ($testSeriesPostData) {
184
            $seriesA = array_filter($testSeriesPostData, function ($row) use ($rowA) {
185
                return ($rowA['id'] == $row['post']);
186
            });
187
            $seriesB = array_filter($testSeriesPostData, function ($row) use ($rowB) {
188
                return ($rowB['id'] == $row['post']);
189
            });
190
191
            return (reset($seriesA)['order'] > reset($seriesB)['order']);
192
        });
193
194
        $this->assertNotFalse($data);
195
        $this->assertInternalType('array', $data);
196
        foreach ($testPostData as $key => $testPostRow) {
197
            $this->assertInternalType('array', $data[$key]);
198
            $this->assertArrayHasKey('post', $data[$key]);
199
            $this->assertEquals($testPostRow['id'], $data[$key]['post']);
200
        }
201
    }
202
 
203
    public function testGetSeriesForPostSeriesFilter()
204
    {
205
        $testPostAData = [
206
            [
207
                'id' => rand(1, 100),
208
                'display' => 1,
209
            ],
210
            [
211
                'id' => rand(101, 200),
212
                'display' => 1,
213
            ],
214
        ];
215
216
        $testPostBData = [
217
            [
218
                'id' => rand(501, 600),
219
                'display' => 1,
220
            ],
221
            [
222
                'id' => rand(601, 700),
223
                'display' => 1,
224
            ],
225
        ];
226
227
        $testSeriesData = [
228
            [
229
                'id' => rand(1, 100),
230
            ],
231
            [
232
                'id' => rand(101, 200),
233
            ],
234
        ];
235
236
        $testSeriesPostData = [];
237
        foreach ($testPostAData as $testPostDataRow) {
238
            array_push($testSeriesPostData, [
239
                'series' => $testSeriesData[0]['id'],
240
                'post' => $testPostDataRow['id'],
241
            ]);
242
        }
243
        foreach ($testPostBData as $testPostDataRow) {
244
            array_push($testSeriesPostData, [
245
                'series' => $testSeriesData[1]['id'],
246
                'post' => $testPostDataRow['id'],
247
            ]);
248
        }
249
250
        $testPostData = array_merge($testPostAData, $testPostBData);
251
        array_walk($testPostData, [$this, 'insertPostData']);
252
        array_walk($testSeriesData, [$this, 'insertSeriesData']);
253
        array_walk($testSeriesPostData, [$this, 'insertSeriesPostData']);
254
255
        $repository = new MysqlSeriesRepository(self::$connection);
256
        $data = $repository->getSeriesForPost(reset($testPostAData)['id']);
257
258
        $this->assertNotFalse($data);
259
        $this->assertInternalType('array', $data);
260
261
        $testPosts = array_column($testPostAData, 'id');
262
        $dataPosts = array_column($data, 'post');
263
264
        $this->assertEmpty(array_merge(
265
            array_diff($testPosts, $dataPosts),
266
            array_diff($dataPosts, $testPosts)
267
        ));
268
    }
269
 
270
    public function testGetSeriesForPostInactive()
271
    {
272
        $testPostData = [
273
            [
274
                'id' => rand(1, 100),
275
                'display' => 1,
276
            ],
277
            [
278
                'id' => rand(101, 200),
279
                'display' => 0,
280
            ],
281
            [
282
                'id' => rand(201, 300),
283
                'display' => 0,
284
            ],
285
        ];
286
287
        $testSeriesData = [
288
            [
289
                'id' => rand(1, 100),
290
            ],
291
        ];
292
293
        $testSeriesPostData = [];
294
        foreach ($testPostData as $testPostDataRow) {
295
            array_push($testSeriesPostData, [
296
                'series' => reset($testSeriesData)['id'],
297
                'post' => $testPostDataRow['id'],
298
            ]);
299
        }
300
301
        array_walk($testPostData, [$this, 'insertPostData']);
302
        array_walk($testSeriesData, [$this, 'insertSeriesData']);
303
        array_walk($testSeriesPostData, [$this, 'insertSeriesPostData']);
304
305
        $repository = new MysqlSeriesRepository(self::$connection);
306
        $data = $repository->getSeriesForPost(reset($testPostData)['id']);
307
308
        $this->assertNotFalse($data);
309
        $this->assertInternalType('array', $data);
310
311
        $testPostData = array_filter($testPostData, function ($row) {
312
            return ($row['display'] == 1);
313
        });
314
        $testPosts = array_column($testPostData, 'id');
315
        $dataPosts = array_column($data, 'post');
316
317
        $this->assertEmpty(array_merge(
318
            array_diff($testPosts, $dataPosts),
319
            array_diff($dataPosts, $testPosts)
320
        ));
321
    }
322
323
    public function testGetSeriesForPostFailure()
324
    {
325
        $repository = new MysqlSeriesRepository(self::$connection);
326
        $data = $repository->getSeriesForPost(rand(1, 100));
327
328
        $this->assertEmpty($data);
329
        $this->assertInternalType('array', $data);
330
    }
331
332
    protected function insertPostData(array $data)
333
    {
334
        $defaultData = [
335
            'id' => null,
336
            'title' => '',
337
            'path' => '',
338
            'category' => '',
339
            'date' => '',
340
            'body' => '',
341
            'display' => 0,
342
        ];
343
344
        $data = array_merge($defaultData, $data);
345
346
        return self::$connection->getDefault()->perform("
347
            INSERT INTO `jpemeric_blog`.`post`
348
                (id, title, path, category, date, body, display)
349
            VALUES
350
                (:id, :title, :path, :category, :date, :body, :display)",
351
            $data
352
        );
353
    }
354
355
    protected function insertSeriesData(array $data)
356
    {
357
        $defaultData = [
358
            'id' => null,
359
            'title' => '',
360
            'description' => '',
361
        ];
362
363
        $data = array_merge($defaultData, $data);
364
365
        return self::$connection->getDefault()->perform("
366
            INSERT INTO `jpemeric_blog`.`series`
367
                (id, title, description)
368
            VALUES
369
                (:id, :title, :description)",
370
            $data
371
        );
372
    }
373
374
    protected function insertSeriesPostData(array $data)
375
    {
376
        $defaultData = [
377
            'series' => '',
378
            'post' => '',
379
            'order' => 0,
380
        ];
381
382
        $data = array_merge($defaultData, $data);
383
384
        return self::$connection->getDefault()->perform("
385
            INSERT INTO `jpemeric_blog`.`series_post`
386
                (series, post, `order`)
387
            VALUES
388
                (:series, :post, :order)",
389
            $data
390
        );
391
    }
392
393
    protected function tearDown()
394
    {
395
        self::$connection->getDefault()->perform("DELETE FROM `jpemeric_blog`.`post`");
396
        self::$connection->getDefault()->perform("DELETE FROM `jpemeric_blog`.`series`");
397
        self::$connection->getDefault()->perform("DELETE FROM `jpemeric_blog`.`series_post`");
398
    }
399
400
    public static function tearDownAfterClass()
401
    {
402
        self::$connection->getDefault()->disconnect();
403
        unlink('jpemeric_blog.db');
404
    }
405
}
406