aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2017-05-07 19:23:32 +0200
committerArthurHoaro <arthur@hoa.ro>2017-05-07 19:23:32 +0200
commitfcf141926da98a4a656a785df991858819961319 (patch)
tree049c1ff6b770e759ca7a96b30e6476b9f18cbfa3 /tests
parent8868f3ca461011a8fb6dd9f90b60ed697ab52fc5 (diff)
parent54c8e8d2998c5ab5ffd08ae8f1fa11276773c16c (diff)
downloadShaarli-fcf141926da98a4a656a785df991858819961319.tar.gz
Shaarli-fcf141926da98a4a656a785df991858819961319.tar.zst
Shaarli-fcf141926da98a4a656a785df991858819961319.zip
Merge tag 'v0.9.0' into latest
Release v0.9.0
Diffstat (limited to 'tests')
-rw-r--r--tests/ApplicationUtilsTest.php55
-rw-r--r--tests/FeedBuilderTest.php14
-rw-r--r--tests/FileUtilsTest.php108
-rw-r--r--tests/HistoryTest.php207
-rw-r--r--tests/HttpUtils/ServerUrlTest.php13
-rw-r--r--tests/LinkDBTest.php2
-rw-r--r--tests/LinkFilterTest.php73
-rw-r--r--tests/NetscapeBookmarkUtils/BookmarkImportTest.php89
-rw-r--r--tests/PluginManagerTest.php1
-rw-r--r--tests/ThemeUtilsTest.php55
-rw-r--r--tests/TimeZoneTest.php83
-rw-r--r--tests/Updater/UpdaterTest.php228
-rw-r--r--tests/Url/CleanupUrlTest.php102
-rw-r--r--tests/Url/UrlTest.php8
-rw-r--r--tests/UtilsTest.php166
-rw-r--r--tests/api/ApiMiddlewareTest.php208
-rw-r--r--tests/api/ApiUtilsTest.php352
-rw-r--r--tests/api/controllers/DeleteLinkTest.php126
-rw-r--r--tests/api/controllers/GetLinkIdTest.php132
-rw-r--r--tests/api/controllers/GetLinksTest.php389
-rw-r--r--tests/api/controllers/HistoryTest.php216
-rw-r--r--tests/api/controllers/InfoTest.php115
-rw-r--r--tests/api/controllers/PostLinkTest.php216
-rw-r--r--tests/api/controllers/PutLinkTest.php222
-rw-r--r--tests/config/ConfigJsonTest.php13
-rw-r--r--tests/config/ConfigManagerTest.php9
-rw-r--r--tests/config/ConfigPhpTest.php5
-rw-r--r--tests/config/ConfigPluginTest.php10
-rw-r--r--tests/languages/bootstrap.php7
-rw-r--r--tests/languages/de/UtilsDeTest.php119
-rw-r--r--tests/languages/en/UtilsEnTest.php119
-rw-r--r--tests/languages/fr/UtilsFrTest.php119
-rw-r--r--tests/plugins/PluginAddlinkTest.php46
-rw-r--r--tests/plugins/PluginArchiveorgTest.php10
-rw-r--r--tests/plugins/PluginIssoTest.php15
-rw-r--r--tests/plugins/PluginMarkdownTest.php21
-rw-r--r--tests/plugins/PluginPlayvideosTest.php6
-rw-r--r--tests/plugins/PluginPubsubhubbubTest.php55
-rw-r--r--tests/plugins/PluginQrcodeTest.php (renamed from tests/plugins/PlugQrcodeTest.php)13
-rw-r--r--tests/plugins/PluginReadityourselfTest.php98
-rw-r--r--tests/plugins/PluginWallabagTest.php9
-rw-r--r--tests/plugins/WallabagInstanceTest.php8
-rw-r--r--tests/utils/ReferenceHistory.php82
-rw-r--r--tests/utils/ReferenceLinkDB.php2
-rw-r--r--tests/utils/config/configJson.json.php3
45 files changed, 3614 insertions, 335 deletions
diff --git a/tests/ApplicationUtilsTest.php b/tests/ApplicationUtilsTest.php
index 861b8d4e..ff4c9e17 100644
--- a/tests/ApplicationUtilsTest.php
+++ b/tests/ApplicationUtilsTest.php
@@ -1,9 +1,10 @@
1<?php 1<?php
2use Shaarli\Config\ConfigManager;
3
2/** 4/**
3 * ApplicationUtils' tests 5 * ApplicationUtils' tests
4 */ 6 */
5 7
6require_once 'application/config/ConfigManager.php';
7require_once 'application/ApplicationUtils.php'; 8require_once 'application/ApplicationUtils.php';
8 9
9/** 10/**
@@ -16,7 +17,7 @@ class FakeApplicationUtils extends ApplicationUtils
16 /** 17 /**
17 * Toggle HTTP requests, allow overriding the version code 18 * Toggle HTTP requests, allow overriding the version code
18 */ 19 */
19 public static function getLatestGitVersionCode($url, $timeout=0) 20 public static function getVersion($url, $timeout=0)
20 { 21 {
21 return self::$VERSION_CODE; 22 return self::$VERSION_CODE;
22 } 23 }
@@ -44,17 +45,27 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase
44 } 45 }
45 46
46 /** 47 /**
48 * Remove test version file if it exists
49 */
50 public function tearDown()
51 {
52 if (is_file('sandbox/version.php')) {
53 unlink('sandbox/version.php');
54 }
55 }
56
57 /**
47 * Retrieve the latest version code available on Git 58 * Retrieve the latest version code available on Git
48 * 59 *
49 * Expected format: Semantic Versioning - major.minor.patch 60 * Expected format: Semantic Versioning - major.minor.patch
50 */ 61 */
51 public function testGetLatestGitVersionCode() 62 public function testGetVersionCode()
52 { 63 {
53 $testTimeout = 10; 64 $testTimeout = 10;
54 65
55 $this->assertEquals( 66 $this->assertEquals(
56 '0.5.4', 67 '0.5.4',
57 ApplicationUtils::getLatestGitVersionCode( 68 ApplicationUtils::getVersion(
58 'https://raw.githubusercontent.com/shaarli/Shaarli/' 69 'https://raw.githubusercontent.com/shaarli/Shaarli/'
59 .'v0.5.4/shaarli_version.php', 70 .'v0.5.4/shaarli_version.php',
60 $testTimeout 71 $testTimeout
@@ -62,23 +73,35 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase
62 ); 73 );
63 $this->assertRegExp( 74 $this->assertRegExp(
64 self::$versionPattern, 75 self::$versionPattern,
65 ApplicationUtils::getLatestGitVersionCode( 76 ApplicationUtils::getVersion(
66 'https://raw.githubusercontent.com/shaarli/Shaarli/' 77 'https://raw.githubusercontent.com/shaarli/Shaarli/'
67 .'master/shaarli_version.php', 78 .'latest/shaarli_version.php',
68 $testTimeout 79 $testTimeout
69 ) 80 )
70 ); 81 );
71 } 82 }
72 83
73 /** 84 /**
74 * Attempt to retrieve the latest version from an invalid URL 85 * Attempt to retrieve the latest version from an invalid File
75 */ 86 */
76 public function testGetLatestGitVersionCodeInvalidUrl() 87 public function testGetVersionCodeFromFile()
88 {
89 file_put_contents('sandbox/version.php', '<?php /* 1.2.3 */ ?>'. PHP_EOL);
90 $this->assertEquals(
91 '1.2.3',
92 ApplicationUtils::getVersion('sandbox/version.php', 1)
93 );
94 }
95
96 /**
97 * Attempt to retrieve the latest version from an invalid File
98 */
99 public function testGetVersionCodeInvalidFile()
77 { 100 {
78 $oldlog = ini_get('error_log'); 101 $oldlog = ini_get('error_log');
79 ini_set('error_log', '/dev/null'); 102 ini_set('error_log', '/dev/null');
80 $this->assertFalse( 103 $this->assertFalse(
81 ApplicationUtils::getLatestGitVersionCode('htttp://null.io', 1) 104 ApplicationUtils::getVersion('idontexist', 1)
82 ); 105 );
83 ini_set('error_log', $oldlog); 106 ini_set('error_log', $oldlog);
84 } 107 }
@@ -289,6 +312,7 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase
289 $conf->set('resource.page_cache', 'pagecache'); 312 $conf->set('resource.page_cache', 'pagecache');
290 $conf->set('resource.raintpl_tmp', 'tmp'); 313 $conf->set('resource.raintpl_tmp', 'tmp');
291 $conf->set('resource.raintpl_tpl', 'tpl'); 314 $conf->set('resource.raintpl_tpl', 'tpl');
315 $conf->set('resource.theme', 'default');
292 $conf->set('resource.update_check', 'data/lastupdatecheck.txt'); 316 $conf->set('resource.update_check', 'data/lastupdatecheck.txt');
293 317
294 $this->assertEquals( 318 $this->assertEquals(
@@ -312,10 +336,12 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase
312 $conf->set('resource.page_cache', 'null/pagecache'); 336 $conf->set('resource.page_cache', 'null/pagecache');
313 $conf->set('resource.raintpl_tmp', 'null/tmp'); 337 $conf->set('resource.raintpl_tmp', 'null/tmp');
314 $conf->set('resource.raintpl_tpl', 'null/tpl'); 338 $conf->set('resource.raintpl_tpl', 'null/tpl');
339 $conf->set('resource.raintpl_theme', 'null/tpl/default');
315 $conf->set('resource.update_check', 'null/data/lastupdatecheck.txt'); 340 $conf->set('resource.update_check', 'null/data/lastupdatecheck.txt');
316 $this->assertEquals( 341 $this->assertEquals(
317 array( 342 array(
318 '"null/tpl" directory is not readable', 343 '"null/tpl" directory is not readable',
344 '"null/tpl/default" directory is not readable',
319 '"null/cache" directory is not readable', 345 '"null/cache" directory is not readable',
320 '"null/cache" directory is not writable', 346 '"null/cache" directory is not writable',
321 '"null/data" directory is not readable', 347 '"null/data" directory is not readable',
@@ -328,4 +354,15 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase
328 ApplicationUtils::checkResourcePermissions($conf) 354 ApplicationUtils::checkResourcePermissions($conf)
329 ); 355 );
330 } 356 }
357
358 /**
359 * Check update with 'dev' as curent version (master branch).
360 * It should always return false.
361 */
362 public function testCheckUpdateDev()
363 {
364 $this->assertFalse(
365 ApplicationUtils::checkUpdate('dev', self::$testUpdateFile, 100, true, true)
366 );
367 }
331} 368}
diff --git a/tests/FeedBuilderTest.php b/tests/FeedBuilderTest.php
index 06a44506..a590306d 100644
--- a/tests/FeedBuilderTest.php
+++ b/tests/FeedBuilderTest.php
@@ -75,7 +75,6 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase
75 $data = $feedBuilder->buildData(); 75 $data = $feedBuilder->buildData();
76 // Test headers (RSS) 76 // Test headers (RSS)
77 $this->assertEquals(self::$RSS_LANGUAGE, $data['language']); 77 $this->assertEquals(self::$RSS_LANGUAGE, $data['language']);
78 $this->assertEmpty($data['pubsubhub_url']);
79 $this->assertRegExp('/Wed, 03 Aug 2016 09:30:33 \+\d{4}/', $data['last_update']); 78 $this->assertRegExp('/Wed, 03 Aug 2016 09:30:33 \+\d{4}/', $data['last_update']);
80 $this->assertEquals(true, $data['show_dates']); 79 $this->assertEquals(true, $data['show_dates']);
81 $this->assertEquals('http://host.tld/index.php?do=feed', $data['self_link']); 80 $this->assertEquals('http://host.tld/index.php?do=feed', $data['self_link']);
@@ -211,19 +210,6 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase
211 } 210 }
212 211
213 /** 212 /**
214 * Test buildData with hide dates settings.
215 */
216 public function testBuildDataPubsubhub()
217 {
218 $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, null, false);
219 $feedBuilder->setLocale(self::$LOCALE);
220 $feedBuilder->setPubsubhubUrl('http://pubsubhub.io');
221 $data = $feedBuilder->buildData();
222 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
223 $this->assertEquals('http://pubsubhub.io', $data['pubsubhub_url']);
224 }
225
226 /**
227 * Test buildData when Shaarli is served from a subdirectory 213 * Test buildData when Shaarli is served from a subdirectory
228 */ 214 */
229 public function testBuildDataServerSubdir() 215 public function testBuildDataServerSubdir()
diff --git a/tests/FileUtilsTest.php b/tests/FileUtilsTest.php
new file mode 100644
index 00000000..d764e495
--- /dev/null
+++ b/tests/FileUtilsTest.php
@@ -0,0 +1,108 @@
1<?php
2
3require_once 'application/FileUtils.php';
4
5/**
6 * Class FileUtilsTest
7 *
8 * Test file utility class.
9 */
10class FileUtilsTest extends PHPUnit_Framework_TestCase
11{
12 /**
13 * @var string Test file path.
14 */
15 protected static $file = 'sandbox/flat.db';
16
17 /**
18 * Delete test file after every test.
19 */
20 public function tearDown()
21 {
22 @unlink(self::$file);
23 }
24
25 /**
26 * Test writeDB, then readDB with different data.
27 */
28 public function testSimpleWriteRead()
29 {
30 $data = ['blue', 'red'];
31 $this->assertTrue(FileUtils::writeFlatDB(self::$file, $data) > 0);
32 $this->assertTrue(startsWith(file_get_contents(self::$file), '<?php /*'));
33 $this->assertEquals($data, FileUtils::readFlatDB(self::$file));
34
35 $data = 0;
36 $this->assertTrue(FileUtils::writeFlatDB(self::$file, $data) > 0);
37 $this->assertEquals($data, FileUtils::readFlatDB(self::$file));
38
39 $data = null;
40 $this->assertTrue(FileUtils::writeFlatDB(self::$file, $data) > 0);
41 $this->assertEquals($data, FileUtils::readFlatDB(self::$file));
42
43 $data = false;
44 $this->assertTrue(FileUtils::writeFlatDB(self::$file, $data) > 0);
45 $this->assertEquals($data, FileUtils::readFlatDB(self::$file));
46 }
47
48 /**
49 * File not writable: raise an exception.
50 *
51 * @expectedException IOException
52 * @expectedExceptionMessage Error accessing "sandbox/flat.db"
53 */
54 public function testWriteWithoutPermission()
55 {
56 touch(self::$file);
57 chmod(self::$file, 0440);
58 FileUtils::writeFlatDB(self::$file, null);
59 }
60
61 /**
62 * Folder non existent: raise an exception.
63 *
64 * @expectedException IOException
65 * @expectedExceptionMessage Error accessing "nopefolder"
66 */
67 public function testWriteFolderDoesNotExist()
68 {
69 FileUtils::writeFlatDB('nopefolder/file', null);
70 }
71
72 /**
73 * Folder non writable: raise an exception.
74 *
75 * @expectedException IOException
76 * @expectedExceptionMessage Error accessing "sandbox"
77 */
78 public function testWriteFolderPermission()
79 {
80 chmod(dirname(self::$file), 0555);
81 try {
82 FileUtils::writeFlatDB(self::$file, null);
83 } catch (Exception $e) {
84 chmod(dirname(self::$file), 0755);
85 throw $e;
86 }
87 }
88
89 /**
90 * Read non existent file, use default parameter.
91 */
92 public function testReadNotExistentFile()
93 {
94 $this->assertEquals(null, FileUtils::readFlatDB(self::$file));
95 $this->assertEquals(['test'], FileUtils::readFlatDB(self::$file, ['test']));
96 }
97
98 /**
99 * Read non readable file, use default parameter.
100 */
101 public function testReadNotReadable()
102 {
103 touch(self::$file);
104 chmod(self::$file, 0220);
105 $this->assertEquals(null, FileUtils::readFlatDB(self::$file));
106 $this->assertEquals(['test'], FileUtils::readFlatDB(self::$file, ['test']));
107 }
108}
diff --git a/tests/HistoryTest.php b/tests/HistoryTest.php
new file mode 100644
index 00000000..d3bef5a3
--- /dev/null
+++ b/tests/HistoryTest.php
@@ -0,0 +1,207 @@
1<?php
2
3require_once 'application/History.php';
4
5
6class HistoryTest extends PHPUnit_Framework_TestCase
7{
8 /**
9 * @var string History file path
10 */
11 protected static $historyFilePath = 'sandbox/history.php';
12
13 /**
14 * Delete history file.
15 */
16 public function tearDown()
17 {
18 @unlink(self::$historyFilePath);
19 }
20
21 /**
22 * Test that the history file is created if it doesn't exist.
23 */
24 public function testConstructLazyLoading()
25 {
26 new History(self::$historyFilePath);
27 $this->assertFileNotExists(self::$historyFilePath);
28 }
29
30 /**
31 * Test that the history file is created if it doesn't exist.
32 */
33 public function testAddEventCreateFile()
34 {
35 $history = new History(self::$historyFilePath);
36 $history->updateSettings();
37 $this->assertFileExists(self::$historyFilePath);
38 }
39
40 /**
41 * Not writable history file: raise an exception.
42 *
43 * @expectedException Exception
44 * @expectedExceptionMessage History file isn't readable or writable
45 */
46 public function testConstructNotWritable()
47 {
48 touch(self::$historyFilePath);
49 chmod(self::$historyFilePath, 0440);
50 $history = new History(self::$historyFilePath);
51 $history->updateSettings();
52 }
53
54 /**
55 * Not parsable history file: raise an exception.
56 *
57 * @expectedException Exception
58 * @expectedExceptionMessageRegExp /Could not parse history file/
59 */
60 public function testConstructNotParsable()
61 {
62 file_put_contents(self::$historyFilePath, 'not parsable');
63 $history = new History(self::$historyFilePath);
64 // gzinflate generates a warning
65 @$history->updateSettings();
66 }
67
68 /**
69 * Test add link event
70 */
71 public function testAddLink()
72 {
73 $history = new History(self::$historyFilePath);
74 $history->addLink(['id' => 0]);
75 $actual = $history->getHistory()[0];
76 $this->assertEquals(History::CREATED, $actual['event']);
77 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
78 $this->assertEquals(0, $actual['id']);
79
80 $history = new History(self::$historyFilePath);
81 $history->addLink(['id' => 1]);
82 $actual = $history->getHistory()[0];
83 $this->assertEquals(History::CREATED, $actual['event']);
84 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
85 $this->assertEquals(1, $actual['id']);
86
87 $history = new History(self::$historyFilePath);
88 $history->addLink(['id' => 'str']);
89 $actual = $history->getHistory()[0];
90 $this->assertEquals(History::CREATED, $actual['event']);
91 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
92 $this->assertEquals('str', $actual['id']);
93 }
94
95 /**
96 * Test updated link event
97 */
98 public function testUpdateLink()
99 {
100 $history = new History(self::$historyFilePath);
101 $history->updateLink(['id' => 1]);
102 $actual = $history->getHistory()[0];
103 $this->assertEquals(History::UPDATED, $actual['event']);
104 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
105 $this->assertEquals(1, $actual['id']);
106 }
107
108 /**
109 * Test delete link event
110 */
111 public function testDeleteLink()
112 {
113 $history = new History(self::$historyFilePath);
114 $history->deleteLink(['id' => 1]);
115 $actual = $history->getHistory()[0];
116 $this->assertEquals(History::DELETED, $actual['event']);
117 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
118 $this->assertEquals(1, $actual['id']);
119 }
120
121 /**
122 * Test updated settings event
123 */
124 public function testUpdateSettings()
125 {
126 $history = new History(self::$historyFilePath);
127 $history->updateSettings();
128 $actual = $history->getHistory()[0];
129 $this->assertEquals(History::SETTINGS, $actual['event']);
130 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
131 $this->assertEmpty($actual['id']);
132 }
133
134 /**
135 * Make sure that new items are stored at the beginning
136 */
137 public function testHistoryOrder()
138 {
139 $history = new History(self::$historyFilePath);
140 $history->updateLink(['id' => 1]);
141 $actual = $history->getHistory()[0];
142 $this->assertEquals(History::UPDATED, $actual['event']);
143 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
144 $this->assertEquals(1, $actual['id']);
145
146 $history->addLink(['id' => 1]);
147 $actual = $history->getHistory()[0];
148 $this->assertEquals(History::CREATED, $actual['event']);
149 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
150 $this->assertEquals(1, $actual['id']);
151 }
152
153 /**
154 * Re-read history from file after writing an event
155 */
156 public function testHistoryRead()
157 {
158 $history = new History(self::$historyFilePath);
159 $history->updateLink(['id' => 1]);
160 $history = new History(self::$historyFilePath);
161 $actual = $history->getHistory()[0];
162 $this->assertEquals(History::UPDATED, $actual['event']);
163 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
164 $this->assertEquals(1, $actual['id']);
165 }
166
167 /**
168 * Re-read history from file after writing an event and make sure that the order is correct
169 */
170 public function testHistoryOrderRead()
171 {
172 $history = new History(self::$historyFilePath);
173 $history->updateLink(['id' => 1]);
174 $history->addLink(['id' => 1]);
175
176 $history = new History(self::$historyFilePath);
177 $actual = $history->getHistory()[0];
178 $this->assertEquals(History::CREATED, $actual['event']);
179 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
180 $this->assertEquals(1, $actual['id']);
181
182 $actual = $history->getHistory()[1];
183 $this->assertEquals(History::UPDATED, $actual['event']);
184 $this->assertTrue(new DateTime('-2 seconds') < $actual['datetime']);
185 $this->assertEquals(1, $actual['id']);
186 }
187
188 /**
189 * Test retention time: delete old entries.
190 */
191 public function testHistoryRententionTime()
192 {
193 $history = new History(self::$historyFilePath, 5);
194 $history->updateLink(['id' => 1]);
195 $this->assertEquals(1, count($history->getHistory()));
196 $arr = $history->getHistory();
197 $arr[0]['datetime'] = new DateTime('-1 hour');
198 FileUtils::writeFlatDB(self::$historyFilePath, $arr);
199
200 $history = new History(self::$historyFilePath, 60);
201 $this->assertEquals(1, count($history->getHistory()));
202 $this->assertEquals(1, $history->getHistory()[0]['id']);
203 $history->updateLink(['id' => 2]);
204 $this->assertEquals(1, count($history->getHistory()));
205 $this->assertEquals(2, $history->getHistory()[0]['id']);
206 }
207}
diff --git a/tests/HttpUtils/ServerUrlTest.php b/tests/HttpUtils/ServerUrlTest.php
index 8a55a220..7fdad659 100644
--- a/tests/HttpUtils/ServerUrlTest.php
+++ b/tests/HttpUtils/ServerUrlTest.php
@@ -69,6 +69,19 @@ class ServerUrlTest extends PHPUnit_Framework_TestCase
69 ); 69 );
70 70
71 $this->assertEquals( 71 $this->assertEquals(
72 'https://host.tld',
73 server_url(
74 array(
75 'HTTPS' => 'Off',
76 'SERVER_NAME' => 'host.tld',
77 'SERVER_PORT' => '80',
78 'HTTP_X_FORWARDED_PROTO' => 'https',
79 'HTTP_X_FORWARDED_PORT' => '443'
80 )
81 )
82 );
83
84 $this->assertEquals(
72 'https://host.tld:4974', 85 'https://host.tld:4974',
73 server_url( 86 server_url(
74 array( 87 array(
diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php
index 1f62a34a..7bf98f92 100644
--- a/tests/LinkDBTest.php
+++ b/tests/LinkDBTest.php
@@ -101,7 +101,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
101 * Attempt to instantiate a LinkDB whereas the datastore is not writable 101 * Attempt to instantiate a LinkDB whereas the datastore is not writable
102 * 102 *
103 * @expectedException IOException 103 * @expectedException IOException
104 * @expectedExceptionMessageRegExp /Error accessing\nnull/ 104 * @expectedExceptionMessageRegExp /Error accessing "null"/
105 */ 105 */
106 public function testConstructDatastoreNotWriteable() 106 public function testConstructDatastoreNotWriteable()
107 { 107 {
diff --git a/tests/LinkFilterTest.php b/tests/LinkFilterTest.php
index 21d680a5..37d5ca30 100644
--- a/tests/LinkFilterTest.php
+++ b/tests/LinkFilterTest.php
@@ -13,12 +13,17 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
13 protected static $linkFilter; 13 protected static $linkFilter;
14 14
15 /** 15 /**
16 * @var ReferenceLinkDB instance
17 */
18 protected static $refDB;
19
20 /**
16 * Instanciate linkFilter with ReferenceLinkDB data. 21 * Instanciate linkFilter with ReferenceLinkDB data.
17 */ 22 */
18 public static function setUpBeforeClass() 23 public static function setUpBeforeClass()
19 { 24 {
20 $refDB = new ReferenceLinkDB(); 25 self::$refDB = new ReferenceLinkDB();
21 self::$linkFilter = new LinkFilter($refDB->getLinks()); 26 self::$linkFilter = new LinkFilter(self::$refDB->getLinks());
22 } 27 }
23 28
24 /** 29 /**
@@ -27,14 +32,30 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
27 public function testFilter() 32 public function testFilter()
28 { 33 {
29 $this->assertEquals( 34 $this->assertEquals(
30 ReferenceLinkDB::$NB_LINKS_TOTAL, 35 self::$refDB->countLinks(),
31 count(self::$linkFilter->filter('', '')) 36 count(self::$linkFilter->filter('', ''))
32 ); 37 );
33 38
39 $this->assertEquals(
40 self::$refDB->countLinks(),
41 count(self::$linkFilter->filter('', '', 'all'))
42 );
43
44 $this->assertEquals(
45 self::$refDB->countLinks(),
46 count(self::$linkFilter->filter('', '', 'randomstr'))
47 );
48
34 // Private only. 49 // Private only.
35 $this->assertEquals( 50 $this->assertEquals(
36 2, 51 self::$refDB->countPrivateLinks(),
37 count(self::$linkFilter->filter('', '', false, true)) 52 count(self::$linkFilter->filter('', '', false, 'private'))
53 );
54
55 // Public only.
56 $this->assertEquals(
57 self::$refDB->countPublicLinks(),
58 count(self::$linkFilter->filter('', '', false, 'public'))
38 ); 59 );
39 60
40 $this->assertEquals( 61 $this->assertEquals(
@@ -58,10 +79,26 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
58 count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false)) 79 count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false))
59 ); 80 );
60 81
82 $this->assertEquals(
83 4,
84 count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'all'))
85 );
86
87 $this->assertEquals(
88 4,
89 count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'default-blabla'))
90 );
91
61 // Private only. 92 // Private only.
62 $this->assertEquals( 93 $this->assertEquals(
63 1, 94 1,
64 count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, true)) 95 count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'private'))
96 );
97
98 // Public only.
99 $this->assertEquals(
100 3,
101 count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'public'))
65 ); 102 );
66 } 103 }
67 104
@@ -253,14 +290,30 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
253 public function testFilterFullTextTags() 290 public function testFilterFullTextTags()
254 { 291 {
255 $this->assertEquals( 292 $this->assertEquals(
256 2, 293 6,
257 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'gnu')) 294 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web'))
295 );
296
297 $this->assertEquals(
298 6,
299 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'all'))
300 );
301
302 $this->assertEquals(
303 6,
304 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'bla'))
258 ); 305 );
259 306
260 // Private only. 307 // Private only.
261 $this->assertEquals( 308 $this->assertEquals(
262 1, 309 1,
263 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, true)) 310 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'private'))
311 );
312
313 // Public only.
314 $this->assertEquals(
315 5,
316 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'public'))
264 ); 317 );
265 } 318 }
266 319
@@ -409,7 +462,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
409 LinkFilter::$FILTER_TAG, 462 LinkFilter::$FILTER_TAG,
410 $hashtag, 463 $hashtag,
411 false, 464 false,
412 true 465 'private'
413 )) 466 ))
414 ); 467 );
415 } 468 }
diff --git a/tests/NetscapeBookmarkUtils/BookmarkImportTest.php b/tests/NetscapeBookmarkUtils/BookmarkImportTest.php
index 0ca07eac..5fc1d1e8 100644
--- a/tests/NetscapeBookmarkUtils/BookmarkImportTest.php
+++ b/tests/NetscapeBookmarkUtils/BookmarkImportTest.php
@@ -2,6 +2,7 @@
2 2
3require_once 'application/NetscapeBookmarkUtils.php'; 3require_once 'application/NetscapeBookmarkUtils.php';
4 4
5use Shaarli\Config\ConfigManager;
5 6
6/** 7/**
7 * Utility function to load a file's metadata in a $_FILES-like array 8 * Utility function to load a file's metadata in a $_FILES-like array
@@ -33,6 +34,11 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
33 protected static $testDatastore = 'sandbox/datastore.php'; 34 protected static $testDatastore = 'sandbox/datastore.php';
34 35
35 /** 36 /**
37 * @var string History file path
38 */
39 protected static $historyFilePath = 'sandbox/history.php';
40
41 /**
36 * @var LinkDB private LinkDB instance 42 * @var LinkDB private LinkDB instance
37 */ 43 */
38 protected $linkDb = null; 44 protected $linkDb = null;
@@ -43,6 +49,16 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
43 protected $pagecache = 'tests'; 49 protected $pagecache = 'tests';
44 50
45 /** 51 /**
52 * @var ConfigManager instance.
53 */
54 protected $conf;
55
56 /**
57 * @var History instance.
58 */
59 protected $history;
60
61 /**
46 * @var string Save the current timezone. 62 * @var string Save the current timezone.
47 */ 63 */
48 protected static $defaultTimeZone; 64 protected static $defaultTimeZone;
@@ -65,6 +81,17 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
65 // start with an empty datastore 81 // start with an empty datastore
66 file_put_contents(self::$testDatastore, '<?php /* S7QysKquBQA= */ ?>'); 82 file_put_contents(self::$testDatastore, '<?php /* S7QysKquBQA= */ ?>');
67 $this->linkDb = new LinkDB(self::$testDatastore, true, false); 83 $this->linkDb = new LinkDB(self::$testDatastore, true, false);
84 $this->conf = new ConfigManager('tests/utils/config/configJson');
85 $this->conf->set('resource.page_cache', $this->pagecache);
86 $this->history = new History(self::$historyFilePath);
87 }
88
89 /**
90 * Delete history file.
91 */
92 public function tearDown()
93 {
94 @unlink(self::$historyFilePath);
68 } 95 }
69 96
70 public static function tearDownAfterClass() 97 public static function tearDownAfterClass()
@@ -81,7 +108,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
81 $this->assertEquals( 108 $this->assertEquals(
82 'File empty.htm (0 bytes) has an unknown file format.' 109 'File empty.htm (0 bytes) has an unknown file format.'
83 .' Nothing was imported.', 110 .' Nothing was imported.',
84 NetscapeBookmarkUtils::import(NULL, $files, NULL, NULL) 111 NetscapeBookmarkUtils::import(null, $files, null, $this->conf, $this->history)
85 ); 112 );
86 $this->assertEquals(0, count($this->linkDb)); 113 $this->assertEquals(0, count($this->linkDb));
87 } 114 }
@@ -94,7 +121,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
94 $files = file2array('no_doctype.htm'); 121 $files = file2array('no_doctype.htm');
95 $this->assertEquals( 122 $this->assertEquals(
96 'File no_doctype.htm (350 bytes) has an unknown file format. Nothing was imported.', 123 'File no_doctype.htm (350 bytes) has an unknown file format. Nothing was imported.',
97 NetscapeBookmarkUtils::import(NULL, $files, NULL, NULL) 124 NetscapeBookmarkUtils::import(null, $files, null, $this->conf, $this->history)
98 ); 125 );
99 $this->assertEquals(0, count($this->linkDb)); 126 $this->assertEquals(0, count($this->linkDb));
100 } 127 }
@@ -108,7 +135,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
108 $this->assertEquals( 135 $this->assertEquals(
109 'File internet_explorer_encoding.htm (356 bytes) was successfully processed:' 136 'File internet_explorer_encoding.htm (356 bytes) was successfully processed:'
110 .' 1 links imported, 0 links overwritten, 0 links skipped.', 137 .' 1 links imported, 0 links overwritten, 0 links skipped.',
111 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->pagecache) 138 NetscapeBookmarkUtils::import([], $files, $this->linkDb, $this->conf, $this->history)
112 ); 139 );
113 $this->assertEquals(1, count($this->linkDb)); 140 $this->assertEquals(1, count($this->linkDb));
114 $this->assertEquals(0, count_private($this->linkDb)); 141 $this->assertEquals(0, count_private($this->linkDb));
@@ -137,7 +164,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
137 $this->assertEquals( 164 $this->assertEquals(
138 'File netscape_nested.htm (1337 bytes) was successfully processed:' 165 'File netscape_nested.htm (1337 bytes) was successfully processed:'
139 .' 8 links imported, 0 links overwritten, 0 links skipped.', 166 .' 8 links imported, 0 links overwritten, 0 links skipped.',
140 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->pagecache) 167 NetscapeBookmarkUtils::import([], $files, $this->linkDb, $this->conf, $this->history)
141 ); 168 );
142 $this->assertEquals(8, count($this->linkDb)); 169 $this->assertEquals(8, count($this->linkDb));
143 $this->assertEquals(2, count_private($this->linkDb)); 170 $this->assertEquals(2, count_private($this->linkDb));
@@ -259,7 +286,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
259 $this->assertEquals( 286 $this->assertEquals(
260 'File netscape_basic.htm (482 bytes) was successfully processed:' 287 'File netscape_basic.htm (482 bytes) was successfully processed:'
261 .' 2 links imported, 0 links overwritten, 0 links skipped.', 288 .' 2 links imported, 0 links overwritten, 0 links skipped.',
262 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->pagecache) 289 NetscapeBookmarkUtils::import([], $files, $this->linkDb, $this->conf, $this->history)
263 ); 290 );
264 291
265 $this->assertEquals(2, count($this->linkDb)); 292 $this->assertEquals(2, count($this->linkDb));
@@ -304,7 +331,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
304 $this->assertEquals( 331 $this->assertEquals(
305 'File netscape_basic.htm (482 bytes) was successfully processed:' 332 'File netscape_basic.htm (482 bytes) was successfully processed:'
306 .' 2 links imported, 0 links overwritten, 0 links skipped.', 333 .' 2 links imported, 0 links overwritten, 0 links skipped.',
307 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 334 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
308 ); 335 );
309 $this->assertEquals(2, count($this->linkDb)); 336 $this->assertEquals(2, count($this->linkDb));
310 $this->assertEquals(1, count_private($this->linkDb)); 337 $this->assertEquals(1, count_private($this->linkDb));
@@ -348,7 +375,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
348 $this->assertEquals( 375 $this->assertEquals(
349 'File netscape_basic.htm (482 bytes) was successfully processed:' 376 'File netscape_basic.htm (482 bytes) was successfully processed:'
350 .' 2 links imported, 0 links overwritten, 0 links skipped.', 377 .' 2 links imported, 0 links overwritten, 0 links skipped.',
351 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 378 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
352 ); 379 );
353 $this->assertEquals(2, count($this->linkDb)); 380 $this->assertEquals(2, count($this->linkDb));
354 $this->assertEquals(0, count_private($this->linkDb)); 381 $this->assertEquals(0, count_private($this->linkDb));
@@ -372,7 +399,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
372 $this->assertEquals( 399 $this->assertEquals(
373 'File netscape_basic.htm (482 bytes) was successfully processed:' 400 'File netscape_basic.htm (482 bytes) was successfully processed:'
374 .' 2 links imported, 0 links overwritten, 0 links skipped.', 401 .' 2 links imported, 0 links overwritten, 0 links skipped.',
375 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 402 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
376 ); 403 );
377 $this->assertEquals(2, count($this->linkDb)); 404 $this->assertEquals(2, count($this->linkDb));
378 $this->assertEquals(2, count_private($this->linkDb)); 405 $this->assertEquals(2, count_private($this->linkDb));
@@ -398,7 +425,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
398 $this->assertEquals( 425 $this->assertEquals(
399 'File netscape_basic.htm (482 bytes) was successfully processed:' 426 'File netscape_basic.htm (482 bytes) was successfully processed:'
400 .' 2 links imported, 0 links overwritten, 0 links skipped.', 427 .' 2 links imported, 0 links overwritten, 0 links skipped.',
401 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 428 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
402 ); 429 );
403 $this->assertEquals(2, count($this->linkDb)); 430 $this->assertEquals(2, count($this->linkDb));
404 $this->assertEquals(2, count_private($this->linkDb)); 431 $this->assertEquals(2, count_private($this->linkDb));
@@ -418,7 +445,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
418 $this->assertEquals( 445 $this->assertEquals(
419 'File netscape_basic.htm (482 bytes) was successfully processed:' 446 'File netscape_basic.htm (482 bytes) was successfully processed:'
420 .' 2 links imported, 2 links overwritten, 0 links skipped.', 447 .' 2 links imported, 2 links overwritten, 0 links skipped.',
421 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 448 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
422 ); 449 );
423 $this->assertEquals(2, count($this->linkDb)); 450 $this->assertEquals(2, count($this->linkDb));
424 $this->assertEquals(0, count_private($this->linkDb)); 451 $this->assertEquals(0, count_private($this->linkDb));
@@ -444,7 +471,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
444 $this->assertEquals( 471 $this->assertEquals(
445 'File netscape_basic.htm (482 bytes) was successfully processed:' 472 'File netscape_basic.htm (482 bytes) was successfully processed:'
446 .' 2 links imported, 0 links overwritten, 0 links skipped.', 473 .' 2 links imported, 0 links overwritten, 0 links skipped.',
447 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 474 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
448 ); 475 );
449 $this->assertEquals(2, count($this->linkDb)); 476 $this->assertEquals(2, count($this->linkDb));
450 $this->assertEquals(0, count_private($this->linkDb)); 477 $this->assertEquals(0, count_private($this->linkDb));
@@ -465,7 +492,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
465 $this->assertEquals( 492 $this->assertEquals(
466 'File netscape_basic.htm (482 bytes) was successfully processed:' 493 'File netscape_basic.htm (482 bytes) was successfully processed:'
467 .' 2 links imported, 2 links overwritten, 0 links skipped.', 494 .' 2 links imported, 2 links overwritten, 0 links skipped.',
468 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 495 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
469 ); 496 );
470 $this->assertEquals(2, count($this->linkDb)); 497 $this->assertEquals(2, count($this->linkDb));
471 $this->assertEquals(2, count_private($this->linkDb)); 498 $this->assertEquals(2, count_private($this->linkDb));
@@ -489,7 +516,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
489 $this->assertEquals( 516 $this->assertEquals(
490 'File netscape_basic.htm (482 bytes) was successfully processed:' 517 'File netscape_basic.htm (482 bytes) was successfully processed:'
491 .' 2 links imported, 0 links overwritten, 0 links skipped.', 518 .' 2 links imported, 0 links overwritten, 0 links skipped.',
492 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 519 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
493 ); 520 );
494 $this->assertEquals(2, count($this->linkDb)); 521 $this->assertEquals(2, count($this->linkDb));
495 $this->assertEquals(0, count_private($this->linkDb)); 522 $this->assertEquals(0, count_private($this->linkDb));
@@ -499,7 +526,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
499 $this->assertEquals( 526 $this->assertEquals(
500 'File netscape_basic.htm (482 bytes) was successfully processed:' 527 'File netscape_basic.htm (482 bytes) was successfully processed:'
501 .' 0 links imported, 0 links overwritten, 2 links skipped.', 528 .' 0 links imported, 0 links overwritten, 2 links skipped.',
502 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 529 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
503 ); 530 );
504 $this->assertEquals(2, count($this->linkDb)); 531 $this->assertEquals(2, count($this->linkDb));
505 $this->assertEquals(0, count_private($this->linkDb)); 532 $this->assertEquals(0, count_private($this->linkDb));
@@ -518,7 +545,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
518 $this->assertEquals( 545 $this->assertEquals(
519 'File netscape_basic.htm (482 bytes) was successfully processed:' 546 'File netscape_basic.htm (482 bytes) was successfully processed:'
520 .' 2 links imported, 0 links overwritten, 0 links skipped.', 547 .' 2 links imported, 0 links overwritten, 0 links skipped.',
521 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 548 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
522 ); 549 );
523 $this->assertEquals(2, count($this->linkDb)); 550 $this->assertEquals(2, count($this->linkDb));
524 $this->assertEquals(0, count_private($this->linkDb)); 551 $this->assertEquals(0, count_private($this->linkDb));
@@ -545,7 +572,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
545 $this->assertEquals( 572 $this->assertEquals(
546 'File netscape_basic.htm (482 bytes) was successfully processed:' 573 'File netscape_basic.htm (482 bytes) was successfully processed:'
547 .' 2 links imported, 0 links overwritten, 0 links skipped.', 574 .' 2 links imported, 0 links overwritten, 0 links skipped.',
548 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->pagecache) 575 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history)
549 ); 576 );
550 $this->assertEquals(2, count($this->linkDb)); 577 $this->assertEquals(2, count($this->linkDb));
551 $this->assertEquals(0, count_private($this->linkDb)); 578 $this->assertEquals(0, count_private($this->linkDb));
@@ -570,7 +597,7 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
570 $this->assertEquals( 597 $this->assertEquals(
571 'File same_date.htm (453 bytes) was successfully processed:' 598 'File same_date.htm (453 bytes) was successfully processed:'
572 .' 3 links imported, 0 links overwritten, 0 links skipped.', 599 .' 3 links imported, 0 links overwritten, 0 links skipped.',
573 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->pagecache) 600 NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf, $this->history)
574 ); 601 );
575 $this->assertEquals(3, count($this->linkDb)); 602 $this->assertEquals(3, count($this->linkDb));
576 $this->assertEquals(0, count_private($this->linkDb)); 603 $this->assertEquals(0, count_private($this->linkDb));
@@ -587,4 +614,32 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase
587 $this->linkDb[2]['id'] 614 $this->linkDb[2]['id']
588 ); 615 );
589 } 616 }
617
618 public function testImportCreateUpdateHistory()
619 {
620 $post = [
621 'privacy' => 'public',
622 'overwrite' => 'true',
623 ];
624 $files = file2array('netscape_basic.htm');
625 $nbLinks = 2;
626 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history);
627 $history = $this->history->getHistory();
628 $this->assertEquals($nbLinks, count($history));
629 foreach ($history as $value) {
630 $this->assertEquals(History::CREATED, $value['event']);
631 $this->assertTrue(new DateTime('-5 seconds') < $value['datetime']);
632 $this->assertTrue(is_int($value['id']));
633 }
634
635 // re-import as private, enable overwriting
636 NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history);
637 $history = $this->history->getHistory();
638 $this->assertEquals($nbLinks * 2, count($history));
639 for ($i = 0 ; $i < $nbLinks ; $i++) {
640 $this->assertEquals(History::UPDATED, $history[$i]['event']);
641 $this->assertTrue(new DateTime('-5 seconds') < $history[$i]['datetime']);
642 $this->assertTrue(is_int($history[$i]['id']));
643 }
644 }
590} 645}
diff --git a/tests/PluginManagerTest.php b/tests/PluginManagerTest.php
index ddf48185..01de959c 100644
--- a/tests/PluginManagerTest.php
+++ b/tests/PluginManagerTest.php
@@ -1,4 +1,5 @@
1<?php 1<?php
2use Shaarli\Config\ConfigManager;
2 3
3/** 4/**
4 * Plugin Manager tests 5 * Plugin Manager tests
diff --git a/tests/ThemeUtilsTest.php b/tests/ThemeUtilsTest.php
new file mode 100644
index 00000000..e44564be
--- /dev/null
+++ b/tests/ThemeUtilsTest.php
@@ -0,0 +1,55 @@
1<?php
2
3namespace Shaarli;
4
5/**
6 * Class ThemeUtilsTest
7 *
8 * @package Shaarli
9 */
10class ThemeUtilsTest extends \PHPUnit_Framework_TestCase
11{
12 /**
13 * Test getThemes() with existing theme directories.
14 */
15 public function testGetThemes()
16 {
17 $themes = ['theme1', 'default', 'Bl1p_- bL0p'];
18 foreach ($themes as $theme) {
19 mkdir('sandbox/tpl/'. $theme, 0755, true);
20 }
21
22 // include a file which should be ignored
23 touch('sandbox/tpl/supertheme');
24
25 $res = ThemeUtils::getThemes('sandbox/tpl/');
26 foreach ($res as $theme) {
27 $this->assertTrue(in_array($theme, $themes));
28 }
29 $this->assertFalse(in_array('supertheme', $res));
30
31 foreach ($themes as $theme) {
32 rmdir('sandbox/tpl/'. $theme);
33 }
34 unlink('sandbox/tpl/supertheme');
35 rmdir('sandbox/tpl');
36 }
37
38 /**
39 * Test getThemes() without any theme dir.
40 */
41 public function testGetThemesEmpty()
42 {
43 mkdir('sandbox/tpl/', 0755, true);
44 $this->assertEquals([], ThemeUtils::getThemes('sandbox/tpl/'));
45 rmdir('sandbox/tpl/');
46 }
47
48 /**
49 * Test getThemes() with an invalid path.
50 */
51 public function testGetThemesInvalid()
52 {
53 $this->assertEquals([], ThemeUtils::getThemes('nope'));
54 }
55}
diff --git a/tests/TimeZoneTest.php b/tests/TimeZoneTest.php
index 2976d116..127fdc19 100644
--- a/tests/TimeZoneTest.php
+++ b/tests/TimeZoneTest.php
@@ -11,24 +11,45 @@ require_once 'application/TimeZone.php';
11class TimeZoneTest extends PHPUnit_Framework_TestCase 11class TimeZoneTest extends PHPUnit_Framework_TestCase
12{ 12{
13 /** 13 /**
14 * @var array of timezones
15 */
16 protected $installedTimezones;
17
18 public function setUp()
19 {
20 $this->installedTimezones = [
21 'Antarctica/Syowa',
22 'Europe/London',
23 'Europe/Paris',
24 'UTC'
25 ];
26 }
27
28 /**
14 * Generate a timezone selection form 29 * Generate a timezone selection form
15 */ 30 */
16 public function testGenerateTimeZoneForm() 31 public function testGenerateTimeZoneForm()
17 { 32 {
18 $generated = generateTimeZoneForm(); 33 $expected = [
34 'continents' => [
35 'Antarctica',
36 'Europe',
37 'UTC',
38 'selected' => '',
39 ],
40 'cities' => [
41 ['continent' => 'Antarctica', 'city' => 'Syowa'],
42 ['continent' => 'Europe', 'city' => 'London'],
43 ['continent' => 'Europe', 'city' => 'Paris'],
44 ['continent' => 'UTC', 'city' => 'UTC'],
45 'selected' => '',
46 ]
47 ];
19 48
20 // HTML form 49 list($continents, $cities) = generateTimeZoneData($this->installedTimezones);
21 $this->assertStringStartsWith('Continent:<select', $generated[0]);
22 $this->assertContains('selected="selected"', $generated[0]);
23 $this->assertStringEndsWith('</select><br />', $generated[0]);
24 50
25 // Javascript handler 51 $this->assertEquals($expected['continents'], $continents);
26 $this->assertStringStartsWith('<script>', $generated[1]); 52 $this->assertEquals($expected['cities'], $cities);
27 $this->assertContains(
28 '<option value=\"Bermuda\">Bermuda<\/option>',
29 $generated[1]
30 );
31 $this->assertStringEndsWith('</script>', $generated[1]);
32 } 53 }
33 54
34 /** 55 /**
@@ -36,28 +57,26 @@ class TimeZoneTest extends PHPUnit_Framework_TestCase
36 */ 57 */
37 public function testGenerateTimeZoneFormPreselected() 58 public function testGenerateTimeZoneFormPreselected()
38 { 59 {
39 $generated = generateTimeZoneForm('Antarctica/Syowa'); 60 $expected = [
40 61 'continents' => [
41 // HTML form 62 'Antarctica',
42 $this->assertStringStartsWith('Continent:<select', $generated[0]); 63 'Europe',
43 $this->assertContains( 64 'UTC',
44 'value="Antarctica" selected="selected"', 65 'selected' => 'Antarctica',
45 $generated[0] 66 ],
46 ); 67 'cities' => [
47 $this->assertContains( 68 ['continent' => 'Antarctica', 'city' => 'Syowa'],
48 'value="Syowa" selected="selected"', 69 ['continent' => 'Europe', 'city' => 'London'],
49 $generated[0] 70 ['continent' => 'Europe', 'city' => 'Paris'],
50 ); 71 ['continent' => 'UTC', 'city' => 'UTC'],
51 $this->assertStringEndsWith('</select><br />', $generated[0]); 72 'selected' => 'Syowa',
73 ]
74 ];
52 75
76 list($continents, $cities) = generateTimeZoneData($this->installedTimezones, 'Antarctica/Syowa');
53 77
54 // Javascript handler 78 $this->assertEquals($expected['continents'], $continents);
55 $this->assertStringStartsWith('<script>', $generated[1]); 79 $this->assertEquals($expected['cities'], $cities);
56 $this->assertContains(
57 '<option value=\"Bermuda\">Bermuda<\/option>',
58 $generated[1]
59 );
60 $this->assertStringEndsWith('</script>', $generated[1]);
61 } 80 }
62 81
63 /** 82 /**
diff --git a/tests/Updater/UpdaterTest.php b/tests/Updater/UpdaterTest.php
index a3e8a4d2..11b6444a 100644
--- a/tests/Updater/UpdaterTest.php
+++ b/tests/Updater/UpdaterTest.php
@@ -1,7 +1,10 @@
1<?php 1<?php
2use Shaarli\Config\ConfigJson;
3use Shaarli\Config\ConfigManager;
4use Shaarli\Config\ConfigPhp;
2 5
3require_once 'application/config/ConfigManager.php';
4require_once 'tests/Updater/DummyUpdater.php'; 6require_once 'tests/Updater/DummyUpdater.php';
7require_once 'inc/rain.tpl.class.php';
5 8
6/** 9/**
7 * Class UpdaterTest. 10 * Class UpdaterTest.
@@ -271,7 +274,7 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
271 public function testEscapeConfig() 274 public function testEscapeConfig()
272 { 275 {
273 $sandbox = 'sandbox/config'; 276 $sandbox = 'sandbox/config';
274 copy(self::$configFile .'.json.php', $sandbox .'.json.php'); 277 copy(self::$configFile . '.json.php', $sandbox . '.json.php');
275 $this->conf = new ConfigManager($sandbox); 278 $this->conf = new ConfigManager($sandbox);
276 $title = '<script>alert("title");</script>'; 279 $title = '<script>alert("title");</script>';
277 $headerLink = '<script>alert("header_link");</script>'; 280 $headerLink = '<script>alert("header_link");</script>';
@@ -286,7 +289,43 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
286 $this->assertEquals(escape($title), $this->conf->get('general.title')); 289 $this->assertEquals(escape($title), $this->conf->get('general.title'));
287 $this->assertEquals(escape($headerLink), $this->conf->get('general.header_link')); 290 $this->assertEquals(escape($headerLink), $this->conf->get('general.header_link'));
288 $this->assertEquals(escape($redirectorUrl), $this->conf->get('redirector.url')); 291 $this->assertEquals(escape($redirectorUrl), $this->conf->get('redirector.url'));
289 unlink($sandbox .'.json.php'); 292 unlink($sandbox . '.json.php');
293 }
294
295 /**
296 * Test updateMethodApiSettings(): create default settings for the API (enabled + secret).
297 */
298 public function testUpdateApiSettings()
299 {
300 $confFile = 'sandbox/config';
301 copy(self::$configFile .'.json.php', $confFile .'.json.php');
302 $conf = new ConfigManager($confFile);
303 $updater = new Updater(array(), array(), $conf, true);
304
305 $this->assertFalse($conf->exists('api.enabled'));
306 $this->assertFalse($conf->exists('api.secret'));
307 $updater->updateMethodApiSettings();
308 $conf->reload();
309 $this->assertTrue($conf->get('api.enabled'));
310 $this->assertTrue($conf->exists('api.secret'));
311 unlink($confFile .'.json.php');
312 }
313
314 /**
315 * Test updateMethodApiSettings(): already set, do nothing.
316 */
317 public function testUpdateApiSettingsNothingToDo()
318 {
319 $confFile = 'sandbox/config';
320 copy(self::$configFile .'.json.php', $confFile .'.json.php');
321 $conf = new ConfigManager($confFile);
322 $conf->set('api.enabled', false);
323 $conf->set('api.secret', '');
324 $updater = new Updater(array(), array(), $conf, true);
325 $updater->updateMethodApiSettings();
326 $this->assertFalse($conf->get('api.enabled'));
327 $this->assertEmpty($conf->get('api.secret'));
328 unlink($confFile .'.json.php');
290 } 329 }
291 330
292 /** 331 /**
@@ -387,6 +426,90 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
387 } 426 }
388 427
389 /** 428 /**
429 * Test defaultTheme update with default settings: nothing to do.
430 */
431 public function testDefaultThemeWithDefaultSettings()
432 {
433 $sandbox = 'sandbox/config';
434 copy(self::$configFile . '.json.php', $sandbox . '.json.php');
435 $this->conf = new ConfigManager($sandbox);
436 $updater = new Updater([], [], $this->conf, true);
437 $this->assertTrue($updater->updateMethodDefaultTheme());
438
439 $this->assertEquals('tpl/', $this->conf->get('resource.raintpl_tpl'));
440 $this->assertEquals('default', $this->conf->get('resource.theme'));
441 $this->conf = new ConfigManager($sandbox);
442 $this->assertEquals('tpl/', $this->conf->get('resource.raintpl_tpl'));
443 $this->assertEquals('default', $this->conf->get('resource.theme'));
444 unlink($sandbox . '.json.php');
445 }
446
447 /**
448 * Test defaultTheme update with a custom theme in a subfolder
449 */
450 public function testDefaultThemeWithCustomTheme()
451 {
452 $theme = 'iamanartist';
453 $sandbox = 'sandbox/config';
454 copy(self::$configFile . '.json.php', $sandbox . '.json.php');
455 $this->conf = new ConfigManager($sandbox);
456 mkdir('sandbox/'. $theme);
457 touch('sandbox/'. $theme .'/linklist.html');
458 $this->conf->set('resource.raintpl_tpl', 'sandbox/'. $theme .'/');
459 $updater = new Updater([], [], $this->conf, true);
460 $this->assertTrue($updater->updateMethodDefaultTheme());
461
462 $this->assertEquals('sandbox', $this->conf->get('resource.raintpl_tpl'));
463 $this->assertEquals($theme, $this->conf->get('resource.theme'));
464 $this->conf = new ConfigManager($sandbox);
465 $this->assertEquals('sandbox', $this->conf->get('resource.raintpl_tpl'));
466 $this->assertEquals($theme, $this->conf->get('resource.theme'));
467 unlink($sandbox . '.json.php');
468 unlink('sandbox/'. $theme .'/linklist.html');
469 rmdir('sandbox/'. $theme);
470 }
471
472 /**
473 * Test updateMethodDefaultThemeVintage with the default theme enabled.
474 */
475 public function testSetDefaultThemeToVintage()
476 {
477 $sandboxConf = 'sandbox/config';
478 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php');
479 $this->conf = new ConfigManager($sandboxConf);
480
481 $this->conf->set('resource.theme', 'default');
482 $updater = new Updater([], [], $this->conf, true);
483 $this->assertTrue($updater->updateMethodDefaultThemeVintage());
484 $this->assertEquals('vintage', $this->conf->get('resource.theme'));
485
486 // reload from file
487 $this->conf = new ConfigManager($sandboxConf);
488 $this->assertEquals('vintage', $this->conf->get('resource.theme'));
489 }
490
491 /**
492 * Test updateMethodDefaultThemeVintage with custom theme enabled => nothing to do.
493 */
494 public function testSetDefaultThemeNothingToDo()
495 {
496 $sandboxConf = 'sandbox/config';
497 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php');
498 $this->conf = new ConfigManager($sandboxConf);
499
500 $theme = 'myawesometheme';
501 $this->conf->set('resource.theme', $theme);
502 $this->conf->write(true);
503 $updater = new Updater([], [], $this->conf, true);
504 $this->assertTrue($updater->updateMethodDefaultThemeVintage());
505 $this->assertEquals($theme, $this->conf->get('resource.theme'));
506
507 // reload from file
508 $this->conf = new ConfigManager($sandboxConf);
509 $this->assertEquals($theme, $this->conf->get('resource.theme'));
510 }
511
512 /**
390 * Test updateMethodEscapeMarkdown with markdown plugin enabled 513 * Test updateMethodEscapeMarkdown with markdown plugin enabled
391 * => setting markdown_escape set to false. 514 * => setting markdown_escape set to false.
392 */ 515 */
@@ -396,8 +519,8 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
396 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); 519 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php');
397 $this->conf = new ConfigManager($sandboxConf); 520 $this->conf = new ConfigManager($sandboxConf);
398 521
399 $this->conf->set('general.enabled_plugins', array('markdown')); 522 $this->conf->set('general.enabled_plugins', ['markdown']);
400 $updater = new Updater(array(), array(), $this->conf, true); 523 $updater = new Updater([], [], $this->conf, true);
401 $this->assertTrue($updater->updateMethodEscapeMarkdown()); 524 $this->assertTrue($updater->updateMethodEscapeMarkdown());
402 $this->assertFalse($this->conf->get('security.markdown_escape')); 525 $this->assertFalse($this->conf->get('security.markdown_escape'));
403 526
@@ -406,6 +529,7 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
406 $this->assertFalse($this->conf->get('security.markdown_escape')); 529 $this->assertFalse($this->conf->get('security.markdown_escape'));
407 } 530 }
408 531
532
409 /** 533 /**
410 * Test updateMethodEscapeMarkdown with markdown plugin disabled 534 * Test updateMethodEscapeMarkdown with markdown plugin disabled
411 * => setting markdown_escape set to true. 535 * => setting markdown_escape set to true.
@@ -416,8 +540,8 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
416 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); 540 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php');
417 $this->conf = new ConfigManager($sandboxConf); 541 $this->conf = new ConfigManager($sandboxConf);
418 542
419 $this->conf->set('general.enabled_plugins', array()); 543 $this->conf->set('general.enabled_plugins', []);
420 $updater = new Updater(array(), array(), $this->conf, true); 544 $updater = new Updater([], [], $this->conf, true);
421 $this->assertTrue($updater->updateMethodEscapeMarkdown()); 545 $this->assertTrue($updater->updateMethodEscapeMarkdown());
422 $this->assertTrue($this->conf->get('security.markdown_escape')); 546 $this->assertTrue($this->conf->get('security.markdown_escape'));
423 547
@@ -435,7 +559,7 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
435 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); 559 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php');
436 $this->conf = new ConfigManager($sandboxConf); 560 $this->conf = new ConfigManager($sandboxConf);
437 $this->conf->set('security.markdown_escape', true); 561 $this->conf->set('security.markdown_escape', true);
438 $updater = new Updater(array(), array(), $this->conf, true); 562 $updater = new Updater([], [], $this->conf, true);
439 $this->assertTrue($updater->updateMethodEscapeMarkdown()); 563 $this->assertTrue($updater->updateMethodEscapeMarkdown());
440 $this->assertTrue($this->conf->get('security.markdown_escape')); 564 $this->assertTrue($this->conf->get('security.markdown_escape'));
441 } 565 }
@@ -446,8 +570,94 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
446 public function testEscapeMarkdownSettingNothingToDoDisabled() 570 public function testEscapeMarkdownSettingNothingToDoDisabled()
447 { 571 {
448 $this->conf->set('security.markdown_escape', false); 572 $this->conf->set('security.markdown_escape', false);
449 $updater = new Updater(array(), array(), $this->conf, true); 573 $updater = new Updater([], [], $this->conf, true);
450 $this->assertTrue($updater->updateMethodEscapeMarkdown()); 574 $this->assertTrue($updater->updateMethodEscapeMarkdown());
451 $this->assertFalse($this->conf->get('security.markdown_escape')); 575 $this->assertFalse($this->conf->get('security.markdown_escape'));
452 } 576 }
577
578 /**
579 * Test updateMethodPiwikUrl with valid data
580 */
581 public function testUpdatePiwikUrlValid()
582 {
583 $sandboxConf = 'sandbox/config';
584 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php');
585 $this->conf = new ConfigManager($sandboxConf);
586 $url = 'mypiwik.tld';
587 $this->conf->set('plugins.PIWIK_URL', $url);
588 $updater = new Updater([], [], $this->conf, true);
589 $this->assertTrue($updater->updateMethodPiwikUrl());
590 $this->assertEquals('http://'. $url, $this->conf->get('plugins.PIWIK_URL'));
591
592 // reload from file
593 $this->conf = new ConfigManager($sandboxConf);
594 $this->assertEquals('http://'. $url, $this->conf->get('plugins.PIWIK_URL'));
595 }
596
597 /**
598 * Test updateMethodPiwikUrl without setting
599 */
600 public function testUpdatePiwikUrlEmpty()
601 {
602 $updater = new Updater([], [], $this->conf, true);
603 $this->assertTrue($updater->updateMethodPiwikUrl());
604 $this->assertEmpty($this->conf->get('plugins.PIWIK_URL'));
605 }
606
607 /**
608 * Test updateMethodPiwikUrl: valid URL, nothing to do
609 */
610 public function testUpdatePiwikUrlNothingToDo()
611 {
612 $url = 'https://mypiwik.tld';
613 $this->conf->set('plugins.PIWIK_URL', $url);
614 $updater = new Updater([], [], $this->conf, true);
615 $this->assertTrue($updater->updateMethodPiwikUrl());
616 $this->assertEquals($url, $this->conf->get('plugins.PIWIK_URL'));
617 }
618
619 /**
620 * Test updateMethodAtomDefault with show_atom set to false
621 * => update to true.
622 */
623 public function testUpdateMethodAtomDefault()
624 {
625 $sandboxConf = 'sandbox/config';
626 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php');
627 $this->conf = new ConfigManager($sandboxConf);
628 $this->conf->set('feed.show_atom', false);
629 $updater = new Updater([], [], $this->conf, true);
630 $this->assertTrue($updater->updateMethodAtomDefault());
631 $this->assertTrue($this->conf->get('feed.show_atom'));
632 // reload from file
633 $this->conf = new ConfigManager($sandboxConf);
634 $this->assertTrue($this->conf->get('feed.show_atom'));
635 }
636 /**
637 * Test updateMethodAtomDefault with show_atom not set.
638 * => nothing to do
639 */
640 public function testUpdateMethodAtomDefaultNoExist()
641 {
642 $sandboxConf = 'sandbox/config';
643 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php');
644 $this->conf = new ConfigManager($sandboxConf);
645 $updater = new Updater([], [], $this->conf, true);
646 $this->assertTrue($updater->updateMethodAtomDefault());
647 $this->assertTrue($this->conf->get('feed.show_atom'));
648 }
649 /**
650 * Test updateMethodAtomDefault with show_atom set to true.
651 * => nothing to do
652 */
653 public function testUpdateMethodAtomDefaultAlreadyTrue()
654 {
655 $sandboxConf = 'sandbox/config';
656 copy(self::$configFile . '.json.php', $sandboxConf . '.json.php');
657 $this->conf = new ConfigManager($sandboxConf);
658 $this->conf->set('feed.show_atom', true);
659 $updater = new Updater([], [], $this->conf, true);
660 $this->assertTrue($updater->updateMethodAtomDefault());
661 $this->assertTrue($this->conf->get('feed.show_atom'));
662 }
453} 663}
diff --git a/tests/Url/CleanupUrlTest.php b/tests/Url/CleanupUrlTest.php
index ba9a0437..1407d7d2 100644
--- a/tests/Url/CleanupUrlTest.php
+++ b/tests/Url/CleanupUrlTest.php
@@ -8,7 +8,13 @@ require_once 'application/Url.php';
8class CleanupUrlTest extends PHPUnit_Framework_TestCase 8class CleanupUrlTest extends PHPUnit_Framework_TestCase
9{ 9{
10 /** 10 /**
11 * Clean empty UrlThanks for building nothing 11 * @var string reference URL
12 */
13 protected $ref = 'http://domain.tld:3000';
14
15
16 /**
17 * Clean empty URL
12 */ 18 */
13 public function testCleanupUrlEmpty() 19 public function testCleanupUrlEmpty()
14 { 20 {
@@ -16,59 +22,87 @@ class CleanupUrlTest extends PHPUnit_Framework_TestCase
16 } 22 }
17 23
18 /** 24 /**
19 * Clean an already cleaned Url 25 * Clean an already cleaned URL
20 */ 26 */
21 public function testCleanupUrlAlreadyClean() 27 public function testCleanupUrlAlreadyClean()
22 { 28 {
23 $ref = 'http://domain.tld:3000'; 29 $this->assertEquals($this->ref, cleanup_url($this->ref));
24 $this->assertEquals($ref, cleanup_url($ref)); 30 $this->ref2 = $this->ref.'/path/to/dir/';
25 $ref = $ref.'/path/to/dir/'; 31 $this->assertEquals($this->ref2, cleanup_url($this->ref2));
26 $this->assertEquals($ref, cleanup_url($ref)); 32 }
33
34 /**
35 * Clean URL fragments
36 */
37 public function testCleanupUrlFragment()
38 {
39 $this->assertEquals($this->ref, cleanup_url($this->ref.'#tk.rss_all'));
40 $this->assertEquals($this->ref, cleanup_url($this->ref.'#xtor=RSS-'));
41 $this->assertEquals($this->ref, cleanup_url($this->ref.'#xtor=RSS-U3ht0tkc4b'));
42 }
43
44 /**
45 * Clean URL query - single annoying parameter
46 */
47 public function testCleanupUrlQuerySingle()
48 {
49 $this->assertEquals($this->ref, cleanup_url($this->ref.'?action_object_map=junk'));
50 $this->assertEquals($this->ref, cleanup_url($this->ref.'?action_ref_map=Cr4p!'));
51 $this->assertEquals($this->ref, cleanup_url($this->ref.'?action_type_map=g4R84g3'));
52
53 $this->assertEquals($this->ref, cleanup_url($this->ref.'?fb_stuff=v41u3'));
54 $this->assertEquals($this->ref, cleanup_url($this->ref.'?fb=71m3w4573'));
55
56 $this->assertEquals($this->ref, cleanup_url($this->ref.'?utm_campaign=zomg'));
57 $this->assertEquals($this->ref, cleanup_url($this->ref.'?utm_medium=numnum'));
58 $this->assertEquals($this->ref, cleanup_url($this->ref.'?utm_source=c0d3'));
59 $this->assertEquals($this->ref, cleanup_url($this->ref.'?utm_term=1n4l'));
60
61 $this->assertEquals($this->ref, cleanup_url($this->ref.'?xtor=some-url'));
62
63 $this->assertEquals($this->ref, cleanup_url($this->ref.'?campaign_name=junk'));
64 $this->assertEquals($this->ref, cleanup_url($this->ref.'?campaign_start=junk'));
65 $this->assertEquals($this->ref, cleanup_url($this->ref.'?campaign_item_index=junk'));
27 } 66 }
28 67
29 /** 68 /**
30 * Clean Url needing cleaning 69 * Clean URL query - multiple annoying parameters
31 */ 70 */
32 public function testCleanupUrlNeedClean() 71 public function testCleanupUrlQueryMultiple()
33 { 72 {
34 $ref = 'http://domain.tld:3000'; 73 $this->assertEquals($this->ref, cleanup_url($this->ref.'?xtor=some-url&fb=som3th1ng'));
35 $this->assertEquals($ref, cleanup_url($ref.'#tk.rss_all')); 74
36 $this->assertEquals($ref, cleanup_url($ref.'#xtor=RSS-')); 75 $this->assertEquals($this->ref, cleanup_url(
37 $this->assertEquals($ref, cleanup_url($ref.'#xtor=RSS-U3ht0tkc4b')); 76 $this->ref.'?fb=stuff&utm_campaign=zomg&utm_medium=numnum&utm_source=c0d3'
38 $this->assertEquals($ref, cleanup_url($ref.'?action_object_map=junk'));
39 $this->assertEquals($ref, cleanup_url($ref.'?action_ref_map=Cr4p!'));
40 $this->assertEquals($ref, cleanup_url($ref.'?action_type_map=g4R84g3'));
41
42 $this->assertEquals($ref, cleanup_url($ref.'?fb_stuff=v41u3'));
43 $this->assertEquals($ref, cleanup_url($ref.'?fb=71m3w4573'));
44
45 $this->assertEquals($ref, cleanup_url($ref.'?utm_campaign=zomg'));
46 $this->assertEquals($ref, cleanup_url($ref.'?utm_medium=numnum'));
47 $this->assertEquals($ref, cleanup_url($ref.'?utm_source=c0d3'));
48 $this->assertEquals($ref, cleanup_url($ref.'?utm_term=1n4l'));
49
50 $this->assertEquals($ref, cleanup_url($ref.'?xtor=some-url'));
51 $this->assertEquals($ref, cleanup_url($ref.'?xtor=some-url&fb=som3th1ng'));
52 $this->assertEquals($ref, cleanup_url(
53 $ref.'?fb=stuff&utm_campaign=zomg&utm_medium=numnum&utm_source=c0d3'
54 )); 77 ));
55 $this->assertEquals($ref, cleanup_url( 78
56 $ref.'?xtor=some-url&fb=som3th1ng#tk.rss_all' 79 $this->assertEquals($this->ref, cleanup_url(
80 $this->ref.'?campaign_start=zomg&campaign_name=numnum'
81 ));
82 }
83
84 /**
85 * Clean URL query - multiple annoying parameters and fragment
86 */
87 public function testCleanupUrlQueryFragment()
88 {
89 $this->assertEquals($this->ref, cleanup_url(
90 $this->ref.'?xtor=some-url&fb=som3th1ng#tk.rss_all'
57 )); 91 ));
58 92
59 // ditch annoying query params and fragment, keep useful params 93 // ditch annoying query params and fragment, keep useful params
60 $this->assertEquals( 94 $this->assertEquals(
61 $ref.'?my=stuff&is=kept', 95 $this->ref.'?my=stuff&is=kept',
62 cleanup_url( 96 cleanup_url(
63 $ref.'?fb=zomg&my=stuff&utm_medium=numnum&is=kept#tk.rss_all' 97 $this->ref.'?fb=zomg&my=stuff&utm_medium=numnum&is=kept#tk.rss_all'
64 ) 98 )
65 ); 99 );
66 100
67 // ditch annoying query params, keep useful params and fragment 101 // ditch annoying query params, keep useful params and fragment
68 $this->assertEquals( 102 $this->assertEquals(
69 $ref.'?my=stuff&is=kept#again', 103 $this->ref.'?my=stuff&is=kept#again',
70 cleanup_url( 104 cleanup_url(
71 $ref.'?fb=zomg&my=stuff&utm_medium=numnum&is=kept#again' 105 $this->ref.'?fb=zomg&my=stuff&utm_medium=numnum&is=kept#again'
72 ) 106 )
73 ); 107 );
74 } 108 }
diff --git a/tests/Url/UrlTest.php b/tests/Url/UrlTest.php
index 05862372..aa2f2234 100644
--- a/tests/Url/UrlTest.php
+++ b/tests/Url/UrlTest.php
@@ -157,7 +157,7 @@ class UrlTest extends PHPUnit_Framework_TestCase
157 /** 157 /**
158 * Test add trailing slash. 158 * Test add trailing slash.
159 */ 159 */
160 function testAddTrailingSlash() 160 public function testAddTrailingSlash()
161 { 161 {
162 $strOn = 'http://randomstr.com/test/'; 162 $strOn = 'http://randomstr.com/test/';
163 $strOff = 'http://randomstr.com/test'; 163 $strOff = 'http://randomstr.com/test';
@@ -168,7 +168,7 @@ class UrlTest extends PHPUnit_Framework_TestCase
168 /** 168 /**
169 * Test valid HTTP url. 169 * Test valid HTTP url.
170 */ 170 */
171 function testUrlIsHttp() 171 public function testUrlIsHttp()
172 { 172 {
173 $url = new Url(self::$baseUrl); 173 $url = new Url(self::$baseUrl);
174 $this->assertTrue($url->isHttp()); 174 $this->assertTrue($url->isHttp());
@@ -177,7 +177,7 @@ class UrlTest extends PHPUnit_Framework_TestCase
177 /** 177 /**
178 * Test non HTTP url. 178 * Test non HTTP url.
179 */ 179 */
180 function testUrlIsNotHttp() 180 public function testUrlIsNotHttp()
181 { 181 {
182 $url = new Url('ftp://save.tld/mysave'); 182 $url = new Url('ftp://save.tld/mysave');
183 $this->assertFalse($url->isHttp()); 183 $this->assertFalse($url->isHttp());
@@ -186,7 +186,7 @@ class UrlTest extends PHPUnit_Framework_TestCase
186 /** 186 /**
187 * Test International Domain Name to ASCII conversion 187 * Test International Domain Name to ASCII conversion
188 */ 188 */
189 function testIdnToAscii() 189 public function testIdnToAscii()
190 { 190 {
191 $ind = 'http://www.académie-française.fr/'; 191 $ind = 'http://www.académie-française.fr/';
192 $expected = 'http://www.xn--acadmie-franaise-npb1a.fr/'; 192 $expected = 'http://www.xn--acadmie-franaise-npb1a.fr/';
diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php
index 6a7870c4..d6a0aad5 100644
--- a/tests/UtilsTest.php
+++ b/tests/UtilsTest.php
@@ -4,6 +4,7 @@
4 */ 4 */
5 5
6require_once 'application/Utils.php'; 6require_once 'application/Utils.php';
7require_once 'application/Languages.php';
7require_once 'tests/utils/ReferenceSessionIdHashes.php'; 8require_once 'tests/utils/ReferenceSessionIdHashes.php';
8 9
9// Initialize reference data before PHPUnit starts a session 10// Initialize reference data before PHPUnit starts a session
@@ -23,7 +24,12 @@ class UtilsTest extends PHPUnit_Framework_TestCase
23 24
24 // Expected log date format 25 // Expected log date format
25 protected static $dateFormat = 'Y/m/d H:i:s'; 26 protected static $dateFormat = 'Y/m/d H:i:s';
26 27
28 /**
29 * @var string Save the current timezone.
30 */
31 protected static $defaultTimeZone;
32
27 33
28 /** 34 /**
29 * Assign reference data 35 * Assign reference data
@@ -31,6 +37,17 @@ class UtilsTest extends PHPUnit_Framework_TestCase
31 public static function setUpBeforeClass() 37 public static function setUpBeforeClass()
32 { 38 {
33 self::$sidHashes = ReferenceSessionIdHashes::getHashes(); 39 self::$sidHashes = ReferenceSessionIdHashes::getHashes();
40 self::$defaultTimeZone = date_default_timezone_get();
41 // Timezone without DST for test consistency
42 date_default_timezone_set('Africa/Nairobi');
43 }
44
45 /**
46 * Reset the timezone
47 */
48 public static function tearDownAfterClass()
49 {
50 date_default_timezone_set(self::$defaultTimeZone);
34 } 51 }
35 52
36 /** 53 /**
@@ -253,4 +270,151 @@ class UtilsTest extends PHPUnit_Framework_TestCase
253 is_session_id_valid('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=') 270 is_session_id_valid('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=')
254 ); 271 );
255 } 272 }
273
274 /**
275 * Test generateSecretApi.
276 */
277 public function testGenerateSecretApi()
278 {
279 $this->assertEquals(12, strlen(generate_api_secret('foo', 'bar')));
280 }
281
282 /**
283 * Test generateSecretApi with invalid parameters.
284 */
285 public function testGenerateSecretApiInvalid()
286 {
287 $this->assertFalse(generate_api_secret('', ''));
288 $this->assertFalse(generate_api_secret(false, false));
289 }
290
291 /**
292 * Test normalize_spaces.
293 */
294 public function testNormalizeSpace()
295 {
296 $str = ' foo bar is important ';
297 $this->assertEquals('foo bar is important', normalize_spaces($str));
298 $this->assertEquals('foo', normalize_spaces('foo'));
299 $this->assertEquals('', normalize_spaces(''));
300 $this->assertEquals(null, normalize_spaces(null));
301 }
302
303 /**
304 * Test arrays_combine
305 */
306 public function testCartesianProductGenerator()
307 {
308 $arr = [['ab', 'cd'], ['ef', 'gh'], ['ij', 'kl'], ['m']];
309 $expected = [
310 ['ab', 'ef', 'ij', 'm'],
311 ['ab', 'ef', 'kl', 'm'],
312 ['ab', 'gh', 'ij', 'm'],
313 ['ab', 'gh', 'kl', 'm'],
314 ['cd', 'ef', 'ij', 'm'],
315 ['cd', 'ef', 'kl', 'm'],
316 ['cd', 'gh', 'ij', 'm'],
317 ['cd', 'gh', 'kl', 'm'],
318 ];
319 $this->assertEquals($expected, iterator_to_array(cartesian_product_generator($arr)));
320 }
321
322 /**
323 * Test date_format() with invalid parameter.
324 */
325 public function testDateFormatInvalid()
326 {
327 $this->assertFalse(format_date([]));
328 $this->assertFalse(format_date(null));
329 }
330
331 /**
332 * Test is_integer_mixed with valid values
333 */
334 public function testIsIntegerMixedValid()
335 {
336 $this->assertTrue(is_integer_mixed(12));
337 $this->assertTrue(is_integer_mixed('12'));
338 $this->assertTrue(is_integer_mixed(-12));
339 $this->assertTrue(is_integer_mixed('-12'));
340 $this->assertTrue(is_integer_mixed(0));
341 $this->assertTrue(is_integer_mixed('0'));
342 $this->assertTrue(is_integer_mixed(0x0a));
343 }
344
345 /**
346 * Test is_integer_mixed with invalid values
347 */
348 public function testIsIntegerMixedInvalid()
349 {
350 $this->assertFalse(is_integer_mixed(true));
351 $this->assertFalse(is_integer_mixed(false));
352 $this->assertFalse(is_integer_mixed([]));
353 $this->assertFalse(is_integer_mixed(['test']));
354 $this->assertFalse(is_integer_mixed([12]));
355 $this->assertFalse(is_integer_mixed(new DateTime()));
356 $this->assertFalse(is_integer_mixed('0x0a'));
357 $this->assertFalse(is_integer_mixed('12k'));
358 $this->assertFalse(is_integer_mixed('k12'));
359 $this->assertFalse(is_integer_mixed(''));
360 }
361
362 /**
363 * Test return_bytes
364 */
365 public function testReturnBytes()
366 {
367 $this->assertEquals(2 * 1024, return_bytes('2k'));
368 $this->assertEquals(2 * 1024, return_bytes('2K'));
369 $this->assertEquals(2 * (pow(1024, 2)), return_bytes('2m'));
370 $this->assertEquals(2 * (pow(1024, 2)), return_bytes('2M'));
371 $this->assertEquals(2 * (pow(1024, 3)), return_bytes('2g'));
372 $this->assertEquals(2 * (pow(1024, 3)), return_bytes('2G'));
373 $this->assertEquals(374, return_bytes('374'));
374 $this->assertEquals(374, return_bytes(374));
375 $this->assertEquals(0, return_bytes('0'));
376 $this->assertEquals(0, return_bytes(0));
377 $this->assertEquals(-1, return_bytes('-1'));
378 $this->assertEquals(-1, return_bytes(-1));
379 $this->assertEquals('', return_bytes(''));
380 }
381
382 /**
383 * Test human_bytes
384 */
385 public function testHumanBytes()
386 {
387 $this->assertEquals('2kiB', human_bytes(2 * 1024));
388 $this->assertEquals('2kiB', human_bytes(strval(2 * 1024)));
389 $this->assertEquals('2MiB', human_bytes(2 * (pow(1024, 2))));
390 $this->assertEquals('2MiB', human_bytes(strval(2 * (pow(1024, 2)))));
391 $this->assertEquals('2GiB', human_bytes(2 * (pow(1024, 3))));
392 $this->assertEquals('2GiB', human_bytes(strval(2 * (pow(1024, 3)))));
393 $this->assertEquals('374B', human_bytes(374));
394 $this->assertEquals('374B', human_bytes('374'));
395 $this->assertEquals('232kiB', human_bytes(237481));
396 $this->assertEquals('Unlimited', human_bytes('0'));
397 $this->assertEquals('Unlimited', human_bytes(0));
398 $this->assertEquals('Setting not set', human_bytes(''));
399 }
400
401 /**
402 * Test get_max_upload_size with formatting
403 */
404 public function testGetMaxUploadSize()
405 {
406 $this->assertEquals('1MiB', get_max_upload_size(2097152, '1024k'));
407 $this->assertEquals('1MiB', get_max_upload_size('1m', '2m'));
408 $this->assertEquals('100B', get_max_upload_size(100, 100));
409 }
410
411 /**
412 * Test get_max_upload_size without formatting
413 */
414 public function testGetMaxUploadSizeRaw()
415 {
416 $this->assertEquals('1048576', get_max_upload_size(2097152, '1024k', false));
417 $this->assertEquals('1048576', get_max_upload_size('1m', '2m', false));
418 $this->assertEquals('100', get_max_upload_size(100, 100, false));
419 }
256} 420}
diff --git a/tests/api/ApiMiddlewareTest.php b/tests/api/ApiMiddlewareTest.php
new file mode 100644
index 00000000..23a56b1c
--- /dev/null
+++ b/tests/api/ApiMiddlewareTest.php
@@ -0,0 +1,208 @@
1<?php
2namespace Shaarli\Api;
3
4use Shaarli\Config\ConfigManager;
5
6use Slim\Container;
7use Slim\Http\Environment;
8use Slim\Http\Request;
9use Slim\Http\Response;
10
11/**
12 * Class ApiMiddlewareTest
13 *
14 * Test the REST API Slim Middleware.
15 *
16 * Note that we can't test a valid use case here, because the middleware
17 * needs to call a valid controller/action during its execution.
18 *
19 * @package Api
20 */
21class ApiMiddlewareTest extends \PHPUnit_Framework_TestCase
22{
23 /**
24 * @var string datastore to test write operations
25 */
26 protected static $testDatastore = 'sandbox/datastore.php';
27
28 /**
29 * @var \ConfigManager instance
30 */
31 protected $conf;
32
33 /**
34 * @var \ReferenceLinkDB instance.
35 */
36 protected $refDB = null;
37
38 /**
39 * @var Container instance.
40 */
41 protected $container;
42
43 /**
44 * Before every test, instantiate a new Api with its config, plugins and links.
45 */
46 public function setUp()
47 {
48 $this->conf = new ConfigManager('tests/utils/config/configJson.json.php');
49 $this->conf->set('api.secret', 'NapoleonWasALizard');
50
51 $this->refDB = new \ReferenceLinkDB();
52 $this->refDB->write(self::$testDatastore);
53
54 $this->container = new Container();
55 $this->container['conf'] = $this->conf;
56 }
57
58 /**
59 * After every test, remove the test datastore.
60 */
61 public function tearDown()
62 {
63 @unlink(self::$testDatastore);
64 }
65
66 /**
67 * Invoke the middleware with the API disabled:
68 * should return a 401 error Unauthorized.
69 */
70 public function testInvokeMiddlewareApiDisabled()
71 {
72 $this->conf->set('api.enabled', false);
73 $mw = new ApiMiddleware($this->container);
74 $env = Environment::mock([
75 'REQUEST_METHOD' => 'GET',
76 'REQUEST_URI' => '/echo',
77 ]);
78 $request = Request::createFromEnvironment($env);
79 $response = new Response();
80 /** @var Response $response */
81 $response = $mw($request, $response, null);
82
83 $this->assertEquals(401, $response->getStatusCode());
84 $body = json_decode((string) $response->getBody());
85 $this->assertEquals('Not authorized', $body);
86 }
87
88 /**
89 * Invoke the middleware with the API disabled in debug mode:
90 * should return a 401 error Unauthorized - with a specific message and a stacktrace.
91 */
92 public function testInvokeMiddlewareApiDisabledDebug()
93 {
94 $this->conf->set('api.enabled', false);
95 $this->conf->set('dev.debug', true);
96 $mw = new ApiMiddleware($this->container);
97 $env = Environment::mock([
98 'REQUEST_METHOD' => 'GET',
99 'REQUEST_URI' => '/echo',
100 ]);
101 $request = Request::createFromEnvironment($env);
102 $response = new Response();
103 /** @var Response $response */
104 $response = $mw($request, $response, null);
105
106 $this->assertEquals(401, $response->getStatusCode());
107 $body = json_decode((string) $response->getBody());
108 $this->assertEquals('Not authorized: API is disabled', $body->message);
109 $this->assertContains('ApiAuthorizationException', $body->stacktrace);
110 }
111
112 /**
113 * Invoke the middleware without a token (debug):
114 * should return a 401 error Unauthorized - with a specific message and a stacktrace.
115 */
116 public function testInvokeMiddlewareNoTokenProvidedDebug()
117 {
118 $this->conf->set('dev.debug', true);
119 $mw = new ApiMiddleware($this->container);
120 $env = Environment::mock([
121 'REQUEST_METHOD' => 'GET',
122 'REQUEST_URI' => '/echo',
123 ]);
124 $request = Request::createFromEnvironment($env);
125 $response = new Response();
126 /** @var Response $response */
127 $response = $mw($request, $response, null);
128
129 $this->assertEquals(401, $response->getStatusCode());
130 $body = json_decode((string) $response->getBody());
131 $this->assertEquals('Not authorized: JWT token not provided', $body->message);
132 $this->assertContains('ApiAuthorizationException', $body->stacktrace);
133 }
134
135 /**
136 * Invoke the middleware without a secret set in settings (debug):
137 * should return a 401 error Unauthorized - with a specific message and a stacktrace.
138 */
139 public function testInvokeMiddlewareNoSecretSetDebug()
140 {
141 $this->conf->set('dev.debug', true);
142 $this->conf->set('api.secret', '');
143 $mw = new ApiMiddleware($this->container);
144 $env = Environment::mock([
145 'REQUEST_METHOD' => 'GET',
146 'REQUEST_URI' => '/echo',
147 'HTTP_AUTHORIZATION'=> 'Bearer jwt',
148 ]);
149 $request = Request::createFromEnvironment($env);
150 $response = new Response();
151 /** @var Response $response */
152 $response = $mw($request, $response, null);
153
154 $this->assertEquals(401, $response->getStatusCode());
155 $body = json_decode((string) $response->getBody());
156 $this->assertEquals('Not authorized: Token secret must be set in Shaarli\'s administration', $body->message);
157 $this->assertContains('ApiAuthorizationException', $body->stacktrace);
158 }
159
160 /**
161 * Invoke the middleware with an invalid JWT token header
162 */
163 public function testInvalidJwtAuthHeaderDebug()
164 {
165 $this->conf->set('dev.debug', true);
166 $mw = new ApiMiddleware($this->container);
167 $env = Environment::mock([
168 'REQUEST_METHOD' => 'GET',
169 'REQUEST_URI' => '/echo',
170 'HTTP_AUTHORIZATION'=> 'PolarBearer jwt',
171 ]);
172 $request = Request::createFromEnvironment($env);
173 $response = new Response();
174 /** @var Response $response */
175 $response = $mw($request, $response, null);
176
177 $this->assertEquals(401, $response->getStatusCode());
178 $body = json_decode((string) $response->getBody());
179 $this->assertEquals('Not authorized: Invalid JWT header', $body->message);
180 $this->assertContains('ApiAuthorizationException', $body->stacktrace);
181 }
182
183 /**
184 * Invoke the middleware with an invalid JWT token (debug):
185 * should return a 401 error Unauthorized - with a specific message and a stacktrace.
186 *
187 * Note: specific JWT errors tests are handled in ApiUtilsTest.
188 */
189 public function testInvokeMiddlewareInvalidJwtDebug()
190 {
191 $this->conf->set('dev.debug', true);
192 $mw = new ApiMiddleware($this->container);
193 $env = Environment::mock([
194 'REQUEST_METHOD' => 'GET',
195 'REQUEST_URI' => '/echo',
196 'HTTP_AUTHORIZATION'=> 'Bearer jwt',
197 ]);
198 $request = Request::createFromEnvironment($env);
199 $response = new Response();
200 /** @var Response $response */
201 $response = $mw($request, $response, null);
202
203 $this->assertEquals(401, $response->getStatusCode());
204 $body = json_decode((string) $response->getBody());
205 $this->assertEquals('Not authorized: Malformed JWT token', $body->message);
206 $this->assertContains('ApiAuthorizationException', $body->stacktrace);
207 }
208}
diff --git a/tests/api/ApiUtilsTest.php b/tests/api/ApiUtilsTest.php
new file mode 100644
index 00000000..62baf4c5
--- /dev/null
+++ b/tests/api/ApiUtilsTest.php
@@ -0,0 +1,352 @@
1<?php
2
3namespace Shaarli\Api;
4
5use Shaarli\Base64Url;
6
7
8/**
9 * Class ApiUtilsTest
10 */
11class ApiUtilsTest extends \PHPUnit_Framework_TestCase
12{
13 /**
14 * Force the timezone for ISO datetimes.
15 */
16 public static function setUpBeforeClass()
17 {
18 date_default_timezone_set('UTC');
19 }
20
21 /**
22 * Generate a valid JWT token.
23 *
24 * @param string $secret API secret used to generate the signature.
25 *
26 * @return string Generated token.
27 */
28 public static function generateValidJwtToken($secret)
29 {
30 $header = Base64Url::encode('{
31 "typ": "JWT",
32 "alg": "HS512"
33 }');
34 $payload = Base64Url::encode('{
35 "iat": '. time() .'
36 }');
37 $signature = Base64Url::encode(hash_hmac('sha512', $header .'.'. $payload , $secret, true));
38 return $header .'.'. $payload .'.'. $signature;
39 }
40
41 /**
42 * Generate a JWT token from given header and payload.
43 *
44 * @param string $header Header in JSON format.
45 * @param string $payload Payload in JSON format.
46 * @param string $secret API secret used to hash the signature.
47 *
48 * @return string JWT token.
49 */
50 public static function generateCustomJwtToken($header, $payload, $secret)
51 {
52 $header = Base64Url::encode($header);
53 $payload = Base64Url::encode($payload);
54 $signature = Base64Url::encode(hash_hmac('sha512', $header . '.' . $payload, $secret, true));
55 return $header . '.' . $payload . '.' . $signature;
56 }
57
58 /**
59 * Test validateJwtToken() with a valid JWT token.
60 */
61 public function testValidateJwtTokenValid()
62 {
63 $secret = 'WarIsPeace';
64 ApiUtils::validateJwtToken(self::generateValidJwtToken($secret), $secret);
65 }
66
67 /**
68 * Test validateJwtToken() with a malformed JWT token.
69 *
70 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
71 * @expectedExceptionMessage Malformed JWT token
72 */
73 public function testValidateJwtTokenMalformed()
74 {
75 $token = 'ABC.DEF';
76 ApiUtils::validateJwtToken($token, 'foo');
77 }
78
79 /**
80 * Test validateJwtToken() with an empty JWT token.
81 *
82 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
83 * @expectedExceptionMessage Malformed JWT token
84 */
85 public function testValidateJwtTokenMalformedEmpty()
86 {
87 $token = false;
88 ApiUtils::validateJwtToken($token, 'foo');
89 }
90
91 /**
92 * Test validateJwtToken() with a JWT token without header.
93 *
94 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
95 * @expectedExceptionMessage Malformed JWT token
96 */
97 public function testValidateJwtTokenMalformedEmptyHeader()
98 {
99 $token = '.payload.signature';
100 ApiUtils::validateJwtToken($token, 'foo');
101 }
102
103 /**
104 * Test validateJwtToken() with a JWT token without payload
105 *
106 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
107 * @expectedExceptionMessage Malformed JWT token
108 */
109 public function testValidateJwtTokenMalformedEmptyPayload()
110 {
111 $token = 'header..signature';
112 ApiUtils::validateJwtToken($token, 'foo');
113 }
114
115 /**
116 * Test validateJwtToken() with a JWT token with an empty signature.
117 *
118 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
119 * @expectedExceptionMessage Invalid JWT signature
120 */
121 public function testValidateJwtTokenInvalidSignatureEmpty()
122 {
123 $token = 'header.payload.';
124 ApiUtils::validateJwtToken($token, 'foo');
125 }
126
127 /**
128 * Test validateJwtToken() with a JWT token with an invalid signature.
129 *
130 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
131 * @expectedExceptionMessage Invalid JWT signature
132 */
133 public function testValidateJwtTokenInvalidSignature()
134 {
135 $token = 'header.payload.nope';
136 ApiUtils::validateJwtToken($token, 'foo');
137 }
138
139 /**
140 * Test validateJwtToken() with a JWT token with a signature generated with the wrong API secret.
141 *
142 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
143 * @expectedExceptionMessage Invalid JWT signature
144 */
145 public function testValidateJwtTokenInvalidSignatureSecret()
146 {
147 ApiUtils::validateJwtToken(self::generateValidJwtToken('foo'), 'bar');
148 }
149
150 /**
151 * Test validateJwtToken() with a JWT token with a an invalid header (not JSON).
152 *
153 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
154 * @expectedExceptionMessage Invalid JWT header
155 */
156 public function testValidateJwtTokenInvalidHeader()
157 {
158 $token = $this->generateCustomJwtToken('notJSON', '{"JSON":1}', 'secret');
159 ApiUtils::validateJwtToken($token, 'secret');
160 }
161
162 /**
163 * Test validateJwtToken() with a JWT token with a an invalid payload (not JSON).
164 *
165 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
166 * @expectedExceptionMessage Invalid JWT payload
167 */
168 public function testValidateJwtTokenInvalidPayload()
169 {
170 $token = $this->generateCustomJwtToken('{"JSON":1}', 'notJSON', 'secret');
171 ApiUtils::validateJwtToken($token, 'secret');
172 }
173
174 /**
175 * Test validateJwtToken() with a JWT token without issued time.
176 *
177 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
178 * @expectedExceptionMessage Invalid JWT issued time
179 */
180 public function testValidateJwtTokenInvalidTimeEmpty()
181 {
182 $token = $this->generateCustomJwtToken('{"JSON":1}', '{"JSON":1}', 'secret');
183 ApiUtils::validateJwtToken($token, 'secret');
184 }
185
186 /**
187 * Test validateJwtToken() with an expired JWT token.
188 *
189 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
190 * @expectedExceptionMessage Invalid JWT issued time
191 */
192 public function testValidateJwtTokenInvalidTimeExpired()
193 {
194 $token = $this->generateCustomJwtToken('{"JSON":1}', '{"iat":' . (time() - 600) . '}', 'secret');
195 ApiUtils::validateJwtToken($token, 'secret');
196 }
197
198 /**
199 * Test validateJwtToken() with a JWT token issued in the future.
200 *
201 * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException
202 * @expectedExceptionMessage Invalid JWT issued time
203 */
204 public function testValidateJwtTokenInvalidTimeFuture()
205 {
206 $token = $this->generateCustomJwtToken('{"JSON":1}', '{"iat":' . (time() + 60) . '}', 'secret');
207 ApiUtils::validateJwtToken($token, 'secret');
208 }
209
210 /**
211 * Test formatLink() with a link using all useful fields.
212 */
213 public function testFormatLinkComplete()
214 {
215 $indexUrl = 'https://domain.tld/sub/';
216 $link = [
217 'id' => 12,
218 'url' => 'http://lol.lol',
219 'shorturl' => 'abc',
220 'title' => 'Important Title',
221 'description' => 'It is very lol<tag>' . PHP_EOL . 'new line',
222 'tags' => 'blip .blop ',
223 'private' => '1',
224 'created' => \DateTime::createFromFormat('Ymd_His', '20170107_160102'),
225 'updated' => \DateTime::createFromFormat('Ymd_His', '20170107_160612'),
226 ];
227
228 $expected = [
229 'id' => 12,
230 'url' => 'http://lol.lol',
231 'shorturl' => 'abc',
232 'title' => 'Important Title',
233 'description' => 'It is very lol<tag>' . PHP_EOL . 'new line',
234 'tags' => ['blip', '.blop'],
235 'private' => true,
236 'created' => '2017-01-07T16:01:02+00:00',
237 'updated' => '2017-01-07T16:06:12+00:00',
238 ];
239
240 $this->assertEquals($expected, ApiUtils::formatLink($link, $indexUrl));
241 }
242
243 /**
244 * Test formatLink() with only minimal fields filled, and internal link.
245 */
246 public function testFormatLinkMinimalNote()
247 {
248 $indexUrl = 'https://domain.tld/sub/';
249 $link = [
250 'id' => 12,
251 'url' => '?abc',
252 'shorturl' => 'abc',
253 'title' => 'Note',
254 'description' => '',
255 'tags' => '',
256 'private' => '',
257 'created' => \DateTime::createFromFormat('Ymd_His', '20170107_160102'),
258 ];
259
260 $expected = [
261 'id' => 12,
262 'url' => 'https://domain.tld/sub/?abc',
263 'shorturl' => 'abc',
264 'title' => 'Note',
265 'description' => '',
266 'tags' => [],
267 'private' => false,
268 'created' => '2017-01-07T16:01:02+00:00',
269 'updated' => '',
270 ];
271
272 $this->assertEquals($expected, ApiUtils::formatLink($link, $indexUrl));
273 }
274
275 /**
276 * Test updateLink with valid data, and also unnecessary fields.
277 */
278 public function testUpdateLink()
279 {
280 $created = \DateTime::createFromFormat('Ymd_His', '20170107_160102');
281 $old = [
282 'id' => 12,
283 'url' => '?abc',
284 'shorturl' => 'abc',
285 'title' => 'Note',
286 'description' => '',
287 'tags' => '',
288 'private' => '',
289 'created' => $created,
290 ];
291
292 $new = [
293 'id' => 13,
294 'shorturl' => 'nope',
295 'url' => 'http://somewhere.else',
296 'title' => 'Le Cid',
297 'description' => 'Percé jusques au fond du cœur [...]',
298 'tags' => 'corneille rodrigue',
299 'private' => true,
300 'created' => 'creation',
301 'updated' => 'updation',
302 ];
303
304 $result = ApiUtils::updateLink($old, $new);
305 $this->assertEquals(12, $result['id']);
306 $this->assertEquals('http://somewhere.else', $result['url']);
307 $this->assertEquals('abc', $result['shorturl']);
308 $this->assertEquals('Le Cid', $result['title']);
309 $this->assertEquals('Percé jusques au fond du cœur [...]', $result['description']);
310 $this->assertEquals('corneille rodrigue', $result['tags']);
311 $this->assertEquals(true, $result['private']);
312 $this->assertEquals($created, $result['created']);
313 $this->assertTrue(new \DateTime('5 seconds ago') < $result['updated']);
314 }
315
316 /**
317 * Test updateLink with minimal data.
318 */
319 public function testUpdateLinkMinimal()
320 {
321 $created = \DateTime::createFromFormat('Ymd_His', '20170107_160102');
322 $old = [
323 'id' => 12,
324 'url' => '?abc',
325 'shorturl' => 'abc',
326 'title' => 'Note',
327 'description' => 'Interesting description!',
328 'tags' => 'doggo',
329 'private' => true,
330 'created' => $created,
331 ];
332
333 $new = [
334 'url' => '',
335 'title' => '',
336 'description' => '',
337 'tags' => '',
338 'private' => false,
339 ];
340
341 $result = ApiUtils::updateLink($old, $new);
342 $this->assertEquals(12, $result['id']);
343 $this->assertEquals('?abc', $result['url']);
344 $this->assertEquals('abc', $result['shorturl']);
345 $this->assertEquals('?abc', $result['title']);
346 $this->assertEquals('', $result['description']);
347 $this->assertEquals('', $result['tags']);
348 $this->assertEquals(false, $result['private']);
349 $this->assertEquals($created, $result['created']);
350 $this->assertTrue(new \DateTime('5 seconds ago') < $result['updated']);
351 }
352}
diff --git a/tests/api/controllers/DeleteLinkTest.php b/tests/api/controllers/DeleteLinkTest.php
new file mode 100644
index 00000000..7d797137
--- /dev/null
+++ b/tests/api/controllers/DeleteLinkTest.php
@@ -0,0 +1,126 @@
1<?php
2
3
4namespace Shaarli\Api\Controllers;
5
6use Shaarli\Config\ConfigManager;
7use Slim\Container;
8use Slim\Http\Environment;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12class DeleteLinkTest extends \PHPUnit_Framework_TestCase
13{
14 /**
15 * @var string datastore to test write operations
16 */
17 protected static $testDatastore = 'sandbox/datastore.php';
18
19 /**
20 * @var string datastore to test write operations
21 */
22 protected static $testHistory = 'sandbox/history.php';
23
24 /**
25 * @var ConfigManager instance
26 */
27 protected $conf;
28
29 /**
30 * @var \ReferenceLinkDB instance.
31 */
32 protected $refDB = null;
33
34 /**
35 * @var \LinkDB instance.
36 */
37 protected $linkDB;
38
39 /**
40 * @var \History instance.
41 */
42 protected $history;
43
44 /**
45 * @var Container instance.
46 */
47 protected $container;
48
49 /**
50 * @var Links controller instance.
51 */
52 protected $controller;
53
54 /**
55 * Before each test, instantiate a new Api with its config, plugins and links.
56 */
57 public function setUp()
58 {
59 $this->conf = new ConfigManager('tests/utils/config/configJson');
60 $this->refDB = new \ReferenceLinkDB();
61 $this->refDB->write(self::$testDatastore);
62 $this->linkDB = new \LinkDB(self::$testDatastore, true, false);
63 $refHistory = new \ReferenceHistory();
64 $refHistory->write(self::$testHistory);
65 $this->history = new \History(self::$testHistory);
66 $this->container = new Container();
67 $this->container['conf'] = $this->conf;
68 $this->container['db'] = $this->linkDB;
69 $this->container['history'] = $this->history;
70
71 $this->controller = new Links($this->container);
72 }
73
74 /**
75 * After each test, remove the test datastore.
76 */
77 public function tearDown()
78 {
79 @unlink(self::$testDatastore);
80 @unlink(self::$testHistory);
81 }
82
83 /**
84 * Test DELETE link endpoint: the link should be removed.
85 */
86 public function testDeleteLinkValid()
87 {
88 $id = '41';
89 $this->assertTrue(isset($this->linkDB[$id]));
90 $env = Environment::mock([
91 'REQUEST_METHOD' => 'DELETE',
92 ]);
93 $request = Request::createFromEnvironment($env);
94
95 $response = $this->controller->deleteLink($request, new Response(), ['id' => $id]);
96 $this->assertEquals(204, $response->getStatusCode());
97 $this->assertEmpty((string) $response->getBody());
98
99 $this->linkDB = new \LinkDB(self::$testDatastore, true, false);
100 $this->assertFalse(isset($this->linkDB[$id]));
101
102 $historyEntry = $this->history->getHistory()[0];
103 $this->assertEquals(\History::DELETED, $historyEntry['event']);
104 $this->assertTrue(
105 (new \DateTime())->add(\DateInterval::createFromDateString('-5 seconds')) < $historyEntry['datetime']
106 );
107 $this->assertEquals($id, $historyEntry['id']);
108 }
109
110 /**
111 * Test DELETE link endpoint: reach not existing ID.
112 *
113 * @expectedException Shaarli\Api\Exceptions\ApiLinkNotFoundException
114 */
115 public function testDeleteLink404()
116 {
117 $id = -1;
118 $this->assertFalse(isset($this->linkDB[$id]));
119 $env = Environment::mock([
120 'REQUEST_METHOD' => 'DELETE',
121 ]);
122 $request = Request::createFromEnvironment($env);
123
124 $this->controller->deleteLink($request, new Response(), ['id' => $id]);
125 }
126}
diff --git a/tests/api/controllers/GetLinkIdTest.php b/tests/api/controllers/GetLinkIdTest.php
new file mode 100644
index 00000000..57528d5a
--- /dev/null
+++ b/tests/api/controllers/GetLinkIdTest.php
@@ -0,0 +1,132 @@
1<?php
2
3namespace Shaarli\Api\Controllers;
4
5use Shaarli\Config\ConfigManager;
6
7use Slim\Container;
8use Slim\Http\Environment;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12/**
13 * Class GetLinkIdTest
14 *
15 * Test getLink by ID API service.
16 *
17 * @see http://shaarli.github.io/api-documentation/#links-link-get
18 *
19 * @package Shaarli\Api\Controllers
20 */
21class GetLinkIdTest extends \PHPUnit_Framework_TestCase
22{
23 /**
24 * @var string datastore to test write operations
25 */
26 protected static $testDatastore = 'sandbox/datastore.php';
27
28 /**
29 * @var ConfigManager instance
30 */
31 protected $conf;
32
33 /**
34 * @var \ReferenceLinkDB instance.
35 */
36 protected $refDB = null;
37
38 /**
39 * @var Container instance.
40 */
41 protected $container;
42
43 /**
44 * @var Links controller instance.
45 */
46 protected $controller;
47
48 /**
49 * Number of JSON fields per link.
50 */
51 const NB_FIELDS_LINK = 9;
52
53 /**
54 * Before each test, instantiate a new Api with its config, plugins and links.
55 */
56 public function setUp()
57 {
58 $this->conf = new ConfigManager('tests/utils/config/configJson');
59 $this->refDB = new \ReferenceLinkDB();
60 $this->refDB->write(self::$testDatastore);
61
62 $this->container = new Container();
63 $this->container['conf'] = $this->conf;
64 $this->container['db'] = new \LinkDB(self::$testDatastore, true, false);
65 $this->container['history'] = null;
66
67 $this->controller = new Links($this->container);
68 }
69
70 /**
71 * After each test, remove the test datastore.
72 */
73 public function tearDown()
74 {
75 @unlink(self::$testDatastore);
76 }
77
78 /**
79 * Test basic getLink service: return link ID=41.
80 */
81 public function testGetLinkId()
82 {
83 // Used by index_url().
84 $_SERVER['SERVER_NAME'] = 'domain.tld';
85 $_SERVER['SERVER_PORT'] = 80;
86 $_SERVER['SCRIPT_NAME'] = '/';
87
88 $id = 41;
89 $env = Environment::mock([
90 'REQUEST_METHOD' => 'GET',
91 ]);
92 $request = Request::createFromEnvironment($env);
93
94 $response = $this->controller->getLink($request, new Response(), ['id' => $id]);
95 $this->assertEquals(200, $response->getStatusCode());
96 $data = json_decode((string) $response->getBody(), true);
97 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
98 $this->assertEquals($id, $data['id']);
99
100 // Check link elements
101 $this->assertEquals('http://domain.tld/?WDWyig', $data['url']);
102 $this->assertEquals('WDWyig', $data['shorturl']);
103 $this->assertEquals('Link title: @website', $data['title']);
104 $this->assertEquals(
105 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag',
106 $data['description']
107 );
108 $this->assertEquals('sTuff', $data['tags'][0]);
109 $this->assertEquals(false, $data['private']);
110 $this->assertEquals(
111 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20150310_114651')->format(\DateTime::ATOM),
112 $data['created']
113 );
114 $this->assertEmpty($data['updated']);
115 }
116
117 /**
118 * Test basic getLink service: get non existent link => ApiLinkNotFoundException.
119 *
120 * @expectedException Shaarli\Api\Exceptions\ApiLinkNotFoundException
121 * @expectedExceptionMessage Link not found
122 */
123 public function testGetLink404()
124 {
125 $env = Environment::mock([
126 'REQUEST_METHOD' => 'GET',
127 ]);
128 $request = Request::createFromEnvironment($env);
129
130 $this->controller->getLink($request, new Response(), ['id' => -1]);
131 }
132}
diff --git a/tests/api/controllers/GetLinksTest.php b/tests/api/controllers/GetLinksTest.php
new file mode 100644
index 00000000..84ae7f7a
--- /dev/null
+++ b/tests/api/controllers/GetLinksTest.php
@@ -0,0 +1,389 @@
1<?php
2namespace Shaarli\Api\Controllers;
3
4use Shaarli\Config\ConfigManager;
5
6use Slim\Container;
7use Slim\Http\Environment;
8use Slim\Http\Request;
9use Slim\Http\Response;
10
11/**
12 * Class GetLinksTest
13 *
14 * Test get Link list REST API service.
15 *
16 * @see http://shaarli.github.io/api-documentation/#links-links-collection-get
17 *
18 * @package Shaarli\Api\Controllers
19 */
20class GetLinksTest extends \PHPUnit_Framework_TestCase
21{
22 /**
23 * @var string datastore to test write operations
24 */
25 protected static $testDatastore = 'sandbox/datastore.php';
26
27 /**
28 * @var ConfigManager instance
29 */
30 protected $conf;
31
32 /**
33 * @var \ReferenceLinkDB instance.
34 */
35 protected $refDB = null;
36
37 /**
38 * @var Container instance.
39 */
40 protected $container;
41
42 /**
43 * @var Links controller instance.
44 */
45 protected $controller;
46
47 /**
48 * Number of JSON field per link.
49 */
50 const NB_FIELDS_LINK = 9;
51
52 /**
53 * Before every test, instantiate a new Api with its config, plugins and links.
54 */
55 public function setUp()
56 {
57 $this->conf = new ConfigManager('tests/utils/config/configJson');
58 $this->refDB = new \ReferenceLinkDB();
59 $this->refDB->write(self::$testDatastore);
60
61 $this->container = new Container();
62 $this->container['conf'] = $this->conf;
63 $this->container['db'] = new \LinkDB(self::$testDatastore, true, false);
64 $this->container['history'] = null;
65
66 $this->controller = new Links($this->container);
67 }
68
69 /**
70 * After every test, remove the test datastore.
71 */
72 public function tearDown()
73 {
74 @unlink(self::$testDatastore);
75 }
76
77 /**
78 * Test basic getLinks service: returns all links.
79 */
80 public function testGetLinks()
81 {
82 // Used by index_url().
83 $_SERVER['SERVER_NAME'] = 'domain.tld';
84 $_SERVER['SERVER_PORT'] = 80;
85 $_SERVER['SCRIPT_NAME'] = '/';
86
87 $env = Environment::mock([
88 'REQUEST_METHOD' => 'GET',
89 ]);
90 $request = Request::createFromEnvironment($env);
91
92 $response = $this->controller->getLinks($request, new Response());
93 $this->assertEquals(200, $response->getStatusCode());
94 $data = json_decode((string) $response->getBody(), true);
95 $this->assertEquals($this->refDB->countLinks(), count($data));
96
97 // Check order
98 $order = [41, 8, 6, 7, 0, 1, 4, 42];
99 $cpt = 0;
100 foreach ($data as $link) {
101 $this->assertEquals(self::NB_FIELDS_LINK, count($link));
102 $this->assertEquals($order[$cpt++], $link['id']);
103 }
104
105 // Check first element fields
106 $first = $data[0];
107 $this->assertEquals('http://domain.tld/?WDWyig', $first['url']);
108 $this->assertEquals('WDWyig', $first['shorturl']);
109 $this->assertEquals('Link title: @website', $first['title']);
110 $this->assertEquals(
111 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag',
112 $first['description']
113 );
114 $this->assertEquals('sTuff', $first['tags'][0]);
115 $this->assertEquals(false, $first['private']);
116 $this->assertEquals(
117 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20150310_114651')->format(\DateTime::ATOM),
118 $first['created']
119 );
120 $this->assertEmpty($first['updated']);
121
122 // Multi tags
123 $link = $data[1];
124 $this->assertEquals(7, count($link['tags']));
125
126 // Update date
127 $this->assertEquals(
128 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20160803_093033')->format(\DateTime::ATOM),
129 $link['updated']
130 );
131 }
132
133 /**
134 * Test getLinks service with offset and limit parameter:
135 * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
136 */
137 public function testGetLinksOffsetLimit()
138 {
139 $env = Environment::mock([
140 'REQUEST_METHOD' => 'GET',
141 'QUERY_STRING' => 'offset=1&limit=1'
142 ]);
143 $request = Request::createFromEnvironment($env);
144 $response = $this->controller->getLinks($request, new Response());
145 $this->assertEquals(200, $response->getStatusCode());
146 $data = json_decode((string) $response->getBody(), true);
147 $this->assertEquals(1, count($data));
148 $this->assertEquals(8, $data[0]['id']);
149 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
150 }
151
152 /**
153 * Test getLinks with limit=all (return all link).
154 */
155 public function testGetLinksLimitAll()
156 {
157 $env = Environment::mock([
158 'REQUEST_METHOD' => 'GET',
159 'QUERY_STRING' => 'limit=all'
160 ]);
161 $request = Request::createFromEnvironment($env);
162 $response = $this->controller->getLinks($request, new Response());
163 $this->assertEquals(200, $response->getStatusCode());
164 $data = json_decode((string) $response->getBody(), true);
165 $this->assertEquals($this->refDB->countLinks(), count($data));
166 // Check order
167 $order = [41, 8, 6, 7, 0, 1, 4, 42];
168 $cpt = 0;
169 foreach ($data as $link) {
170 $this->assertEquals(self::NB_FIELDS_LINK, count($link));
171 $this->assertEquals($order[$cpt++], $link['id']);
172 }
173 }
174
175 /**
176 * Test getLinks service with offset and limit parameter:
177 * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
178 */
179 public function testGetLinksOffsetTooHigh()
180 {
181 $env = Environment::mock([
182 'REQUEST_METHOD' => 'GET',
183 'QUERY_STRING' => 'offset=100'
184 ]);
185 $request = Request::createFromEnvironment($env);
186 $response = $this->controller->getLinks($request, new Response());
187 $this->assertEquals(200, $response->getStatusCode());
188 $data = json_decode((string) $response->getBody(), true);
189 $this->assertEmpty(count($data));
190 }
191
192 /**
193 * Test getLinks with visibility parameter set to all
194 */
195 public function testGetLinksVisibilityAll()
196 {
197 $env = Environment::mock(
198 [
199 'REQUEST_METHOD' => 'GET',
200 'QUERY_STRING' => 'visibility=all'
201 ]
202 );
203 $request = Request::createFromEnvironment($env);
204 $response = $this->controller->getLinks($request, new Response());
205 $this->assertEquals(200, $response->getStatusCode());
206 $data = json_decode((string)$response->getBody(), true);
207 $this->assertEquals($this->refDB->countLinks(), count($data));
208 $this->assertEquals(41, $data[0]['id']);
209 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
210 }
211
212 /**
213 * Test getLinks with visibility parameter set to private
214 */
215 public function testGetLinksVisibilityPrivate()
216 {
217 $env = Environment::mock([
218 'REQUEST_METHOD' => 'GET',
219 'QUERY_STRING' => 'visibility=private'
220 ]);
221 $request = Request::createFromEnvironment($env);
222 $response = $this->controller->getLinks($request, new Response());
223 $this->assertEquals(200, $response->getStatusCode());
224 $data = json_decode((string) $response->getBody(), true);
225 $this->assertEquals($this->refDB->countPrivateLinks(), count($data));
226 $this->assertEquals(6, $data[0]['id']);
227 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
228 }
229
230 /**
231 * Test getLinks with visibility parameter set to public
232 */
233 public function testGetLinksVisibilityPublic()
234 {
235 $env = Environment::mock(
236 [
237 'REQUEST_METHOD' => 'GET',
238 'QUERY_STRING' => 'visibility=public'
239 ]
240 );
241 $request = Request::createFromEnvironment($env);
242 $response = $this->controller->getLinks($request, new Response());
243 $this->assertEquals(200, $response->getStatusCode());
244 $data = json_decode((string)$response->getBody(), true);
245 $this->assertEquals($this->refDB->countPublicLinks(), count($data));
246 $this->assertEquals(41, $data[0]['id']);
247 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
248 }
249
250 /**
251 * Test getLinks service with offset and limit parameter:
252 * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
253 */
254 public function testGetLinksSearchTerm()
255 {
256 // Only in description - 1 result
257 $env = Environment::mock([
258 'REQUEST_METHOD' => 'GET',
259 'QUERY_STRING' => 'searchterm=Tropical'
260 ]);
261 $request = Request::createFromEnvironment($env);
262 $response = $this->controller->getLinks($request, new Response());
263 $this->assertEquals(200, $response->getStatusCode());
264 $data = json_decode((string) $response->getBody(), true);
265 $this->assertEquals(1, count($data));
266 $this->assertEquals(1, $data[0]['id']);
267 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
268
269 // Only in tags - 1 result
270 $env = Environment::mock([
271 'REQUEST_METHOD' => 'GET',
272 'QUERY_STRING' => 'searchterm=tag3'
273 ]);
274 $request = Request::createFromEnvironment($env);
275 $response = $this->controller->getLinks($request, new Response());
276 $this->assertEquals(200, $response->getStatusCode());
277 $data = json_decode((string) $response->getBody(), true);
278 $this->assertEquals(1, count($data));
279 $this->assertEquals(0, $data[0]['id']);
280 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
281
282 // Multiple results (2)
283 $env = Environment::mock([
284 'REQUEST_METHOD' => 'GET',
285 'QUERY_STRING' => 'searchterm=stallman'
286 ]);
287 $request = Request::createFromEnvironment($env);
288 $response = $this->controller->getLinks($request, new Response());
289 $this->assertEquals(200, $response->getStatusCode());
290 $data = json_decode((string) $response->getBody(), true);
291 $this->assertEquals(2, count($data));
292 $this->assertEquals(41, $data[0]['id']);
293 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
294 $this->assertEquals(8, $data[1]['id']);
295 $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
296
297 // Multiword - 2 results
298 $env = Environment::mock([
299 'REQUEST_METHOD' => 'GET',
300 'QUERY_STRING' => 'searchterm=stallman+software'
301 ]);
302 $request = Request::createFromEnvironment($env);
303 $response = $this->controller->getLinks($request, new Response());
304 $this->assertEquals(200, $response->getStatusCode());
305 $data = json_decode((string) $response->getBody(), true);
306 $this->assertEquals(2, count($data));
307 $this->assertEquals(41, $data[0]['id']);
308 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
309 $this->assertEquals(8, $data[1]['id']);
310 $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
311
312 // URL encoding
313 $env = Environment::mock([
314 'REQUEST_METHOD' => 'GET',
315 'QUERY_STRING' => 'searchterm='. urlencode('@web')
316 ]);
317 $request = Request::createFromEnvironment($env);
318 $response = $this->controller->getLinks($request, new Response());
319 $this->assertEquals(200, $response->getStatusCode());
320 $data = json_decode((string) $response->getBody(), true);
321 $this->assertEquals(2, count($data));
322 $this->assertEquals(41, $data[0]['id']);
323 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
324 $this->assertEquals(8, $data[1]['id']);
325 $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
326 }
327
328 public function testGetLinksSearchTermNoResult()
329 {
330 $env = Environment::mock([
331 'REQUEST_METHOD' => 'GET',
332 'QUERY_STRING' => 'searchterm=nope'
333 ]);
334 $request = Request::createFromEnvironment($env);
335 $response = $this->controller->getLinks($request, new Response());
336 $this->assertEquals(200, $response->getStatusCode());
337 $data = json_decode((string) $response->getBody(), true);
338 $this->assertEquals(0, count($data));
339 }
340
341 public function testGetLinksSearchTags()
342 {
343 // Single tag
344 $env = Environment::mock([
345 'REQUEST_METHOD' => 'GET',
346 'QUERY_STRING' => 'searchtags=dev',
347 ]);
348 $request = Request::createFromEnvironment($env);
349 $response = $this->controller->getLinks($request, new Response());
350 $this->assertEquals(200, $response->getStatusCode());
351 $data = json_decode((string) $response->getBody(), true);
352 $this->assertEquals(2, count($data));
353 $this->assertEquals(0, $data[0]['id']);
354 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
355 $this->assertEquals(4, $data[1]['id']);
356 $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
357
358 // Multitag + exclude
359 $env = Environment::mock([
360 'REQUEST_METHOD' => 'GET',
361 'QUERY_STRING' => 'searchtags=stuff+-gnu',
362 ]);
363 $request = Request::createFromEnvironment($env);
364 $response = $this->controller->getLinks($request, new Response());
365 $this->assertEquals(200, $response->getStatusCode());
366 $data = json_decode((string) $response->getBody(), true);
367 $this->assertEquals(1, count($data));
368 $this->assertEquals(41, $data[0]['id']);
369 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
370 }
371
372 /**
373 * Test getLinks service with search tags+terms.
374 */
375 public function testGetLinksSearchTermsAndTags()
376 {
377 $env = Environment::mock([
378 'REQUEST_METHOD' => 'GET',
379 'QUERY_STRING' => 'searchterm=poke&searchtags=dev',
380 ]);
381 $request = Request::createFromEnvironment($env);
382 $response = $this->controller->getLinks($request, new Response());
383 $this->assertEquals(200, $response->getStatusCode());
384 $data = json_decode((string) $response->getBody(), true);
385 $this->assertEquals(1, count($data));
386 $this->assertEquals(0, $data[0]['id']);
387 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
388 }
389}
diff --git a/tests/api/controllers/HistoryTest.php b/tests/api/controllers/HistoryTest.php
new file mode 100644
index 00000000..61046d97
--- /dev/null
+++ b/tests/api/controllers/HistoryTest.php
@@ -0,0 +1,216 @@
1<?php
2
3
4namespace Shaarli\Api\Controllers;
5
6
7use Shaarli\Config\ConfigManager;
8use Slim\Container;
9use Slim\Http\Environment;
10use Slim\Http\Request;
11use Slim\Http\Response;
12
13require_once 'tests/utils/ReferenceHistory.php';
14
15class HistoryTest extends \PHPUnit_Framework_TestCase
16{
17 /**
18 * @var string datastore to test write operations
19 */
20 protected static $testHistory = 'sandbox/history.php';
21
22 /**
23 * @var ConfigManager instance
24 */
25 protected $conf;
26
27 /**
28 * @var \ReferenceHistory instance.
29 */
30 protected $refHistory = null;
31
32 /**
33 * @var Container instance.
34 */
35 protected $container;
36
37 /**
38 * @var History controller instance.
39 */
40 protected $controller;
41
42 /**
43 * Before every test, instantiate a new Api with its config, plugins and links.
44 */
45 public function setUp()
46 {
47 $this->conf = new ConfigManager('tests/utils/config/configJson.json.php');
48 $this->refHistory = new \ReferenceHistory();
49 $this->refHistory->write(self::$testHistory);
50 $this->container = new Container();
51 $this->container['conf'] = $this->conf;
52 $this->container['db'] = true;
53 $this->container['history'] = new \History(self::$testHistory);
54
55 $this->controller = new History($this->container);
56 }
57
58 /**
59 * After every test, remove the test datastore.
60 */
61 public function tearDown()
62 {
63 @unlink(self::$testHistory);
64 }
65
66 /**
67 * Test /history service without parameter.
68 */
69 public function testGetHistory()
70 {
71 $env = Environment::mock([
72 'REQUEST_METHOD' => 'GET',
73 ]);
74 $request = Request::createFromEnvironment($env);
75
76 $response = $this->controller->getHistory($request, new Response());
77 $this->assertEquals(200, $response->getStatusCode());
78 $data = json_decode((string) $response->getBody(), true);
79
80 $this->assertEquals($this->refHistory->count(), count($data));
81
82 $this->assertEquals(\History::DELETED, $data[0]['event']);
83 $this->assertEquals(
84 \DateTime::createFromFormat('Ymd_His', '20170303_121216')->format(\DateTime::ATOM),
85 $data[0]['datetime']
86 );
87 $this->assertEquals(124, $data[0]['id']);
88
89 $this->assertEquals(\History::SETTINGS, $data[1]['event']);
90 $this->assertEquals(
91 \DateTime::createFromFormat('Ymd_His', '20170302_121215')->format(\DateTime::ATOM),
92 $data[1]['datetime']
93 );
94 $this->assertNull($data[1]['id']);
95
96 $this->assertEquals(\History::UPDATED, $data[2]['event']);
97 $this->assertEquals(
98 \DateTime::createFromFormat('Ymd_His', '20170301_121214')->format(\DateTime::ATOM),
99 $data[2]['datetime']
100 );
101 $this->assertEquals(123, $data[2]['id']);
102
103 $this->assertEquals(\History::CREATED, $data[3]['event']);
104 $this->assertEquals(
105 \DateTime::createFromFormat('Ymd_His', '20170201_121214')->format(\DateTime::ATOM),
106 $data[3]['datetime']
107 );
108 $this->assertEquals(124, $data[3]['id']);
109
110 $this->assertEquals(\History::CREATED, $data[4]['event']);
111 $this->assertEquals(
112 \DateTime::createFromFormat('Ymd_His', '20170101_121212')->format(\DateTime::ATOM),
113 $data[4]['datetime']
114 );
115 $this->assertEquals(123, $data[4]['id']);
116 }
117
118 /**
119 * Test /history service with limit parameter.
120 */
121 public function testGetHistoryLimit()
122 {
123 $env = Environment::mock([
124 'REQUEST_METHOD' => 'GET',
125 'QUERY_STRING' => 'limit=1'
126 ]);
127 $request = Request::createFromEnvironment($env);
128
129 $response = $this->controller->getHistory($request, new Response());
130 $this->assertEquals(200, $response->getStatusCode());
131 $data = json_decode((string) $response->getBody(), true);
132
133 $this->assertEquals(1, count($data));
134
135 $this->assertEquals(\History::DELETED, $data[0]['event']);
136 $this->assertEquals(
137 \DateTime::createFromFormat('Ymd_His', '20170303_121216')->format(\DateTime::ATOM),
138 $data[0]['datetime']
139 );
140 $this->assertEquals(124, $data[0]['id']);
141 }
142
143 /**
144 * Test /history service with offset parameter.
145 */
146 public function testGetHistoryOffset()
147 {
148 $env = Environment::mock([
149 'REQUEST_METHOD' => 'GET',
150 'QUERY_STRING' => 'offset=4'
151 ]);
152 $request = Request::createFromEnvironment($env);
153
154 $response = $this->controller->getHistory($request, new Response());
155 $this->assertEquals(200, $response->getStatusCode());
156 $data = json_decode((string) $response->getBody(), true);
157
158 $this->assertEquals(1, count($data));
159
160 $this->assertEquals(\History::CREATED, $data[0]['event']);
161 $this->assertEquals(
162 \DateTime::createFromFormat('Ymd_His', '20170101_121212')->format(\DateTime::ATOM),
163 $data[0]['datetime']
164 );
165 $this->assertEquals(123, $data[0]['id']);
166 }
167
168 /**
169 * Test /history service with since parameter.
170 */
171 public function testGetHistorySince()
172 {
173 $env = Environment::mock([
174 'REQUEST_METHOD' => 'GET',
175 'QUERY_STRING' => 'since=2017-03-03T00:00:00%2B00:00'
176 ]);
177 $request = Request::createFromEnvironment($env);
178
179 $response = $this->controller->getHistory($request, new Response());
180 $this->assertEquals(200, $response->getStatusCode());
181 $data = json_decode((string) $response->getBody(), true);
182
183 $this->assertEquals(1, count($data));
184
185 $this->assertEquals(\History::DELETED, $data[0]['event']);
186 $this->assertEquals(
187 \DateTime::createFromFormat('Ymd_His', '20170303_121216')->format(\DateTime::ATOM),
188 $data[0]['datetime']
189 );
190 $this->assertEquals(124, $data[0]['id']);
191 }
192
193 /**
194 * Test /history service with since parameter.
195 */
196 public function testGetHistorySinceOffsetLimit()
197 {
198 $env = Environment::mock([
199 'REQUEST_METHOD' => 'GET',
200 'QUERY_STRING' => 'since=2017-02-01T00:00:00%2B00:00&offset=1&limit=1'
201 ]);
202 $request = Request::createFromEnvironment($env);
203
204 $response = $this->controller->getHistory($request, new Response());
205 $this->assertEquals(200, $response->getStatusCode());
206 $data = json_decode((string) $response->getBody(), true);
207
208 $this->assertEquals(1, count($data));
209
210 $this->assertEquals(\History::SETTINGS, $data[0]['event']);
211 $this->assertEquals(
212 \DateTime::createFromFormat('Ymd_His', '20170302_121215')->format(\DateTime::ATOM),
213 $data[0]['datetime']
214 );
215 }
216}
diff --git a/tests/api/controllers/InfoTest.php b/tests/api/controllers/InfoTest.php
new file mode 100644
index 00000000..e85eb281
--- /dev/null
+++ b/tests/api/controllers/InfoTest.php
@@ -0,0 +1,115 @@
1<?php
2namespace Shaarli\Api\Controllers;
3
4use Shaarli\Config\ConfigManager;
5
6use Slim\Container;
7use Slim\Http\Environment;
8use Slim\Http\Request;
9use Slim\Http\Response;
10
11/**
12 * Class InfoTest
13 *
14 * Test REST API controller Info.
15 *
16 * @package Api\Controllers
17 */
18class InfoTest extends \PHPUnit_Framework_TestCase
19{
20 /**
21 * @var string datastore to test write operations
22 */
23 protected static $testDatastore = 'sandbox/datastore.php';
24
25 /**
26 * @var ConfigManager instance
27 */
28 protected $conf;
29
30 /**
31 * @var \ReferenceLinkDB instance.
32 */
33 protected $refDB = null;
34
35 /**
36 * @var Container instance.
37 */
38 protected $container;
39
40 /**
41 * @var Info controller instance.
42 */
43 protected $controller;
44
45 /**
46 * Before every test, instantiate a new Api with its config, plugins and links.
47 */
48 public function setUp()
49 {
50 $this->conf = new ConfigManager('tests/utils/config/configJson.json.php');
51 $this->refDB = new \ReferenceLinkDB();
52 $this->refDB->write(self::$testDatastore);
53
54 $this->container = new Container();
55 $this->container['conf'] = $this->conf;
56 $this->container['db'] = new \LinkDB(self::$testDatastore, true, false);
57 $this->container['history'] = null;
58
59 $this->controller = new Info($this->container);
60 }
61
62 /**
63 * After every test, remove the test datastore.
64 */
65 public function tearDown()
66 {
67 @unlink(self::$testDatastore);
68 }
69
70 /**
71 * Test /info service.
72 */
73 public function testGetInfo()
74 {
75 $env = Environment::mock([
76 'REQUEST_METHOD' => 'GET',
77 ]);
78 $request = Request::createFromEnvironment($env);
79
80 $response = $this->controller->getInfo($request, new Response());
81 $this->assertEquals(200, $response->getStatusCode());
82 $data = json_decode((string) $response->getBody(), true);
83
84 $this->assertEquals(8, $data['global_counter']);
85 $this->assertEquals(2, $data['private_counter']);
86 $this->assertEquals('Shaarli', $data['settings']['title']);
87 $this->assertEquals('?', $data['settings']['header_link']);
88 $this->assertEquals('UTC', $data['settings']['timezone']);
89 $this->assertEquals(ConfigManager::$DEFAULT_PLUGINS, $data['settings']['enabled_plugins']);
90 $this->assertEquals(false, $data['settings']['default_private_links']);
91
92 $title = 'My links';
93 $headerLink = 'http://shaarli.tld';
94 $timezone = 'Europe/Paris';
95 $enabledPlugins = array('foo', 'bar');
96 $defaultPrivateLinks = true;
97 $this->conf->set('general.title', $title);
98 $this->conf->set('general.header_link', $headerLink);
99 $this->conf->set('general.timezone', $timezone);
100 $this->conf->set('general.enabled_plugins', $enabledPlugins);
101 $this->conf->set('privacy.default_private_links', $defaultPrivateLinks);
102
103 $response = $this->controller->getInfo($request, new Response());
104 $this->assertEquals(200, $response->getStatusCode());
105 $data = json_decode((string) $response->getBody(), true);
106
107 $this->assertEquals(8, $data['global_counter']);
108 $this->assertEquals(2, $data['private_counter']);
109 $this->assertEquals($title, $data['settings']['title']);
110 $this->assertEquals($headerLink, $data['settings']['header_link']);
111 $this->assertEquals($timezone, $data['settings']['timezone']);
112 $this->assertEquals($enabledPlugins, $data['settings']['enabled_plugins']);
113 $this->assertEquals($defaultPrivateLinks, $data['settings']['default_private_links']);
114 }
115}
diff --git a/tests/api/controllers/PostLinkTest.php b/tests/api/controllers/PostLinkTest.php
new file mode 100644
index 00000000..31954e39
--- /dev/null
+++ b/tests/api/controllers/PostLinkTest.php
@@ -0,0 +1,216 @@
1<?php
2
3namespace Shaarli\Api\Controllers;
4
5
6use Shaarli\Config\ConfigManager;
7use Slim\Container;
8use Slim\Http\Environment;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12/**
13 * Class PostLinkTest
14 *
15 * Test POST Link REST API service.
16 *
17 * @package Shaarli\Api\Controllers
18 */
19class PostLinkTest extends \PHPUnit_Framework_TestCase
20{
21 /**
22 * @var string datastore to test write operations
23 */
24 protected static $testDatastore = 'sandbox/datastore.php';
25
26 /**
27 * @var string datastore to test write operations
28 */
29 protected static $testHistory = 'sandbox/history.php';
30
31 /**
32 * @var ConfigManager instance
33 */
34 protected $conf;
35
36 /**
37 * @var \ReferenceLinkDB instance.
38 */
39 protected $refDB = null;
40
41 /**
42 * @var \History instance.
43 */
44 protected $history;
45
46 /**
47 * @var Container instance.
48 */
49 protected $container;
50
51 /**
52 * @var Links controller instance.
53 */
54 protected $controller;
55
56 /**
57 * Number of JSON field per link.
58 */
59 const NB_FIELDS_LINK = 9;
60
61 /**
62 * Before every test, instantiate a new Api with its config, plugins and links.
63 */
64 public function setUp()
65 {
66 $this->conf = new ConfigManager('tests/utils/config/configJson.json.php');
67 $this->refDB = new \ReferenceLinkDB();
68 $this->refDB->write(self::$testDatastore);
69
70 $refHistory = new \ReferenceHistory();
71 $refHistory->write(self::$testHistory);
72 $this->history = new \History(self::$testHistory);
73
74 $this->container = new Container();
75 $this->container['conf'] = $this->conf;
76 $this->container['db'] = new \LinkDB(self::$testDatastore, true, false);
77 $this->container['history'] = new \History(self::$testHistory);
78
79 $this->controller = new Links($this->container);
80
81 $mock = $this->getMock('\Slim\Router', ['relativePathFor']);
82 $mock->expects($this->any())
83 ->method('relativePathFor')
84 ->willReturn('api/v1/links/1');
85
86 // affect @property-read... seems to work
87 $this->controller->getCi()->router = $mock;
88
89 // Used by index_url().
90 $this->controller->getCi()['environment'] = [
91 'SERVER_NAME' => 'domain.tld',
92 'SERVER_PORT' => 80,
93 'SCRIPT_NAME' => '/',
94 ];
95 }
96
97 /**
98 * After every test, remove the test datastore.
99 */
100 public function tearDown()
101 {
102 @unlink(self::$testDatastore);
103 @unlink(self::$testHistory);
104 }
105
106 /**
107 * Test link creation without any field: creates a blank note.
108 */
109 public function testPostLinkMinimal()
110 {
111 $env = Environment::mock([
112 'REQUEST_METHOD' => 'POST',
113 ]);
114
115 $request = Request::createFromEnvironment($env);
116
117 $response = $this->controller->postLink($request, new Response());
118 $this->assertEquals(201, $response->getStatusCode());
119 $this->assertEquals('api/v1/links/1', $response->getHeader('Location')[0]);
120 $data = json_decode((string) $response->getBody(), true);
121 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
122 $this->assertEquals(43, $data['id']);
123 $this->assertRegExp('/[\w-_]{6}/', $data['shorturl']);
124 $this->assertEquals('http://domain.tld/?' . $data['shorturl'], $data['url']);
125 $this->assertEquals('?' . $data['shorturl'], $data['title']);
126 $this->assertEquals('', $data['description']);
127 $this->assertEquals([], $data['tags']);
128 $this->assertEquals(false, $data['private']);
129 $this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created']));
130 $this->assertEquals('', $data['updated']);
131
132 $historyEntry = $this->history->getHistory()[0];
133 $this->assertEquals(\History::CREATED, $historyEntry['event']);
134 $this->assertTrue(
135 (new \DateTime())->add(\DateInterval::createFromDateString('-5 seconds')) < $historyEntry['datetime']
136 );
137 $this->assertEquals(43, $historyEntry['id']);
138 }
139
140 /**
141 * Test link creation with all available fields.
142 */
143 public function testPostLinkFull()
144 {
145 $link = [
146 'url' => 'website.tld/test?foo=bar',
147 'title' => 'new entry',
148 'description' => 'shaare description',
149 'tags' => ['one', 'two'],
150 'private' => true,
151 ];
152 $env = Environment::mock([
153 'REQUEST_METHOD' => 'POST',
154 'CONTENT_TYPE' => 'application/json'
155 ]);
156
157 $request = Request::createFromEnvironment($env);
158 $request = $request->withParsedBody($link);
159 $response = $this->controller->postLink($request, new Response());
160
161 $this->assertEquals(201, $response->getStatusCode());
162 $this->assertEquals('api/v1/links/1', $response->getHeader('Location')[0]);
163 $data = json_decode((string) $response->getBody(), true);
164 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
165 $this->assertEquals(43, $data['id']);
166 $this->assertRegExp('/[\w-_]{6}/', $data['shorturl']);
167 $this->assertEquals('http://' . $link['url'], $data['url']);
168 $this->assertEquals($link['title'], $data['title']);
169 $this->assertEquals($link['description'], $data['description']);
170 $this->assertEquals($link['tags'], $data['tags']);
171 $this->assertEquals(true, $data['private']);
172 $this->assertTrue(new \DateTime('2 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created']));
173 $this->assertEquals('', $data['updated']);
174 }
175
176 /**
177 * Test link creation with an existing link (duplicate URL). Should return a 409 HTTP error and the existing link.
178 */
179 public function testPostLinkDuplicate()
180 {
181 $link = [
182 'url' => 'mediagoblin.org/',
183 'title' => 'new entry',
184 'description' => 'shaare description',
185 'tags' => ['one', 'two'],
186 'private' => true,
187 ];
188 $env = Environment::mock([
189 'REQUEST_METHOD' => 'POST',
190 'CONTENT_TYPE' => 'application/json'
191 ]);
192
193 $request = Request::createFromEnvironment($env);
194 $request = $request->withParsedBody($link);
195 $response = $this->controller->postLink($request, new Response());
196
197 $this->assertEquals(409, $response->getStatusCode());
198 $data = json_decode((string) $response->getBody(), true);
199 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
200 $this->assertEquals(7, $data['id']);
201 $this->assertEquals('IuWvgA', $data['shorturl']);
202 $this->assertEquals('http://mediagoblin.org/', $data['url']);
203 $this->assertEquals('MediaGoblin', $data['title']);
204 $this->assertEquals('A free software media publishing platform #hashtagOther', $data['description']);
205 $this->assertEquals(['gnu', 'media', 'web', '.hidden', 'hashtag'], $data['tags']);
206 $this->assertEquals(false, $data['private']);
207 $this->assertEquals(
208 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20130614_184135'),
209 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
210 );
211 $this->assertEquals(
212 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20130615_184230'),
213 \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
214 );
215 }
216}
diff --git a/tests/api/controllers/PutLinkTest.php b/tests/api/controllers/PutLinkTest.php
new file mode 100644
index 00000000..8a562571
--- /dev/null
+++ b/tests/api/controllers/PutLinkTest.php
@@ -0,0 +1,222 @@
1<?php
2
3
4namespace Shaarli\Api\Controllers;
5
6
7use Shaarli\Config\ConfigManager;
8use Slim\Container;
9use Slim\Http\Environment;
10use Slim\Http\Request;
11use Slim\Http\Response;
12
13class PutLinkTest extends \PHPUnit_Framework_TestCase
14{
15 /**
16 * @var string datastore to test write operations
17 */
18 protected static $testDatastore = 'sandbox/datastore.php';
19
20 /**
21 * @var string datastore to test write operations
22 */
23 protected static $testHistory = 'sandbox/history.php';
24
25 /**
26 * @var ConfigManager instance
27 */
28 protected $conf;
29
30 /**
31 * @var \ReferenceLinkDB instance.
32 */
33 protected $refDB = null;
34
35 /**
36 * @var \History instance.
37 */
38 protected $history;
39
40 /**
41 * @var Container instance.
42 */
43 protected $container;
44
45 /**
46 * @var Links controller instance.
47 */
48 protected $controller;
49
50 /**
51 * Number of JSON field per link.
52 */
53 const NB_FIELDS_LINK = 9;
54
55 /**
56 * Before every test, instantiate a new Api with its config, plugins and links.
57 */
58 public function setUp()
59 {
60 $this->conf = new ConfigManager('tests/utils/config/configJson.json.php');
61 $this->refDB = new \ReferenceLinkDB();
62 $this->refDB->write(self::$testDatastore);
63
64 $refHistory = new \ReferenceHistory();
65 $refHistory->write(self::$testHistory);
66 $this->history = new \History(self::$testHistory);
67
68 $this->container = new Container();
69 $this->container['conf'] = $this->conf;
70 $this->container['db'] = new \LinkDB(self::$testDatastore, true, false);
71 $this->container['history'] = new \History(self::$testHistory);
72
73 $this->controller = new Links($this->container);
74
75 // Used by index_url().
76 $this->controller->getCi()['environment'] = [
77 'SERVER_NAME' => 'domain.tld',
78 'SERVER_PORT' => 80,
79 'SCRIPT_NAME' => '/',
80 ];
81 }
82
83 /**
84 * After every test, remove the test datastore.
85 */
86 public function tearDown()
87 {
88 @unlink(self::$testDatastore);
89 @unlink(self::$testHistory);
90 }
91
92 /**
93 * Test link update without value: reset the link to default values
94 */
95 public function testPutLinkMinimal()
96 {
97 $env = Environment::mock([
98 'REQUEST_METHOD' => 'PUT',
99 ]);
100 $id = '41';
101 $request = Request::createFromEnvironment($env);
102
103 $response = $this->controller->putLink($request, new Response(), ['id' => $id]);
104 $this->assertEquals(200, $response->getStatusCode());
105 $data = json_decode((string) $response->getBody(), true);
106 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
107 $this->assertEquals($id, $data['id']);
108 $this->assertEquals('WDWyig', $data['shorturl']);
109 $this->assertEquals('http://domain.tld/?WDWyig', $data['url']);
110 $this->assertEquals('?WDWyig', $data['title']);
111 $this->assertEquals('', $data['description']);
112 $this->assertEquals([], $data['tags']);
113 $this->assertEquals(false, $data['private']);
114 $this->assertEquals(
115 \DateTime::createFromFormat('Ymd_His', '20150310_114651'),
116 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
117 );
118 $this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated']));
119
120 $historyEntry = $this->history->getHistory()[0];
121 $this->assertEquals(\History::UPDATED, $historyEntry['event']);
122 $this->assertTrue(
123 (new \DateTime())->add(\DateInterval::createFromDateString('-5 seconds')) < $historyEntry['datetime']
124 );
125 $this->assertEquals($id, $historyEntry['id']);
126 }
127
128 /**
129 * Test link update with new values
130 */
131 public function testPutLinkWithValues()
132 {
133 $env = Environment::mock([
134 'REQUEST_METHOD' => 'PUT',
135 'CONTENT_TYPE' => 'application/json'
136 ]);
137 $id = 41;
138 $update = [
139 'url' => 'http://somewhere.else',
140 'title' => 'Le Cid',
141 'description' => 'Percé jusques au fond du cœur [...]',
142 'tags' => ['corneille', 'rodrigue'],
143 'private' => true,
144 ];
145 $request = Request::createFromEnvironment($env);
146 $request = $request->withParsedBody($update);
147
148 $response = $this->controller->putLink($request, new Response(), ['id' => $id]);
149 $this->assertEquals(200, $response->getStatusCode());
150 $data = json_decode((string) $response->getBody(), true);
151 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
152 $this->assertEquals($id, $data['id']);
153 $this->assertEquals('WDWyig', $data['shorturl']);
154 $this->assertEquals('http://somewhere.else', $data['url']);
155 $this->assertEquals('Le Cid', $data['title']);
156 $this->assertEquals('Percé jusques au fond du cœur [...]', $data['description']);
157 $this->assertEquals(['corneille', 'rodrigue'], $data['tags']);
158 $this->assertEquals(true, $data['private']);
159 $this->assertEquals(
160 \DateTime::createFromFormat('Ymd_His', '20150310_114651'),
161 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
162 );
163 $this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated']));
164 }
165
166 /**
167 * Test link update with an existing URL: 409 Conflict with the existing link as body
168 */
169 public function testPutLinkDuplicate()
170 {
171 $link = [
172 'url' => 'mediagoblin.org/',
173 'title' => 'new entry',
174 'description' => 'shaare description',
175 'tags' => ['one', 'two'],
176 'private' => true,
177 ];
178 $env = Environment::mock([
179 'REQUEST_METHOD' => 'PUT',
180 'CONTENT_TYPE' => 'application/json'
181 ]);
182
183 $request = Request::createFromEnvironment($env);
184 $request = $request->withParsedBody($link);
185 $response = $this->controller->putLink($request, new Response(), ['id' => 41]);
186
187 $this->assertEquals(409, $response->getStatusCode());
188 $data = json_decode((string) $response->getBody(), true);
189 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
190 $this->assertEquals(7, $data['id']);
191 $this->assertEquals('IuWvgA', $data['shorturl']);
192 $this->assertEquals('http://mediagoblin.org/', $data['url']);
193 $this->assertEquals('MediaGoblin', $data['title']);
194 $this->assertEquals('A free software media publishing platform #hashtagOther', $data['description']);
195 $this->assertEquals(['gnu', 'media', 'web', '.hidden', 'hashtag'], $data['tags']);
196 $this->assertEquals(false, $data['private']);
197 $this->assertEquals(
198 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20130614_184135'),
199 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
200 );
201 $this->assertEquals(
202 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20130615_184230'),
203 \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
204 );
205 }
206
207 /**
208 * Test link update on non existent link => ApiLinkNotFoundException.
209 *
210 * @expectedException Shaarli\Api\Exceptions\ApiLinkNotFoundException
211 * @expectedExceptionMessage Link not found
212 */
213 public function testGetLink404()
214 {
215 $env = Environment::mock([
216 'REQUEST_METHOD' => 'PUT',
217 ]);
218 $request = Request::createFromEnvironment($env);
219
220 $this->controller->putLink($request, new Response(), ['id' => -1]);
221 }
222}
diff --git a/tests/config/ConfigJsonTest.php b/tests/config/ConfigJsonTest.php
index 07f6ab49..d237bc80 100644
--- a/tests/config/ConfigJsonTest.php
+++ b/tests/config/ConfigJsonTest.php
@@ -1,11 +1,10 @@
1<?php 1<?php
2 2namespace Shaarli\Config;
3require_once 'application/config/ConfigJson.php';
4 3
5/** 4/**
6 * Class ConfigJsonTest 5 * Class ConfigJsonTest
7 */ 6 */
8class ConfigJsonTest extends PHPUnit_Framework_TestCase 7class ConfigJsonTest extends \PHPUnit_Framework_TestCase
9{ 8{
10 /** 9 /**
11 * @var ConfigJson 10 * @var ConfigJson
@@ -40,8 +39,8 @@ class ConfigJsonTest extends PHPUnit_Framework_TestCase
40 /** 39 /**
41 * Read a non existent config file -> empty array. 40 * Read a non existent config file -> empty array.
42 * 41 *
43 * @expectedException Exception 42 * @expectedException \Exception
44 * @expectedExceptionMessage An error occurred while parsing JSON file: error code #4 43 * @expectedExceptionMessageRegExp /An error occurred while parsing JSON configuration file \([\w\/\.]+\): error code #4/
45 */ 44 */
46 public function testReadInvalidJson() 45 public function testReadInvalidJson()
47 { 46 {
@@ -112,7 +111,7 @@ class ConfigJsonTest extends PHPUnit_Framework_TestCase
112 /** 111 /**
113 * Write to invalid path. 112 * Write to invalid path.
114 * 113 *
115 * @expectedException IOException 114 * @expectedException \IOException
116 */ 115 */
117 public function testWriteInvalidArray() 116 public function testWriteInvalidArray()
118 { 117 {
@@ -123,7 +122,7 @@ class ConfigJsonTest extends PHPUnit_Framework_TestCase
123 /** 122 /**
124 * Write to invalid path. 123 * Write to invalid path.
125 * 124 *
126 * @expectedException IOException 125 * @expectedException \IOException
127 */ 126 */
128 public function testWriteInvalidBlank() 127 public function testWriteInvalidBlank()
129 { 128 {
diff --git a/tests/config/ConfigManagerTest.php b/tests/config/ConfigManagerTest.php
index 436e3d67..1ec447b2 100644
--- a/tests/config/ConfigManagerTest.php
+++ b/tests/config/ConfigManagerTest.php
@@ -1,4 +1,5 @@
1<?php 1<?php
2namespace Shaarli\Config;
2 3
3/** 4/**
4 * Unit tests for Class ConfigManagerTest 5 * Unit tests for Class ConfigManagerTest
@@ -6,7 +7,7 @@
6 * Note: it only test the manager with ConfigJson, 7 * Note: it only test the manager with ConfigJson,
7 * ConfigPhp is only a workaround to handle the transition to JSON type. 8 * ConfigPhp is only a workaround to handle the transition to JSON type.
8 */ 9 */
9class ConfigManagerTest extends PHPUnit_Framework_TestCase 10class ConfigManagerTest extends \PHPUnit_Framework_TestCase
10{ 11{
11 /** 12 /**
12 * @var ConfigManager 13 * @var ConfigManager
@@ -83,7 +84,7 @@ class ConfigManagerTest extends PHPUnit_Framework_TestCase
83 /** 84 /**
84 * Set with an empty key. 85 * Set with an empty key.
85 * 86 *
86 * @expectedException Exception 87 * @expectedException \Exception
87 * @expectedExceptionMessageRegExp #^Invalid setting key parameter. String expected, got.*# 88 * @expectedExceptionMessageRegExp #^Invalid setting key parameter. String expected, got.*#
88 */ 89 */
89 public function testSetEmptyKey() 90 public function testSetEmptyKey()
@@ -94,7 +95,7 @@ class ConfigManagerTest extends PHPUnit_Framework_TestCase
94 /** 95 /**
95 * Set with an array key. 96 * Set with an array key.
96 * 97 *
97 * @expectedException Exception 98 * @expectedException \Exception
98 * @expectedExceptionMessageRegExp #^Invalid setting key parameter. String expected, got.*# 99 * @expectedExceptionMessageRegExp #^Invalid setting key parameter. String expected, got.*#
99 */ 100 */
100 public function testSetArrayKey() 101 public function testSetArrayKey()
@@ -105,7 +106,7 @@ class ConfigManagerTest extends PHPUnit_Framework_TestCase
105 /** 106 /**
106 * Try to write the config without mandatory parameter (e.g. 'login'). 107 * Try to write the config without mandatory parameter (e.g. 'login').
107 * 108 *
108 * @expectedException MissingFieldConfigException 109 * @expectedException Shaarli\Config\Exception\MissingFieldConfigException
109 */ 110 */
110 public function testWriteMissingParameter() 111 public function testWriteMissingParameter()
111 { 112 {
diff --git a/tests/config/ConfigPhpTest.php b/tests/config/ConfigPhpTest.php
index 58cd8d2a..abfbb305 100644
--- a/tests/config/ConfigPhpTest.php
+++ b/tests/config/ConfigPhpTest.php
@@ -1,11 +1,10 @@
1<?php 1<?php
2 2namespace Shaarli\Config;
3require_once 'application/config/ConfigPhp.php';
4 3
5/** 4/**
6 * Class ConfigPhpTest 5 * Class ConfigPhpTest
7 */ 6 */
8class ConfigPhpTest extends PHPUnit_Framework_TestCase 7class ConfigPhpTest extends \PHPUnit_Framework_TestCase
9{ 8{
10 /** 9 /**
11 * @var ConfigPhp 10 * @var ConfigPhp
diff --git a/tests/config/ConfigPluginTest.php b/tests/config/ConfigPluginTest.php
index 3b37cd79..deb02c9e 100644
--- a/tests/config/ConfigPluginTest.php
+++ b/tests/config/ConfigPluginTest.php
@@ -1,14 +1,14 @@
1<?php 1<?php
2/** 2namespace Shaarli\Config;
3 * Config' tests 3
4 */ 4use Shaarli\Config\Exception\PluginConfigOrderException;
5 5
6require_once 'application/config/ConfigPlugin.php'; 6require_once 'application/config/ConfigPlugin.php';
7 7
8/** 8/**
9 * Unitary tests for Shaarli config related functions 9 * Unitary tests for Shaarli config related functions
10 */ 10 */
11class ConfigPluginTest extends PHPUnit_Framework_TestCase 11class ConfigPluginTest extends \PHPUnit_Framework_TestCase
12{ 12{
13 /** 13 /**
14 * Test save_plugin_config with valid data. 14 * Test save_plugin_config with valid data.
@@ -39,7 +39,7 @@ class ConfigPluginTest extends PHPUnit_Framework_TestCase
39 /** 39 /**
40 * Test save_plugin_config with invalid data. 40 * Test save_plugin_config with invalid data.
41 * 41 *
42 * @expectedException PluginConfigOrderException 42 * @expectedException Shaarli\Config\Exception\PluginConfigOrderException
43 */ 43 */
44 public function testSavePluginConfigInvalid() 44 public function testSavePluginConfigInvalid()
45 { 45 {
diff --git a/tests/languages/bootstrap.php b/tests/languages/bootstrap.php
new file mode 100644
index 00000000..95609210
--- /dev/null
+++ b/tests/languages/bootstrap.php
@@ -0,0 +1,7 @@
1<?php
2if (! empty('UT_LOCALE')) {
3 setlocale(LC_ALL, getenv('UT_LOCALE'));
4}
5
6require_once 'vendor/autoload.php';
7
diff --git a/tests/languages/de/UtilsDeTest.php b/tests/languages/de/UtilsDeTest.php
new file mode 100644
index 00000000..6c9c9adc
--- /dev/null
+++ b/tests/languages/de/UtilsDeTest.php
@@ -0,0 +1,119 @@
1<?php
2
3require_once 'tests/UtilsTest.php';
4
5
6class UtilsDeTest extends UtilsTest
7{
8 /**
9 * Test date_format().
10 */
11 public function testDateFormat()
12 {
13 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
14 $this->assertRegExp('/1\. Januar 2017 (um )?10:11:12 GMT\+0?3(:00)?/', format_date($date, true, true));
15 }
16
17 /**
18 * Test date_format() without time.
19 */
20 public function testDateFormatNoTime()
21 {
22 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
23 $this->assertRegExp('/1\. Januar 2017/', format_date($date, false,true));
24 }
25
26 /**
27 * Test date_format() using builtin PHP function strftime.
28 */
29 public function testDateFormatDefault()
30 {
31 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
32 $this->assertEquals('So 01 Jan 2017 10:11:12 EAT', format_date($date, true, false));
33 }
34
35 /**
36 * Test date_format() using builtin PHP function strftime without time.
37 */
38 public function testDateFormatDefaultNoTime()
39 {
40 $date = DateTime::createFromFormat('Ymd_His', '20170201_101112');
41 $this->assertEquals('01.02.2017', format_date($date, false, false));
42 }
43
44 /**
45 * Test autoLocale with a simple value
46 */
47 public function testAutoLocaleValid()
48 {
49 $current = setlocale(LC_ALL, 0);
50 $header = 'en-us';
51 autoLocale($header);
52 $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0));
53
54 setlocale(LC_ALL, $current);
55 }
56
57 /**
58 * Test autoLocale with an alternative locale value
59 */
60 public function testAutoLocaleValidAlternative()
61 {
62 $current = setlocale(LC_ALL, 0);
63 $header = 'en_us.UTF8';
64 autoLocale($header);
65 $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0));
66
67 setlocale(LC_ALL, $current);
68 }
69
70 /**
71 * Test autoLocale with multiples value, the first one is valid
72 */
73 public function testAutoLocaleMultipleFirstValid()
74 {
75 $current = setlocale(LC_ALL, 0);
76 $header = 'en-us,de-de';
77 autoLocale($header);
78 $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0));
79
80 setlocale(LC_ALL, $current);
81 }
82
83 /**
84 * Test autoLocale with multiples value, the second one is valid
85 */
86 public function testAutoLocaleMultipleSecondValid()
87 {
88 $current = setlocale(LC_ALL, 0);
89 $header = 'pt_BR,fr-fr';
90 autoLocale($header);
91 $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0));
92
93 setlocale(LC_ALL, $current);
94 }
95
96 /**
97 * Test autoLocale without value: defaults to en_US.
98 */
99 public function testAutoLocaleBlank()
100 {
101 $current = setlocale(LC_ALL, 0);
102 autoLocale('');
103 $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0));
104
105 setlocale(LC_ALL, $current);
106 }
107
108 /**
109 * Test autoLocale with an invalid value: defaults to en_US.
110 */
111 public function testAutoLocaleInvalid()
112 {
113 $current = setlocale(LC_ALL, 0);
114 autoLocale('pt_BR');
115 $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0));
116
117 setlocale(LC_ALL, $current);
118 }
119}
diff --git a/tests/languages/en/UtilsEnTest.php b/tests/languages/en/UtilsEnTest.php
new file mode 100644
index 00000000..d8680b2b
--- /dev/null
+++ b/tests/languages/en/UtilsEnTest.php
@@ -0,0 +1,119 @@
1<?php
2
3require_once 'tests/UtilsTest.php';
4
5
6class UtilsEnTest extends UtilsTest
7{
8 /**
9 * Test date_format().
10 */
11 public function testDateFormat()
12 {
13 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
14 $this->assertRegExp('/January 1, 2017 (at )?10:11:12 AM GMT\+0?3(:00)?/', format_date($date, true, true));
15 }
16
17 /**
18 * Test date_format() without time.
19 */
20 public function testDateFormatNoTime()
21 {
22 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
23 $this->assertRegExp('/January 1, 2017/', format_date($date, false, true));
24 }
25
26 /**
27 * Test date_format() using builtin PHP function strftime.
28 */
29 public function testDateFormatDefault()
30 {
31 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
32 $this->assertEquals('Sun 01 Jan 2017 10:11:12 AM EAT', format_date($date, true, false));
33 }
34
35 /**
36 * Test date_format() using builtin PHP function strftime without time.
37 */
38 public function testDateFormatDefaultNoTime()
39 {
40 $date = DateTime::createFromFormat('Ymd_His', '20170201_101112');
41 $this->assertEquals('02/01/2017', format_date($date, false, false));
42 }
43
44 /**
45 * Test autoLocale with a simple value
46 */
47 public function testAutoLocaleValid()
48 {
49 $current = setlocale(LC_ALL, 0);
50 $header = 'de-de';
51 autoLocale($header);
52 $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0));
53
54 setlocale(LC_ALL, $current);
55 }
56
57 /**
58 * Test autoLocale with an alternative locale value
59 */
60 public function testAutoLocaleValidAlternative()
61 {
62 $current = setlocale(LC_ALL, 0);
63 $header = 'de_de.UTF8';
64 autoLocale($header);
65 $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0));
66
67 setlocale(LC_ALL, $current);
68 }
69
70 /**
71 * Test autoLocale with multiples value, the first one is valid
72 */
73 public function testAutoLocaleMultipleFirstValid()
74 {
75 $current = setlocale(LC_ALL, 0);
76 $header = 'de-de;en-us';
77 autoLocale($header);
78 $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0));
79
80 setlocale(LC_ALL, $current);
81 }
82
83 /**
84 * Test autoLocale with multiples value, the second one is valid
85 */
86 public function testAutoLocaleMultipleSecondValid()
87 {
88 $current = setlocale(LC_ALL, 0);
89 $header = 'pt_BR,fr-fr';
90 autoLocale($header);
91 $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0));
92
93 setlocale(LC_ALL, $current);
94 }
95
96 /**
97 * Test autoLocale without value: defaults to en_US.
98 */
99 public function testAutoLocaleBlank()
100 {
101 $current = setlocale(LC_ALL, 0);
102 autoLocale('');
103 $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0));
104
105 setlocale(LC_ALL, $current);
106 }
107
108 /**
109 * Test autoLocale with an invalid value: defaults to en_US.
110 */
111 public function testAutoLocaleInvalid()
112 {
113 $current = setlocale(LC_ALL, 0);
114 autoLocale('pt_BR');
115 $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0));
116
117 setlocale(LC_ALL, $current);
118 }
119}
diff --git a/tests/languages/fr/UtilsFrTest.php b/tests/languages/fr/UtilsFrTest.php
new file mode 100644
index 00000000..0d50a878
--- /dev/null
+++ b/tests/languages/fr/UtilsFrTest.php
@@ -0,0 +1,119 @@
1<?php
2
3require_once 'tests/UtilsTest.php';
4
5
6class UtilsFrTest extends UtilsTest
7{
8 /**
9 * Test date_format().
10 */
11 public function testDateFormat()
12 {
13 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
14 $this->assertRegExp('/1 janvier 2017 (à )?10:11:12 UTC\+0?3(:00)?/', format_date($date));
15 }
16
17 /**
18 * Test date_format() without time.
19 */
20 public function testDateFormatNoTime()
21 {
22 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
23 $this->assertRegExp('/1 janvier 2017/', format_date($date, false, true));
24 }
25
26 /**
27 * Test date_format() using builtin PHP function strftime.
28 */
29 public function testDateFormatDefault()
30 {
31 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
32 $this->assertEquals('dim. 01 janv. 2017 10:11:12 EAT', format_date($date, true, false));
33 }
34
35 /**
36 * Test date_format() using builtin PHP function strftime without time.
37 */
38 public function testDateFormatDefaultNoTime()
39 {
40 $date = DateTime::createFromFormat('Ymd_His', '20170201_101112');
41 $this->assertEquals('01/02/2017', format_date($date, false, false));
42 }
43
44 /**
45 * Test autoLocale with a simple value
46 */
47 public function testAutoLocaleValid()
48 {
49 $current = setlocale(LC_ALL, 0);
50 $header = 'de-de';
51 autoLocale($header);
52 $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0));
53
54 setlocale(LC_ALL, $current);
55 }
56
57 /**
58 * Test autoLocale with an alternative locale value
59 */
60 public function testAutoLocaleValidAlternative()
61 {
62 $current = setlocale(LC_ALL, 0);
63 $header = 'de_de.UTF8';
64 autoLocale($header);
65 $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0));
66
67 setlocale(LC_ALL, $current);
68 }
69
70 /**
71 * Test autoLocale with multiples value, the first one is valid
72 */
73 public function testAutoLocaleMultipleFirstValid()
74 {
75 $current = setlocale(LC_ALL, 0);
76 $header = 'de-de;en-us';
77 autoLocale($header);
78 $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0));
79
80 setlocale(LC_ALL, $current);
81 }
82
83 /**
84 * Test autoLocale with multiples value, the second one is valid
85 */
86 public function testAutoLocaleMultipleSecondValid()
87 {
88 $current = setlocale(LC_ALL, 0);
89 $header = 'pt_BR,de-de';
90 autoLocale($header);
91 $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0));
92
93 setlocale(LC_ALL, $current);
94 }
95
96 /**
97 * Test autoLocale without value: defaults to en_US.
98 */
99 public function testAutoLocaleBlank()
100 {
101 $current = setlocale(LC_ALL, 0);
102 autoLocale('');
103 $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0));
104
105 setlocale(LC_ALL, $current);
106 }
107
108 /**
109 * Test autoLocale with an invalid value: defaults to en_US.
110 */
111 public function testAutoLocaleInvalid()
112 {
113 $current = setlocale(LC_ALL, 0);
114 autoLocale('pt_BR');
115 $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0));
116
117 setlocale(LC_ALL, $current);
118 }
119}
diff --git a/tests/plugins/PluginAddlinkTest.php b/tests/plugins/PluginAddlinkTest.php
index a2f25bec..b6239e7f 100644
--- a/tests/plugins/PluginAddlinkTest.php
+++ b/tests/plugins/PluginAddlinkTest.php
@@ -16,7 +16,7 @@ class PluginAddlinkTest extends PHPUnit_Framework_TestCase
16 /** 16 /**
17 * Reset plugin path. 17 * Reset plugin path.
18 */ 18 */
19 function setUp() 19 public function setUp()
20 { 20 {
21 PluginManager::$PLUGINS_PATH = 'plugins'; 21 PluginManager::$PLUGINS_PATH = 'plugins';
22 } 22 }
@@ -24,7 +24,7 @@ class PluginAddlinkTest extends PHPUnit_Framework_TestCase
24 /** 24 /**
25 * Test render_header hook while logged in. 25 * Test render_header hook while logged in.
26 */ 26 */
27 function testAddlinkHeaderLoggedIn() 27 public function testAddlinkHeaderLoggedIn()
28 { 28 {
29 $str = 'stuff'; 29 $str = 'stuff';
30 $data = array($str => $str); 30 $data = array($str => $str);
@@ -46,7 +46,7 @@ class PluginAddlinkTest extends PHPUnit_Framework_TestCase
46 /** 46 /**
47 * Test render_header hook while logged out. 47 * Test render_header hook while logged out.
48 */ 48 */
49 function testAddlinkHeaderLoggedOut() 49 public function testAddlinkHeaderLoggedOut()
50 { 50 {
51 $str = 'stuff'; 51 $str = 'stuff';
52 $data = array($str => $str); 52 $data = array($str => $str);
@@ -57,44 +57,4 @@ class PluginAddlinkTest extends PHPUnit_Framework_TestCase
57 $this->assertEquals($str, $data[$str]); 57 $this->assertEquals($str, $data[$str]);
58 $this->assertArrayNotHasKey('fields_toolbar', $data); 58 $this->assertArrayNotHasKey('fields_toolbar', $data);
59 } 59 }
60
61 /**
62 * Test render_includes hook while logged in.
63 */
64 function testAddlinkIncludesLoggedIn()
65 {
66 $str = 'stuff';
67 $data = array($str => $str);
68 $data['_PAGE_'] = Router::$PAGE_LINKLIST;
69 $data['_LOGGEDIN_'] = true;
70
71 $data = hook_addlink_toolbar_render_includes($data);
72 $this->assertEquals($str, $data[$str]);
73 $this->assertEquals(1, count($data['css_files']));
74
75 $str = 'stuff';
76 $data = array($str => $str);
77 $data['_PAGE_'] = $str;
78 $data['_LOGGEDIN_'] = true;
79
80 $data = hook_addlink_toolbar_render_includes($data);
81 $this->assertEquals($str, $data[$str]);
82 $this->assertArrayNotHasKey('css_files', $data);
83 }
84
85 /**
86 * Test render_includes hook.
87 * Should not affect css files while logged out.
88 */
89 function testAddlinkIncludesLoggedOut()
90 {
91 $str = 'stuff';
92 $data = array($str => $str);
93 $data['_PAGE_'] = Router::$PAGE_LINKLIST;
94 $data['_LOGGEDIN_'] = false;
95
96 $data = hook_addlink_toolbar_render_includes($data);
97 $this->assertEquals($str, $data[$str]);
98 $this->assertArrayNotHasKey('css_files', $data);
99 }
100} 60}
diff --git a/tests/plugins/PluginArchiveorgTest.php b/tests/plugins/PluginArchiveorgTest.php
index 4daa4c9d..fecd5f2c 100644
--- a/tests/plugins/PluginArchiveorgTest.php
+++ b/tests/plugins/PluginArchiveorgTest.php
@@ -15,7 +15,7 @@ class PluginArchiveorgTest extends PHPUnit_Framework_TestCase
15 /** 15 /**
16 * Reset plugin path 16 * Reset plugin path
17 */ 17 */
18 function setUp() 18 public function setUp()
19 { 19 {
20 PluginManager::$PLUGINS_PATH = 'plugins'; 20 PluginManager::$PLUGINS_PATH = 'plugins';
21 } 21 }
@@ -23,7 +23,7 @@ class PluginArchiveorgTest extends PHPUnit_Framework_TestCase
23 /** 23 /**
24 * Test render_linklist hook on external links. 24 * Test render_linklist hook on external links.
25 */ 25 */
26 function testArchiveorgLinklistOnExternalLinks() 26 public function testArchiveorgLinklistOnExternalLinks()
27 { 27 {
28 $str = 'http://randomstr.com/test'; 28 $str = 'http://randomstr.com/test';
29 29
@@ -48,13 +48,12 @@ class PluginArchiveorgTest extends PHPUnit_Framework_TestCase
48 // plugin data 48 // plugin data
49 $this->assertEquals(1, count($link['link_plugin'])); 49 $this->assertEquals(1, count($link['link_plugin']));
50 $this->assertNotFalse(strpos($link['link_plugin'][0], $str)); 50 $this->assertNotFalse(strpos($link['link_plugin'][0], $str));
51
52 } 51 }
53 52
54 /** 53 /**
55 * Test render_linklist hook on internal links. 54 * Test render_linklist hook on internal links.
56 */ 55 */
57 function testArchiveorgLinklistOnInternalLinks() 56 public function testArchiveorgLinklistOnInternalLinks()
58 { 57 {
59 $internalLink1 = 'http://shaarli.shaarli/?qvMAqg'; 58 $internalLink1 = 'http://shaarli.shaarli/?qvMAqg';
60 $internalLinkRealURL1 = '?qvMAqg'; 59 $internalLinkRealURL1 = '?qvMAqg';
@@ -101,7 +100,6 @@ class PluginArchiveorgTest extends PHPUnit_Framework_TestCase
101 ) 100 )
102 ); 101 );
103 102
104
105 $data = hook_archiveorg_render_linklist($data); 103 $data = hook_archiveorg_render_linklist($data);
106 104
107 // Case n°1: first link type, public 105 // Case n°1: first link type, public
@@ -136,7 +134,5 @@ class PluginArchiveorgTest extends PHPUnit_Framework_TestCase
136 $link = $data['links'][5]; 134 $link = $data['links'][5];
137 135
138 $this->assertArrayNotHasKey('link_plugin', $link); 136 $this->assertArrayNotHasKey('link_plugin', $link);
139
140 } 137 }
141
142} 138}
diff --git a/tests/plugins/PluginIssoTest.php b/tests/plugins/PluginIssoTest.php
index 6b7904dd..0ae73183 100644
--- a/tests/plugins/PluginIssoTest.php
+++ b/tests/plugins/PluginIssoTest.php
@@ -1,4 +1,5 @@
1<?php 1<?php
2use Shaarli\Config\ConfigManager;
2 3
3require_once 'plugins/isso/isso.php'; 4require_once 'plugins/isso/isso.php';
4 5
@@ -12,7 +13,7 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase
12 /** 13 /**
13 * Reset plugin path 14 * Reset plugin path
14 */ 15 */
15 function setUp() 16 public function setUp()
16 { 17 {
17 PluginManager::$PLUGINS_PATH = 'plugins'; 18 PluginManager::$PLUGINS_PATH = 'plugins';
18 } 19 }
@@ -20,7 +21,7 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase
20 /** 21 /**
21 * Test Isso init without errors. 22 * Test Isso init without errors.
22 */ 23 */
23 function testWallabagInitNoError() 24 public function testWallabagInitNoError()
24 { 25 {
25 $conf = new ConfigManager(''); 26 $conf = new ConfigManager('');
26 $conf->set('plugins.ISSO_SERVER', 'value'); 27 $conf->set('plugins.ISSO_SERVER', 'value');
@@ -31,7 +32,7 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase
31 /** 32 /**
32 * Test Isso init with errors. 33 * Test Isso init with errors.
33 */ 34 */
34 function testWallabagInitError() 35 public function testWallabagInitError()
35 { 36 {
36 $conf = new ConfigManager(''); 37 $conf = new ConfigManager('');
37 $errors = isso_init($conf); 38 $errors = isso_init($conf);
@@ -41,7 +42,7 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase
41 /** 42 /**
42 * Test render_linklist hook with valid settings to display the comment form. 43 * Test render_linklist hook with valid settings to display the comment form.
43 */ 44 */
44 function testIssoDisplayed() 45 public function testIssoDisplayed()
45 { 46 {
46 $conf = new ConfigManager(''); 47 $conf = new ConfigManager('');
47 $conf->set('plugins.ISSO_SERVER', 'value'); 48 $conf->set('plugins.ISSO_SERVER', 'value');
@@ -81,7 +82,7 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase
81 /** 82 /**
82 * Test isso plugin when multiple links are displayed (shouldn't be displayed). 83 * Test isso plugin when multiple links are displayed (shouldn't be displayed).
83 */ 84 */
84 function testIssoMultipleLinks() 85 public function testIssoMultipleLinks()
85 { 86 {
86 $conf = new ConfigManager(''); 87 $conf = new ConfigManager('');
87 $conf->set('plugins.ISSO_SERVER', 'value'); 88 $conf->set('plugins.ISSO_SERVER', 'value');
@@ -113,7 +114,7 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase
113 /** 114 /**
114 * Test isso plugin when using search (shouldn't be displayed). 115 * Test isso plugin when using search (shouldn't be displayed).
115 */ 116 */
116 function testIssoNotDisplayedWhenSearch() 117 public function testIssoNotDisplayedWhenSearch()
117 { 118 {
118 $conf = new ConfigManager(''); 119 $conf = new ConfigManager('');
119 $conf->set('plugins.ISSO_SERVER', 'value'); 120 $conf->set('plugins.ISSO_SERVER', 'value');
@@ -141,7 +142,7 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase
141 /** 142 /**
142 * Test isso plugin without server configuration (shouldn't be displayed). 143 * Test isso plugin without server configuration (shouldn't be displayed).
143 */ 144 */
144 function testIssoWithoutConf() 145 public function testIssoWithoutConf()
145 { 146 {
146 $data = 'abc'; 147 $data = 'abc';
147 $conf = new ConfigManager(''); 148 $conf = new ConfigManager('');
diff --git a/tests/plugins/PluginMarkdownTest.php b/tests/plugins/PluginMarkdownTest.php
index f1e1acf8..d8180ad6 100644
--- a/tests/plugins/PluginMarkdownTest.php
+++ b/tests/plugins/PluginMarkdownTest.php
@@ -1,4 +1,5 @@
1<?php 1<?php
2use Shaarli\Config\ConfigManager;
2 3
3/** 4/**
4 * PluginMarkdownTest.php 5 * PluginMarkdownTest.php
@@ -21,7 +22,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase
21 /** 22 /**
22 * Reset plugin path 23 * Reset plugin path
23 */ 24 */
24 function setUp() 25 public function setUp()
25 { 26 {
26 PluginManager::$PLUGINS_PATH = 'plugins'; 27 PluginManager::$PLUGINS_PATH = 'plugins';
27 $this->conf = new ConfigManager('tests/utils/config/configJson'); 28 $this->conf = new ConfigManager('tests/utils/config/configJson');
@@ -31,7 +32,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase
31 * Test render_linklist hook. 32 * Test render_linklist hook.
32 * Only check that there is basic markdown rendering. 33 * Only check that there is basic markdown rendering.
33 */ 34 */
34 function testMarkdownLinklist() 35 public function testMarkdownLinklist()
35 { 36 {
36 $markdown = '# My title' . PHP_EOL . 'Very interesting content.'; 37 $markdown = '# My title' . PHP_EOL . 'Very interesting content.';
37 $data = array( 38 $data = array(
@@ -51,7 +52,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase
51 * Test render_daily hook. 52 * Test render_daily hook.
52 * Only check that there is basic markdown rendering. 53 * Only check that there is basic markdown rendering.
53 */ 54 */
54 function testMarkdownDaily() 55 public function testMarkdownDaily()
55 { 56 {
56 $markdown = '# My title' . PHP_EOL . 'Very interesting content.'; 57 $markdown = '# My title' . PHP_EOL . 'Very interesting content.';
57 $data = array( 58 $data = array(
@@ -75,7 +76,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase
75 /** 76 /**
76 * Test reverse_text2clickable(). 77 * Test reverse_text2clickable().
77 */ 78 */
78 function testReverseText2clickable() 79 public function testReverseText2clickable()
79 { 80 {
80 $text = 'stuff http://hello.there/is=someone#here otherstuff'; 81 $text = 'stuff http://hello.there/is=someone#here otherstuff';
81 $clickableText = text2clickable($text, ''); 82 $clickableText = text2clickable($text, '');
@@ -86,7 +87,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase
86 /** 87 /**
87 * Test reverse_nl2br(). 88 * Test reverse_nl2br().
88 */ 89 */
89 function testReverseNl2br() 90 public function testReverseNl2br()
90 { 91 {
91 $text = 'stuff' . PHP_EOL . 'otherstuff'; 92 $text = 'stuff' . PHP_EOL . 'otherstuff';
92 $processedText = nl2br($text); 93 $processedText = nl2br($text);
@@ -97,7 +98,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase
97 /** 98 /**
98 * Test reverse_space2nbsp(). 99 * Test reverse_space2nbsp().
99 */ 100 */
100 function testReverseSpace2nbsp() 101 public function testReverseSpace2nbsp()
101 { 102 {
102 $text = ' stuff' . PHP_EOL . ' otherstuff and another'; 103 $text = ' stuff' . PHP_EOL . ' otherstuff and another';
103 $processedText = space2nbsp($text); 104 $processedText = space2nbsp($text);
@@ -108,7 +109,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase
108 /** 109 /**
109 * Test sanitize_html(). 110 * Test sanitize_html().
110 */ 111 */
111 function testSanitizeHtml() 112 public function testSanitizeHtml()
112 { 113 {
113 $input = '< script src="js.js"/>'; 114 $input = '< script src="js.js"/>';
114 $input .= '< script attr>alert(\'xss\');</script>'; 115 $input .= '< script attr>alert(\'xss\');</script>';
@@ -127,7 +128,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase
127 /** 128 /**
128 * Test the no markdown tag. 129 * Test the no markdown tag.
129 */ 130 */
130 function testNoMarkdownTag() 131 public function testNoMarkdownTag()
131 { 132 {
132 $str = 'All _work_ and `no play` makes Jack a *dull* boy.'; 133 $str = 'All _work_ and `no play` makes Jack a *dull* boy.';
133 $data = array( 134 $data = array(
@@ -166,7 +167,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase
166 /** 167 /**
167 * Test that a close value to nomarkdown is not understand as nomarkdown (previous value `.nomarkdown`). 168 * Test that a close value to nomarkdown is not understand as nomarkdown (previous value `.nomarkdown`).
168 */ 169 */
169 function testNoMarkdownNotExcactlyMatching() 170 public function testNoMarkdownNotExcactlyMatching()
170 { 171 {
171 $str = 'All _work_ and `no play` makes Jack a *dull* boy.'; 172 $str = 'All _work_ and `no play` makes Jack a *dull* boy.';
172 $data = array( 173 $data = array(
@@ -184,7 +185,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase
184 /** 185 /**
185 * Test hashtag links processed with markdown. 186 * Test hashtag links processed with markdown.
186 */ 187 */
187 function testMarkdownHashtagLinks() 188 public function testMarkdownHashtagLinks()
188 { 189 {
189 $md = file_get_contents('tests/plugins/resources/markdown.md'); 190 $md = file_get_contents('tests/plugins/resources/markdown.md');
190 $md = format_description($md); 191 $md = format_description($md);
diff --git a/tests/plugins/PluginPlayvideosTest.php b/tests/plugins/PluginPlayvideosTest.php
index be1ef774..29ad047f 100644
--- a/tests/plugins/PluginPlayvideosTest.php
+++ b/tests/plugins/PluginPlayvideosTest.php
@@ -16,7 +16,7 @@ class PluginPlayvideosTest extends PHPUnit_Framework_TestCase
16 /** 16 /**
17 * Reset plugin path 17 * Reset plugin path
18 */ 18 */
19 function setUp() 19 public function setUp()
20 { 20 {
21 PluginManager::$PLUGINS_PATH = 'plugins'; 21 PluginManager::$PLUGINS_PATH = 'plugins';
22 } 22 }
@@ -24,7 +24,7 @@ class PluginPlayvideosTest extends PHPUnit_Framework_TestCase
24 /** 24 /**
25 * Test render_linklist hook. 25 * Test render_linklist hook.
26 */ 26 */
27 function testPlayvideosHeader() 27 public function testPlayvideosHeader()
28 { 28 {
29 $str = 'stuff'; 29 $str = 'stuff';
30 $data = array($str => $str); 30 $data = array($str => $str);
@@ -43,7 +43,7 @@ class PluginPlayvideosTest extends PHPUnit_Framework_TestCase
43 /** 43 /**
44 * Test render_footer hook. 44 * Test render_footer hook.
45 */ 45 */
46 function testPlayvideosFooter() 46 public function testPlayvideosFooter()
47 { 47 {
48 $str = 'stuff'; 48 $str = 'stuff';
49 $data = array($str => $str); 49 $data = array($str => $str);
diff --git a/tests/plugins/PluginPubsubhubbubTest.php b/tests/plugins/PluginPubsubhubbubTest.php
new file mode 100644
index 00000000..69d00936
--- /dev/null
+++ b/tests/plugins/PluginPubsubhubbubTest.php
@@ -0,0 +1,55 @@
1<?php
2use Shaarli\Config\ConfigManager;
3
4require_once 'plugins/pubsubhubbub/pubsubhubbub.php';
5require_once 'application/Router.php';
6
7/**
8 * Class PluginPubsubhubbubTest
9 * Unit test for the pubsubhubbub plugin
10 */
11class PluginPubsubhubbubTest extends PHPUnit_Framework_TestCase
12{
13 /**
14 * @var string Config file path (without extension).
15 */
16 protected static $configFile = 'tests/utils/config/configJson';
17
18 /**
19 * Reset plugin path
20 */
21 public function setUp()
22 {
23 PluginManager::$PLUGINS_PATH = 'plugins';
24 }
25
26 /**
27 * Test render_feed hook with an RSS feed.
28 */
29 public function testPubSubRssRenderFeed()
30 {
31 $hub = 'http://domain.hub';
32 $conf = new ConfigManager(self::$configFile);
33 $conf->set('plugins.PUBSUBHUB_URL', $hub);
34 $data['_PAGE_'] = Router::$PAGE_FEED_RSS;
35
36 $data = hook_pubsubhubbub_render_feed($data, $conf);
37 $expected = '<atom:link rel="hub" href="'. $hub .'" />';
38 $this->assertEquals($expected, $data['feed_plugins_header'][0]);
39 }
40
41 /**
42 * Test render_feed hook with an ATOM feed.
43 */
44 public function testPubSubAtomRenderFeed()
45 {
46 $hub = 'http://domain.hub';
47 $conf = new ConfigManager(self::$configFile);
48 $conf->set('plugins.PUBSUBHUB_URL', $hub);
49 $data['_PAGE_'] = Router::$PAGE_FEED_ATOM;
50
51 $data = hook_pubsubhubbub_render_feed($data, $conf);
52 $expected = '<link rel="hub" href="'. $hub .'" />';
53 $this->assertEquals($expected, $data['feed_plugins_header'][0]);
54 }
55}
diff --git a/tests/plugins/PlugQrcodeTest.php b/tests/plugins/PluginQrcodeTest.php
index 86dc7f29..ebfadddf 100644
--- a/tests/plugins/PlugQrcodeTest.php
+++ b/tests/plugins/PluginQrcodeTest.php
@@ -1,29 +1,28 @@
1<?php 1<?php
2
3/** 2/**
4 * PlugQrcodeTest.php 3 * PluginQrcodeTest.php
5 */ 4 */
6 5
7require_once 'plugins/qrcode/qrcode.php'; 6require_once 'plugins/qrcode/qrcode.php';
8require_once 'application/Router.php'; 7require_once 'application/Router.php';
9 8
10/** 9/**
11 * Class PlugQrcodeTest 10 * Class PluginQrcodeTest
12 * Unit test for the QR-Code plugin 11 * Unit test for the QR-Code plugin
13 */ 12 */
14class PlugQrcodeTest extends PHPUnit_Framework_TestCase 13class PluginQrcodeTest extends PHPUnit_Framework_TestCase
15{ 14{
16 /** 15 /**
17 * Reset plugin path 16 * Reset plugin path
18 */ 17 */
19 function setUp() { 18 public function setUp() {
20 PluginManager::$PLUGINS_PATH = 'plugins'; 19 PluginManager::$PLUGINS_PATH = 'plugins';
21 } 20 }
22 21
23 /** 22 /**
24 * Test render_linklist hook. 23 * Test render_linklist hook.
25 */ 24 */
26 function testQrcodeLinklist() 25 public function testQrcodeLinklist()
27 { 26 {
28 $str = 'http://randomstr.com/test'; 27 $str = 'http://randomstr.com/test';
29 $data = array( 28 $data = array(
@@ -49,7 +48,7 @@ class PlugQrcodeTest extends PHPUnit_Framework_TestCase
49 /** 48 /**
50 * Test render_footer hook. 49 * Test render_footer hook.
51 */ 50 */
52 function testQrcodeFooter() 51 public function testQrcodeFooter()
53 { 52 {
54 $str = 'stuff'; 53 $str = 'stuff';
55 $data = array($str => $str); 54 $data = array($str => $str);
diff --git a/tests/plugins/PluginReadityourselfTest.php b/tests/plugins/PluginReadityourselfTest.php
deleted file mode 100644
index 532db146..00000000
--- a/tests/plugins/PluginReadityourselfTest.php
+++ /dev/null
@@ -1,98 +0,0 @@
1<?php
2
3/**
4 * PluginReadityourselfTest.php.php
5 */
6
7require_once 'plugins/readityourself/readityourself.php';
8
9/**
10 * Class PluginWallabagTest
11 * Unit test for the Wallabag plugin
12 */
13class PluginReadityourselfTest extends PHPUnit_Framework_TestCase
14{
15 /**
16 * Reset plugin path
17 */
18 function setUp()
19 {
20 PluginManager::$PLUGINS_PATH = 'plugins';
21 }
22
23 /**
24 * Test Readityourself init without errors.
25 */
26 function testReadityourselfInitNoError()
27 {
28 $conf = new ConfigManager('');
29 $conf->set('plugins.READITYOUSELF_URL', 'value');
30 $errors = readityourself_init($conf);
31 $this->assertEmpty($errors);
32 }
33
34 /**
35 * Test Readityourself init with errors.
36 */
37 function testReadityourselfInitError()
38 {
39 $conf = new ConfigManager('');
40 $errors = readityourself_init($conf);
41 $this->assertNotEmpty($errors);
42 }
43
44 /**
45 * Test render_linklist hook.
46 */
47 function testReadityourselfLinklist()
48 {
49 $conf = new ConfigManager('');
50 $conf->set('plugins.READITYOUSELF_URL', 'value');
51 $str = 'http://randomstr.com/test';
52 $data = array(
53 'title' => $str,
54 'links' => array(
55 array(
56 'url' => $str,
57 )
58 )
59 );
60
61 $data = hook_readityourself_render_linklist($data, $conf);
62 $link = $data['links'][0];
63 // data shouldn't be altered
64 $this->assertEquals($str, $data['title']);
65 $this->assertEquals($str, $link['url']);
66
67 // plugin data
68 $this->assertEquals(1, count($link['link_plugin']));
69 $this->assertNotFalse(strpos($link['link_plugin'][0], $str));
70 }
71
72 /**
73 * Test without config: nothing should happened.
74 */
75 function testReadityourselfLinklistWithoutConfig()
76 {
77 $conf = new ConfigManager('');
78 $conf->set('plugins.READITYOUSELF_URL', null);
79 $str = 'http://randomstr.com/test';
80 $data = array(
81 'title' => $str,
82 'links' => array(
83 array(
84 'url' => $str,
85 )
86 )
87 );
88
89 $data = hook_readityourself_render_linklist($data, $conf);
90 $link = $data['links'][0];
91 // data shouldn't be altered
92 $this->assertEquals($str, $data['title']);
93 $this->assertEquals($str, $link['url']);
94
95 // plugin data
96 $this->assertArrayNotHasKey('link_plugin', $link);
97 }
98}
diff --git a/tests/plugins/PluginWallabagTest.php b/tests/plugins/PluginWallabagTest.php
index 2c268cbd..76b7887e 100644
--- a/tests/plugins/PluginWallabagTest.php
+++ b/tests/plugins/PluginWallabagTest.php
@@ -1,4 +1,5 @@
1<?php 1<?php
2use Shaarli\Config\ConfigManager;
2 3
3/** 4/**
4 * PluginWallabagTest.php.php 5 * PluginWallabagTest.php.php
@@ -15,7 +16,7 @@ class PluginWallabagTest extends PHPUnit_Framework_TestCase
15 /** 16 /**
16 * Reset plugin path 17 * Reset plugin path
17 */ 18 */
18 function setUp() 19 public function setUp()
19 { 20 {
20 PluginManager::$PLUGINS_PATH = 'plugins'; 21 PluginManager::$PLUGINS_PATH = 'plugins';
21 } 22 }
@@ -23,7 +24,7 @@ class PluginWallabagTest extends PHPUnit_Framework_TestCase
23 /** 24 /**
24 * Test wallabag init without errors. 25 * Test wallabag init without errors.
25 */ 26 */
26 function testWallabagInitNoError() 27 public function testWallabagInitNoError()
27 { 28 {
28 $conf = new ConfigManager(''); 29 $conf = new ConfigManager('');
29 $conf->set('plugins.WALLABAG_URL', 'value'); 30 $conf->set('plugins.WALLABAG_URL', 'value');
@@ -34,7 +35,7 @@ class PluginWallabagTest extends PHPUnit_Framework_TestCase
34 /** 35 /**
35 * Test wallabag init with errors. 36 * Test wallabag init with errors.
36 */ 37 */
37 function testWallabagInitError() 38 public function testWallabagInitError()
38 { 39 {
39 $conf = new ConfigManager(''); 40 $conf = new ConfigManager('');
40 $errors = wallabag_init($conf); 41 $errors = wallabag_init($conf);
@@ -44,7 +45,7 @@ class PluginWallabagTest extends PHPUnit_Framework_TestCase
44 /** 45 /**
45 * Test render_linklist hook. 46 * Test render_linklist hook.
46 */ 47 */
47 function testWallabagLinklist() 48 public function testWallabagLinklist()
48 { 49 {
49 $conf = new ConfigManager(''); 50 $conf = new ConfigManager('');
50 $conf->set('plugins.WALLABAG_URL', 'value'); 51 $conf->set('plugins.WALLABAG_URL', 'value');
diff --git a/tests/plugins/WallabagInstanceTest.php b/tests/plugins/WallabagInstanceTest.php
index 7c14c1df..2c466871 100644
--- a/tests/plugins/WallabagInstanceTest.php
+++ b/tests/plugins/WallabagInstanceTest.php
@@ -15,7 +15,7 @@ class WallabagInstanceTest extends PHPUnit_Framework_TestCase
15 /** 15 /**
16 * Reset plugin path 16 * Reset plugin path
17 */ 17 */
18 function setUp() 18 public function setUp()
19 { 19 {
20 $this->instance = 'http://some.url'; 20 $this->instance = 'http://some.url';
21 } 21 }
@@ -23,7 +23,7 @@ class WallabagInstanceTest extends PHPUnit_Framework_TestCase
23 /** 23 /**
24 * Test WallabagInstance with API V1. 24 * Test WallabagInstance with API V1.
25 */ 25 */
26 function testWallabagInstanceV1() 26 public function testWallabagInstanceV1()
27 { 27 {
28 $instance = new WallabagInstance($this->instance, 1); 28 $instance = new WallabagInstance($this->instance, 1);
29 $expected = $this->instance . '/?plainurl='; 29 $expected = $this->instance . '/?plainurl=';
@@ -34,7 +34,7 @@ class WallabagInstanceTest extends PHPUnit_Framework_TestCase
34 /** 34 /**
35 * Test WallabagInstance with API V2. 35 * Test WallabagInstance with API V2.
36 */ 36 */
37 function testWallabagInstanceV2() 37 public function testWallabagInstanceV2()
38 { 38 {
39 $instance = new WallabagInstance($this->instance, 2); 39 $instance = new WallabagInstance($this->instance, 2);
40 $expected = $this->instance . '/bookmarklet?url='; 40 $expected = $this->instance . '/bookmarklet?url=';
@@ -45,7 +45,7 @@ class WallabagInstanceTest extends PHPUnit_Framework_TestCase
45 /** 45 /**
46 * Test WallabagInstance with an invalid API version. 46 * Test WallabagInstance with an invalid API version.
47 */ 47 */
48 function testWallabagInstanceInvalidVersion() 48 public function testWallabagInstanceInvalidVersion()
49 { 49 {
50 $instance = new WallabagInstance($this->instance, false); 50 $instance = new WallabagInstance($this->instance, false);
51 $expected = $this->instance . '/?plainurl='; 51 $expected = $this->instance . '/?plainurl=';
diff --git a/tests/utils/ReferenceHistory.php b/tests/utils/ReferenceHistory.php
new file mode 100644
index 00000000..75cbb326
--- /dev/null
+++ b/tests/utils/ReferenceHistory.php
@@ -0,0 +1,82 @@
1<?php
2
3/**
4 * Populates a reference history
5 */
6class ReferenceHistory
7{
8 private $count;
9
10 private $history = [];
11
12 /**
13 * Populates the test DB with reference data
14 */
15 public function __construct()
16 {
17 $this->addEntry(
18 History::DELETED,
19 DateTime::createFromFormat('Ymd_His', '20170303_121216'),
20 124
21 );
22
23 $this->addEntry(
24 History::SETTINGS,
25 DateTime::createFromFormat('Ymd_His', '20170302_121215')
26 );
27
28 $this->addEntry(
29 History::UPDATED,
30 DateTime::createFromFormat('Ymd_His', '20170301_121214'),
31 123
32 );
33
34 $this->addEntry(
35 History::CREATED,
36 DateTime::createFromFormat('Ymd_His', '20170201_121214'),
37 124
38 );
39
40 $this->addEntry(
41 History::CREATED,
42 DateTime::createFromFormat('Ymd_His', '20170101_121212'),
43 123
44 );
45 }
46
47 /**
48 * Adds a new history entry
49 *
50 * @param string $event Event identifier
51 * @param DateTime $datetime creation date
52 * @param int $id optional: related link ID
53 */
54 protected function addEntry($event, $datetime, $id = null)
55 {
56 $link = [
57 'event' => $event,
58 'datetime' => $datetime,
59 'id' => $id,
60 ];
61 $this->history[] = $link;
62 $this->count++;
63 }
64
65 /**
66 * Writes data to the datastore
67 *
68 * @param string $filename write history content to.
69 */
70 public function write($filename)
71 {
72 FileUtils::writeFlatDB($filename, $this->history);
73 }
74
75 /**
76 * Returns the number of links in the reference data
77 */
78 public function count()
79 {
80 return $this->count;
81 }
82}
diff --git a/tests/utils/ReferenceLinkDB.php b/tests/utils/ReferenceLinkDB.php
index 36d58c68..1f4b3063 100644
--- a/tests/utils/ReferenceLinkDB.php
+++ b/tests/utils/ReferenceLinkDB.php
@@ -56,7 +56,7 @@ class ReferenceLinkDB
56 0, 56 0,
57 DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20130614_184135'), 57 DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20130614_184135'),
58 'gnu media web .hidden hashtag', 58 'gnu media web .hidden hashtag',
59 null, 59 DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20130615_184230'),
60 'IuWvgA' 60 'IuWvgA'
61 ); 61 );
62 62
diff --git a/tests/utils/config/configJson.json.php b/tests/utils/config/configJson.json.php
index 06a302e8..9c9288f3 100644
--- a/tests/utils/config/configJson.json.php
+++ b/tests/utils/config/configJson.json.php
@@ -24,7 +24,8 @@
24 }, 24 },
25 "resource": { 25 "resource": {
26 "datastore": "tests\/utils\/config\/datastore.php", 26 "datastore": "tests\/utils\/config\/datastore.php",
27 "data_dir": "tests\/utils\/config" 27 "data_dir": "sandbox/",
28 "raintpl_tpl": "tpl/"
28 }, 29 },
29 "plugins": { 30 "plugins": {
30 "WALLABAG_VERSION": 1 31 "WALLABAG_VERSION": 1