Failed Conditions
Push — master ( 798ab2...6213fb )
by Sam
09:34
created

ImporterTest::testInvalidMembership()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
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 4
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 testFuzzyCountry(): void
76
    {
77
        $this->expectErrorMessage('A la ligne 1 : Pays "suise" introuvable. Vouliez-vous dire "Suisse" ?');
78
79
        $this->import('tests/data/importer/invalid-country.csv');
80
    }
81
82
    public function testImport(): void
83
    {
84
        $this->assertUser([
85
            'email' => '[email protected]',
86
            'subscription_type' => null,
87
            'subscription_last_review_id' => null,
88
            'membership' => 'none',
89
            'first_name' => 'Hector',
90
            'last_name' => 'Barbossa',
91
            'street' => '',
92
            'postcode' => '',
93
            'locality' => '',
94
            'country_id' => '1',
95
            'phone' => '',
96
            'web_temporary_access' => '0',
97
            'password' => 'aa08769cdcb26674c6706093503ff0a3',
98
        ]);
99
100
        $otherMember = [
101
            'email' => '[email protected]',
102
            'subscription_type' => 'digital',
103
            'subscription_last_review_id' => '3001',
104
            'membership' => 'member',
105
            'first_name' => 'Elizabeth',
106
            'last_name' => 'Swann',
107
            'street' => '',
108
            'postcode' => '',
109
            'locality' => '',
110
            'country_id' => '1',
111
            'phone' => '',
112
            'web_temporary_access' => '0',
113
            'password' => '1895eaf4aad48bd97ec1a2fd15336591',
114
        ];
115
        $this->assertUser($otherMember);
116
117
        $this->assertShouldDeleteUserCount(0);
118
        $actual = $this->import('tests/data/importer/normal.csv');
119
120
        self::assertArrayHasKey('time', $actual);
121
        unset($actual['time']);
122
123
        $expected = [
124
            'updatedUsers' => 4,
125
            'updatedOrganizations' => 1,
126
            'deletedOrganizations' => 2,
127
            'totalUsers' => 6,
128
            'totalOrganizations' => 1,
129
            'totalLines' => 5,
130
        ];
131
        self::assertSame($expected, $actual);
132
133
        $this->assertShouldDeleteUserCount(2);
134
135
        $this->assertUser([
136
            'email' => '[email protected]',
137
            'subscription_type' => null,
138
            'subscription_last_review_id' => null,
139
            'membership' => 'none',
140
            'first_name' => '',
141
            'last_name' => '',
142
            'street' => '',
143
            'postcode' => '',
144
            'locality' => '',
145
            'country_id' => null,
146
            'phone' => '',
147
            'web_temporary_access' => '0',
148
            'password' => '',
149
        ]);
150
151
        $this->assertUser([
152
            'email' => 'thé[email protected]',
153
            'subscription_type' => 'paper',
154
            'subscription_last_review_id' => '3000',
155
            'membership' => 'member',
156
            'first_name' => '',
157
            'last_name' => '',
158
            'street' => '',
159
            'postcode' => '',
160
            'locality' => '',
161
            'country_id' => null,
162
            'phone' => '',
163
            'web_temporary_access' => '0',
164
            'password' => '',
165
        ]);
166
167
        $this->assertUser([
168
            'email' => '[email protected]',
169
            'subscription_type' => 'both',
170
            'subscription_last_review_id' => null,
171
            'membership' => 'member',
172
            'first_name' => 'Roger "Bob"',
173
            'last_name' => 'Doe',
174
            'street' => 'Main street',
175
            'postcode' => '2000',
176
            'locality' => 'New York',
177
            'country_id' => '2',
178
            'phone' => '032 987 65 43',
179
            'web_temporary_access' => '0',
180
            'password' => 'aa08769cdcb26674c6706093503ff0a3',
181
        ]);
182
183
        $this->assertOrganization([
184
            'pattern' => '.*@university\.com',
185
            'subscription_last_review_id' => '3001',
186
        ]);
187
188
        // Unchanged
189
        $this->assertUser($otherMember);
190
    }
