Passed
Push — master ( b8255a...26b0ba )
by Adrien
08:35
created

ImporterTest::testBomIsSkipped()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 15
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 18
rs 9.7666
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 testInvalidMembership(): void
34
    {
35
        $this->expectErrorMessage('A la ligne 1 : Le membership aux artisans est invalide : foo');
36
        $this->import('tests/data/importer/invalid-membership.csv');
37
    }
38
39
    public function testInvalidEmpty(): void
40
    {
41
        $this->expectErrorMessage('A la ligne 1 : Il faut soit un email, soit un pattern, mais aucun existe');
42
        $this->import('tests/data/importer/invalid-empty.csv');
43
    }
44
45
    public function testInvalidDuplicatedEmail(): void
46
    {
47
        $this->expectErrorMessage("A la ligne 3 : L'email \"[email protected]\" est dupliqué et a déjà été vu à la ligne 1");
48
        $this->import('tests/data/importer/invalid-duplicated-email.csv');
49
    }
50
51
    public function testInvalidDuplicatedPattern(): void
52
    {
53
        $this->expectErrorMessage('A la ligne 2 : Le pattern ".*@university\.com" est dupliqué et a déjà été vu à la ligne 1');
54
        $this->import('tests/data/importer/invalid-duplicated-pattern.csv');
55
    }
56
57
    public function testInvalidReviewNumber(): void
58
    {
59
        $this->expectErrorMessage('A la ligne 1 : Un numéro de revue doit être entièrement numérique, mais est : foo');
60
        $this->import('tests/data/importer/invalid-review-number.csv');
61
    }
62
63
    public function testInvalidMissingReviewNumber(): void
64
    {
65
        $this->expectErrorMessage('A la ligne 1 : Revue introuvable pour le numéro de revue : 123');
66
        $this->import('tests/data/importer/invalid-missing-review-number.csv');
67
    }
68
69
    public function testInvalidColumnCount(): void
70
    {
71
        $this->expectErrorMessage('A la ligne 1 : Doit avoir exactement 12 colonnes, mais en a 5');
72
        $this->import('tests/data/importer/invalid-column-count.csv');
73
    }
74
75
    public function testInvalidSubscriptionType(): void
76
    {
77
        $this->expectErrorMessage('A la ligne 1 : Le subscriptionType est invalide : foo');
78
        $this->import('tests/data/importer/invalid-subscription-type.csv');
79
    }
80
81
    public function testFuzzyCountry(): void
82
    {
83
        $this->expectErrorMessage('A la ligne 1 : Pays "suise" introuvable. Vouliez-vous dire "Suisse" ?');
84
85
        $this->import('tests/data/importer/invalid-country.csv');
86
    }
87
88
    public function testImport(): void
89
    {
90
        $this->assertUser([
91
            'email' => '[email protected]',
92
            'subscription_type' => null,
93
            'subscription_last_review_id' => null,
94
            'membership' => 'none',
95
            'first_name' => 'Hector',
96
            'last_name' => 'Barbossa',
97
            'street' => '',
98
            'postcode' => '',
99
            'locality' => '',
100
            'country_id' => '1',
101
            'phone' => '',
102
            'web_temporary_access' => '0',
103
            'password' => 'aa08769cdcb26674c6706093503ff0a3',
104
        ]);
105
106
        $otherMember = [
107
            'email' => '[email protected]',
108
            'subscription_type' => 'digital',
109
            'subscription_last_review_id' => '3001',
110
            'membership' => 'payed',
111
            'first_name' => 'Elizabeth',
112
            'last_name' => 'Swann',
113
            'street' => '',
114
            'postcode' => '',
115
            'locality' => '',
116
            'country_id' => '1',
117
            'phone' => '',
118
            'web_temporary_access' => '0',
119
            'password' => '1895eaf4aad48bd97ec1a2fd15336591',
120
        ];
121
        $this->assertUser($otherMember);
122
123
        $this->assertShouldDeleteUserCount(0);
124
        $actual = $this->import('tests/data/importer/normal.csv');
125
126
        self::assertArrayHasKey('time', $actual);
127
        unset($actual['time']);
128
129
        $expected = [
130
            'updatedUsers' => 4,
131
            'updatedOrganizations' => 1,
132
            'deletedOrganizations' => 2,
133
            'totalUsers' => 6,
134
            'totalOrganizations' => 1,
135
            'totalLines' => 5,
136
        ];
137
        self::assertSame($expected, $actual);
138
139
        $this->assertShouldDeleteUserCount(2);
140
141
        $this->assertUser([
142
            'email' => '[email protected]',
143
            'subscription_type' => null,
144
            'subscription_last_review_id' => null,
145
            'membership' => 'none',
146
            'first_name' => '',
147
            'last_name' => '',
148
            'street' => '',
149
            'postcode' => '',
150
            'locality' => '',
151
            'country_id' => null,
152
            'phone' => '',
153
            'web_temporary_access' => '0',
154
            'password' => '',
155
        ]);
156
157
        $this->assertUser([
158
            'email' => 'thé[email protected]',
159
            'subscription_type' => 'paper',
160
            'subscription_last_review_id' => '3000',
161
            'membership' => 'due',
162
            'first_name' => '',
163
            'last_name' => '',
164
            'street' => '',
165
            'postcode' => '',
166
            'locality' => '',
167
            'country_id' => null,
168
            'phone' => '',
169
            'web_temporary_access' => '0',
170
            'password' => '',
171
        ]);
172
173
        $this->assertUser([
174
            'email' => '[email protected]',
175
            'subscription_type' => null,
176
            'subscription_last_review_id' => null,
177
            'membership' => 'payed',
178
            'first_name' => 'Roger "Bob"',
179
            'last_name' => 'Doe',
180
            'street' => 'Main street',
181
            'postcode' => '2000',
182
            'locality' => 'New York',
183
            'country_id' => '2',
184
            'phone' => '032 987 65 43',
185
            'web_temporary_access' => '0',
186
            'password' => 'aa08769cdcb26674c6706093503ff0a3',
187
        ]);
188
189
        $this->assertOrganization([
190
            'pattern' => '.*@university\.com',
191
            'subscription_last_review_id' => '3001',
192
        ]);
193
194
        // Unchanged
195
        $this->assertUser($otherMember);
196
    }
