3 require_once 'application/NetscapeBookmarkUtils.php';
5 use Shaarli\Config\ConfigManager
;
8 * Utility function to load a file's metadata in a $_FILES-like array
10 * @param string $filename Basename of the file
12 * @return array A $_FILES-like array
14 function file2array($filename)
17 'filetoupload' => array(
19 'tmp_name' => __DIR__
. '/input/' . $filename,
20 'size' => filesize(__DIR__
. '/input/' . $filename)
27 * Netscape bookmark import
29 class BookmarkImportTest
extends PHPUnit_Framework_TestCase
32 * @var string datastore to test write operations
34 protected static $testDatastore = 'sandbox/datastore.php';
37 * @var LinkDB private LinkDB instance
39 protected $linkDb = null;
42 * @var string Dummy page cache
44 protected $pagecache = 'tests';
47 * @var ConfigManager instance.
52 * @var string Save the current timezone.
54 protected static $defaultTimeZone;
56 public static function setUpBeforeClass()
58 self
::$defaultTimeZone = date_default_timezone_get();
59 // Timezone without DST for test consistency
60 date_default_timezone_set('Africa/Nairobi');
64 * Resets test data before each test
66 protected function setUp()
68 if (file_exists(self
::$testDatastore)) {
69 unlink(self
::$testDatastore);
71 // start with an empty datastore
72 file_put_contents(self
::$testDatastore, '<?php /* S7QysKquBQA= */ ?>');
73 $this->linkDb
= new LinkDB(self
::$testDatastore, true, false);
74 $this->conf
= new ConfigManager('tests/utils/config/configJson');
75 $this->conf
->set('resource.page_cache', $this->pagecache
);
78 public static function tearDownAfterClass()
80 date_default_timezone_set(self
::$defaultTimeZone);
84 * Attempt to import bookmarks from an empty file
86 public function testImportEmptyData()
88 $files = file2array('empty.htm');
90 'File empty.htm (0 bytes) has an unknown file format.'
91 .' Nothing was imported.',
92 NetscapeBookmarkUtils
::import(NULL, $files, NULL, $this->conf
)
94 $this->assertEquals(0, count($this->linkDb
));
98 * Attempt to import bookmarks from a file with no Doctype
100 public function testImportNoDoctype()
102 $files = file2array('no_doctype.htm');
104 'File no_doctype.htm (350 bytes) has an unknown file format. Nothing was imported.',
105 NetscapeBookmarkUtils
::import(NULL, $files, NULL, $this->conf
)
107 $this->assertEquals(0, count($this->linkDb
));
111 * Ensure IE dumps are supported
113 public function testImportInternetExplorerEncoding()
115 $files = file2array('internet_explorer_encoding.htm');
117 'File internet_explorer_encoding.htm (356 bytes) was successfully processed:'
118 .' 1 links imported, 0 links overwritten, 0 links skipped.',
119 NetscapeBookmarkUtils
::import(array(), $files, $this->linkDb
, $this->conf
)
121 $this->assertEquals(1, count($this->linkDb
));
122 $this->assertEquals(0, count_private($this->linkDb
));
127 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160618_203944'),
128 'title' => 'Hg Init a Mercurial tutorial by Joel Spolsky',
129 'url' => 'http://hginit.com/',
133 'shorturl' => 'La37cg',
135 $this->linkDb
->getLinkFromUrl('http://hginit.com/')
140 * Import bookmarks nested in a folder hierarchy
142 public function testImportNested()
144 $files = file2array('netscape_nested.htm');
146 'File netscape_nested.htm (1337 bytes) was successfully processed:'
147 .' 8 links imported, 0 links overwritten, 0 links skipped.',
148 NetscapeBookmarkUtils
::import(array(), $files, $this->linkDb
, $this->conf
)
150 $this->assertEquals(8, count($this->linkDb
));
151 $this->assertEquals(2, count_private($this->linkDb
));
156 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160225_235541'),
157 'title' => 'Nested 1',
158 'url' => 'http://nest.ed/1',
161 'tags' => 'tag1 tag2',
162 'shorturl' => 'KyDNKA',
164 $this->linkDb
->getLinkFromUrl('http://nest.ed/1')
169 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160225_235542'),
170 'title' => 'Nested 1-1',
171 'url' => 'http://nest.ed/1-1',
174 'tags' => 'folder1 tag1 tag2',
175 'shorturl' => 'T2LnXg',
177 $this->linkDb
->getLinkFromUrl('http://nest.ed/1-1')
182 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160225_235547'),
183 'title' => 'Nested 1-2',
184 'url' => 'http://nest.ed/1-2',
187 'tags' => 'folder1 tag3 tag4',
188 'shorturl' => '46SZxA',
190 $this->linkDb
->getLinkFromUrl('http://nest.ed/1-2')
195 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160202_202222'),
196 'title' => 'Nested 2-1',
197 'url' => 'http://nest.ed/2-1',
198 'description' => 'First link of the second section',
201 'shorturl' => '4UHOSw',
203 $this->linkDb
->getLinkFromUrl('http://nest.ed/2-1')
208 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160119_230227'),
209 'title' => 'Nested 2-2',
210 'url' => 'http://nest.ed/2-2',
211 'description' => 'Second link of the second section',
214 'shorturl' => 'yfzwbw',
216 $this->linkDb
->getLinkFromUrl('http://nest.ed/2-2')
221 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160202_202222'),
222 'title' => 'Nested 3-1',
223 'url' => 'http://nest.ed/3-1',
226 'tags' => 'folder3 folder3-1 tag3',
227 'shorturl' => 'UwxIUQ',
229 $this->linkDb
->getLinkFromUrl('http://nest.ed/3-1')
234 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160119_230227'),
235 'title' => 'Nested 3-2',
236 'url' => 'http://nest.ed/3-2',
239 'tags' => 'folder3 folder3-1',
240 'shorturl' => 'p8dyZg',
242 $this->linkDb
->getLinkFromUrl('http://nest.ed/3-2')
247 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160229_111541'),
248 'title' => 'Nested 2',
249 'url' => 'http://nest.ed/2',
253 'shorturl' => 'Gt3Uug',
255 $this->linkDb
->getLinkFromUrl('http://nest.ed/2')
260 * Import bookmarks with the default privacy setting (reuse from file)
262 * The $_POST array is not set.
264 public function testImportDefaultPrivacyNoPost()
266 $files = file2array('netscape_basic.htm');
268 'File netscape_basic.htm (482 bytes) was successfully processed:'
269 .' 2 links imported, 0 links overwritten, 0 links skipped.',
270 NetscapeBookmarkUtils
::import(array(), $files, $this->linkDb
, $this->conf
)
273 $this->assertEquals(2, count($this->linkDb
));
274 $this->assertEquals(1, count_private($this->linkDb
));
279 // Old link - UTC+4 (note that TZ in the import file is ignored).
280 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20001010_135536'),
281 'title' => 'Secret stuff',
282 'url' => 'https://private.tld',
283 'description' => "Super-secret stuff you're not supposed to know about",
285 'tags' => 'private secret',
286 'shorturl' => 'EokDtA',
288 $this->linkDb
->getLinkFromUrl('https://private.tld')
293 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160225_235548'),
294 'title' => 'Public stuff',
295 'url' => 'http://public.tld',
298 'tags' => 'public hello world',
299 'shorturl' => 'Er9ddA',
301 $this->linkDb
->getLinkFromUrl('http://public.tld')
306 * Import bookmarks with the default privacy setting (reuse from file)
308 public function testImportKeepPrivacy()
310 $post = array('privacy' => 'default');
311 $files = file2array('netscape_basic.htm');
313 'File netscape_basic.htm (482 bytes) was successfully processed:'
314 .' 2 links imported, 0 links overwritten, 0 links skipped.',
315 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
317 $this->assertEquals(2, count($this->linkDb
));
318 $this->assertEquals(1, count_private($this->linkDb
));
323 // Note that TZ in the import file is ignored.
324 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20001010_135536'),
325 'title' => 'Secret stuff',
326 'url' => 'https://private.tld',
327 'description' => "Super-secret stuff you're not supposed to know about",
329 'tags' => 'private secret',
330 'shorturl' => 'EokDtA',
332 $this->linkDb
->getLinkFromUrl('https://private.tld')
337 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160225_235548'),
338 'title' => 'Public stuff',
339 'url' => 'http://public.tld',
342 'tags' => 'public hello world',
343 'shorturl' => 'Er9ddA',
345 $this->linkDb
->getLinkFromUrl('http://public.tld')
350 * Import links as public
352 public function testImportAsPublic()
354 $post = array('privacy' => 'public');
355 $files = file2array('netscape_basic.htm');
357 'File netscape_basic.htm (482 bytes) was successfully processed:'
358 .' 2 links imported, 0 links overwritten, 0 links skipped.',
359 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
361 $this->assertEquals(2, count($this->linkDb
));
362 $this->assertEquals(0, count_private($this->linkDb
));
365 $this->linkDb
[0]['private']
369 $this->linkDb
[1]['private']
374 * Import links as private
376 public function testImportAsPrivate()
378 $post = array('privacy' => 'private');
379 $files = file2array('netscape_basic.htm');
381 'File netscape_basic.htm (482 bytes) was successfully processed:'
382 .' 2 links imported, 0 links overwritten, 0 links skipped.',
383 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
385 $this->assertEquals(2, count($this->linkDb
));
386 $this->assertEquals(2, count_private($this->linkDb
));
389 $this->linkDb
['0']['private']
393 $this->linkDb
['1']['private']
398 * Overwrite private links so they become public
400 public function testOverwriteAsPublic()
402 $files = file2array('netscape_basic.htm');
404 // import links as private
405 $post = array('privacy' => 'private');
407 'File netscape_basic.htm (482 bytes) was successfully processed:'
408 .' 2 links imported, 0 links overwritten, 0 links skipped.',
409 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
411 $this->assertEquals(2, count($this->linkDb
));
412 $this->assertEquals(2, count_private($this->linkDb
));
415 $this->linkDb
[0]['private']
419 $this->linkDb
[1]['private']
421 // re-import as public, enable overwriting
423 'privacy' => 'public',
424 'overwrite' => 'true'
427 'File netscape_basic.htm (482 bytes) was successfully processed:'
428 .' 2 links imported, 2 links overwritten, 0 links skipped.',
429 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
431 $this->assertEquals(2, count($this->linkDb
));
432 $this->assertEquals(0, count_private($this->linkDb
));
435 $this->linkDb
[0]['private']
439 $this->linkDb
[1]['private']
444 * Overwrite public links so they become private
446 public function testOverwriteAsPrivate()
448 $files = file2array('netscape_basic.htm');
450 // import links as public
451 $post = array('privacy' => 'public');
453 'File netscape_basic.htm (482 bytes) was successfully processed:'
454 .' 2 links imported, 0 links overwritten, 0 links skipped.',
455 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
457 $this->assertEquals(2, count($this->linkDb
));
458 $this->assertEquals(0, count_private($this->linkDb
));
461 $this->linkDb
['0']['private']
465 $this->linkDb
['1']['private']
468 // re-import as private, enable overwriting
470 'privacy' => 'private',
471 'overwrite' => 'true'
474 'File netscape_basic.htm (482 bytes) was successfully processed:'
475 .' 2 links imported, 2 links overwritten, 0 links skipped.',
476 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
478 $this->assertEquals(2, count($this->linkDb
));
479 $this->assertEquals(2, count_private($this->linkDb
));
482 $this->linkDb
['0']['private']
486 $this->linkDb
['1']['private']
491 * Attept to import the same links twice without enabling overwriting
493 public function testSkipOverwrite()
495 $post = array('privacy' => 'public');
496 $files = file2array('netscape_basic.htm');
498 'File netscape_basic.htm (482 bytes) was successfully processed:'
499 .' 2 links imported, 0 links overwritten, 0 links skipped.',
500 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
502 $this->assertEquals(2, count($this->linkDb
));
503 $this->assertEquals(0, count_private($this->linkDb
));
505 // re-import as private, DO NOT enable overwriting
506 $post = array('privacy' => 'private');
508 'File netscape_basic.htm (482 bytes) was successfully processed:'
509 .' 0 links imported, 0 links overwritten, 2 links skipped.',
510 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
512 $this->assertEquals(2, count($this->linkDb
));
513 $this->assertEquals(0, count_private($this->linkDb
));
517 * Add user-specified tags to all imported bookmarks
519 public function testSetDefaultTags()
522 'privacy' => 'public',
523 'default_tags' => 'tag1,tag2 tag3'
525 $files = file2array('netscape_basic.htm');
527 'File netscape_basic.htm (482 bytes) was successfully processed:'
528 .' 2 links imported, 0 links overwritten, 0 links skipped.',
529 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
531 $this->assertEquals(2, count($this->linkDb
));
532 $this->assertEquals(0, count_private($this->linkDb
));
534 'tag1 tag2 tag3 private secret',
535 $this->linkDb
['0']['tags']
538 'tag1 tag2 tag3 public hello world',
539 $this->linkDb
['1']['tags']
544 * The user-specified tags contain characters to be escaped
546 public function testSanitizeDefaultTags()
549 'privacy' => 'public',
550 'default_tags' => 'tag1&,tag2 "tag3"'
552 $files = file2array('netscape_basic.htm');
554 'File netscape_basic.htm (482 bytes) was successfully processed:'
555 .' 2 links imported, 0 links overwritten, 0 links skipped.',
556 NetscapeBookmarkUtils
::import($post, $files, $this->linkDb
, $this->conf
)
558 $this->assertEquals(2, count($this->linkDb
));
559 $this->assertEquals(0, count_private($this->linkDb
));
561 'tag1& tag2 "tag3" private secret',
562 $this->linkDb
['0']['tags']
565 'tag1& tag2 "tag3" public hello world',
566 $this->linkDb
['1']['tags']
571 * Ensure each imported bookmark has a unique id
573 * See https://github.com/shaarli/Shaarli/issues/351
575 public function testImportSameDate()
577 $files = file2array('same_date.htm');
579 'File same_date.htm (453 bytes) was successfully processed:'
580 .' 3 links imported, 0 links overwritten, 0 links skipped.',
581 NetscapeBookmarkUtils
::import(array(), $files, $this->linkDb
, $this->conf
)
583 $this->assertEquals(3, count($this->linkDb
));
584 $this->assertEquals(0, count_private($this->linkDb
));
587 $this->linkDb
[0]['id']
591 $this->linkDb
[1]['id']
595 $this->linkDb
[2]['id']