3 require_once 'application/NetscapeBookmarkUtils.php';
7 * Utility function to load a file's metadata in a $_FILES-like array
9 * @param string $filename Basename of the file
11 * @return array A $_FILES-like array
13 function file2array($filename)
16 'filetoupload' => array(
18 'tmp_name' => __DIR__
. '/input/' . $filename,
19 'size' => filesize(__DIR__
. '/input/' . $filename)
26 * Netscape bookmark import
28 class BookmarkImportTest
extends PHPUnit_Framework_TestCase
31 * @var string datastore to test write operations
33 protected static $testDatastore = 'sandbox/datastore.php';
36 * @var LinkDB private LinkDB instance
38 protected $linkDb = null;
41 * @var string Dummy page cache
43 protected $pagecache = 'tests';
46 * @var ConfigManager instance.
51 * @var string Save the current timezone.
53 protected static $defaultTimeZone;
55 public static function setUpBeforeClass()
57 self
::$defaultTimeZone = date_default_timezone_get();
58 // Timezone without DST for test consistency
59 date_default_timezone_set('Africa/Nairobi');
63 * Resets test data before each test
65 protected function setUp()
67 if (file_exists(self
::$testDatastore)) {
68 unlink(self
::$testDatastore);
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
);
77 public static function tearDownAfterClass()
79 date_default_timezone_set(self
::$defaultTimeZone);
83 * Attempt to import bookmarks from an empty file
85 public function testImportEmptyData()
87 $files = file2array('empty.htm');
89 'File empty.htm (0 bytes) has an unknown file format.'
90 .' Nothing was imported.',
91 NetscapeBookmarkUtils
::import(NULL, $files, NULL, $this->conf
)
93 $this->assertEquals(0, count($this->linkDb
));
97 * Attempt to import bookmarks from a file with no Doctype
99 public function testImportNoDoctype()
101 $files = file2array('no_doctype.htm');
103 'File no_doctype.htm (350 bytes) has an unknown file format. Nothing was imported.',
104 NetscapeBookmarkUtils
::import(NULL, $files, NULL, $this->conf
)
106 $this->assertEquals(0, count($this->linkDb
));
110 * Ensure IE dumps are supported
112 public function testImportInternetExplorerEncoding()
114 $files = file2array('internet_explorer_encoding.htm');
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
)
120 $this->assertEquals(1, count($this->linkDb
));
121 $this->assertEquals(0, count_private($this->linkDb
));
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/',
132 'shorturl' => 'La37cg',
134 $this->linkDb
->getLinkFromUrl('http://hginit.com/')
139 * Import bookmarks nested in a folder hierarchy
141 public function testImportNested()
143 $files = file2array('netscape_nested.htm');
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
)
149 $this->assertEquals(8, count($this->linkDb
));
150 $this->assertEquals(2, count_private($this->linkDb
));
155 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160225_235541'),
156 'title' => 'Nested 1',
157 'url' => 'http://nest.ed/1',
160 'tags' => 'tag1 tag2',
161 'shorturl' => 'KyDNKA',
163 $this->linkDb
->getLinkFromUrl('http://nest.ed/1')
168 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160225_235542'),
169 'title' => 'Nested 1-1',
170 'url' => 'http://nest.ed/1-1',
173 'tags' => 'folder1 tag1 tag2',
174 'shorturl' => 'T2LnXg',
176 $this->linkDb
->getLinkFromUrl('http://nest.ed/1-1')
181 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160225_235547'),
182 'title' => 'Nested 1-2',
183 'url' => 'http://nest.ed/1-2',
186 'tags' => 'folder1 tag3 tag4',
187 'shorturl' => '46SZxA',
189 $this->linkDb
->getLinkFromUrl('http://nest.ed/1-2')
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',
200 'shorturl' => '4UHOSw',
202 $this->linkDb
->getLinkFromUrl('http://nest.ed/2-1')
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',
213 'shorturl' => 'yfzwbw',
215 $this->linkDb
->getLinkFromUrl('http://nest.ed/2-2')
220 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160202_202222'),
221 'title' => 'Nested 3-1',
222 'url' => 'http://nest.ed/3-1',
225 'tags' => 'folder3 folder3-1 tag3',
226 'shorturl' => 'UwxIUQ',
228 $this->linkDb
->getLinkFromUrl('http://nest.ed/3-1')
233 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160119_230227'),
234 'title' => 'Nested 3-2',
235 'url' => 'http://nest.ed/3-2',
238 'tags' => 'folder3 folder3-1',
239 'shorturl' => 'p8dyZg',
241 $this->linkDb
->getLinkFromUrl('http://nest.ed/3-2')
246 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160229_111541'),
247 'title' => 'Nested 2',
248 'url' => 'http://nest.ed/2',
252 'shorturl' => 'Gt3Uug',
254 $this->linkDb
->getLinkFromUrl('http://nest.ed/2')
259 * Import bookmarks with the default privacy setting (reuse from file)
261 * The $_POST array is not set.
263 public function testImportDefaultPrivacyNoPost()
265 $files = file2array('netscape_basic.htm');
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
)
272 $this->assertEquals(2, count($this->linkDb
));
273 $this->assertEquals(1, count_private($this->linkDb
));
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",
284 'tags' => 'private secret',
285 'shorturl' => 'EokDtA',
287 $this->linkDb
->getLinkFromUrl('https://private.tld')
292 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160225_235548'),
293 'title' => 'Public stuff',
294 'url' => 'http://public.tld',
297 'tags' => 'public hello world',
298 'shorturl' => 'Er9ddA',
300 $this->linkDb
->getLinkFromUrl('http://public.tld')
305 * Import bookmarks with the default privacy setting (reuse from file)
307 public function testImportKeepPrivacy()
309 $post = array('privacy' => 'default');
310 $files = file2array('netscape_basic.htm');
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
)
316 $this->assertEquals(2, count($this->linkDb
));
317 $this->assertEquals(1, count_private($this->linkDb
));
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",
328 'tags' => 'private secret',
329 'shorturl' => 'EokDtA',
331 $this->linkDb
->getLinkFromUrl('https://private.tld')
336 'created' => DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160225_235548'),
337 'title' => 'Public stuff',
338 'url' => 'http://public.tld',
341 'tags' => 'public hello world',
342 'shorturl' => 'Er9ddA',
344 $this->linkDb
->getLinkFromUrl('http://public.tld')
349 * Import links as public
351 public function testImportAsPublic()
353 $post = array('privacy' => 'public');
354 $files = file2array('netscape_basic.htm');
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
)
360 $this->assertEquals(2, count($this->linkDb
));
361 $this->assertEquals(0, count_private($this->linkDb
));
364 $this->linkDb
[0]['private']
368 $this->linkDb
[1]['private']
373 * Import links as private
375 public function testImportAsPrivate()
377 $post = array('privacy' => 'private');
378 $files = file2array('netscape_basic.htm');
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
)
384 $this->assertEquals(2, count($this->linkDb
));
385 $this->assertEquals(2, count_private($this->linkDb
));
388 $this->linkDb
['0']['private']
392 $this->linkDb
['1']['private']
397 * Overwrite private links so they become public
399 public function testOverwriteAsPublic()
401 $files = file2array('netscape_basic.htm');
403 // import links as private
404 $post = array('privacy' => 'private');
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
)
410 $this->assertEquals(2, count($this->linkDb
));
411 $this->assertEquals(2, count_private($this->linkDb
));
414 $this->linkDb
[0]['private']
418 $this->linkDb
[1]['private']
420 // re-import as public, enable overwriting
422 'privacy' => 'public',
423 'overwrite' => 'true'
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
)
430 $this->assertEquals(2, count($this->linkDb
));
431 $this->assertEquals(0, count_private($this->linkDb
));
434 $this->linkDb
[0]['private']
438 $this->linkDb
[1]['private']
443 * Overwrite public links so they become private
445 public function testOverwriteAsPrivate()
447 $files = file2array('netscape_basic.htm');
449 // import links as public
450 $post = array('privacy' => 'public');
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
)
456 $this->assertEquals(2, count($this->linkDb
));
457 $this->assertEquals(0, count_private($this->linkDb
));
460 $this->linkDb
['0']['private']
464 $this->linkDb
['1']['private']
467 // re-import as private, enable overwriting
469 'privacy' => 'private',
470 'overwrite' => 'true'
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
)
477 $this->assertEquals(2, count($this->linkDb
));
478 $this->assertEquals(2, count_private($this->linkDb
));
481 $this->linkDb
['0']['private']
485 $this->linkDb
['1']['private']
490 * Attept to import the same links twice without enabling overwriting
492 public function testSkipOverwrite()
494 $post = array('privacy' => 'public');
495 $files = file2array('netscape_basic.htm');
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
)
501 $this->assertEquals(2, count($this->linkDb
));
502 $this->assertEquals(0, count_private($this->linkDb
));
504 // re-import as private, DO NOT enable overwriting
505 $post = array('privacy' => 'private');
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
)
511 $this->assertEquals(2, count($this->linkDb
));
512 $this->assertEquals(0, count_private($this->linkDb
));
516 * Add user-specified tags to all imported bookmarks
518 public function testSetDefaultTags()
521 'privacy' => 'public',
522 'default_tags' => 'tag1,tag2 tag3'
524 $files = file2array('netscape_basic.htm');
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
)
530 $this->assertEquals(2, count($this->linkDb
));
531 $this->assertEquals(0, count_private($this->linkDb
));
533 'tag1 tag2 tag3 private secret',
534 $this->linkDb
['0']['tags']
537 'tag1 tag2 tag3 public hello world',
538 $this->linkDb
['1']['tags']
543 * The user-specified tags contain characters to be escaped
545 public function testSanitizeDefaultTags()
548 'privacy' => 'public',
549 'default_tags' => 'tag1&,tag2 "tag3"'
551 $files = file2array('netscape_basic.htm');
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
)
557 $this->assertEquals(2, count($this->linkDb
));
558 $this->assertEquals(0, count_private($this->linkDb
));
560 'tag1& tag2 "tag3" private secret',
561 $this->linkDb
['0']['tags']
564 'tag1& tag2 "tag3" public hello world',
565 $this->linkDb
['1']['tags']
570 * Ensure each imported bookmark has a unique id
572 * See https://github.com/shaarli/Shaarli/issues/351
574 public function testImportSameDate()
576 $files = file2array('same_date.htm');
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
)
582 $this->assertEquals(3, count($this->linkDb
));
583 $this->assertEquals(0, count_private($this->linkDb
));
586 $this->linkDb
[0]['id']
590 $this->linkDb
[1]['id']
594 $this->linkDb
[2]['id']