1
|
|
|
<?php |
2
|
|
|
/* Copyright (C) 2016 Michael Giesler |
3
|
|
|
* |
4
|
|
|
* This file is part of Dembelo. |
5
|
|
|
* |
6
|
|
|
* Dembelo is free software: you can redistribute it and/or modify |
7
|
|
|
* it under the terms of the GNU Affero General Public License as published by |
8
|
|
|
* the Free Software Foundation, either version 3 of the License, or |
9
|
|
|
* (at your option) any later version. |
10
|
|
|
* |
11
|
|
|
* Dembelo is distributed in the hope that it will be useful, |
12
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14
|
|
|
* GNU Affero General Public License 3 for more details. |
15
|
|
|
* |
16
|
|
|
* You should have received a copy of the GNU Affero General Public License 3 |
17
|
|
|
* along with Dembelo. If not, see <http://www.gnu.org/licenses/>. |
18
|
|
|
*/ |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @package AdminBundle\Test |
22
|
|
|
*/ |
23
|
|
|
|
24
|
|
|
// @codingStandardsIgnoreStart |
25
|
|
|
namespace AdminBundle\Model; |
26
|
|
|
|
27
|
|
|
use AdminBundle\Tests\Model\ImportTwineTest; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* mock function |
31
|
|
|
* |
32
|
|
|
* @param string $filename |
33
|
|
|
* @return bool |
34
|
|
|
*/ |
35
|
|
|
function fopen($filename) |
36
|
|
|
{ |
37
|
|
|
return strpos($filename, 'readable') !== false; |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* mock function |
42
|
|
|
*/ |
43
|
|
|
function fclose() |
44
|
|
|
{ |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* mock function |
49
|
|
|
* |
50
|
|
|
* @return bool|mixed |
51
|
|
|
*/ |
52
|
|
|
function fread() |
53
|
|
|
{ |
54
|
|
|
if (empty(ImportTwineTest::$freadStack)) { |
55
|
|
|
return false; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
return array_shift(ImportTwineTest::$freadStack); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* mock function |
63
|
|
|
* |
64
|
|
|
* @return bool |
65
|
|
|
*/ |
66
|
|
|
function feof() |
67
|
|
|
{ |
68
|
|
|
return empty(ImportTwineTest::$freadStack); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* mock function |
73
|
|
|
* |
74
|
|
|
* @return int |
75
|
|
|
*/ |
76
|
|
|
function fseek() |
77
|
|
|
{ |
78
|
|
|
return 0; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* @param Resource $parser |
83
|
|
|
*/ |
84
|
|
|
function xml_parser_free($parser) |
85
|
|
|
{ |
86
|
|
|
ImportTwineTest::$parserFreeCalled = true; |
87
|
|
|
|
88
|
|
|
return \xml_parser_free($parser); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
namespace AdminBundle\Tests\Model; |
92
|
|
|
|
93
|
|
|
use AdminBundle\Model\ImportTwine; |
94
|
|
|
use AdminBundle\Service\TwineImport\FileExtractor; |
95
|
|
|
use AdminBundle\Service\TwineImport\HitchParser; |
96
|
|
|
use DembeloMain\Document\Importfile; |
97
|
|
|
use DembeloMain\Document\Textnode; |
98
|
|
|
use DembeloMain\Model\Repository\Doctrine\ODM\TextNodeRepository; |
99
|
|
|
use DembeloMain\Model\Repository\TextNodeRepositoryInterface; |
100
|
|
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; |
101
|
|
|
|
102
|
|
|
// @codingStandardsIgnoreEnd |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Class ImportTwineTest |
106
|
|
|
* @package AdminBundle\Tests\Model |
107
|
|
|
*/ |
108
|
|
|
class ImportTwineTest extends WebTestCase |
109
|
|
|
{ |
110
|
|
|
|
111
|
|
|
public static $freadStack = []; |
112
|
|
|
public static $parserFreeCalled = false; |
113
|
|
|
private $mocks; |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* @var ImportTwine |
117
|
|
|
*/ |
118
|
|
|
private $importTwine; |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* @var \PHPUnit_Framework_MockObject_MockObject|TextNodeRepositoryInterface |
122
|
|
|
*/ |
123
|
|
|
private $textnodeRepository; |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* @var \PHPUnit_Framework_MockObject_MockObject|HitchParser |
127
|
|
|
*/ |
128
|
|
|
private $hitchParserMock; |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @var \PHPUnit_Framework_MockObject_MockObject|FileExtractor |
132
|
|
|
*/ |
133
|
|
|
private $fileExtractorMock; |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* resets some variables |
137
|
|
|
*/ |
138
|
|
|
public function setUp() |
139
|
|
|
{ |
140
|
|
|
self::$freadStack = []; |
141
|
|
|
$this->mocks = []; |
142
|
|
|
self::$parserFreeCalled = false; |
143
|
|
|
|
144
|
|
|
$this->textnodeRepository = $this->getTextnodeRepositoryMock(); |
145
|
|
|
$this->hitchParserMock = $this->createHitchParserMock(); |
146
|
|
|
$this->fileExtractorMock = $this->createFileExtractorMock(); |
147
|
|
|
|
148
|
|
|
$this->importTwine = new ImportTwine( |
149
|
|
|
$this->textnodeRepository, |
150
|
|
|
$this->hitchParserMock, |
151
|
|
|
$this->fileExtractorMock |
152
|
|
|
); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* @expectedException Exception |
157
|
|
|
* @expectedExceptionMessage File 'somefilename_readable' isn't a Twine archive file |
158
|
|
|
*/ |
159
|
|
View Code Duplication |
public function testRunWithWrongFileFormat() |
|
|
|
|
160
|
|
|
{ |
161
|
|
|
$dm = $this->getDmMock(); |
162
|
|
|
$importfile = $this->getDummyImportfile(); |
163
|
|
|
|
164
|
|
|
$this->fileExtractorMock->expects(self::any()) |
165
|
|
|
->method('extract') |
166
|
|
|
->willReturn('readable.extracted'); |
167
|
|
|
|
168
|
|
|
self::$freadStack = ['erste Zeile', 'zweite Zeile']; |
169
|
|
|
|
170
|
|
|
$this->importTwine->run($importfile); |
171
|
|
|
$dm->expects($this->never()) |
172
|
|
|
->method('persist'); |
173
|
|
|
$dm->expects($this->never()) |
174
|
|
|
->method('flush'); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* @expectedException Exception |
179
|
|
|
* @expectedExceptionMessage File 'somefilename_readable' seems to be empty. |
180
|
|
|
*/ |
181
|
|
View Code Duplication |
public function testRunWithEmptyFirstLine() |
|
|
|
|
182
|
|
|
{ |
183
|
|
|
$dm = $this->getDmMock(); |
184
|
|
|
$importfile = $this->getDummyImportfile(); |
185
|
|
|
|
186
|
|
|
$this->fileExtractorMock->expects(self::any()) |
187
|
|
|
->method('extract') |
188
|
|
|
->willReturn('readable.extracted'); |
189
|
|
|
|
190
|
|
|
self::$freadStack = ['']; |
191
|
|
|
|
192
|
|
|
$this->importTwine->run($importfile); |
193
|
|
|
$dm->expects($this->never()) |
194
|
|
|
->method('persist'); |
195
|
|
|
$dm->expects($this->never()) |
196
|
|
|
->method('flush'); |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* tests the run method with correct but incomplete data |
201
|
|
|
* |
202
|
|
|
* @throws \Exception |
203
|
|
|
*/ |
204
|
|
View Code Duplication |
public function testRunWithCorrectButIncompleteData() |
|
|
|
|
205
|
|
|
{ |
206
|
|
|
$dm = $this->getDmMock(); |
207
|
|
|
$importfile = $this->getDummyImportfile(); |
208
|
|
|
|
209
|
|
|
$this->fileExtractorMock->expects(self::any()) |
210
|
|
|
->method('extract') |
211
|
|
|
->willReturn('readable.extracted'); |
212
|
|
|
|
213
|
|
|
self::$freadStack = ['<tw-storydata hurz>', 'zweite Zeile']; |
214
|
|
|
|
215
|
|
|
$retVal = $this->importTwine->run($importfile); |
216
|
|
|
$this->assertTrue($retVal); |
217
|
|
|
$dm->expects($this->never()) |
218
|
|
|
->method('persist'); |
219
|
|
|
$dm->expects($this->never()) |
220
|
|
|
->method('flush'); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* tests the run method when no textnode is written |
225
|
|
|
* |
226
|
|
|
* @throws \Exception |
227
|
|
|
*/ |
228
|
|
|
public function testRunButNoTextnodeIsWritten() |
229
|
|
|
{ |
230
|
|
|
$importfile = $this->getDummyImportfile(); |
231
|
|
|
|
232
|
|
|
$this->fileExtractorMock->expects(self::any()) |
233
|
|
|
->method('extract') |
234
|
|
|
->willReturn('readable.extracted'); |
235
|
|
|
|
236
|
|
|
self::$freadStack = [ |
237
|
|
|
'<tw-storydata ', |
238
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
239
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
240
|
|
|
'<tw-passagedata pid="1" name="someNodeName" tags="Freigegeben ID:foobar" position="104,30">lorem impsum', |
241
|
|
|
'lorem impsum</tw-passagedata></tw-storydata>', |
242
|
|
|
]; |
243
|
|
|
|
244
|
|
|
$textnode = new Textnode(); |
245
|
|
|
$textnode->setId('someTextnodeId'); |
246
|
|
|
|
247
|
|
|
$this->textnodeRepository->expects($this->any()) |
248
|
|
|
->method('find') |
249
|
|
|
->will($this->returnValue($textnode)); |
250
|
|
|
|
251
|
|
|
$this->textnodeRepository->expects($this->any()) |
252
|
|
|
->method('findByTwineId') |
253
|
|
|
->willReturn($textnode); |
254
|
|
|
|
255
|
|
|
$retVal = $this->importTwine->run($importfile); |
256
|
|
|
$this->assertTrue($retVal); |
257
|
|
|
$this->textnodeRepository->expects($this->never()) |
258
|
|
|
->method('save'); |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* tests the run method with a single node containing text |
263
|
|
|
* |
264
|
|
|
* @throws \Exception |
265
|
|
|
*/ |
266
|
|
View Code Duplication |
public function testRunWithSingleNodeWithText() |
|
|
|
|
267
|
|
|
{ |
268
|
|
|
$importfile = $this->getDummyImportfile(); |
269
|
|
|
|
270
|
|
|
$this->fileExtractorMock->expects(self::any()) |
271
|
|
|
->method('extract') |
272
|
|
|
->willReturn('readable.extracted'); |
273
|
|
|
|
274
|
|
|
self::$freadStack = [ |
275
|
|
|
'<tw-storydata ', |
276
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
277
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
278
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="Freigegeben ID:foobar" position="104,30">lorem ipsum', |
279
|
|
|
'lorem ipsum</tw-passagedata></tw-storydata>', |
280
|
|
|
]; |
281
|
|
|
|
282
|
|
|
$textnode = new Textnode(); |
283
|
|
|
$textnode->setId('someTextnodeId'); |
284
|
|
|
|
285
|
|
|
$this->textnodeRepository->expects($this->any()) |
286
|
|
|
->method('find') |
287
|
|
|
->willReturn($textnode); |
288
|
|
|
|
289
|
|
|
$this->textnodeRepository->expects($this->any()) |
290
|
|
|
->method('findByTwineId') |
291
|
|
|
->willReturn($textnode); |
292
|
|
|
|
293
|
|
|
$this->textnodeRepository->expects($this->once()) |
294
|
|
|
->method('save') |
295
|
|
|
->with($this->callback(function ($textnode) { |
|
|
|
|
296
|
|
|
return $textnode instanceof Textnode |
297
|
|
|
&& $textnode->getText() === "lorem ipsumlorem ipsum"; |
298
|
|
|
})); |
299
|
|
|
|
300
|
|
|
$retVal = $this->importTwine->run($importfile); |
301
|
|
|
$this->assertTrue($retVal); |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* @expectedException \Exception |
306
|
|
|
* @expectedExceptionMessage The Twine archive file has a textnode which contains a malformed link that starts with '[[' but has no corresponding ']]'. |
307
|
|
|
*/ |
308
|
|
View Code Duplication |
public function testRunWithUnfinishedLinkTag() |
|
|
|
|
309
|
|
|
{ |
310
|
|
|
$importfile = $this->getDummyImportfile(); |
311
|
|
|
|
312
|
|
|
$this->fileExtractorMock->expects(self::any()) |
313
|
|
|
->method('extract') |
314
|
|
|
->willReturn('readable.extracted'); |
315
|
|
|
|
316
|
|
|
self::$freadStack = [ |
317
|
|
|
'<tw-storydata ', |
318
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
319
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
320
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="Freigegeben ID:foobar" position="104,30">lorem ipsum', |
321
|
|
|
'ein [[kaputter Link</tw-passagedata></tw-storydata>', |
322
|
|
|
]; |
323
|
|
|
|
324
|
|
|
$textnode = new Textnode(); |
325
|
|
|
$textnode->setId('someTextnodeId'); |
326
|
|
|
|
327
|
|
|
$this->textnodeRepository->expects($this->any()) |
328
|
|
|
->method('find') |
329
|
|
|
->willReturn($textnode); |
330
|
|
|
|
331
|
|
|
$this->textnodeRepository->expects($this->any()) |
332
|
|
|
->method('findByTwineId') |
333
|
|
|
->willReturn($textnode); |
334
|
|
|
|
335
|
|
|
$this->textnodeRepository->expects($this->any()) |
336
|
|
|
->method('save') |
337
|
|
|
->with($this->callback(function ($textnode) { |
|
|
|
|
338
|
|
|
return $textnode instanceof Textnode |
339
|
|
|
&& $textnode->getText() === "lorem ipsumein [[kaputter Link"; |
340
|
|
|
})); |
341
|
|
|
|
342
|
|
|
$retVal = $this->importTwine->run($importfile); |
343
|
|
|
$this->assertTrue($retVal); |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
/** |
347
|
|
|
* check if exception is thrown when no licensee is available |
348
|
|
|
* |
349
|
|
|
* @expectedException Exception |
350
|
|
|
* @expectedExceptionMessage no licensee available |
351
|
|
|
*/ |
352
|
|
|
public function testRunWithExceptionWhenNoLicenseeIsAvailable() |
353
|
|
|
{ |
354
|
|
|
$importfile = $this->getDummyImportfile(['licenseeId' => null]); |
355
|
|
|
|
356
|
|
|
$this->importTwine->run($importfile); |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* check if exception is thrown when no licensee is available |
361
|
|
|
* |
362
|
|
|
* @expectedException Exception |
363
|
|
|
* @expectedExceptionMessage no filename available |
364
|
|
|
*/ |
365
|
|
|
public function testRunWithExceptionWhenNoFilenameIsAvailable() |
366
|
|
|
{ |
367
|
|
|
$importfile = $this->getDummyImportfile(['filename' => null]); |
368
|
|
|
|
369
|
|
|
$this->importTwine->run($importfile); |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
/** |
373
|
|
|
* @expectedException Exception |
374
|
|
|
* @expectedExceptionMessage no ID given for Textnode "someNodeName1" |
375
|
|
|
*/ |
376
|
|
View Code Duplication |
public function testRunWithTextnodeWithoutTwineID() |
|
|
|
|
377
|
|
|
{ |
378
|
|
|
$importfile = $this->getDummyImportfile(); |
379
|
|
|
|
380
|
|
|
$this->fileExtractorMock->expects(self::any()) |
381
|
|
|
->method('extract') |
382
|
|
|
->willReturn('readable.extracted'); |
383
|
|
|
|
384
|
|
|
self::$freadStack = [ |
385
|
|
|
'<tw-storydata ', |
386
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
387
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
388
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="Freigegeben" position="104,30">lorem ipsum', |
389
|
|
|
'lorem ipsum</tw-passagedata></tw-storydata>', |
390
|
|
|
]; |
391
|
|
|
|
392
|
|
|
$textnode = new Textnode(); |
393
|
|
|
|
394
|
|
|
$this->textnodeRepository->expects($this->any()) |
395
|
|
|
->method('find') |
396
|
|
|
->will($this->returnValue($textnode)); |
397
|
|
|
|
398
|
|
|
$this->textnodeRepository->expects($this->never()) |
399
|
|
|
->method('save'); |
400
|
|
|
|
401
|
|
|
$this->importTwine->run($importfile); |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* @expectedException Exception |
406
|
|
|
* @expectedExceptionMessage no ID given for Textnode "someNodeName1" |
407
|
|
|
*/ |
408
|
|
View Code Duplication |
public function testRunWithTextnodeWithoutAnyTag() |
|
|
|
|
409
|
|
|
{ |
410
|
|
|
$importfile = $this->getDummyImportfile(); |
411
|
|
|
|
412
|
|
|
$this->fileExtractorMock->expects(self::any()) |
413
|
|
|
->method('extract') |
414
|
|
|
->willReturn('readable.extracted'); |
415
|
|
|
|
416
|
|
|
self::$freadStack = [ |
417
|
|
|
'<tw-storydata ', |
418
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
419
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
420
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="" position="104,30">lorem ipsum', |
421
|
|
|
'lorem ipsum</tw-passagedata></tw-storydata>', |
422
|
|
|
]; |
423
|
|
|
|
424
|
|
|
$textnode = new Textnode(); |
425
|
|
|
|
426
|
|
|
$this->textnodeRepository->expects($this->any()) |
427
|
|
|
->method('find') |
428
|
|
|
->will($this->returnValue($textnode)); |
429
|
|
|
|
430
|
|
|
$this->textnodeRepository->expects($this->never()) |
431
|
|
|
->method('save'); |
432
|
|
|
|
433
|
|
|
$this->importTwine->run($importfile); |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* tests identifying a textnode by a twine ID |
438
|
|
|
* @throws \Exception |
439
|
|
|
*/ |
440
|
|
View Code Duplication |
public function testRunWithTextnodeWithTwineID() |
|
|
|
|
441
|
|
|
{ |
442
|
|
|
$importfile = $this->getDummyImportfile(); |
443
|
|
|
|
444
|
|
|
$this->fileExtractorMock->expects(self::any()) |
445
|
|
|
->method('extract') |
446
|
|
|
->willReturn('readable.extracted'); |
447
|
|
|
|
448
|
|
|
self::$freadStack = [ |
449
|
|
|
'<tw-storydata ', |
450
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
451
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
452
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="Freigegeben ID:foobar" position="104,30">lorem ipsum', |
453
|
|
|
'lorem ipsum</tw-passagedata></tw-storydata>', |
454
|
|
|
]; |
455
|
|
|
|
456
|
|
|
$textnode = new Textnode(); |
457
|
|
|
$textnode->setId('someTextnodeId'); |
458
|
|
|
|
459
|
|
|
$this->textnodeRepository->expects($this->any()) |
460
|
|
|
->method('find') |
461
|
|
|
->will($this->returnValue($textnode)); |
462
|
|
|
|
463
|
|
|
$this->textnodeRepository->expects($this->once()) |
464
|
|
|
->method('findByTwineId') |
465
|
|
|
->with($importfile, 'foobar') |
|
|
|
|
466
|
|
|
->willReturn($textnode); |
467
|
|
|
|
468
|
|
|
$this->importTwine->run($importfile); |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
/** |
472
|
|
|
* tests the freeing of xml parser |
473
|
|
|
* @throws \Exception |
474
|
|
|
*/ |
475
|
|
View Code Duplication |
public function testParserFree() |
|
|
|
|
476
|
|
|
{ |
477
|
|
|
$importfile = $this->getDummyImportfile(); |
478
|
|
|
|
479
|
|
|
$this->fileExtractorMock->expects(self::any()) |
480
|
|
|
->method('extract') |
481
|
|
|
->willReturn('readable.extracted'); |
482
|
|
|
|
483
|
|
|
self::$freadStack = [ |
484
|
|
|
'<tw-storydata ', |
485
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
486
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
487
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="Freigegeben ID:foobar" position="104,30">lorem ipsum', |
488
|
|
|
'lorem ipsum</tw-passagedata></tw-storydata>', |
489
|
|
|
]; |
490
|
|
|
|
491
|
|
|
$textnode = new Textnode(); |
492
|
|
|
$textnode->setId('someTextnodeId'); |
493
|
|
|
|
494
|
|
|
$this->textnodeRepository->expects($this->any()) |
495
|
|
|
->method('find') |
496
|
|
|
->will($this->returnValue($textnode)); |
497
|
|
|
|
498
|
|
|
$this->textnodeRepository->expects($this->once()) |
499
|
|
|
->method('findByTwineId') |
500
|
|
|
->with($importfile, 'foobar') |
|
|
|
|
501
|
|
|
->willReturn($textnode); |
502
|
|
|
|
503
|
|
|
$this->importTwine->run($importfile); |
504
|
|
|
|
505
|
|
|
$this->assertTrue(self::$parserFreeCalled); |
506
|
|
|
} |
507
|
|
|
|
508
|
|
|
/** |
509
|
|
|
* tests disabling of a textnode that is no longer found in import file |
510
|
|
|
* @throws \Exception |
511
|
|
|
*/ |
512
|
|
|
public function testRunWithTextnodeDeletedInImportfile() |
513
|
|
|
{ |
514
|
|
|
$importfile = $this->getDummyImportfile(); |
515
|
|
|
|
516
|
|
|
$this->fileExtractorMock->expects(self::any()) |
517
|
|
|
->method('extract') |
518
|
|
|
->willReturn('readable.extracted'); |
519
|
|
|
|
520
|
|
|
self::$freadStack = [ |
521
|
|
|
'<tw-storydata ', |
522
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
523
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
524
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="Freigegeben ID:foobar" position="104,30">lorem ipsum', |
525
|
|
|
'lorem ipsum</tw-passagedata></tw-storydata>', |
526
|
|
|
]; |
527
|
|
|
|
528
|
|
|
$textnode = new Textnode(); |
529
|
|
|
$textnode->setId('someTextnodeId'); |
530
|
|
|
|
531
|
|
|
$this->textnodeRepository->expects($this->any()) |
532
|
|
|
->method('find') |
533
|
|
|
->will($this->returnValue($textnode)); |
534
|
|
|
|
535
|
|
|
$this->textnodeRepository->expects($this->once()) |
536
|
|
|
->method('findByTwineId') |
537
|
|
|
->with($importfile, 'foobar') |
|
|
|
|
538
|
|
|
->will($this->returnValue($textnode)); |
539
|
|
|
|
540
|
|
|
$this->textnodeRepository->expects($this->once()) |
541
|
|
|
->method('disableOrphanedNodes') |
542
|
|
|
->with($importfile, [$textnode->getId()]); |
543
|
|
|
|
544
|
|
|
$this->importTwine->run($importfile); |
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
/** |
548
|
|
|
* @expectedException Exception |
549
|
|
|
* @expectedExceptionMessage There is a 'tw-passagedata' in the Twine archive file 'somefilename_readable' which has a non unique 'id' tag [someTwineId], in node 'someNodeName2' |
550
|
|
|
*/ |
551
|
|
|
public function testRunWithDuplicateTwineId() |
552
|
|
|
{ |
553
|
|
|
$importfile = $this->getDummyImportfile(); |
554
|
|
|
|
555
|
|
|
$this->fileExtractorMock->expects(self::any()) |
556
|
|
|
->method('extract') |
557
|
|
|
->willReturn('readable.extracted'); |
558
|
|
|
|
559
|
|
|
self::$freadStack = [ |
560
|
|
|
'<tw-storydata ', |
561
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
562
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
563
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="ID:someTwineId" position="104,30">lorem ipsum', |
564
|
|
|
'lorem ipsum</tw-passagedata>', |
565
|
|
|
'<tw-passagedata pid="2" name="someNodeName2" tags="ID:someTwineId" position="104,30">lorem ipsum', |
566
|
|
|
'lorem ipsum</tw-passagedata>', |
567
|
|
|
'</tw-storydata>', |
568
|
|
|
]; |
569
|
|
|
|
570
|
|
|
$textnode = new Textnode(); |
571
|
|
|
|
572
|
|
|
$this->textnodeRepository->expects($this->any()) |
573
|
|
|
->method('find') |
574
|
|
|
->will($this->returnValue($textnode)); |
575
|
|
|
|
576
|
|
|
$this->textnodeRepository->expects($this->once()) |
577
|
|
|
->method('save'); |
578
|
|
|
|
579
|
|
|
$this->importTwine->run($importfile); |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
/** |
583
|
|
|
* tests a hitch to another textnode |
584
|
|
|
* @throws \Exception |
585
|
|
|
*/ |
586
|
|
|
public function testRunWithLinkToAnotherTextnode() |
587
|
|
|
{ |
588
|
|
|
$importfile = $this->getDummyImportfile(); |
589
|
|
|
|
590
|
|
|
$this->fileExtractorMock->expects(self::any()) |
591
|
|
|
->method('extract') |
592
|
|
|
->willReturn('readable.extracted'); |
593
|
|
|
|
594
|
|
|
self::$freadStack = [ |
595
|
|
|
'<tw-storydata ', |
596
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
597
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
598
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="ID:someTwineId1" position="104,30">lorem ipsum', |
599
|
|
|
'lorem ipsum [[Linkdata->someNodeName2]]</tw-passagedata>', |
600
|
|
|
'<tw-passagedata pid="2" name="someNodeName2" tags="ID:someTwineId2" position="104,30">lorem ipsum', |
601
|
|
|
'lorem ipsum</tw-passagedata>', |
602
|
|
|
'</tw-storydata>', |
603
|
|
|
]; |
604
|
|
|
|
605
|
|
|
$textnode1 = new Textnode(); |
606
|
|
|
$textnode1->setText('lorem ipsum [[Linkdata->someNodeName2]]'); |
607
|
|
|
$textnode1->setId('someId0'); |
608
|
|
|
|
609
|
|
|
$textnode2 = new Textnode(); |
610
|
|
|
$textnode2->setId('someId1'); |
611
|
|
|
|
612
|
|
|
$this->hitchParserMock->expects(self::once()) |
613
|
|
|
->method('parseSingleArrowRight') |
614
|
|
|
->with('Linkdata->someNodeName2') |
|
|
|
|
615
|
|
|
->willReturn( |
616
|
|
|
[ |
617
|
|
|
'description' => 'some description', |
618
|
|
|
'textnodeId' => 'someTextnodeId', |
619
|
|
|
'status' => Textnode::HITCH_STATUS_ACTIVE, |
620
|
|
|
] |
621
|
|
|
); |
622
|
|
|
|
623
|
|
|
$this->textnodeRepository->expects($this->any()) |
624
|
|
|
->method('find') |
625
|
|
|
->will($this->returnValue($textnode1)); |
626
|
|
|
|
627
|
|
|
$this->textnodeRepository->expects($this->any()) |
628
|
|
|
->method('save') |
629
|
|
|
->willReturnCallback(function ($textnode) { |
630
|
|
|
static $counter = 0; |
631
|
|
|
$textnode->setId('someTextnode'.$counter++); |
632
|
|
|
}); |
633
|
|
|
|
634
|
|
|
$returnValue = $this->importTwine->run($importfile); |
635
|
|
|
|
636
|
|
|
$this->assertTrue($returnValue); |
637
|
|
|
} |
638
|
|
|
|
639
|
|
|
/** |
640
|
|
|
* tests run() with setting of metadata |
641
|
|
|
*/ |
642
|
|
|
public function testRunWithMetadataSetting() |
643
|
|
|
{ |
644
|
|
|
$importfile = $this->getDummyImportfile(); |
645
|
|
|
|
646
|
|
|
$this->fileExtractorMock->expects(self::any()) |
647
|
|
|
->method('extract') |
648
|
|
|
->willReturn('readable.extracted'); |
649
|
|
|
|
650
|
|
|
self::$freadStack = [ |
651
|
|
|
'<tw-storydata ', |
652
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
653
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
654
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="ID:someTwineId1" position="104,30">lorem ipsum', |
655
|
|
|
'lorem ipsum [[Linkdata->someNodeName2]]</tw-passagedata>', |
656
|
|
|
'<tw-passagedata pid="2" name="someNodeName2" tags="ID:someTwineId2" position="104,30">lorem ipsum', |
657
|
|
|
'lorem ipsum [[metakey>:<metavalue]]</tw-passagedata>', |
658
|
|
|
'</tw-storydata>', |
659
|
|
|
]; |
660
|
|
|
|
661
|
|
|
$textnode1 = new Textnode(); |
662
|
|
|
$textnode1->setText('lorem ipsum [[metakey>:<metavalue]]'); |
663
|
|
|
$textnode1->setId('someId0'); |
664
|
|
|
|
665
|
|
|
$this->textnodeRepository->expects($this->any()) |
666
|
|
|
->method('find') |
667
|
|
|
->will($this->returnValue($textnode1)); |
668
|
|
|
|
669
|
|
|
$this->textnodeRepository->expects($this->any()) |
670
|
|
|
->method('findByTwineId') |
671
|
|
|
->will($this->returnValue($textnode1)); |
672
|
|
|
|
673
|
|
|
$returnValue = $this->importTwine->run($importfile); |
674
|
|
|
self::assertTrue($returnValue); |
675
|
|
|
$metadata = $textnode1->getMetadata(); |
676
|
|
|
self::assertInternalType('array', $metadata); |
677
|
|
|
self::assertArrayHasKey('metakey', $metadata); |
678
|
|
|
self::assertEquals('metavalue', $metadata['metakey']); |
679
|
|
|
} |
680
|
|
|
|
681
|
|
|
/** |
682
|
|
|
* @expectedException \Exception |
683
|
|
|
* @expectedExceptionMessageRegExp /invalid element.*>:</ |
684
|
|
|
*/ |
685
|
|
View Code Duplication |
public function testRunWithMetadataSettingForInvalidFormat() |
|
|
|
|
686
|
|
|
{ |
687
|
|
|
$importfile = $this->getDummyImportfile(); |
688
|
|
|
|
689
|
|
|
$this->fileExtractorMock->expects(self::any()) |
690
|
|
|
->method('extract') |
691
|
|
|
->willReturn('readable.extracted'); |
692
|
|
|
|
693
|
|
|
self::$freadStack = [ |
694
|
|
|
'<tw-storydata ', |
695
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
696
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
697
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="ID:someTwineId1" position="104,30">lorem ipsum', |
698
|
|
|
'lorem ipsum [[Linkdata->someNodeName2]]</tw-passagedata>', |
699
|
|
|
'<tw-passagedata pid="2" name="someNodeName2" tags="ID:someTwineId2" position="104,30">lorem ipsum', |
700
|
|
|
'lorem ipsum [[>:<metavalue]]</tw-passagedata>', |
701
|
|
|
'</tw-storydata>', |
702
|
|
|
]; |
703
|
|
|
|
704
|
|
|
$textnode1 = new Textnode(); |
705
|
|
|
$textnode1->setText('lorem ipsum [[>:<metavalue]]'); |
706
|
|
|
$textnode1->setId('someId0'); |
707
|
|
|
|
708
|
|
|
$this->textnodeRepository->expects($this->any()) |
709
|
|
|
->method('find') |
710
|
|
|
->will($this->returnValue($textnode1)); |
711
|
|
|
|
712
|
|
|
$this->textnodeRepository->expects($this->any()) |
713
|
|
|
->method('findByTwineId') |
714
|
|
|
->will($this->returnValue($textnode1)); |
715
|
|
|
|
716
|
|
|
$this->importTwine->run($importfile); |
717
|
|
|
} |
718
|
|
|
|
719
|
|
|
/** |
720
|
|
|
* @expectedException \Exception |
721
|
|
|
* @expectedExceptionMessageRegExp /contains the metadata field/ |
722
|
|
|
*/ |
723
|
|
View Code Duplication |
public function testRunWithMetadataSettingForAnAlreadyExistingMetadataKey() |
|
|
|
|
724
|
|
|
{ |
725
|
|
|
$importfile = $this->getDummyImportfile(); |
726
|
|
|
|
727
|
|
|
$this->fileExtractorMock->expects(self::any()) |
728
|
|
|
->method('extract') |
729
|
|
|
->willReturn('readable.extracted'); |
730
|
|
|
|
731
|
|
|
self::$freadStack = [ |
732
|
|
|
'<tw-storydata ', |
733
|
|
|
'<tw-storydata name="someStoryName" startnode="1" creator="Twine" creator-version="2.0.8" ifid="8E30D51C-4980-4161-B57F-B11C752E879A" format="Harlowe" options=""><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>'."\n", |
734
|
|
|
'<script role="script" id="twine-user-script" type="text/twine-javascript"></script>'."\n", |
735
|
|
|
'<tw-passagedata pid="1" name="someNodeName1" tags="ID:someTwineId1" position="104,30">lorem ipsum', |
736
|
|
|
'lorem ipsum [[Linkdata->someNodeName2]]</tw-passagedata>', |
737
|
|
|
'<tw-passagedata pid="2" name="someNodeName2" tags="ID:someTwineId2" position="104,30">lorem ipsum', |
738
|
|
|
'lorem ipsum [[Autor>:<metavalue]]</tw-passagedata>', |
739
|
|
|
'</tw-storydata>', |
740
|
|
|
]; |
741
|
|
|
|
742
|
|
|
$textnode1 = new Textnode(); |
743
|
|
|
$textnode1->setId('someId0'); |
744
|
|
|
$textnode1->setMetadata(['metakey' => 'someValue']); |
745
|
|
|
|
746
|
|
|
$this->textnodeRepository->expects($this->any()) |
747
|
|
|
->method('find') |
748
|
|
|
->will($this->returnValue($textnode1)); |
749
|
|
|
|
750
|
|
|
$this->textnodeRepository->expects($this->any()) |
751
|
|
|
->method('findByTwineId') |
752
|
|
|
->will($this->returnValue($textnode1)); |
753
|
|
|
|
754
|
|
|
$this->importTwine->run($importfile); |
755
|
|
|
} |
756
|
|
|
|
757
|
|
|
private function getDummyImportfile(array $data = []) |
758
|
|
|
{ |
759
|
|
|
$default = [ |
760
|
|
|
'filename' => 'somefilename_readable', |
761
|
|
|
'licenseeId' => 'somelicenseeId', |
762
|
|
|
'author' => 'someAuthor', |
763
|
|
|
'publisher' => 'somePublisher', |
764
|
|
|
'id' => 'someImportFileId', |
765
|
|
|
]; |
766
|
|
|
|
767
|
|
|
$importfileData = array_merge($default, $data); |
768
|
|
|
|
769
|
|
|
$importfile = new Importfile(); |
770
|
|
|
if (null !== $importfileData['filename']) { |
771
|
|
|
$importfile->setFilename($importfileData['filename']); |
772
|
|
|
} |
773
|
|
|
if (null !== $importfileData['licenseeId']) { |
774
|
|
|
$importfile->setLicenseeId($importfileData['licenseeId']); |
775
|
|
|
} |
776
|
|
|
if (null !== $importfileData['author']) { |
777
|
|
|
$importfile->setAuthor($importfileData['author']); |
778
|
|
|
} |
779
|
|
|
if (null !== $importfileData['publisher']) { |
780
|
|
|
$importfile->setPublisher($importfileData['publisher']); |
781
|
|
|
} |
782
|
|
|
if (null !== $importfileData['id']) { |
783
|
|
|
$importfile->setId($importfileData['id']); |
784
|
|
|
} |
785
|
|
|
|
786
|
|
|
return $importfile; |
787
|
|
|
} |
788
|
|
|
|
789
|
|
|
/** |
790
|
|
|
* @return \PHPUnit_Framework_MockObject_MockObject|TextNodeRepository |
791
|
|
|
*/ |
792
|
|
|
private function getTextnodeRepositoryMock() |
793
|
|
|
{ |
794
|
|
|
return $this->getMockBuilder(TextNodeRepository::class)->disableOriginalConstructor()->setMethods(['createQueryBuilder', 'field', 'equals', 'getQuery', 'save', 'find', 'findByTwineId', 'disableOrphanedNodes', 'setHyphenatedText'])->getMock(); |
795
|
|
|
} |
796
|
|
|
|
797
|
|
|
private function getDmMock() |
798
|
|
|
{ |
799
|
|
|
return $this->getMockBuilder('dmMock')->setMethods(['flush', 'persist', 'find'])->getMock(); |
800
|
|
|
} |
801
|
|
|
|
802
|
|
|
/** |
803
|
|
|
* @return \PHPUnit_Framework_MockObject_MockObject|HitchParser |
804
|
|
|
*/ |
805
|
|
|
private function createHitchParserMock(): HitchParser |
806
|
|
|
{ |
807
|
|
|
return $this->createMock(HitchParser::class); |
|
|
|
|
808
|
|
|
} |
809
|
|
|
|
810
|
|
|
/** |
811
|
|
|
* @return \PHPUnit_Framework_MockObject_MockObject|FileExtractor |
812
|
|
|
*/ |
813
|
|
|
private function createFileExtractorMock(): FileExtractor |
814
|
|
|
{ |
815
|
|
|
return $this->createMock(FileExtractor::class); |
|
|
|
|
816
|
|
|
} |
817
|
|
|
} |
818
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.