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