Passed
Push — master ( aafc79...755445 )
by Adrien
11:37
created

ImporterTest::testInvalidMultipleErrors()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 5
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ApplicationTest\Service;
6
7
use Application\Service\Importer;
8
use ApplicationTest\Traits\TestWithTransactionAndUser;
9
use PHPUnit\Framework\TestCase;
10
11
class ImporterTest extends TestCase
12
{
13
    use TestWithTransactionAndUser;
14
15
    public function testInvalidFilename(): void
16
    {
17
        $this->expectErrorMessage('File not found: non-existing-filename.csv');
18
        $this->import('non-existing-filename.csv');
19
    }
20
21
    public function testInvalidEmail(): void
22
    {
23
        $this->expectErrorMessage('A la ligne 1 : Ce n\'est pas une addresse email valide : "fo[o"');
24
        $this->import('tests/data/importer/invalid-email.csv');
25
    }
26
27
    public function testInvalidPattern(): void
28
    {
29
        $this->expectErrorMessage('A la ligne 1 : Ce n\'est pas une expression régulière valide : "fo[o"');
30
        $this->import('tests/data/importer/invalid-pattern.csv');
31
    }
32
33
    public function testInvalidEmpty(): void
34
    {
35
        $this->expectErrorMessage('A la ligne 1 : Il faut soit un email, soit un pattern, mais aucun existe');
36
        $this->import('tests/data/importer/invalid-empty.csv');
37
    }
38
39
    public function testInvalidDuplicatedEmail(): void
40
    {
41
        $this->expectErrorMessage("A la ligne 3 : L'email \"[email protected]\" est dupliqué et a déjà été vu à la ligne 1");
42
        $this->import('tests/data/importer/invalid-duplicated-email.csv');
43
    }
44
45
    public function testInvalidDuplicatedPattern(): void
46
    {
47
        $this->expectErrorMessage('A la ligne 2 : Le pattern ".*@university\.com" est dupliqué et a déjà été vu à la ligne 1');
48
        $this->import('tests/data/importer/invalid-duplicated-pattern.csv');
49
    }
50
51
    public function testInvalidReviewNumber(): void
52
    {
53
        $this->expectErrorMessage('A la ligne 1 : Un numéro de revue doit être entièrement numérique, mais est : "foo"');
54
        $this->import('tests/data/importer/invalid-review-number.csv');
55
    }
56
57
    public function testInvalidMissingReviewNumber(): void
58
    {
59
        $this->expectErrorMessage('A la ligne 1 : Revue introuvable pour le numéro de revue : 123');
60
        $this->import('tests/data/importer/invalid-missing-review-number.csv');
61
    }
62
63
    public function testInvalidColumnCount(): void
64
    {
65
        $this->expectErrorMessage('A la ligne 1 : Doit avoir exactement 14 colonnes, mais en a 5');
66
        $this->import('tests/data/importer/invalid-column-count.csv');
67
    }
68
69
    public function testInvalidSubscriptionType(): void
70
    {
71
        $this->expectErrorMessage('A la ligne 1 : Le subscriptionType est invalide : "foo"');
72
        $this->import('tests/data/importer/invalid-subscription-type.csv');
73
    }
74
75
    public function testInvalidMultipleErrors(): void
76
    {
77
        $this->expectErrorMessage('A la ligne 1 : Pays "suise" introuvable. Vouliez-vous dire "SUISSE" ?
78
A la ligne 2 : Revue introuvable pour le numéro de revue : 123');
79
        $this->import('tests/data/importer/invalid-multiple-errors.csv');
80
    }
81
82
    public function testFuzzyCountry(): void
83
    {
84
        $this->expectErrorMessage('A la ligne 1 : Pays "suise" introuvable. Vouliez-vous dire "SUISSE" ?');
85
86
        $this->import('tests/data/importer/invalid-country.csv');
87
    }
88
89
    public function testCountryWithAccent(): void
90
    {
91
        $this->import('tests/data/importer/valid-country.csv');
92
93
        $this->assertUser([
94
            'email' => '[email protected]',
95
            'subscription_type' => null,
96
            'subscription_last_review_id' => null,
97
            'membership' => 'none',
98
            'first_name' => '',
99
            'last_name' => '',
100
            'street' => '',
101
            'postcode' => '',
102
            'locality' => '',
103
            'country_id' => '51',
104
            'phone' => '',
105
            'web_temporary_access' => '0',
106
            'password' => '',
107
        ]);
108
109
        $this->assertUser([
110
            'email' => '[email protected]',
111
            'subscription_type' => null,
112
            'subscription_last_review_id' => null,
113
            'membership' => 'none',
114
            'first_name' => '',
115
            'last_name' => '',
116
            'street' => '',
117
            'postcode' => '',
118
            'locality' => '',
119
            'country_id' => '51',
120
            'phone' => '',
121
            'web_temporary_access' => '0',
122
            'password' => '',
123
        ]);
124
125
        $this->assertUser([
126
            'email' => '[email protected]',
127
            'subscription_type' => null,
128
            'subscription_last_review_id' => null,
129
            'membership' => 'none',
130
            'first_name' => '',
131
            'last_name' => '',
132
            'street' => '',
133
            'postcode' => '',
134
            'locality' => '',
135
            'country_id' => '29',
136
            'phone' => '',
137
            'web_temporary_access' => '0',
138
            'password' => '',
139
        ]);
140
    }
141
142
    public function testImport(): void
143
    {
144
        $this->assertUser([
145
            'email' => '[email protected]',
146
            'subscription_type' => null,
147
            'subscription_last_review_id' => null,
148
            'membership' => 'none',
149
            'first_name' => 'Hector',
150
            'last_name' => 'Barbossa',
151
            'street' => '',
152
            'postcode' => '',
153
            'locality' => '',
154
            'country_id' => '1',
155
            'phone' => '',
156
            'web_temporary_access' => '0',
157
            'password' => 'aa08769cdcb26674c6706093503ff0a3',
158
        ]);
159
160
        $otherMember = [
161
            'email' => '[email protected]',
162
            'subscription_type' => 'digital',
163
            'subscription_last_review_id' => '3001',
164
            'membership' => 'member',
165
            'first_name' => 'Elizabeth',
166
            'last_name' => 'Swann',
167
            'street' => '',
168
            'postcode' => '',
169
            'locality' => '',
170
            'country_id' => '1',
171
            'phone' => '',
172
            'web_temporary_access' => '0',
173
            'password' => '1895eaf4aad48bd97ec1a2fd15336591',
174
        ];
175
        $this->assertUser($otherMember);
176
177
        $this->assertShouldDeleteUserCount(0);
178
        $actual = $this->import('tests/data/importer/normal.csv');
179
180
        self::assertArrayHasKey('time', $actual);
181
        unset($actual['time']);
182
183
        $expected = [
184
            'updatedUsers' => 4,
185
            'updatedOrganizations' => 1,
186
            'deletedOrganizations' => 2,
187
            'totalUsers' => 6,
188
            'totalOrganizations' => 1,
189
            'totalLines' => 5,
190
        ];
191
        self::assertSame($expected, $actual);
192
193
        $this->assertShouldDeleteUserCount(2);
194
195
        $this->assertUser([
196
            'email' => '[email protected]',
197
            'subscription_type' => null,
198
            'subscription_last_review_id' => null,
199
            'membership' => 'none',
200
            'first_name' => '',
201
            'last_name' => '',
202
            'street' => '',
203
            'postcode' => '',
204
            'locality' => '',
205
            'country_id' => null,
206
            'phone' => '',
207
            'web_temporary_access' => '0',
208
            'password' => '',
209
        ]);
210
211
        $this->assertUser([
212
            'email' => 'thé[email protected]',
213
            'subscription_type' => 'paper',
214
            'subscription_last_review_id' => '3000',
215
            'membership' => 'member',
216
            'first_name' => '',
217
            'last_name' => '',
218
            'street' => '',
219
            'postcode' => '',
220
            'locality' => '',
221
            'country_id' => null,
222
            'phone' => '',
223
            'web_temporary_access' => '0',
224
            'password' => '',
225
        ]);
226
227
        $this->assertUser([
228
            'email' => '[email protected]',
229
            'subscription_type' => 'both',
230
            'subscription_last_review_id' => null,
231
            'membership' => 'member',
232
            'first_name' => 'Roger "Bob"',
233
            'last_name' => 'Doe',
234
            'street' => 'Main street',
235
            'postcode' => '2000',
236
            'locality' => 'New York',
237
            'country_id' => '2',
238
            'phone' => '032 987 65 43',
239
            'web_temporary_access' => '0',
240
            'password' => 'aa08769cdcb26674c6706093503ff0a3',
241
        ]);
242
243
        $this->assertOrganization([
244
            'pattern' => '.*@university\.com',
245
            'subscription_last_review_id' => '3001',
246
        ]);
247
248
        // Unchanged
249
        $this->assertUser($otherMember);
250
    }
251
252
    public function testImportBothInOneLine(): void
253
    {
254
        $this->assertShouldDeleteUserCount(0);
255
        $actual = $this->import('tests/data/importer/both-in-one-line.csv');
256
257
        self::assertArrayHasKey('time', $actual);
258
        unset($actual['time']);
259
260
        $expected = [
261
            'updatedUsers' => 1,
262
            'updatedOrganizations' => 1,
263
            'deletedOrganizations' => 2,
264
            'totalUsers' => 5,
265
            'totalOrganizations' => 1,
266
            'totalLines' => 1,
267
        ];
268
        self::assertSame($expected, $actual);
269
270
        $this->assertShouldDeleteUserCount(4);
271
272
        $this->assertUser([
273
            'email' => '[email protected]',
274
            'subscription_type' => 'digital',
275
            'subscription_last_review_id' => '3001',
276
            'membership' => 'none',
277
            'first_name' => 'John',
278
            'last_name' => 'Doe',
279
            'street' => 'Main street',
280
            'postcode' => '8000',
281
            'locality' => 'Zurich',
282
            'country_id' => '1',
283
            'phone' => '837 28 73',
284
            'web_temporary_access' => '0',
285
            'password' => '',
286
        ]);
287
288
        $this->assertOrganization([
289
            'pattern' => '.*@university\.com',
290
            'subscription_last_review_id' => '3001',
291
        ]);
292
    }
293
294
    public function testBomIsSkipped(): void
295
    {
296
        $this->import('tests/data/importer/bom.csv');
297
298
        $this->assertUser([
299
            'email' => '[email protected]',
300
            'subscription_type' => null,
301
            'subscription_last_review_id' => null,
302
            'membership' => 'none',
303
            'first_name' => '',
304
            'last_name' => '',
305
            'street' => '',
306
            'postcode' => '',
307
            'locality' => '',
308
            'country_id' => null,
309
            'phone' => '',
310
            'web_temporary_access' => '0',
311
            'password' => '',
312
        ]);
313
    }
314
315
    public function testEscapedSequences(): void
316
    {
317
        $this->import('tests/data/importer/escaped.csv');
318
319
        $this->assertUser([
320
            'email' => '[email protected]',
321
            'subscription_type' => null,
322
            'subscription_last_review_id' => null,
323
            'membership' => 'none',
324
            'first_name' => 'test"test\'test\test',
325
            'last_name' => 'test"test\'test\test',
326
            'street' => '',
327
            'postcode' => '',
328
            'locality' => '',
329
            'country_id' => null,
330
            'phone' => '',
331
            'web_temporary_access' => '0',
332
            'password' => '',
333
        ]);
334
    }
335
336
    private function assertShouldDeleteUserCount(int $expected): void
337
    {
338
        $connection = $this->getEntityManager()->getConnection();
339
        $actual = (int) $connection->fetchColumn('SELECT COUNT(*) FROM user WHERE should_delete');
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::fetchColumn() has been deprecated: Use fetchOne() instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

339
        $actual = (int) /** @scrutinizer ignore-deprecated */ $connection->fetchColumn('SELECT COUNT(*) FROM user WHERE should_delete');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
340
341
        self::assertSame($expected, $actual);
342
    }
343
344
    private function assertUser(array $expected): void
345
    {
346
        $connection = $this->getEntityManager()->getConnection();
347
        $actual = $connection->fetchAssoc('SELECT email, subscription_type, subscription_last_review_id, membership, first_name, last_name, street, postcode, locality, country_id, phone, web_temporary_access, password FROM user WHERE email = ?', [$expected['email']]);
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::fetchAssoc() has been deprecated: Use fetchAssociative() ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

347
        $actual = /** @scrutinizer ignore-deprecated */ $connection->fetchAssoc('SELECT email, subscription_type, subscription_last_review_id, membership, first_name, last_name, street, postcode, locality, country_id, phone, web_temporary_access, password FROM user WHERE email = ?', [$expected['email']]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
348
349
        self::assertSame($expected, $actual);
350
    }
351
352
    private function assertOrganization(array $expected): void
353
    {
354
        $connection = $this->getEntityManager()->getConnection();
355
        $actual = $connection->fetchAssoc('SELECT pattern, subscription_last_review_id FROM organization WHERE pattern = ?', [$expected['pattern']]);
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::fetchAssoc() has been deprecated: Use fetchAssociative() ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

355
        $actual = /** @scrutinizer ignore-deprecated */ $connection->fetchAssoc('SELECT pattern, subscription_last_review_id FROM organization WHERE pattern = ?', [$expected['pattern']]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
356
357
        self::assertSame($expected, $actual);
358
    }
359
360
    private function import(string $filename): array
361
    {
362
        $importer = new Importer();
363
        $actual = $importer->import($filename);
364
365
        return $actual;
366
    }
367
}
368