191
192
    public function testImportBothInOneLine(): void
193
    {
194
        $this->assertShouldDeleteUserCount(0);
195
        $actual = $this->import('tests/data/importer/both-in-one-line.csv');
196
197
        self::assertArrayHasKey('time', $actual);
198
        unset($actual['time']);
199
200
        $expected = [
201
            'updatedUsers' => 1,
202
            'updatedOrganizations' => 1,
203
            'deletedOrganizations' => 2,
204
            'totalUsers' => 5,
205
            'totalOrganizations' => 1,
206
            'totalLines' => 1,
207
        ];
208
        self::assertSame($expected, $actual);
209
210
        $this->assertShouldDeleteUserCount(4);
211
212
        $this->assertUser([
213
            'email' => '[email protected]',
214
            'subscription_type' => 'digital',
215
            'subscription_last_review_id' => '3001',
216
            'membership' => 'none',
217
            'first_name' => 'John',
218
            'last_name' => 'Doe',
219
            'street' => 'Main street',
220
            'postcode' => '8000',
221
            'locality' => 'Zurich',
222
            'country_id' => '1',
223
            'phone' => '837 28 73',
224
            'web_temporary_access' => '0',
225
            'password' => '',
226
        ]);
227
228
        $this->assertOrganization([
229
            'pattern' => '.*@university\.com',
230
            'subscription_last_review_id' => '3001',
231
        ]);
232
    }
233
234
    public function testBomIsSkipped(): void
235
    {
236
        $this->import('tests/data/importer/bom.csv');
237
238
        $this->assertUser([
239
            'email' => '[email protected]',
240
            'subscription_type' => null,
241
            'subscription_last_review_id' => null,
242
            'membership' => 'none',
243
            'first_name' => '',
244
            'last_name' => '',
245
            'street' => '',
246
            'postcode' => '',
247
            'locality' => '',
248
            'country_id' => null,
249
            'phone' => '',
250
            'web_temporary_access' => '0',
251
            'password' => '',
252
        ]);
253
    }
254
255
    public function testEscapedSequences(): void
256
    {
257
        $this->import('tests/data/importer/escaped.csv');
258
259
        $this->assertUser([
260
            'email' => '[email protected]',
261
            'subscription_type' => null,
262
            'subscription_last_review_id' => null,
263
            'membership' => 'none',
264
            'first_name' => 'test"test\'test\test',
265
            'last_name' => 'test"test\'test\test',
266
            'street' => '',
267
            'postcode' => '',
268
            'locality' => '',
269
            'country_id' => null,
270
            'phone' => '',
271
            'web_temporary_access' => '0',
272
            'password' => '',
273
        ]);
274
    }
275
276
    private function assertShouldDeleteUserCount(int $expected): void
277
    {
278
        $connection = $this->getEntityManager()->getConnection();
279
        $actual = (int) $connection->fetchColumn('SELECT COUNT(*) FROM user WHERE should_delete');
280
281
        self::assertSame($expected, $actual);
282
    }
283
284
    private function assertUser(array $expected): void
285
    {
286
        $connection = $this->getEntityManager()->getConnection();
287
        $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']]);
288
289
        self::assertSame($expected, $actual);
290
    }
291
292
    private function assertOrganization(array $expected): void
293
    {
294
        $connection = $this->getEntityManager()->getConnection();
295
        $actual = $connection->fetchAssoc('SELECT pattern, subscription_last_review_id FROM organization WHERE pattern = ?', [$expected['pattern']]);
296
297
        self::assertSame($expected, $actual);
298
    }
299
300
    private function import(string $filename): array
301
    {
302
        $importer = new Importer();
303
        $actual = $importer->import($filename);
304
305
        return $actual;
306
    }
307
}
308