]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - tests/NetscapeBookmarkUtils/BookmarkImportTest.php
Move database read/write to FileUtils class + additional unit tests
[github/shaarli/Shaarli.git] / tests / NetscapeBookmarkUtils / BookmarkImportTest.php
CommitLineData
a973afea
V
1<?php
2
3require_once 'application/NetscapeBookmarkUtils.php';
4
87e9631e 5use Shaarli\Config\ConfigManager;
a973afea
V
6
7/**
8 * Utility function to load a file's metadata in a $_FILES-like array
9 *
10 * @param string $filename Basename of the file
11 *
12 * @return array A $_FILES-like array
13 */
14function file2array($filename)
15{
16 return array(
17 'filetoupload' => array(
18 'name' => $filename,
19 'tmp_name' => __DIR__ . '/input/' . $filename,
20 'size' => filesize(__DIR__ . '/input/' . $filename)
21 )
22 );
23}
24
25
26/**
27 * Netscape bookmark import
28 */
29class BookmarkImportTest extends PHPUnit_Framework_TestCase
30{
31 /**
32 * @var string datastore to test write operations
33 */
34 protected static $testDatastore = 'sandbox/datastore.php';
35
36 /**
37 * @var LinkDB private LinkDB instance
38 */
39 protected $linkDb = null;
40
41 /**
42 * @var string Dummy page cache
43 */
44 protected $pagecache = 'tests';
45
48417aed
A
46 /**
47 * @var ConfigManager instance.
48 */
49 protected $conf;
50
c3dfd899
A
51 /**
52 * @var string Save the current timezone.
53 */
54 protected static $defaultTimeZone;
55
56 public static function setUpBeforeClass()
57 {
58 self::$defaultTimeZone = date_default_timezone_get();
59 // Timezone without DST for test consistency
60 date_default_timezone_set('Africa/Nairobi');
61 }
62
a973afea
V
63 /**
64 * Resets test data before each test
65 */
66 protected function setUp()
67 {
68 if (file_exists(self::$testDatastore)) {
69 unlink(self::$testDatastore);
70 }
71 // start with an empty datastore
72 file_put_contents(self::$testDatastore, '<?php /* S7QysKquBQA= */ ?>');
73 $this->linkDb = new LinkDB(self::$testDatastore, true, false);
48417aed
A
74 $this->conf = new ConfigManager('tests/utils/config/configJson');
75 $this->conf->set('resource.page_cache', $this->pagecache);
a973afea
V
76 }
77
c3dfd899
A
78 public static function tearDownAfterClass()
79 {
80 date_default_timezone_set(self::$defaultTimeZone);
81 }
82
a973afea
V
83 /**
84 * Attempt to import bookmarks from an empty file
85 */
86 public function testImportEmptyData()
87 {
88 $files = file2array('empty.htm');
89 $this->assertEquals(
90 'File empty.htm (0 bytes) has an unknown file format.'
91 .' Nothing was imported.',
48417aed 92 NetscapeBookmarkUtils::import(NULL, $files, NULL, $this->conf)
a973afea
V
93 );
94 $this->assertEquals(0, count($this->linkDb));
95 }
96
97 /**
98 * Attempt to import bookmarks from a file with no Doctype
99 */
100 public function testImportNoDoctype()
101 {
102 $files = file2array('no_doctype.htm');
103 $this->assertEquals(
104 'File no_doctype.htm (350 bytes) has an unknown file format. Nothing was imported.',
48417aed 105 NetscapeBookmarkUtils::import(NULL, $files, NULL, $this->conf)
a973afea
V
106 );
107 $this->assertEquals(0, count($this->linkDb));
108 }
109
f4ad7bde
V
110 /**
111 * Ensure IE dumps are supported
112 */
113 public function testImportInternetExplorerEncoding()
114 {
115 $files = file2array('internet_explorer_encoding.htm');
116 $this->assertEquals(
117 'File internet_explorer_encoding.htm (356 bytes) was successfully processed:'
118 .' 1 links imported, 0 links overwritten, 0 links skipped.',
48417aed 119 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
f4ad7bde
V
120 );
121 $this->assertEquals(1, count($this->linkDb));
122 $this->assertEquals(0, count_private($this->linkDb));
123
124 $this->assertEquals(
125 array(
c3dfd899 126 'id' => 0,
d592daea 127 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160618_203944'),
f4ad7bde
V
128 'title' => 'Hg Init a Mercurial tutorial by Joel Spolsky',
129 'url' => 'http://hginit.com/',
130 'description' => '',
131 'private' => 0,
c3dfd899
A
132 'tags' => '',
133 'shorturl' => 'La37cg',
f4ad7bde
V
134 ),
135 $this->linkDb->getLinkFromUrl('http://hginit.com/')
136 );
137 }
138
a973afea
V
139 /**
140 * Import bookmarks nested in a folder hierarchy
141 */
142 public function testImportNested()
143 {
144 $files = file2array('netscape_nested.htm');
145 $this->assertEquals(
146 'File netscape_nested.htm (1337 bytes) was successfully processed:'
147 .' 8 links imported, 0 links overwritten, 0 links skipped.',
48417aed 148 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
a973afea
V
149 );
150 $this->assertEquals(8, count($this->linkDb));
151 $this->assertEquals(2, count_private($this->linkDb));
152
153 $this->assertEquals(
154 array(
c3dfd899 155 'id' => 0,
d592daea 156 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235541'),
a973afea
V
157 'title' => 'Nested 1',
158 'url' => 'http://nest.ed/1',
159 'description' => '',
160 'private' => 0,
c3dfd899
A
161 'tags' => 'tag1 tag2',
162 'shorturl' => 'KyDNKA',
a973afea
V
163 ),
164 $this->linkDb->getLinkFromUrl('http://nest.ed/1')
165 );
166 $this->assertEquals(
167 array(
c3dfd899 168 'id' => 1,
d592daea 169 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235542'),
a973afea
V
170 'title' => 'Nested 1-1',
171 'url' => 'http://nest.ed/1-1',
172 'description' => '',
173 'private' => 0,
c3dfd899
A
174 'tags' => 'folder1 tag1 tag2',
175 'shorturl' => 'T2LnXg',
a973afea
V
176 ),
177 $this->linkDb->getLinkFromUrl('http://nest.ed/1-1')
178 );
179 $this->assertEquals(
180 array(
c3dfd899 181 'id' => 2,
d592daea 182 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235547'),
a973afea
V
183 'title' => 'Nested 1-2',
184 'url' => 'http://nest.ed/1-2',
185 'description' => '',
186 'private' => 0,
c3dfd899
A
187 'tags' => 'folder1 tag3 tag4',
188 'shorturl' => '46SZxA',
a973afea
V
189 ),
190 $this->linkDb->getLinkFromUrl('http://nest.ed/1-2')
191 );
192 $this->assertEquals(
193 array(
c3dfd899 194 'id' => 3,
d592daea 195 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160202_202222'),
a973afea
V
196 'title' => 'Nested 2-1',
197 'url' => 'http://nest.ed/2-1',
198 'description' => 'First link of the second section',
199 'private' => 1,
c3dfd899
A
200 'tags' => 'folder2',
201 'shorturl' => '4UHOSw',
a973afea
V
202 ),
203 $this->linkDb->getLinkFromUrl('http://nest.ed/2-1')
204 );
205 $this->assertEquals(
206 array(
c3dfd899 207 'id' => 4,
d592daea 208 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160119_230227'),
a973afea
V
209 'title' => 'Nested 2-2',
210 'url' => 'http://nest.ed/2-2',
211 'description' => 'Second link of the second section',
212 'private' => 1,
c3dfd899
A
213 'tags' => 'folder2',
214 'shorturl' => 'yfzwbw',
a973afea
V
215 ),
216 $this->linkDb->getLinkFromUrl('http://nest.ed/2-2')
217 );
218 $this->assertEquals(
219 array(
c3dfd899 220 'id' => 5,
d592daea 221 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160202_202222'),
a973afea
V
222 'title' => 'Nested 3-1',
223 'url' => 'http://nest.ed/3-1',
224 'description' => '',
225 'private' => 0,
c3dfd899
A
226 'tags' => 'folder3 folder3-1 tag3',
227 'shorturl' => 'UwxIUQ',
a973afea
V
228 ),
229 $this->linkDb->getLinkFromUrl('http://nest.ed/3-1')
230 );
231 $this->assertEquals(
232 array(
c3dfd899 233 'id' => 6,
d592daea 234 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160119_230227'),
a973afea
V
235 'title' => 'Nested 3-2',
236 'url' => 'http://nest.ed/3-2',
237 'description' => '',
238 'private' => 0,
c3dfd899
A
239 'tags' => 'folder3 folder3-1',
240 'shorturl' => 'p8dyZg',
a973afea
V
241 ),
242 $this->linkDb->getLinkFromUrl('http://nest.ed/3-2')
243 );
244 $this->assertEquals(
245 array(
c3dfd899 246 'id' => 7,
d592daea 247 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160229_111541'),
a973afea
V
248 'title' => 'Nested 2',
249 'url' => 'http://nest.ed/2',
250 'description' => '',
251 'private' => 0,
c3dfd899
A
252 'tags' => 'tag4',
253 'shorturl' => 'Gt3Uug',
a973afea
V
254 ),
255 $this->linkDb->getLinkFromUrl('http://nest.ed/2')
256 );
257 }
258
259 /**
260 * Import bookmarks with the default privacy setting (reuse from file)
261 *
262 * The $_POST array is not set.
263 */
264 public function testImportDefaultPrivacyNoPost()
265 {
266 $files = file2array('netscape_basic.htm');
267 $this->assertEquals(
268 'File netscape_basic.htm (482 bytes) was successfully processed:'
269 .' 2 links imported, 0 links overwritten, 0 links skipped.',
48417aed 270 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
a973afea 271 );
c3dfd899 272
a973afea
V
273 $this->assertEquals(2, count($this->linkDb));
274 $this->assertEquals(1, count_private($this->linkDb));
275
276 $this->assertEquals(
277 array(
c3dfd899
A
278 'id' => 0,
279 // Old link - UTC+4 (note that TZ in the import file is ignored).
d592daea 280 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20001010_135536'),
a973afea
V
281 'title' => 'Secret stuff',
282 'url' => 'https://private.tld',
283 'description' => "Super-secret stuff you're not supposed to know about",
284 'private' => 1,
c3dfd899
A
285 'tags' => 'private secret',
286 'shorturl' => 'EokDtA',
a973afea
V
287 ),
288 $this->linkDb->getLinkFromUrl('https://private.tld')
289 );
290 $this->assertEquals(
291 array(
c3dfd899 292 'id' => 1,
d592daea 293 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235548'),
a973afea
V
294 'title' => 'Public stuff',
295 'url' => 'http://public.tld',
296 'description' => '',
297 'private' => 0,
c3dfd899
A
298 'tags' => 'public hello world',
299 'shorturl' => 'Er9ddA',
a973afea
V
300 ),
301 $this->linkDb->getLinkFromUrl('http://public.tld')
302 );
303 }
304
305 /**
306 * Import bookmarks with the default privacy setting (reuse from file)
307 */
308 public function testImportKeepPrivacy()
309 {
310 $post = array('privacy' => 'default');
311 $files = file2array('netscape_basic.htm');
312 $this->assertEquals(
313 'File netscape_basic.htm (482 bytes) was successfully processed:'
314 .' 2 links imported, 0 links overwritten, 0 links skipped.',
48417aed 315 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
316 );
317 $this->assertEquals(2, count($this->linkDb));
318 $this->assertEquals(1, count_private($this->linkDb));
319
320 $this->assertEquals(
321 array(
c3dfd899
A
322 'id' => 0,
323 // Note that TZ in the import file is ignored.
d592daea 324 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20001010_135536'),
a973afea
V
325 'title' => 'Secret stuff',
326 'url' => 'https://private.tld',
327 'description' => "Super-secret stuff you're not supposed to know about",
328 'private' => 1,
c3dfd899
A
329 'tags' => 'private secret',
330 'shorturl' => 'EokDtA',
a973afea
V
331 ),
332 $this->linkDb->getLinkFromUrl('https://private.tld')
333 );
334 $this->assertEquals(
335 array(
c3dfd899 336 'id' => 1,
d592daea 337 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235548'),
a973afea
V
338 'title' => 'Public stuff',
339 'url' => 'http://public.tld',
340 'description' => '',
341 'private' => 0,
c3dfd899
A
342 'tags' => 'public hello world',
343 'shorturl' => 'Er9ddA',
a973afea
V
344 ),
345 $this->linkDb->getLinkFromUrl('http://public.tld')
346 );
347 }
348
349 /**
350 * Import links as public
351 */
352 public function testImportAsPublic()
353 {
354 $post = array('privacy' => 'public');
355 $files = file2array('netscape_basic.htm');
356 $this->assertEquals(
357 'File netscape_basic.htm (482 bytes) was successfully processed:'
358 .' 2 links imported, 0 links overwritten, 0 links skipped.',
48417aed 359 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
360 );
361 $this->assertEquals(2, count($this->linkDb));
362 $this->assertEquals(0, count_private($this->linkDb));
363 $this->assertEquals(
364 0,
c3dfd899 365 $this->linkDb[0]['private']
a973afea
V
366 );
367 $this->assertEquals(
368 0,
c3dfd899 369 $this->linkDb[1]['private']
a973afea
V
370 );
371 }
372
373 /**
374 * Import links as private
375 */
376 public function testImportAsPrivate()
377 {
378 $post = array('privacy' => 'private');
379 $files = file2array('netscape_basic.htm');
380 $this->assertEquals(
381 'File netscape_basic.htm (482 bytes) was successfully processed:'
382 .' 2 links imported, 0 links overwritten, 0 links skipped.',
48417aed 383 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
384 );
385 $this->assertEquals(2, count($this->linkDb));
386 $this->assertEquals(2, count_private($this->linkDb));
387 $this->assertEquals(
388 1,
c3dfd899 389 $this->linkDb['0']['private']
a973afea
V
390 );
391 $this->assertEquals(
392 1,
c3dfd899 393 $this->linkDb['1']['private']
a973afea
V
394 );
395 }
396
397 /**
398 * Overwrite private links so they become public
399 */
400 public function testOverwriteAsPublic()
401 {
402 $files = file2array('netscape_basic.htm');
403
404 // import links as private
405 $post = array('privacy' => 'private');
406 $this->assertEquals(
407 'File netscape_basic.htm (482 bytes) was successfully processed:'
408 .' 2 links imported, 0 links overwritten, 0 links skipped.',
48417aed 409 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
410 );
411 $this->assertEquals(2, count($this->linkDb));
412 $this->assertEquals(2, count_private($this->linkDb));
413 $this->assertEquals(
414 1,
c3dfd899 415 $this->linkDb[0]['private']
a973afea
V
416 );
417 $this->assertEquals(
418 1,
c3dfd899 419 $this->linkDb[1]['private']
a973afea 420 );
a973afea
V
421 // re-import as public, enable overwriting
422 $post = array(
423 'privacy' => 'public',
424 'overwrite' => 'true'
425 );
426 $this->assertEquals(
427 'File netscape_basic.htm (482 bytes) was successfully processed:'
428 .' 2 links imported, 2 links overwritten, 0 links skipped.',
48417aed 429 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
430 );
431 $this->assertEquals(2, count($this->linkDb));
432 $this->assertEquals(0, count_private($this->linkDb));
433 $this->assertEquals(
434 0,
c3dfd899 435 $this->linkDb[0]['private']
a973afea
V
436 );
437 $this->assertEquals(
438 0,
c3dfd899 439 $this->linkDb[1]['private']
a973afea
V
440 );
441 }
442
443 /**
444 * Overwrite public links so they become private
445 */
446 public function testOverwriteAsPrivate()
447 {
448 $files = file2array('netscape_basic.htm');
449
450 // import links as public
451 $post = array('privacy' => 'public');
452 $this->assertEquals(
453 'File netscape_basic.htm (482 bytes) was successfully processed:'
454 .' 2 links imported, 0 links overwritten, 0 links skipped.',
48417aed 455 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
456 );
457 $this->assertEquals(2, count($this->linkDb));
458 $this->assertEquals(0, count_private($this->linkDb));
459 $this->assertEquals(
460 0,
c3dfd899 461 $this->linkDb['0']['private']
a973afea
V
462 );
463 $this->assertEquals(
464 0,
c3dfd899 465 $this->linkDb['1']['private']
a973afea
V
466 );
467
468 // re-import as private, enable overwriting
469 $post = array(
470 'privacy' => 'private',
471 'overwrite' => 'true'
472 );
473 $this->assertEquals(
474 'File netscape_basic.htm (482 bytes) was successfully processed:'
475 .' 2 links imported, 2 links overwritten, 0 links skipped.',
48417aed 476 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
477 );
478 $this->assertEquals(2, count($this->linkDb));
479 $this->assertEquals(2, count_private($this->linkDb));
480 $this->assertEquals(
481 1,
c3dfd899 482 $this->linkDb['0']['private']
a973afea
V
483 );
484 $this->assertEquals(
485 1,
c3dfd899 486 $this->linkDb['1']['private']
a973afea
V
487 );
488 }
489
490 /**
491 * Attept to import the same links twice without enabling overwriting
492 */
493 public function testSkipOverwrite()
494 {
495 $post = array('privacy' => 'public');
496 $files = file2array('netscape_basic.htm');
497 $this->assertEquals(
498 'File netscape_basic.htm (482 bytes) was successfully processed:'
499 .' 2 links imported, 0 links overwritten, 0 links skipped.',
48417aed 500 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
501 );
502 $this->assertEquals(2, count($this->linkDb));
503 $this->assertEquals(0, count_private($this->linkDb));
504
505 // re-import as private, DO NOT enable overwriting
506 $post = array('privacy' => 'private');
507 $this->assertEquals(
508 'File netscape_basic.htm (482 bytes) was successfully processed:'
509 .' 0 links imported, 0 links overwritten, 2 links skipped.',
48417aed 510 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
511 );
512 $this->assertEquals(2, count($this->linkDb));
513 $this->assertEquals(0, count_private($this->linkDb));
514 }
515
516 /**
517 * Add user-specified tags to all imported bookmarks
518 */
519 public function testSetDefaultTags()
520 {
521 $post = array(
522 'privacy' => 'public',
523 'default_tags' => 'tag1,tag2 tag3'
524 );
525 $files = file2array('netscape_basic.htm');
526 $this->assertEquals(
527 'File netscape_basic.htm (482 bytes) was successfully processed:'
528 .' 2 links imported, 0 links overwritten, 0 links skipped.',
48417aed 529 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
530 );
531 $this->assertEquals(2, count($this->linkDb));
532 $this->assertEquals(0, count_private($this->linkDb));
533 $this->assertEquals(
534 'tag1 tag2 tag3 private secret',
c3dfd899 535 $this->linkDb['0']['tags']
a973afea
V
536 );
537 $this->assertEquals(
538 'tag1 tag2 tag3 public hello world',
c3dfd899 539 $this->linkDb['1']['tags']
a973afea
V
540 );
541 }
542
543 /**
544 * The user-specified tags contain characters to be escaped
545 */
546 public function testSanitizeDefaultTags()
547 {
548 $post = array(
549 'privacy' => 'public',
550 'default_tags' => 'tag1&,tag2 "tag3"'
551 );
552 $files = file2array('netscape_basic.htm');
553 $this->assertEquals(
554 'File netscape_basic.htm (482 bytes) was successfully processed:'
555 .' 2 links imported, 0 links overwritten, 0 links skipped.',
48417aed 556 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
a973afea
V
557 );
558 $this->assertEquals(2, count($this->linkDb));
559 $this->assertEquals(0, count_private($this->linkDb));
560 $this->assertEquals(
561 'tag1&amp; tag2 &quot;tag3&quot; private secret',
c3dfd899 562 $this->linkDb['0']['tags']
a973afea
V
563 );
564 $this->assertEquals(
565 'tag1&amp; tag2 &quot;tag3&quot; public hello world',
c3dfd899 566 $this->linkDb['1']['tags']
a973afea
V
567 );
568 }
569
570 /**
c3dfd899 571 * Ensure each imported bookmark has a unique id
a973afea
V
572 *
573 * See https://github.com/shaarli/Shaarli/issues/351
574 */
575 public function testImportSameDate()
576 {
577 $files = file2array('same_date.htm');
578 $this->assertEquals(
579 'File same_date.htm (453 bytes) was successfully processed:'
580 .' 3 links imported, 0 links overwritten, 0 links skipped.',
48417aed 581 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
a973afea
V
582 );
583 $this->assertEquals(3, count($this->linkDb));
584 $this->assertEquals(0, count_private($this->linkDb));
585 $this->assertEquals(
c3dfd899
A
586 0,
587 $this->linkDb[0]['id']
a973afea
V
588 );
589 $this->assertEquals(
c3dfd899
A
590 1,
591 $this->linkDb[1]['id']
a973afea
V
592 );
593 $this->assertEquals(
c3dfd899
A
594 2,
595 $this->linkDb[2]['id']
a973afea
V
596 );
597 }
598}