197
198
    public function testImportBothInOneLine(): void
199
    {
200
        $this->assertShouldDeleteUserCount(0);
201
        $actual = $this->import('tests/data/importer/both-in-one-line.csv');
202
203
        self::assertArrayHasKey('time', $actual);
204
        unset($actual['time']);
205
206
        $expected = [
207
            'updatedUsers' => 1,
208
            'updatedOrganizations' => 1,
209
            'deletedOrganizations' => 2,
210
            'totalUsers' => 5,
211
            'totalOrganizations' => 1,
212
            'totalLines' => 1,
213
        ];
214
        self::assertSame($expected, $actual);
215
216
        $this->assertShouldDeleteUserCount(4);
217
218
        $this->assertUser([
219
            'email' => '[email protected]',
220
            'subscription_type' => 'digital',
221
            'subscription_last_review_id' => '3001',
222
            'membership' => 'none',
223
            'first_name' => 'John',
224
            'last_name' => 'Doe',
225
            'street' => 'Main street',
226
            'postcode' => '8000',
227
            'locality' => 'Zurich',
228
            'country_id' => '1',
229
            'phone' => '837 28 73',
230
            'web_temporary_access' => '0',
231
            'password' => '',
232
        ]);
233
234
        $this->assertOrganization([
235
            'pattern' => '.*@university\.com',
236
            'subscription_last_review_id' => '3001',
237
        ]);
238
    }
239
240
    public function testBomIsSkipped(): void
241
    {
242
        $this->import('tests/data/importer/bom.csv');
243
244
        $this->assertUser([
245
            'email' => '[email protected]',
246
            'subscription_type' => null,
247
            'subscription_last_review_id' => null,
248
            'membership' => 'none',
249
            'first_name' => '',
250
            'last_name' => '',
251
            'street' => '',
252
            'postcode' => '',
253
            'locality' => '',
254
            'country_id' => null,
255
            'phone' => '',
256
            'web_temporary_access' => '0',
257
            'password' => '',
258
        ]);
259
    }
260
261
    private function assertShouldDeleteUserCount(int $expected): void
262
    {
263
        $connection = $this->getEntityManager()->getConnection();
264
        $actual = (int) $connection->fetchColumn('SELECT COUNT(*) FROM user WHERE should_delete');
265
266
        self::assertSame($expected, $actual);
267
    }
268
269
    private function assertUser(array $expected): void
270
    {
271
        $connection = $this->getEntityManager()->getConnection();
272
        $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']]);
273
274
        self::assertSame($expected, $actual);
275
    }
276
277
    private function assertOrganization(array $expected): void
278
    {
279
        $connection = $this->getEntityManager()->getConnection();
280
        $actual = $connection->fetchAssoc('SELECT pattern, subscription_last_review_id FROM organization WHERE pattern = ?', [$expected['pattern']]);
281
282
        self::assertSame($expected, $actual);
283
    }
284
285
    private function import(string $filename): array
286
    {
287
        $importer = new Importer();
288
        $actual = $importer->import($filename);
289
290
        return $actual;
291
    }
292
}
293