]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - tests/NetscapeBookmarkUtils/BookmarkImportTest.php
Link imports are now logged in `data/` folder, and can be debug using `dev.debug...
[github/shaarli/Shaarli.git] / tests / NetscapeBookmarkUtils / BookmarkImportTest.php
1 <?php
2
3 require_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 */
13 function 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 */
28 class 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
45 /**
46 * @var ConfigManager instance.
47 */
48 protected $conf;
49
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
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);
73 $this->conf = new ConfigManager('tests/utils/config/configJson');
74 $this->conf->set('resource.page_cache', $this->pagecache);
75 }
76
77 public static function tearDownAfterClass()
78 {
79 date_default_timezone_set(self::$defaultTimeZone);
80 }
81
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.',
91 NetscapeBookmarkUtils::import(NULL, $files, NULL, $this->conf)
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.',
104 NetscapeBookmarkUtils::import(NULL, $files, NULL, $this->conf)
105 );
106 $this->assertEquals(0, count($this->linkDb));
107 }
108
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.',
118 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
119 );
120 $this->assertEquals(1, count($this->linkDb));
121 $this->assertEquals(0, count_private($this->linkDb));
122
123 $this->assertEquals(
124 array(
125 'id' => 0,
126 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160618_203944'),
127 'title' => 'Hg Init a Mercurial tutorial by Joel Spolsky',
128 'url' => 'http://hginit.com/',
129 'description' => '',
130 'private' => 0,
131 'tags' => '',
132 'shorturl' => 'La37cg',
133 ),
134 $this->linkDb->getLinkFromUrl('http://hginit.com/')
135 );
136 }
137
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.',
147 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
148 );
149 $this->assertEquals(8, count($this->linkDb));
150 $this->assertEquals(2, count_private($this->linkDb));
151
152 $this->assertEquals(
153 array(
154 'id' => 0,
155 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235541'),
156 'title' => 'Nested 1',
157 'url' => 'http://nest.ed/1',
158 'description' => '',
159 'private' => 0,
160 'tags' => 'tag1 tag2',
161 'shorturl' => 'KyDNKA',
162 ),
163 $this->linkDb->getLinkFromUrl('http://nest.ed/1')
164 );
165 $this->assertEquals(
166 array(
167 'id' => 1,
168 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235542'),
169 'title' => 'Nested 1-1',
170 'url' => 'http://nest.ed/1-1',
171 'description' => '',
172 'private' => 0,
173 'tags' => 'folder1 tag1 tag2',
174 'shorturl' => 'T2LnXg',
175 ),
176 $this->linkDb->getLinkFromUrl('http://nest.ed/1-1')
177 );
178 $this->assertEquals(
179 array(
180 'id' => 2,
181 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235547'),
182 'title' => 'Nested 1-2',
183 'url' => 'http://nest.ed/1-2',
184 'description' => '',
185 'private' => 0,
186 'tags' => 'folder1 tag3 tag4',
187 'shorturl' => '46SZxA',
188 ),
189 $this->linkDb->getLinkFromUrl('http://nest.ed/1-2')
190 );
191 $this->assertEquals(
192 array(
193 'id' => 3,
194 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160202_202222'),
195 'title' => 'Nested 2-1',
196 'url' => 'http://nest.ed/2-1',
197 'description' => 'First link of the second section',
198 'private' => 1,
199 'tags' => 'folder2',
200 'shorturl' => '4UHOSw',
201 ),
202 $this->linkDb->getLinkFromUrl('http://nest.ed/2-1')
203 );
204 $this->assertEquals(
205 array(
206 'id' => 4,
207 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160119_230227'),
208 'title' => 'Nested 2-2',
209 'url' => 'http://nest.ed/2-2',
210 'description' => 'Second link of the second section',
211 'private' => 1,
212 'tags' => 'folder2',
213 'shorturl' => 'yfzwbw',
214 ),
215 $this->linkDb->getLinkFromUrl('http://nest.ed/2-2')
216 );
217 $this->assertEquals(
218 array(
219 'id' => 5,
220 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160202_202222'),
221 'title' => 'Nested 3-1',
222 'url' => 'http://nest.ed/3-1',
223 'description' => '',
224 'private' => 0,
225 'tags' => 'folder3 folder3-1 tag3',
226 'shorturl' => 'UwxIUQ',
227 ),
228 $this->linkDb->getLinkFromUrl('http://nest.ed/3-1')
229 );
230 $this->assertEquals(
231 array(
232 'id' => 6,
233 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160119_230227'),
234 'title' => 'Nested 3-2',
235 'url' => 'http://nest.ed/3-2',
236 'description' => '',
237 'private' => 0,
238 'tags' => 'folder3 folder3-1',
239 'shorturl' => 'p8dyZg',
240 ),
241 $this->linkDb->getLinkFromUrl('http://nest.ed/3-2')
242 );
243 $this->assertEquals(
244 array(
245 'id' => 7,
246 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160229_111541'),
247 'title' => 'Nested 2',
248 'url' => 'http://nest.ed/2',
249 'description' => '',
250 'private' => 0,
251 'tags' => 'tag4',
252 'shorturl' => 'Gt3Uug',
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.',
269 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
270 );
271
272 $this->assertEquals(2, count($this->linkDb));
273 $this->assertEquals(1, count_private($this->linkDb));
274
275 $this->assertEquals(
276 array(
277 'id' => 0,
278 // Old link - UTC+4 (note that TZ in the import file is ignored).
279 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20001010_135536'),
280 'title' => 'Secret stuff',
281 'url' => 'https://private.tld',
282 'description' => "Super-secret stuff you're not supposed to know about",
283 'private' => 1,
284 'tags' => 'private secret',
285 'shorturl' => 'EokDtA',
286 ),
287 $this->linkDb->getLinkFromUrl('https://private.tld')
288 );
289 $this->assertEquals(
290 array(
291 'id' => 1,
292 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235548'),
293 'title' => 'Public stuff',
294 'url' => 'http://public.tld',
295 'description' => '',
296 'private' => 0,
297 'tags' => 'public hello world',
298 'shorturl' => 'Er9ddA',
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.',
314 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
315 );
316 $this->assertEquals(2, count($this->linkDb));
317 $this->assertEquals(1, count_private($this->linkDb));
318
319 $this->assertEquals(
320 array(
321 'id' => 0,
322 // Note that TZ in the import file is ignored.
323 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20001010_135536'),
324 'title' => 'Secret stuff',
325 'url' => 'https://private.tld',
326 'description' => "Super-secret stuff you're not supposed to know about",
327 'private' => 1,
328 'tags' => 'private secret',
329 'shorturl' => 'EokDtA',
330 ),
331 $this->linkDb->getLinkFromUrl('https://private.tld')
332 );
333 $this->assertEquals(
334 array(
335 'id' => 1,
336 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235548'),
337 'title' => 'Public stuff',
338 'url' => 'http://public.tld',
339 'description' => '',
340 'private' => 0,
341 'tags' => 'public hello world',
342 'shorturl' => 'Er9ddA',
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.',
358 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
359 );
360 $this->assertEquals(2, count($this->linkDb));
361 $this->assertEquals(0, count_private($this->linkDb));
362 $this->assertEquals(
363 0,
364 $this->linkDb[0]['private']
365 );
366 $this->assertEquals(
367 0,
368 $this->linkDb[1]['private']
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.',
382 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
383 );
384 $this->assertEquals(2, count($this->linkDb));
385 $this->assertEquals(2, count_private($this->linkDb));
386 $this->assertEquals(
387 1,
388 $this->linkDb['0']['private']
389 );
390 $this->assertEquals(
391 1,
392 $this->linkDb['1']['private']
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.',
408 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
409 );
410 $this->assertEquals(2, count($this->linkDb));
411 $this->assertEquals(2, count_private($this->linkDb));
412 $this->assertEquals(
413 1,
414 $this->linkDb[0]['private']
415 );
416 $this->assertEquals(
417 1,
418 $this->linkDb[1]['private']
419 );
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.',
428 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
429 );
430 $this->assertEquals(2, count($this->linkDb));
431 $this->assertEquals(0, count_private($this->linkDb));
432 $this->assertEquals(
433 0,
434 $this->linkDb[0]['private']
435 );
436 $this->assertEquals(
437 0,
438 $this->linkDb[1]['private']
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.',
454 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
455 );
456 $this->assertEquals(2, count($this->linkDb));
457 $this->assertEquals(0, count_private($this->linkDb));
458 $this->assertEquals(
459 0,
460 $this->linkDb['0']['private']
461 );
462 $this->assertEquals(
463 0,
464 $this->linkDb['1']['private']
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.',
475 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
476 );
477 $this->assertEquals(2, count($this->linkDb));
478 $this->assertEquals(2, count_private($this->linkDb));
479 $this->assertEquals(
480 1,
481 $this->linkDb['0']['private']
482 );
483 $this->assertEquals(
484 1,
485 $this->linkDb['1']['private']
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.',
499 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
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.',
509 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
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.',
528 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
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',
534 $this->linkDb['0']['tags']
535 );
536 $this->assertEquals(
537 'tag1 tag2 tag3 public hello world',
538 $this->linkDb['1']['tags']
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.',
555 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf)
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',
561 $this->linkDb['0']['tags']
562 );
563 $this->assertEquals(
564 'tag1&amp; tag2 &quot;tag3&quot; public hello world',
565 $this->linkDb['1']['tags']
566 );
567 }
568
569 /**
570 * Ensure each imported bookmark has a unique id
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.',
580 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf)
581 );
582 $this->assertEquals(3, count($this->linkDb));
583 $this->assertEquals(0, count_private($this->linkDb));
584 $this->assertEquals(
585 0,
586 $this->linkDb[0]['id']
587 );
588 $this->assertEquals(
589 1,
590 $this->linkDb[1]['id']
591 );
592 $this->assertEquals(
593 2,
594 $this->linkDb[2]['id']
595 );
596 }
597 }