diff options
Diffstat (limited to 'tests')
62 files changed, 5053 insertions, 441 deletions
diff --git a/tests/ApplicationUtilsTest.php b/tests/ApplicationUtilsTest.php index 4a0975bf..ff4c9e17 100644 --- a/tests/ApplicationUtilsTest.php +++ b/tests/ApplicationUtilsTest.php | |||
@@ -1,9 +1,10 @@ | |||
1 | <?php | 1 | <?php |
2 | use Shaarli\Config\ConfigManager; | ||
3 | |||
2 | /** | 4 | /** |
3 | * ApplicationUtils' tests | 5 | * ApplicationUtils' tests |
4 | */ | 6 | */ |
5 | 7 | ||
6 | require_once 'application/config/ConfigManager.php'; | ||
7 | require_once 'application/ApplicationUtils.php'; | 8 | require_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 | .'stable/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 | |||
3 | require_once 'application/FileUtils.php'; | ||
4 | |||
5 | /** | ||
6 | * Class FileUtilsTest | ||
7 | * | ||
8 | * Test file utility class. | ||
9 | */ | ||
10 | class 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 | |||
3 | require_once 'application/History.php'; | ||
4 | |||
5 | |||
6 | class 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/IsHttpsTest.php b/tests/HttpUtils/IsHttpsTest.php new file mode 100644 index 00000000..097f2bcf --- /dev/null +++ b/tests/HttpUtils/IsHttpsTest.php | |||
@@ -0,0 +1,36 @@ | |||
1 | <?php | ||
2 | |||
3 | |||
4 | /** | ||
5 | * Class IsHttpsTest | ||
6 | * | ||
7 | * Test class for is_https() function. | ||
8 | */ | ||
9 | class IsHttpsTest extends PHPUnit_Framework_TestCase | ||
10 | { | ||
11 | |||
12 | /** | ||
13 | * Test is_https with HTTPS values. | ||
14 | */ | ||
15 | public function testIsHttpsTrue() | ||
16 | { | ||
17 | $this->assertTrue(is_https(['HTTPS' => true])); | ||
18 | $this->assertTrue(is_https(['HTTPS' => '1'])); | ||
19 | $this->assertTrue(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => 443])); | ||
20 | $this->assertTrue(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => '443'])); | ||
21 | $this->assertTrue(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => '443,123,456,'])); | ||
22 | } | ||
23 | |||
24 | /** | ||
25 | * Test is_https with HTTP values. | ||
26 | */ | ||
27 | public function testIsHttpsFalse() | ||
28 | { | ||
29 | $this->assertFalse(is_https([])); | ||
30 | $this->assertFalse(is_https(['HTTPS' => false])); | ||
31 | $this->assertFalse(is_https(['HTTPS' => '0'])); | ||
32 | $this->assertFalse(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => 123])); | ||
33 | $this->assertFalse(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => '123'])); | ||
34 | $this->assertFalse(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => ',123,456,'])); | ||
35 | } | ||
36 | } | ||
diff --git a/tests/HttpUtils/ServerUrlTest.php b/tests/HttpUtils/ServerUrlTest.php index 8a55a220..324b827a 100644 --- a/tests/HttpUtils/ServerUrlTest.php +++ b/tests/HttpUtils/ServerUrlTest.php | |||
@@ -39,6 +39,34 @@ class ServerUrlTest extends PHPUnit_Framework_TestCase | |||
39 | } | 39 | } |
40 | 40 | ||
41 | /** | 41 | /** |
42 | * Detect a Proxy that sets Forwarded-Host | ||
43 | */ | ||
44 | public function testHttpsProxyForwardedHost() | ||
45 | { | ||
46 | $this->assertEquals( | ||
47 | 'https://host.tld:8080', | ||
48 | server_url( | ||
49 | array( | ||
50 | 'HTTP_X_FORWARDED_PROTO' => 'https', | ||
51 | 'HTTP_X_FORWARDED_PORT' => '8080', | ||
52 | 'HTTP_X_FORWARDED_HOST' => 'host.tld' | ||
53 | ) | ||
54 | ) | ||
55 | ); | ||
56 | |||
57 | $this->assertEquals( | ||
58 | 'https://host.tld:4974', | ||
59 | server_url( | ||
60 | array( | ||
61 | 'HTTP_X_FORWARDED_PROTO' => 'https, https', | ||
62 | 'HTTP_X_FORWARDED_PORT' => '4974, 80', | ||
63 | 'HTTP_X_FORWARDED_HOST' => 'host.tld, example.com' | ||
64 | ) | ||
65 | ) | ||
66 | ); | ||
67 | } | ||
68 | |||
69 | /** | ||
42 | * Detect a Proxy with SSL enabled | 70 | * Detect a Proxy with SSL enabled |
43 | */ | 71 | */ |
44 | public function testHttpsProxyForward() | 72 | public function testHttpsProxyForward() |
@@ -69,6 +97,19 @@ class ServerUrlTest extends PHPUnit_Framework_TestCase | |||
69 | ); | 97 | ); |
70 | 98 | ||
71 | $this->assertEquals( | 99 | $this->assertEquals( |
100 | 'https://host.tld', | ||
101 | server_url( | ||
102 | array( | ||
103 | 'HTTPS' => 'Off', | ||
104 | 'SERVER_NAME' => 'host.tld', | ||
105 | 'SERVER_PORT' => '80', | ||
106 | 'HTTP_X_FORWARDED_PROTO' => 'https', | ||
107 | 'HTTP_X_FORWARDED_PORT' => '443' | ||
108 | ) | ||
109 | ) | ||
110 | ); | ||
111 | |||
112 | $this->assertEquals( | ||
72 | 'https://host.tld:4974', | 113 | 'https://host.tld:4974', |
73 | server_url( | 114 | server_url( |
74 | array( | 115 | array( |
@@ -145,4 +186,36 @@ class ServerUrlTest extends PHPUnit_Framework_TestCase | |||
145 | ) | 186 | ) |
146 | ); | 187 | ); |
147 | } | 188 | } |
189 | |||
190 | /** | ||
191 | * Misconfigured server (see #1022): Proxy HTTP but 443 | ||
192 | */ | ||
193 | public function testHttpWithPort433() | ||
194 | { | ||
195 | $this->assertEquals( | ||
196 | 'https://host.tld', | ||
197 | server_url( | ||
198 | array( | ||
199 | 'HTTPS' => 'Off', | ||
200 | 'SERVER_NAME' => 'host.tld', | ||
201 | 'SERVER_PORT' => '80', | ||
202 | 'HTTP_X_FORWARDED_PROTO' => 'http', | ||
203 | 'HTTP_X_FORWARDED_PORT' => '443' | ||
204 | ) | ||
205 | ) | ||
206 | ); | ||
207 | |||
208 | $this->assertEquals( | ||
209 | 'https://host.tld', | ||
210 | server_url( | ||
211 | array( | ||
212 | 'HTTPS' => 'Off', | ||
213 | 'SERVER_NAME' => 'host.tld', | ||
214 | 'SERVER_PORT' => '80', | ||
215 | 'HTTP_X_FORWARDED_PROTO' => 'https, http', | ||
216 | 'HTTP_X_FORWARDED_PORT' => '443, 80' | ||
217 | ) | ||
218 | ) | ||
219 | ); | ||
220 | } | ||
148 | } | 221 | } |
diff --git a/tests/LanguagesTest.php b/tests/LanguagesTest.php index 79c136c8..864ce630 100644 --- a/tests/LanguagesTest.php +++ b/tests/LanguagesTest.php | |||
@@ -1,41 +1,203 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | require_once 'application/Languages.php'; | 3 | namespace Shaarli; |
4 | |||
5 | use Shaarli\Config\ConfigManager; | ||
4 | 6 | ||
5 | /** | 7 | /** |
6 | * Class LanguagesTest. | 8 | * Class LanguagesTest. |
7 | */ | 9 | */ |
8 | class LanguagesTest extends PHPUnit_Framework_TestCase | 10 | class LanguagesTest extends \PHPUnit_Framework_TestCase |
9 | { | 11 | { |
10 | /** | 12 | /** |
13 | * @var string Config file path (without extension). | ||
14 | */ | ||
15 | protected static $configFile = 'tests/utils/config/configJson'; | ||
16 | |||
17 | /** | ||
18 | * @var ConfigManager | ||
19 | */ | ||
20 | protected $conf; | ||
21 | |||
22 | /** | ||
23 | * | ||
24 | */ | ||
25 | public function setUp() | ||
26 | { | ||
27 | $this->conf = new ConfigManager(self::$configFile); | ||
28 | } | ||
29 | |||
30 | /** | ||
31 | * Test t() with a simple non identified value. | ||
32 | */ | ||
33 | public function testTranslateSingleNotIDGettext() | ||
34 | { | ||
35 | $this->conf->set('translation.mode', 'gettext'); | ||
36 | new Languages('en', $this->conf); | ||
37 | $text = 'abcdé 564 fgK'; | ||
38 | $this->assertEquals($text, t($text)); | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * Test t() with a simple identified value in gettext mode. | ||
43 | */ | ||
44 | public function testTranslateSingleIDGettext() | ||
45 | { | ||
46 | $this->conf->set('translation.mode', 'gettext'); | ||
47 | new Languages('en', $this->conf); | ||
48 | $text = 'permalink'; | ||
49 | $this->assertEquals($text, t($text)); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Test t() with a non identified plural form in gettext mode. | ||
54 | */ | ||
55 | public function testTranslatePluralNotIDGettext() | ||
56 | { | ||
57 | $this->conf->set('translation.mode', 'gettext'); | ||
58 | new Languages('en', $this->conf); | ||
59 | $text = 'sandwich'; | ||
60 | $nText = 'sandwiches'; | ||
61 | $this->assertEquals('sandwiches', t($text, $nText, 0)); | ||
62 | $this->assertEquals('sandwich', t($text, $nText, 1)); | ||
63 | $this->assertEquals('sandwiches', t($text, $nText, 2)); | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * Test t() with an identified plural form in gettext mode. | ||
68 | */ | ||
69 | public function testTranslatePluralIDGettext() | ||
70 | { | ||
71 | $this->conf->set('translation.mode', 'gettext'); | ||
72 | new Languages('en', $this->conf); | ||
73 | $text = 'shaare'; | ||
74 | $nText = 'shaares'; | ||
75 | // In english, zero is followed by plural form | ||
76 | $this->assertEquals('shaares', t($text, $nText, 0)); | ||
77 | $this->assertEquals('shaare', t($text, $nText, 1)); | ||
78 | $this->assertEquals('shaares', t($text, $nText, 2)); | ||
79 | } | ||
80 | |||
81 | /** | ||
11 | * Test t() with a simple non identified value. | 82 | * Test t() with a simple non identified value. |
12 | */ | 83 | */ |
13 | public function testTranslateSingleNotID() | 84 | public function testTranslateSingleNotIDPhp() |
14 | { | 85 | { |
86 | $this->conf->set('translation.mode', 'php'); | ||
87 | new Languages('en', $this->conf); | ||
15 | $text = 'abcdé 564 fgK'; | 88 | $text = 'abcdé 564 fgK'; |
16 | $this->assertEquals($text, t($text)); | 89 | $this->assertEquals($text, t($text)); |
17 | } | 90 | } |
18 | 91 | ||
19 | /** | 92 | /** |
20 | * Test t() with a non identified plural form. | 93 | * Test t() with a simple identified value in PHP mode. |
21 | */ | 94 | */ |
22 | public function testTranslatePluralNotID() | 95 | public function testTranslateSingleIDPhp() |
23 | { | 96 | { |
24 | $text = '%s sandwich'; | 97 | $this->conf->set('translation.mode', 'php'); |
25 | $nText = '%s sandwiches'; | 98 | new Languages('en', $this->conf); |
26 | $this->assertEquals('0 sandwich', t($text, $nText)); | 99 | $text = 'permalink'; |
27 | $this->assertEquals('1 sandwich', t($text, $nText, 1)); | 100 | $this->assertEquals($text, t($text)); |
28 | $this->assertEquals('2 sandwiches', t($text, $nText, 2)); | ||
29 | } | 101 | } |
30 | 102 | ||
31 | /** | 103 | /** |
32 | * Test t() with a non identified invalid plural form. | 104 | * Test t() with a non identified plural form in PHP mode. |
33 | */ | 105 | */ |
34 | public function testTranslatePluralNotIDInvalid() | 106 | public function testTranslatePluralNotIDPhp() |
35 | { | 107 | { |
108 | $this->conf->set('translation.mode', 'php'); | ||
109 | new Languages('en', $this->conf); | ||
36 | $text = 'sandwich'; | 110 | $text = 'sandwich'; |
37 | $nText = 'sandwiches'; | 111 | $nText = 'sandwiches'; |
112 | $this->assertEquals('sandwiches', t($text, $nText, 0)); | ||
38 | $this->assertEquals('sandwich', t($text, $nText, 1)); | 113 | $this->assertEquals('sandwich', t($text, $nText, 1)); |
39 | $this->assertEquals('sandwiches', t($text, $nText, 2)); | 114 | $this->assertEquals('sandwiches', t($text, $nText, 2)); |
40 | } | 115 | } |
116 | |||
117 | /** | ||
118 | * Test t() with an identified plural form in PHP mode. | ||
119 | */ | ||
120 | public function testTranslatePluralIDPhp() | ||
121 | { | ||
122 | $this->conf->set('translation.mode', 'php'); | ||
123 | new Languages('en', $this->conf); | ||
124 | $text = 'shaare'; | ||
125 | $nText = 'shaares'; | ||
126 | // In english, zero is followed by plural form | ||
127 | $this->assertEquals('shaares', t($text, $nText, 0)); | ||
128 | $this->assertEquals('shaare', t($text, $nText, 1)); | ||
129 | $this->assertEquals('shaares', t($text, $nText, 2)); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Test t() with an invalid language set in the configuration in gettext mode. | ||
134 | */ | ||
135 | public function testTranslateWithInvalidConfLanguageGettext() | ||
136 | { | ||
137 | $this->conf->set('translation.mode', 'gettext'); | ||
138 | $this->conf->set('translation.language', 'nope'); | ||
139 | new Languages('fr', $this->conf); | ||
140 | $text = 'grumble'; | ||
141 | $this->assertEquals($text, t($text)); | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * Test t() with an invalid language set in the configuration in PHP mode. | ||
146 | */ | ||
147 | public function testTranslateWithInvalidConfLanguagePhp() | ||
148 | { | ||
149 | $this->conf->set('translation.mode', 'php'); | ||
150 | $this->conf->set('translation.language', 'nope'); | ||
151 | new Languages('fr', $this->conf); | ||
152 | $text = 'grumble'; | ||
153 | $this->assertEquals($text, t($text)); | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * Test t() with an invalid language set with auto language in gettext mode. | ||
158 | */ | ||
159 | public function testTranslateWithInvalidAutoLanguageGettext() | ||
160 | { | ||
161 | $this->conf->set('translation.mode', 'gettext'); | ||
162 | new Languages('nope', $this->conf); | ||
163 | $text = 'grumble'; | ||
164 | $this->assertEquals($text, t($text)); | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * Test t() with an invalid language set with auto language in PHP mode. | ||
169 | */ | ||
170 | public function testTranslateWithInvalidAutoLanguagePhp() | ||
171 | { | ||
172 | $this->conf->set('translation.mode', 'php'); | ||
173 | new Languages('nope', $this->conf); | ||
174 | $text = 'grumble'; | ||
175 | $this->assertEquals($text, t($text)); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * Test t() with an extension language file in gettext mode | ||
180 | */ | ||
181 | public function testTranslationExtensionGettext() | ||
182 | { | ||
183 | $this->conf->set('translation.mode', 'gettext'); | ||
184 | $this->conf->set('translation.extensions.test', 'tests/utils/languages/'); | ||
185 | new Languages('en', $this->conf); | ||
186 | $txt = 'car'; // ignore me poedit | ||
187 | $this->assertEquals('car', t($txt, $txt, 1, 'test')); | ||
188 | $this->assertEquals('Search', t('Search', 'Search', 1, 'test')); | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * Test t() with an extension language file in PHP mode | ||
193 | */ | ||
194 | public function testTranslationExtensionPhp() | ||
195 | { | ||
196 | $this->conf->set('translation.mode', 'php'); | ||
197 | $this->conf->set('translation.extensions.test', 'tests/utils/languages/'); | ||
198 | new Languages('en', $this->conf); | ||
199 | $txt = 'car'; // ignore me poedit | ||
200 | $this->assertEquals('car', t($txt, $txt, 1, 'test')); | ||
201 | $this->assertEquals('Search', t('Search', 'Search', 1, 'test')); | ||
202 | } | ||
41 | } | 203 | } |
diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php index 1f62a34a..5b2f3667 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 | { |
@@ -297,7 +297,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
297 | 'sTuff' => 2, | 297 | 'sTuff' => 2, |
298 | 'ut' => 1, | 298 | 'ut' => 1, |
299 | ), | 299 | ), |
300 | self::$publicLinkDB->allTags() | 300 | self::$publicLinkDB->linksCountPerTag() |
301 | ); | 301 | ); |
302 | 302 | ||
303 | $this->assertEquals( | 303 | $this->assertEquals( |
@@ -325,7 +325,34 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
325 | 'tag4' => 1, | 325 | 'tag4' => 1, |
326 | 'ut' => 1, | 326 | 'ut' => 1, |
327 | ), | 327 | ), |
328 | self::$privateLinkDB->allTags() | 328 | self::$privateLinkDB->linksCountPerTag() |
329 | ); | ||
330 | $this->assertEquals( | ||
331 | array( | ||
332 | 'web' => 4, | ||
333 | 'cartoon' => 2, | ||
334 | 'gnu' => 1, | ||
335 | 'dev' => 1, | ||
336 | 'samba' => 1, | ||
337 | 'media' => 1, | ||
338 | 'html' => 1, | ||
339 | 'w3c' => 1, | ||
340 | 'css' => 1, | ||
341 | 'Mercurial' => 1, | ||
342 | '.hidden' => 1, | ||
343 | 'hashtag' => 1, | ||
344 | ), | ||
345 | self::$privateLinkDB->linksCountPerTag(['web']) | ||
346 | ); | ||
347 | $this->assertEquals( | ||
348 | array( | ||
349 | 'web' => 1, | ||
350 | 'html' => 1, | ||
351 | 'w3c' => 1, | ||
352 | 'css' => 1, | ||
353 | 'Mercurial' => 1, | ||
354 | ), | ||
355 | self::$privateLinkDB->linksCountPerTag(['web'], 'private') | ||
329 | ); | 356 | ); |
330 | } | 357 | } |
331 | 358 | ||
@@ -448,7 +475,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
448 | public function testReorderLinksDesc() | 475 | public function testReorderLinksDesc() |
449 | { | 476 | { |
450 | self::$privateLinkDB->reorder('ASC'); | 477 | self::$privateLinkDB->reorder('ASC'); |
451 | $linkIds = array(42, 4, 1, 0, 7, 6, 8, 41); | 478 | $linkIds = array(42, 4, 9, 1, 0, 7, 6, 8, 41); |
452 | $cpt = 0; | 479 | $cpt = 0; |
453 | foreach (self::$privateLinkDB as $key => $value) { | 480 | foreach (self::$privateLinkDB as $key => $value) { |
454 | $this->assertEquals($linkIds[$cpt++], $key); | 481 | $this->assertEquals($linkIds[$cpt++], $key); |
@@ -460,4 +487,59 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
460 | $this->assertEquals($linkIds[$cpt++], $key); | 487 | $this->assertEquals($linkIds[$cpt++], $key); |
461 | } | 488 | } |
462 | } | 489 | } |
490 | |||
491 | /** | ||
492 | * Test rename tag with a valid value present in multiple links | ||
493 | */ | ||
494 | public function testRenameTagMultiple() | ||
495 | { | ||
496 | self::$refDB->write(self::$testDatastore); | ||
497 | $linkDB = new LinkDB(self::$testDatastore, true, false); | ||
498 | |||
499 | $res = $linkDB->renameTag('cartoon', 'Taz'); | ||
500 | $this->assertEquals(3, count($res)); | ||
501 | $this->assertContains(' Taz ', $linkDB[4]['tags']); | ||
502 | $this->assertContains(' Taz ', $linkDB[1]['tags']); | ||
503 | $this->assertContains(' Taz ', $linkDB[0]['tags']); | ||
504 | } | ||
505 | |||
506 | /** | ||
507 | * Test rename tag with a valid value | ||
508 | */ | ||
509 | public function testRenameTagCaseSensitive() | ||
510 | { | ||
511 | self::$refDB->write(self::$testDatastore); | ||
512 | $linkDB = new LinkDB(self::$testDatastore, true, false, ''); | ||
513 | |||
514 | $res = $linkDB->renameTag('sTuff', 'Taz'); | ||
515 | $this->assertEquals(1, count($res)); | ||
516 | $this->assertEquals('Taz', $linkDB[41]['tags']); | ||
517 | } | ||
518 | |||
519 | /** | ||
520 | * Test rename tag with invalid values | ||
521 | */ | ||
522 | public function testRenameTagInvalid() | ||
523 | { | ||
524 | $linkDB = new LinkDB(self::$testDatastore, false, false); | ||
525 | |||
526 | $this->assertFalse($linkDB->renameTag('', 'test')); | ||
527 | $this->assertFalse($linkDB->renameTag('', '')); | ||
528 | // tag non existent | ||
529 | $this->assertEquals([], $linkDB->renameTag('test', '')); | ||
530 | $this->assertEquals([], $linkDB->renameTag('test', 'retest')); | ||
531 | } | ||
532 | |||
533 | /** | ||
534 | * Test delete tag with a valid value | ||
535 | */ | ||
536 | public function testDeleteTag() | ||
537 | { | ||
538 | self::$refDB->write(self::$testDatastore); | ||
539 | $linkDB = new LinkDB(self::$testDatastore, true, false); | ||
540 | |||
541 | $res = $linkDB->renameTag('cartoon', null); | ||
542 | $this->assertEquals(3, count($res)); | ||
543 | $this->assertNotContains('cartoon', $linkDB[4]['tags']); | ||
544 | } | ||
463 | } | 545 | } |
diff --git a/tests/LinkFilterTest.php b/tests/LinkFilterTest.php index 21d680a5..9cd6dbd4 100644 --- a/tests/LinkFilterTest.php +++ b/tests/LinkFilterTest.php | |||
@@ -8,17 +8,33 @@ require_once 'application/LinkFilter.php'; | |||
8 | class LinkFilterTest extends PHPUnit_Framework_TestCase | 8 | class LinkFilterTest extends PHPUnit_Framework_TestCase |
9 | { | 9 | { |
10 | /** | 10 | /** |
11 | * @var string Test datastore path. | ||
12 | */ | ||
13 | protected static $testDatastore = 'sandbox/datastore.php'; | ||
14 | /** | ||
11 | * @var LinkFilter instance. | 15 | * @var LinkFilter instance. |
12 | */ | 16 | */ |
13 | protected static $linkFilter; | 17 | protected static $linkFilter; |
14 | 18 | ||
15 | /** | 19 | /** |
20 | * @var ReferenceLinkDB instance | ||
21 | */ | ||
22 | protected static $refDB; | ||
23 | |||
24 | /** | ||
25 | * @var LinkDB instance | ||
26 | */ | ||
27 | protected static $linkDB; | ||
28 | |||
29 | /** | ||
16 | * Instanciate linkFilter with ReferenceLinkDB data. | 30 | * Instanciate linkFilter with ReferenceLinkDB data. |
17 | */ | 31 | */ |
18 | public static function setUpBeforeClass() | 32 | public static function setUpBeforeClass() |
19 | { | 33 | { |
20 | $refDB = new ReferenceLinkDB(); | 34 | self::$refDB = new ReferenceLinkDB(); |
21 | self::$linkFilter = new LinkFilter($refDB->getLinks()); | 35 | self::$refDB->write(self::$testDatastore); |
36 | self::$linkDB = new LinkDB(self::$testDatastore, true, false); | ||
37 | self::$linkFilter = new LinkFilter(self::$linkDB); | ||
22 | } | 38 | } |
23 | 39 | ||
24 | /** | 40 | /** |
@@ -27,14 +43,30 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
27 | public function testFilter() | 43 | public function testFilter() |
28 | { | 44 | { |
29 | $this->assertEquals( | 45 | $this->assertEquals( |
30 | ReferenceLinkDB::$NB_LINKS_TOTAL, | 46 | self::$refDB->countLinks(), |
31 | count(self::$linkFilter->filter('', '')) | 47 | count(self::$linkFilter->filter('', '')) |
32 | ); | 48 | ); |
33 | 49 | ||
50 | $this->assertEquals( | ||
51 | self::$refDB->countLinks(), | ||
52 | count(self::$linkFilter->filter('', '', 'all')) | ||
53 | ); | ||
54 | |||
55 | $this->assertEquals( | ||
56 | self::$refDB->countLinks(), | ||
57 | count(self::$linkFilter->filter('', '', 'randomstr')) | ||
58 | ); | ||
59 | |||
34 | // Private only. | 60 | // Private only. |
35 | $this->assertEquals( | 61 | $this->assertEquals( |
36 | 2, | 62 | self::$refDB->countPrivateLinks(), |
37 | count(self::$linkFilter->filter('', '', false, true)) | 63 | count(self::$linkFilter->filter('', '', false, 'private')) |
64 | ); | ||
65 | |||
66 | // Public only. | ||
67 | $this->assertEquals( | ||
68 | self::$refDB->countPublicLinks(), | ||
69 | count(self::$linkFilter->filter('', '', false, 'public')) | ||
38 | ); | 70 | ); |
39 | 71 | ||
40 | $this->assertEquals( | 72 | $this->assertEquals( |
@@ -43,6 +75,11 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
43 | ); | 75 | ); |
44 | 76 | ||
45 | $this->assertEquals( | 77 | $this->assertEquals( |
78 | self::$refDB->countUntaggedLinks(), | ||
79 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, /*$request=*/'', /*$casesensitive=*/false, /*$visibility=*/'all', /*$untaggedonly=*/true)) | ||
80 | ); | ||
81 | |||
82 | $this->assertEquals( | ||
46 | ReferenceLinkDB::$NB_LINKS_TOTAL, | 83 | ReferenceLinkDB::$NB_LINKS_TOTAL, |
47 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '')) | 84 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '')) |
48 | ); | 85 | ); |
@@ -58,10 +95,26 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
58 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false)) | 95 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false)) |
59 | ); | 96 | ); |
60 | 97 | ||
98 | $this->assertEquals( | ||
99 | 4, | ||
100 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'all')) | ||
101 | ); | ||
102 | |||
103 | $this->assertEquals( | ||
104 | 4, | ||
105 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'default-blabla')) | ||
106 | ); | ||
107 | |||
61 | // Private only. | 108 | // Private only. |
62 | $this->assertEquals( | 109 | $this->assertEquals( |
63 | 1, | 110 | 1, |
64 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, true)) | 111 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'private')) |
112 | ); | ||
113 | |||
114 | // Public only. | ||
115 | $this->assertEquals( | ||
116 | 3, | ||
117 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'public')) | ||
65 | ); | 118 | ); |
66 | } | 119 | } |
67 | 120 | ||
@@ -109,7 +162,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
109 | public function testFilterDay() | 162 | public function testFilterDay() |
110 | { | 163 | { |
111 | $this->assertEquals( | 164 | $this->assertEquals( |
112 | 3, | 165 | 4, |
113 | count(self::$linkFilter->filter(LinkFilter::$FILTER_DAY, '20121206')) | 166 | count(self::$linkFilter->filter(LinkFilter::$FILTER_DAY, '20121206')) |
114 | ); | 167 | ); |
115 | } | 168 | } |
@@ -253,14 +306,30 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
253 | public function testFilterFullTextTags() | 306 | public function testFilterFullTextTags() |
254 | { | 307 | { |
255 | $this->assertEquals( | 308 | $this->assertEquals( |
256 | 2, | 309 | 6, |
257 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'gnu')) | 310 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web')) |
311 | ); | ||
312 | |||
313 | $this->assertEquals( | ||
314 | 6, | ||
315 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'all')) | ||
316 | ); | ||
317 | |||
318 | $this->assertEquals( | ||
319 | 6, | ||
320 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'bla')) | ||
258 | ); | 321 | ); |
259 | 322 | ||
260 | // Private only. | 323 | // Private only. |
261 | $this->assertEquals( | 324 | $this->assertEquals( |
262 | 1, | 325 | 1, |
263 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, true)) | 326 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'private')) |
327 | ); | ||
328 | |||
329 | // Public only. | ||
330 | $this->assertEquals( | ||
331 | 5, | ||
332 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'public')) | ||
264 | ); | 333 | ); |
265 | } | 334 | } |
266 | 335 | ||
@@ -286,7 +355,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
286 | ); | 355 | ); |
287 | 356 | ||
288 | $this->assertEquals( | 357 | $this->assertEquals( |
289 | 7, | 358 | ReferenceLinkDB::$NB_LINKS_TOTAL - 1, |
290 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '-revolution')) | 359 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '-revolution')) |
291 | ); | 360 | ); |
292 | } | 361 | } |
@@ -346,7 +415,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
346 | ); | 415 | ); |
347 | 416 | ||
348 | $this->assertEquals( | 417 | $this->assertEquals( |
349 | 7, | 418 | ReferenceLinkDB::$NB_LINKS_TOTAL - 1, |
350 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, '-free')) | 419 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, '-free')) |
351 | ); | 420 | ); |
352 | } | 421 | } |
@@ -376,6 +445,13 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
376 | 1, | 445 | 1, |
377 | count(self::$linkFilter->filter( | 446 | count(self::$linkFilter->filter( |
378 | LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT, | 447 | LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT, |
448 | array(false, 'PSR-2') | ||
449 | )) | ||
450 | ); | ||
451 | $this->assertEquals( | ||
452 | 1, | ||
453 | count(self::$linkFilter->filter( | ||
454 | LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT, | ||
379 | array($tags, '') | 455 | array($tags, '') |
380 | )) | 456 | )) |
381 | ); | 457 | ); |
@@ -409,7 +485,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
409 | LinkFilter::$FILTER_TAG, | 485 | LinkFilter::$FILTER_TAG, |
410 | $hashtag, | 486 | $hashtag, |
411 | false, | 487 | false, |
412 | true | 488 | 'private' |
413 | )) | 489 | )) |
414 | ); | 490 | ); |
415 | } | 491 | } |
diff --git a/tests/LinkUtilsTest.php b/tests/LinkUtilsTest.php index 7c0d4b0b..7fbd59b0 100644 --- a/tests/LinkUtilsTest.php +++ b/tests/LinkUtilsTest.php | |||
@@ -29,27 +29,13 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase | |||
29 | } | 29 | } |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * Test get_charset() with all priorities. | ||
33 | */ | ||
34 | public function testGetCharset() | ||
35 | { | ||
36 | $headers = array('Content-Type' => 'text/html; charset=Headers'); | ||
37 | $html = '<html><meta>stuff</meta><meta charset="Html"/></html>'; | ||
38 | $default = 'default'; | ||
39 | $this->assertEquals('headers', get_charset($headers, $html, $default)); | ||
40 | $this->assertEquals('html', get_charset(array(), $html, $default)); | ||
41 | $this->assertEquals($default, get_charset(array(), '', $default)); | ||
42 | $this->assertEquals('utf-8', get_charset(array(), '')); | ||
43 | } | ||
44 | |||
45 | /** | ||
46 | * Test headers_extract_charset() when the charset is found. | 32 | * Test headers_extract_charset() when the charset is found. |
47 | */ | 33 | */ |
48 | public function testHeadersExtractExistentCharset() | 34 | public function testHeadersExtractExistentCharset() |
49 | { | 35 | { |
50 | $charset = 'x-MacCroatian'; | 36 | $charset = 'x-MacCroatian'; |
51 | $headers = array('Content-Type' => 'text/html; charset='. $charset); | 37 | $headers = 'text/html; charset='. $charset; |
52 | $this->assertEquals(strtolower($charset), headers_extract_charset($headers)); | 38 | $this->assertEquals(strtolower($charset), header_extract_charset($headers)); |
53 | } | 39 | } |
54 | 40 | ||
55 | /** | 41 | /** |
@@ -57,11 +43,11 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase | |||
57 | */ | 43 | */ |
58 | public function testHeadersExtractNonExistentCharset() | 44 | public function testHeadersExtractNonExistentCharset() |
59 | { | 45 | { |
60 | $headers = array(); | 46 | $headers = ''; |
61 | $this->assertFalse(headers_extract_charset($headers)); | 47 | $this->assertFalse(header_extract_charset($headers)); |
62 | 48 | ||
63 | $headers = array('Content-Type' => 'text/html'); | 49 | $headers = 'text/html'; |
64 | $this->assertFalse(headers_extract_charset($headers)); | 50 | $this->assertFalse(header_extract_charset($headers)); |
65 | } | 51 | } |
66 | 52 | ||
67 | /** | 53 | /** |
@@ -86,6 +72,131 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase | |||
86 | } | 72 | } |
87 | 73 | ||
88 | /** | 74 | /** |
75 | * Test the download callback with valid value | ||
76 | */ | ||
77 | public function testCurlDownloadCallbackOk() | ||
78 | { | ||
79 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_ok'); | ||
80 | $data = [ | ||
81 | 'HTTP/1.1 200 OK', | ||
82 | 'Server: GitHub.com', | ||
83 | 'Date: Sat, 28 Oct 2017 12:01:33 GMT', | ||
84 | 'Content-Type: text/html; charset=utf-8', | ||
85 | 'Status: 200 OK', | ||
86 | 'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea', | ||
87 | '<title>ignored</title>', | ||
88 | ]; | ||
89 | foreach ($data as $key => $line) { | ||
90 | $ignore = null; | ||
91 | $expected = $key !== 'end' ? strlen($line) : false; | ||
92 | $this->assertEquals($expected, $callback($ignore, $line)); | ||
93 | if ($expected === false) { | ||
94 | break; | ||
95 | } | ||
96 | } | ||
97 | $this->assertEquals('utf-8', $charset); | ||
98 | $this->assertEquals('Refactoring · GitHub', $title); | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * Test the download callback with valid values and no charset | ||
103 | */ | ||
104 | public function testCurlDownloadCallbackOkNoCharset() | ||
105 | { | ||
106 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_no_charset'); | ||
107 | $data = [ | ||
108 | 'HTTP/1.1 200 OK', | ||
109 | 'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea', | ||
110 | '<title>ignored</title>', | ||
111 | ]; | ||
112 | foreach ($data as $key => $line) { | ||
113 | $ignore = null; | ||
114 | $this->assertEquals(strlen($line), $callback($ignore, $line)); | ||
115 | } | ||
116 | $this->assertEmpty($charset); | ||
117 | $this->assertEquals('Refactoring · GitHub', $title); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * Test the download callback with valid values and no charset | ||
122 | */ | ||
123 | public function testCurlDownloadCallbackOkHtmlCharset() | ||
124 | { | ||
125 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_no_charset'); | ||
126 | $data = [ | ||
127 | 'HTTP/1.1 200 OK', | ||
128 | '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />', | ||
129 | 'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea', | ||
130 | '<title>ignored</title>', | ||
131 | ]; | ||
132 | foreach ($data as $key => $line) { | ||
133 | $ignore = null; | ||
134 | $expected = $key !== 'end' ? strlen($line) : false; | ||
135 | $this->assertEquals($expected, $callback($ignore, $line)); | ||
136 | if ($expected === false) { | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | $this->assertEquals('utf-8', $charset); | ||
141 | $this->assertEquals('Refactoring · GitHub', $title); | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * Test the download callback with valid values and no title | ||
146 | */ | ||
147 | public function testCurlDownloadCallbackOkNoTitle() | ||
148 | { | ||
149 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_ok'); | ||
150 | $data = [ | ||
151 | 'HTTP/1.1 200 OK', | ||
152 | 'end' => 'th=device-width">Refactoring · GitHub<link rel="search" type="application/opensea', | ||
153 | 'ignored', | ||
154 | ]; | ||
155 | foreach ($data as $key => $line) { | ||
156 | $ignore = null; | ||
157 | $this->assertEquals(strlen($line), $callback($ignore, $line)); | ||
158 | } | ||
159 | $this->assertEquals('utf-8', $charset); | ||
160 | $this->assertEmpty($title); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * Test the download callback with an invalid content type. | ||
165 | */ | ||
166 | public function testCurlDownloadCallbackInvalidContentType() | ||
167 | { | ||
168 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_ct_ko'); | ||
169 | $ignore = null; | ||
170 | $this->assertFalse($callback($ignore, '')); | ||
171 | $this->assertEmpty($charset); | ||
172 | $this->assertEmpty($title); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * Test the download callback with an invalid response code. | ||
177 | */ | ||
178 | public function testCurlDownloadCallbackInvalidResponseCode() | ||
179 | { | ||
180 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_rc_ko'); | ||
181 | $ignore = null; | ||
182 | $this->assertFalse($callback($ignore, '')); | ||
183 | $this->assertEmpty($charset); | ||
184 | $this->assertEmpty($title); | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * Test the download callback with an invalid content type and response code. | ||
189 | */ | ||
190 | public function testCurlDownloadCallbackInvalidContentTypeAndResponseCode() | ||
191 | { | ||
192 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_rs_ct_ko'); | ||
193 | $ignore = null; | ||
194 | $this->assertFalse($callback($ignore, '')); | ||
195 | $this->assertEmpty($charset); | ||
196 | $this->assertEmpty($title); | ||
197 | } | ||
198 | |||
199 | /** | ||
89 | * Test count_private. | 200 | * Test count_private. |
90 | */ | 201 | */ |
91 | public function testCountPrivateLinks() | 202 | public function testCountPrivateLinks() |
@@ -103,6 +214,16 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase | |||
103 | $expectedText = 'stuff <a href="http://hello.there/is=someone#here">http://hello.there/is=someone#here</a> otherstuff'; | 214 | $expectedText = 'stuff <a href="http://hello.there/is=someone#here">http://hello.there/is=someone#here</a> otherstuff'; |
104 | $processedText = text2clickable($text, ''); | 215 | $processedText = text2clickable($text, ''); |
105 | $this->assertEquals($expectedText, $processedText); | 216 | $this->assertEquals($expectedText, $processedText); |
217 | |||
218 | $text = 'stuff http://hello.there/is=someone#here(please) otherstuff'; | ||
219 | $expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)">http://hello.there/is=someone#here(please)</a> otherstuff'; | ||
220 | $processedText = text2clickable($text, ''); | ||
221 | $this->assertEquals($expectedText, $processedText); | ||
222 | |||
223 | $text = 'stuff http://hello.there/is=someone#here(please)&no otherstuff'; | ||
224 | $expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)&no">http://hello.there/is=someone#here(please)&no</a> otherstuff'; | ||
225 | $processedText = text2clickable($text, ''); | ||
226 | $this->assertEquals($expectedText, $processedText); | ||
106 | } | 227 | } |
107 | 228 | ||
108 | /** | 229 | /** |
@@ -121,6 +242,21 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase | |||
121 | } | 242 | } |
122 | 243 | ||
123 | /** | 244 | /** |
245 | * Test text2clickable a redirector set and without URL encode. | ||
246 | */ | ||
247 | public function testText2clickableWithRedirectorDontEncode() | ||
248 | { | ||
249 | $text = 'stuff http://hello.there/?is=someone&or=something#here otherstuff'; | ||
250 | $redirector = 'http://redirector.to'; | ||
251 | $expectedText = 'stuff <a href="'. | ||
252 | $redirector . | ||
253 | 'http://hello.there/?is=someone&or=something#here' . | ||
254 | '">http://hello.there/?is=someone&or=something#here</a> otherstuff'; | ||
255 | $processedText = text2clickable($text, $redirector, false); | ||
256 | $this->assertEquals($expectedText, $processedText); | ||
257 | } | ||
258 | |||
259 | /** | ||
124 | * Test testSpace2nbsp. | 260 | * Test testSpace2nbsp. |
125 | */ | 261 | */ |
126 | public function testSpace2nbsp() | 262 | public function testSpace2nbsp() |
@@ -182,3 +318,96 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase | |||
182 | return str_replace('$1', $hashtag, $hashtagLink); | 318 | return str_replace('$1', $hashtag, $hashtagLink); |
183 | } | 319 | } |
184 | } | 320 | } |
321 | |||
322 | // old style mock: PHPUnit doesn't allow function mock | ||
323 | |||
324 | /** | ||
325 | * Returns code 200 or html content type. | ||
326 | * | ||
327 | * @param resource $ch cURL resource | ||
328 | * @param int $type cURL info type | ||
329 | * | ||
330 | * @return int|string 200 or 'text/html' | ||
331 | */ | ||
332 | function ut_curl_getinfo_ok($ch, $type) | ||
333 | { | ||
334 | switch ($type) { | ||
335 | case CURLINFO_RESPONSE_CODE: | ||
336 | return 200; | ||
337 | case CURLINFO_CONTENT_TYPE: | ||
338 | return 'text/html; charset=utf-8'; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * Returns code 200 or html content type without charset. | ||
344 | * | ||
345 | * @param resource $ch cURL resource | ||
346 | * @param int $type cURL info type | ||
347 | * | ||
348 | * @return int|string 200 or 'text/html' | ||
349 | */ | ||
350 | function ut_curl_getinfo_no_charset($ch, $type) | ||
351 | { | ||
352 | switch ($type) { | ||
353 | case CURLINFO_RESPONSE_CODE: | ||
354 | return 200; | ||
355 | case CURLINFO_CONTENT_TYPE: | ||
356 | return 'text/html'; | ||
357 | } | ||
358 | } | ||
359 | |||
360 | /** | ||
361 | * Invalid response code. | ||
362 | * | ||
363 | * @param resource $ch cURL resource | ||
364 | * @param int $type cURL info type | ||
365 | * | ||
366 | * @return int|string 404 or 'text/html' | ||
367 | */ | ||
368 | function ut_curl_getinfo_rc_ko($ch, $type) | ||
369 | { | ||
370 | switch ($type) { | ||
371 | case CURLINFO_RESPONSE_CODE: | ||
372 | return 404; | ||
373 | case CURLINFO_CONTENT_TYPE: | ||
374 | return 'text/html; charset=utf-8'; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * Invalid content type. | ||
380 | * | ||
381 | * @param resource $ch cURL resource | ||
382 | * @param int $type cURL info type | ||
383 | * | ||
384 | * @return int|string 200 or 'text/plain' | ||
385 | */ | ||
386 | function ut_curl_getinfo_ct_ko($ch, $type) | ||
387 | { | ||
388 | switch ($type) { | ||
389 | case CURLINFO_RESPONSE_CODE: | ||
390 | return 200; | ||
391 | case CURLINFO_CONTENT_TYPE: | ||
392 | return 'text/plain'; | ||
393 | } | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * Invalid response code and content type. | ||
398 | * | ||
399 | * @param resource $ch cURL resource | ||
400 | * @param int $type cURL info type | ||
401 | * | ||
402 | * @return int|string 404 or 'text/plain' | ||
403 | */ | ||
404 | function ut_curl_getinfo_rs_ct_ko($ch, $type) | ||
405 | { | ||
406 | switch ($type) { | ||
407 | case CURLINFO_RESPONSE_CODE: | ||
408 | return 404; | ||
409 | case CURLINFO_CONTENT_TYPE: | ||
410 | return 'text/plain'; | ||
411 | } | ||
412 | } | ||
413 | |||
diff --git a/tests/NetscapeBookmarkUtils/BookmarkImportTest.php b/tests/NetscapeBookmarkUtils/BookmarkImportTest.php index 0ca07eac..4961aa2c 100644 --- a/tests/NetscapeBookmarkUtils/BookmarkImportTest.php +++ b/tests/NetscapeBookmarkUtils/BookmarkImportTest.php | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | require_once 'application/NetscapeBookmarkUtils.php'; | 3 | require_once 'application/NetscapeBookmarkUtils.php'; |
4 | 4 | ||
5 | use 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 | } |
@@ -105,10 +132,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
105 | public function testImportInternetExplorerEncoding() | 132 | public function testImportInternetExplorerEncoding() |
106 | { | 133 | { |
107 | $files = file2array('internet_explorer_encoding.htm'); | 134 | $files = file2array('internet_explorer_encoding.htm'); |
108 | $this->assertEquals( | 135 | $this->assertStringMatchesFormat( |
109 | 'File internet_explorer_encoding.htm (356 bytes) was successfully processed:' | 136 | 'File internet_explorer_encoding.htm (356 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -134,10 +161,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
134 | public function testImportNested() | 161 | public function testImportNested() |
135 | { | 162 | { |
136 | $files = file2array('netscape_nested.htm'); | 163 | $files = file2array('netscape_nested.htm'); |
137 | $this->assertEquals( | 164 | $this->assertStringMatchesFormat( |
138 | 'File netscape_nested.htm (1337 bytes) was successfully processed:' | 165 | 'File netscape_nested.htm (1337 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -256,10 +283,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
256 | public function testImportDefaultPrivacyNoPost() | 283 | public function testImportDefaultPrivacyNoPost() |
257 | { | 284 | { |
258 | $files = file2array('netscape_basic.htm'); | 285 | $files = file2array('netscape_basic.htm'); |
259 | $this->assertEquals( | 286 | $this->assertStringMatchesFormat( |
260 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 287 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -301,10 +328,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
301 | { | 328 | { |
302 | $post = array('privacy' => 'default'); | 329 | $post = array('privacy' => 'default'); |
303 | $files = file2array('netscape_basic.htm'); | 330 | $files = file2array('netscape_basic.htm'); |
304 | $this->assertEquals( | 331 | $this->assertStringMatchesFormat( |
305 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 332 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -345,10 +372,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
345 | { | 372 | { |
346 | $post = array('privacy' => 'public'); | 373 | $post = array('privacy' => 'public'); |
347 | $files = file2array('netscape_basic.htm'); | 374 | $files = file2array('netscape_basic.htm'); |
348 | $this->assertEquals( | 375 | $this->assertStringMatchesFormat( |
349 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 376 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -369,10 +396,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
369 | { | 396 | { |
370 | $post = array('privacy' => 'private'); | 397 | $post = array('privacy' => 'private'); |
371 | $files = file2array('netscape_basic.htm'); | 398 | $files = file2array('netscape_basic.htm'); |
372 | $this->assertEquals( | 399 | $this->assertStringMatchesFormat( |
373 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 400 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -395,10 +422,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
395 | 422 | ||
396 | // import links as private | 423 | // import links as private |
397 | $post = array('privacy' => 'private'); | 424 | $post = array('privacy' => 'private'); |
398 | $this->assertEquals( | 425 | $this->assertStringMatchesFormat( |
399 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 426 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -415,10 +442,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
415 | 'privacy' => 'public', | 442 | 'privacy' => 'public', |
416 | 'overwrite' => 'true' | 443 | 'overwrite' => 'true' |
417 | ); | 444 | ); |
418 | $this->assertEquals( | 445 | $this->assertStringMatchesFormat( |
419 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 446 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -441,10 +468,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
441 | 468 | ||
442 | // import links as public | 469 | // import links as public |
443 | $post = array('privacy' => 'public'); | 470 | $post = array('privacy' => 'public'); |
444 | $this->assertEquals( | 471 | $this->assertStringMatchesFormat( |
445 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 472 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -462,10 +489,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
462 | 'privacy' => 'private', | 489 | 'privacy' => 'private', |
463 | 'overwrite' => 'true' | 490 | 'overwrite' => 'true' |
464 | ); | 491 | ); |
465 | $this->assertEquals( | 492 | $this->assertStringMatchesFormat( |
466 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 493 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -486,20 +513,20 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
486 | { | 513 | { |
487 | $post = array('privacy' => 'public'); | 514 | $post = array('privacy' => 'public'); |
488 | $files = file2array('netscape_basic.htm'); | 515 | $files = file2array('netscape_basic.htm'); |
489 | $this->assertEquals( | 516 | $this->assertStringMatchesFormat( |
490 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 517 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
496 | 523 | ||
497 | // re-import as private, DO NOT enable overwriting | 524 | // re-import as private, DO NOT enable overwriting |
498 | $post = array('privacy' => 'private'); | 525 | $post = array('privacy' => 'private'); |
499 | $this->assertEquals( | 526 | $this->assertStringMatchesFormat( |
500 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 527 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -515,10 +542,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
515 | 'default_tags' => 'tag1,tag2 tag3' | 542 | 'default_tags' => 'tag1,tag2 tag3' |
516 | ); | 543 | ); |
517 | $files = file2array('netscape_basic.htm'); | 544 | $files = file2array('netscape_basic.htm'); |
518 | $this->assertEquals( | 545 | $this->assertStringMatchesFormat( |
519 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 546 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -542,10 +569,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
542 | 'default_tags' => 'tag1&,tag2 "tag3"' | 569 | 'default_tags' => 'tag1&,tag2 "tag3"' |
543 | ); | 570 | ); |
544 | $files = file2array('netscape_basic.htm'); | 571 | $files = file2array('netscape_basic.htm'); |
545 | $this->assertEquals( | 572 | $this->assertStringMatchesFormat( |
546 | 'File netscape_basic.htm (482 bytes) was successfully processed:' | 573 | 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' |
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)); |
@@ -567,10 +594,10 @@ class BookmarkImportTest extends PHPUnit_Framework_TestCase | |||
567 | public function testImportSameDate() | 594 | public function testImportSameDate() |
568 | { | 595 | { |
569 | $files = file2array('same_date.htm'); | 596 | $files = file2array('same_date.htm'); |
570 | $this->assertEquals( | 597 | $this->assertStringMatchesFormat( |
571 | 'File same_date.htm (453 bytes) was successfully processed:' | 598 | 'File same_date.htm (453 bytes) was successfully processed in %d seconds:' |
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,27 @@ 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 | NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history); | ||
626 | $history = $this->history->getHistory(); | ||
627 | $this->assertEquals(1, count($history)); | ||
628 | $this->assertEquals(History::IMPORT, $history[0]['event']); | ||
629 | $this->assertTrue(new DateTime('-5 seconds') < $history[0]['datetime']); | ||
630 | |||
631 | // re-import as private, enable overwriting | ||
632 | NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history); | ||
633 | $history = $this->history->getHistory(); | ||
634 | $this->assertEquals(2, count($history)); | ||
635 | $this->assertEquals(History::IMPORT, $history[0]['event']); | ||
636 | $this->assertTrue(new DateTime('-5 seconds') < $history[0]['datetime']); | ||
637 | $this->assertEquals(History::IMPORT, $history[1]['event']); | ||
638 | $this->assertTrue(new DateTime('-5 seconds') < $history[1]['datetime']); | ||
639 | } | ||
590 | } | 640 | } |
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 |
2 | use Shaarli\Config\ConfigManager; | ||
2 | 3 | ||
3 | /** | 4 | /** |
4 | * Plugin Manager tests | 5 | * Plugin Manager tests |
diff --git a/tests/SessionManagerTest.php b/tests/SessionManagerTest.php new file mode 100644 index 00000000..aa75962a --- /dev/null +++ b/tests/SessionManagerTest.php | |||
@@ -0,0 +1,149 @@ | |||
1 | <?php | ||
2 | require_once 'tests/utils/FakeConfigManager.php'; | ||
3 | |||
4 | // Initialize reference data _before_ PHPUnit starts a session | ||
5 | require_once 'tests/utils/ReferenceSessionIdHashes.php'; | ||
6 | ReferenceSessionIdHashes::genAllHashes(); | ||
7 | |||
8 | use \Shaarli\SessionManager; | ||
9 | use \PHPUnit\Framework\TestCase; | ||
10 | |||
11 | |||
12 | /** | ||
13 | * Test coverage for SessionManager | ||
14 | */ | ||
15 | class SessionManagerTest extends TestCase | ||
16 | { | ||
17 | // Session ID hashes | ||
18 | protected static $sidHashes = null; | ||
19 | |||
20 | // Fake ConfigManager | ||
21 | protected static $conf = null; | ||
22 | |||
23 | /** | ||
24 | * Assign reference data | ||
25 | */ | ||
26 | public static function setUpBeforeClass() | ||
27 | { | ||
28 | self::$sidHashes = ReferenceSessionIdHashes::getHashes(); | ||
29 | self::$conf = new FakeConfigManager(); | ||
30 | } | ||
31 | |||
32 | /** | ||
33 | * Generate a session token | ||
34 | */ | ||
35 | public function testGenerateToken() | ||
36 | { | ||
37 | $session = []; | ||
38 | $sessionManager = new SessionManager($session, self::$conf); | ||
39 | |||
40 | $token = $sessionManager->generateToken(); | ||
41 | |||
42 | $this->assertEquals(1, $session['tokens'][$token]); | ||
43 | $this->assertEquals(40, strlen($token)); | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * Check a session token | ||
48 | */ | ||
49 | public function testCheckToken() | ||
50 | { | ||
51 | $token = '4dccc3a45ad9d03e5542b90c37d8db6d10f2b38b'; | ||
52 | $session = [ | ||
53 | 'tokens' => [ | ||
54 | $token => 1, | ||
55 | ], | ||
56 | ]; | ||
57 | $sessionManager = new SessionManager($session, self::$conf); | ||
58 | |||
59 | // check and destroy the token | ||
60 | $this->assertTrue($sessionManager->checkToken($token)); | ||
61 | $this->assertFalse(isset($session['tokens'][$token])); | ||
62 | |||
63 | // ensure the token has been destroyed | ||
64 | $this->assertFalse($sessionManager->checkToken($token)); | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * Generate and check a session token | ||
69 | */ | ||
70 | public function testGenerateAndCheckToken() | ||
71 | { | ||
72 | $session = []; | ||
73 | $sessionManager = new SessionManager($session, self::$conf); | ||
74 | |||
75 | $token = $sessionManager->generateToken(); | ||
76 | |||
77 | // ensure a token has been generated | ||
78 | $this->assertEquals(1, $session['tokens'][$token]); | ||
79 | $this->assertEquals(40, strlen($token)); | ||
80 | |||
81 | // check and destroy the token | ||
82 | $this->assertTrue($sessionManager->checkToken($token)); | ||
83 | $this->assertFalse(isset($session['tokens'][$token])); | ||
84 | |||
85 | // ensure the token has been destroyed | ||
86 | $this->assertFalse($sessionManager->checkToken($token)); | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * Check an invalid session token | ||
91 | */ | ||
92 | public function testCheckInvalidToken() | ||
93 | { | ||
94 | $session = []; | ||
95 | $sessionManager = new SessionManager($session, self::$conf); | ||
96 | |||
97 | $this->assertFalse($sessionManager->checkToken('4dccc3a45ad9d03e5542b90c37d8db6d10f2b38b')); | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * Test SessionManager::checkId with a valid ID - TEST ALL THE HASHES! | ||
102 | * | ||
103 | * This tests extensively covers all hash algorithms / bit representations | ||
104 | */ | ||
105 | public function testIsAnyHashSessionIdValid() | ||
106 | { | ||
107 | foreach (self::$sidHashes as $algo => $bpcs) { | ||
108 | foreach ($bpcs as $bpc => $hash) { | ||
109 | $this->assertTrue(SessionManager::checkId($hash)); | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * Test checkId with a valid ID - SHA-1 hashes | ||
116 | */ | ||
117 | public function testIsSha1SessionIdValid() | ||
118 | { | ||
119 | $this->assertTrue(SessionManager::checkId(sha1('shaarli'))); | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * Test checkId with a valid ID - SHA-256 hashes | ||
124 | */ | ||
125 | public function testIsSha256SessionIdValid() | ||
126 | { | ||
127 | $this->assertTrue(SessionManager::checkId(hash('sha256', 'shaarli'))); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * Test checkId with a valid ID - SHA-512 hashes | ||
132 | */ | ||
133 | public function testIsSha512SessionIdValid() | ||
134 | { | ||
135 | $this->assertTrue(SessionManager::checkId(hash('sha512', 'shaarli'))); | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * Test checkId with invalid IDs. | ||
140 | */ | ||
141 | public function testIsSessionIdInvalid() | ||
142 | { | ||
143 | $this->assertFalse(SessionManager::checkId('')); | ||
144 | $this->assertFalse(SessionManager::checkId([])); | ||
145 | $this->assertFalse( | ||
146 | SessionManager::checkId('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=') | ||
147 | ); | ||
148 | } | ||
149 | } | ||
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 | |||
3 | namespace Shaarli; | ||
4 | |||
5 | /** | ||
6 | * Class ThemeUtilsTest | ||
7 | * | ||
8 | * @package Shaarli | ||
9 | */ | ||
10 | class 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'; | |||
11 | class TimeZoneTest extends PHPUnit_Framework_TestCase | 11 | class 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..77578528 100644 --- a/tests/Updater/UpdaterTest.php +++ b/tests/Updater/UpdaterTest.php | |||
@@ -1,7 +1,10 @@ | |||
1 | <?php | 1 | <?php |
2 | use Shaarli\Config\ConfigJson; | ||
3 | use Shaarli\Config\ConfigManager; | ||
4 | use Shaarli\Config\ConfigPhp; | ||
2 | 5 | ||
3 | require_once 'application/config/ConfigManager.php'; | ||
4 | require_once 'tests/Updater/DummyUpdater.php'; | 6 | require_once 'tests/Updater/DummyUpdater.php'; |
7 | require_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,50 @@ $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 | /** | ||
390 | * Test updateMethodEscapeMarkdown with markdown plugin enabled | 473 | * Test updateMethodEscapeMarkdown with markdown plugin enabled |
391 | * => setting markdown_escape set to false. | 474 | * => setting markdown_escape set to false. |
392 | */ | 475 | */ |
@@ -396,8 +479,8 @@ $GLOBALS[\'privateLinkByDefault\'] = true;'; | |||
396 | copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); | 479 | copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); |
397 | $this->conf = new ConfigManager($sandboxConf); | 480 | $this->conf = new ConfigManager($sandboxConf); |
398 | 481 | ||
399 | $this->conf->set('general.enabled_plugins', array('markdown')); | 482 | $this->conf->set('general.enabled_plugins', ['markdown']); |
400 | $updater = new Updater(array(), array(), $this->conf, true); | 483 | $updater = new Updater([], [], $this->conf, true); |
401 | $this->assertTrue($updater->updateMethodEscapeMarkdown()); | 484 | $this->assertTrue($updater->updateMethodEscapeMarkdown()); |
402 | $this->assertFalse($this->conf->get('security.markdown_escape')); | 485 | $this->assertFalse($this->conf->get('security.markdown_escape')); |
403 | 486 | ||
@@ -416,8 +499,8 @@ $GLOBALS[\'privateLinkByDefault\'] = true;'; | |||
416 | copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); | 499 | copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); |
417 | $this->conf = new ConfigManager($sandboxConf); | 500 | $this->conf = new ConfigManager($sandboxConf); |
418 | 501 | ||
419 | $this->conf->set('general.enabled_plugins', array()); | 502 | $this->conf->set('general.enabled_plugins', []); |
420 | $updater = new Updater(array(), array(), $this->conf, true); | 503 | $updater = new Updater([], [], $this->conf, true); |
421 | $this->assertTrue($updater->updateMethodEscapeMarkdown()); | 504 | $this->assertTrue($updater->updateMethodEscapeMarkdown()); |
422 | $this->assertTrue($this->conf->get('security.markdown_escape')); | 505 | $this->assertTrue($this->conf->get('security.markdown_escape')); |
423 | 506 | ||
@@ -435,7 +518,7 @@ $GLOBALS[\'privateLinkByDefault\'] = true;'; | |||
435 | copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); | 518 | copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); |
436 | $this->conf = new ConfigManager($sandboxConf); | 519 | $this->conf = new ConfigManager($sandboxConf); |
437 | $this->conf->set('security.markdown_escape', true); | 520 | $this->conf->set('security.markdown_escape', true); |
438 | $updater = new Updater(array(), array(), $this->conf, true); | 521 | $updater = new Updater([], [], $this->conf, true); |
439 | $this->assertTrue($updater->updateMethodEscapeMarkdown()); | 522 | $this->assertTrue($updater->updateMethodEscapeMarkdown()); |
440 | $this->assertTrue($this->conf->get('security.markdown_escape')); | 523 | $this->assertTrue($this->conf->get('security.markdown_escape')); |
441 | } | 524 | } |
@@ -446,8 +529,94 @@ $GLOBALS[\'privateLinkByDefault\'] = true;'; | |||
446 | public function testEscapeMarkdownSettingNothingToDoDisabled() | 529 | public function testEscapeMarkdownSettingNothingToDoDisabled() |
447 | { | 530 | { |
448 | $this->conf->set('security.markdown_escape', false); | 531 | $this->conf->set('security.markdown_escape', false); |
449 | $updater = new Updater(array(), array(), $this->conf, true); | 532 | $updater = new Updater([], [], $this->conf, true); |
450 | $this->assertTrue($updater->updateMethodEscapeMarkdown()); | 533 | $this->assertTrue($updater->updateMethodEscapeMarkdown()); |
451 | $this->assertFalse($this->conf->get('security.markdown_escape')); | 534 | $this->assertFalse($this->conf->get('security.markdown_escape')); |
452 | } | 535 | } |
536 | |||
537 | /** | ||
538 | * Test updateMethodPiwikUrl with valid data | ||
539 | */ | ||
540 | public function testUpdatePiwikUrlValid() | ||
541 | { | ||
542 | $sandboxConf = 'sandbox/config'; | ||
543 | copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); | ||
544 | $this->conf = new ConfigManager($sandboxConf); | ||
545 | $url = 'mypiwik.tld'; | ||
546 | $this->conf->set('plugins.PIWIK_URL', $url); | ||
547 | $updater = new Updater([], [], $this->conf, true); | ||
548 | $this->assertTrue($updater->updateMethodPiwikUrl()); | ||
549 | $this->assertEquals('http://'. $url, $this->conf->get('plugins.PIWIK_URL')); | ||
550 | |||
551 | // reload from file | ||
552 | $this->conf = new ConfigManager($sandboxConf); | ||
553 | $this->assertEquals('http://'. $url, $this->conf->get('plugins.PIWIK_URL')); | ||
554 | } | ||
555 | |||
556 | /** | ||
557 | * Test updateMethodPiwikUrl without setting | ||
558 | */ | ||
559 | public function testUpdatePiwikUrlEmpty() | ||
560 | { | ||
561 | $updater = new Updater([], [], $this->conf, true); | ||
562 | $this->assertTrue($updater->updateMethodPiwikUrl()); | ||
563 | $this->assertEmpty($this->conf->get('plugins.PIWIK_URL')); | ||
564 | } | ||
565 | |||
566 | /** | ||
567 | * Test updateMethodPiwikUrl: valid URL, nothing to do | ||
568 | */ | ||
569 | public function testUpdatePiwikUrlNothingToDo() | ||
570 | { | ||
571 | $url = 'https://mypiwik.tld'; | ||
572 | $this->conf->set('plugins.PIWIK_URL', $url); | ||
573 | $updater = new Updater([], [], $this->conf, true); | ||
574 | $this->assertTrue($updater->updateMethodPiwikUrl()); | ||
575 | $this->assertEquals($url, $this->conf->get('plugins.PIWIK_URL')); | ||
576 | } | ||
577 | |||
578 | /** | ||
579 | * Test updateMethodAtomDefault with show_atom set to false | ||
580 | * => update to true. | ||
581 | */ | ||
582 | public function testUpdateMethodAtomDefault() | ||
583 | { | ||
584 | $sandboxConf = 'sandbox/config'; | ||
585 | copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); | ||
586 | $this->conf = new ConfigManager($sandboxConf); | ||
587 | $this->conf->set('feed.show_atom', false); | ||
588 | $updater = new Updater([], [], $this->conf, true); | ||
589 | $this->assertTrue($updater->updateMethodAtomDefault()); | ||
590 | $this->assertTrue($this->conf->get('feed.show_atom')); | ||
591 | // reload from file | ||
592 | $this->conf = new ConfigManager($sandboxConf); | ||
593 | $this->assertTrue($this->conf->get('feed.show_atom')); | ||
594 | } | ||
595 | /** | ||
596 | * Test updateMethodAtomDefault with show_atom not set. | ||
597 | * => nothing to do | ||
598 | */ | ||
599 | public function testUpdateMethodAtomDefaultNoExist() | ||
600 | { | ||
601 | $sandboxConf = 'sandbox/config'; | ||
602 | copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); | ||
603 | $this->conf = new ConfigManager($sandboxConf); | ||
604 | $updater = new Updater([], [], $this->conf, true); | ||
605 | $this->assertTrue($updater->updateMethodAtomDefault()); | ||
606 | $this->assertTrue($this->conf->get('feed.show_atom')); | ||
607 | } | ||
608 | /** | ||
609 | * Test updateMethodAtomDefault with show_atom set to true. | ||
610 | * => nothing to do | ||
611 | */ | ||
612 | public function testUpdateMethodAtomDefaultAlreadyTrue() | ||
613 | { | ||
614 | $sandboxConf = 'sandbox/config'; | ||
615 | copy(self::$configFile . '.json.php', $sandboxConf . '.json.php'); | ||
616 | $this->conf = new ConfigManager($sandboxConf); | ||
617 | $this->conf->set('feed.show_atom', true); | ||
618 | $updater = new Updater([], [], $this->conf, true); | ||
619 | $this->assertTrue($updater->updateMethodAtomDefault()); | ||
620 | $this->assertTrue($this->conf->get('feed.show_atom')); | ||
621 | } | ||
453 | } | 622 | } |
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'; | |||
8 | class CleanupUrlTest extends PHPUnit_Framework_TestCase | 8 | class 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/Url/WhitelistProtocolsTest.php b/tests/Url/WhitelistProtocolsTest.php new file mode 100644 index 00000000..a3156804 --- /dev/null +++ b/tests/Url/WhitelistProtocolsTest.php | |||
@@ -0,0 +1,63 @@ | |||
1 | <?php | ||
2 | |||
3 | require_once 'application/Url.php'; | ||
4 | |||
5 | use Shaarli\Config\ConfigManager; | ||
6 | |||
7 | /** | ||
8 | * Class WhitelistProtocolsTest | ||
9 | * | ||
10 | * Test whitelist_protocols() function of Url. | ||
11 | */ | ||
12 | class WhitelistProtocolsTest extends PHPUnit_Framework_TestCase | ||
13 | { | ||
14 | /** | ||
15 | * Test whitelist_protocols() on a note (relative URL). | ||
16 | */ | ||
17 | public function testWhitelistProtocolsRelative() | ||
18 | { | ||
19 | $whitelist = ['ftp', 'magnet']; | ||
20 | $url = '?12443564'; | ||
21 | $this->assertEquals($url, whitelist_protocols($url, $whitelist)); | ||
22 | $url = '/path.jpg'; | ||
23 | $this->assertEquals($url, whitelist_protocols($url, $whitelist)); | ||
24 | } | ||
25 | |||
26 | /** | ||
27 | * Test whitelist_protocols() on a note (relative URL). | ||
28 | */ | ||
29 | public function testWhitelistProtocolMissing() | ||
30 | { | ||
31 | $whitelist = ['ftp', 'magnet']; | ||
32 | $url = 'test.tld/path/?query=value#hash'; | ||
33 | $this->assertEquals('http://'. $url, whitelist_protocols($url, $whitelist)); | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * Test whitelist_protocols() with allowed protocols. | ||
38 | */ | ||
39 | public function testWhitelistAllowedProtocol() | ||
40 | { | ||
41 | $whitelist = ['ftp', 'magnet']; | ||
42 | $url = 'http://test.tld/path/?query=value#hash'; | ||
43 | $this->assertEquals($url, whitelist_protocols($url, $whitelist)); | ||
44 | $url = 'https://test.tld/path/?query=value#hash'; | ||
45 | $this->assertEquals($url, whitelist_protocols($url, $whitelist)); | ||
46 | $url = 'ftp://test.tld/path/?query=value#hash'; | ||
47 | $this->assertEquals($url, whitelist_protocols($url, $whitelist)); | ||
48 | $url = 'magnet:test.tld/path/?query=value#hash'; | ||
49 | $this->assertEquals($url, whitelist_protocols($url, $whitelist)); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Test whitelist_protocols() with allowed protocols. | ||
54 | */ | ||
55 | public function testWhitelistDisallowedProtocol() | ||
56 | { | ||
57 | $whitelist = ['ftp', 'magnet']; | ||
58 | $url = 'javascript:alert("xss");'; | ||
59 | $this->assertEquals('http://alert("xss");', whitelist_protocols($url, $whitelist)); | ||
60 | $url = 'other://test.tld/path/?query=value#hash'; | ||
61 | $this->assertEquals('http://test.tld/path/?query=value#hash', whitelist_protocols($url, $whitelist)); | ||
62 | } | ||
63 | } | ||
diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index 6a7870c4..6cd37a7a 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php | |||
@@ -4,10 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | require_once 'application/Utils.php'; | 6 | require_once 'application/Utils.php'; |
7 | require_once 'tests/utils/ReferenceSessionIdHashes.php'; | 7 | require_once 'application/Languages.php'; |
8 | |||
9 | // Initialize reference data before PHPUnit starts a session | ||
10 | ReferenceSessionIdHashes::genAllHashes(); | ||
11 | 8 | ||
12 | 9 | ||
13 | /** | 10 | /** |
@@ -15,22 +12,33 @@ ReferenceSessionIdHashes::genAllHashes(); | |||
15 | */ | 12 | */ |
16 | class UtilsTest extends PHPUnit_Framework_TestCase | 13 | class UtilsTest extends PHPUnit_Framework_TestCase |
17 | { | 14 | { |
18 | // Session ID hashes | ||
19 | protected static $sidHashes = null; | ||
20 | |||
21 | // Log file | 15 | // Log file |
22 | protected static $testLogFile = 'tests.log'; | 16 | protected static $testLogFile = 'tests.log'; |
23 | 17 | ||
24 | // Expected log date format | 18 | // Expected log date format |
25 | protected static $dateFormat = 'Y/m/d H:i:s'; | 19 | protected static $dateFormat = 'Y/m/d H:i:s'; |
26 | 20 | ||
21 | /** | ||
22 | * @var string Save the current timezone. | ||
23 | */ | ||
24 | protected static $defaultTimeZone; | ||
27 | 25 | ||
28 | /** | 26 | /** |
29 | * Assign reference data | 27 | * Assign reference data |
30 | */ | 28 | */ |
31 | public static function setUpBeforeClass() | 29 | public static function setUpBeforeClass() |
32 | { | 30 | { |
33 | self::$sidHashes = ReferenceSessionIdHashes::getHashes(); | 31 | self::$defaultTimeZone = date_default_timezone_get(); |
32 | // Timezone without DST for test consistency | ||
33 | date_default_timezone_set('Africa/Nairobi'); | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * Reset the timezone | ||
38 | */ | ||
39 | public static function tearDownAfterClass() | ||
40 | { | ||
41 | date_default_timezone_set(self::$defaultTimeZone); | ||
34 | } | 42 | } |
35 | 43 | ||
36 | /** | 44 | /** |
@@ -204,53 +212,263 @@ class UtilsTest extends PHPUnit_Framework_TestCase | |||
204 | $this->assertEquals('?', generateLocation($ref, 'localhost')); | 212 | $this->assertEquals('?', generateLocation($ref, 'localhost')); |
205 | } | 213 | } |
206 | 214 | ||
215 | |||
207 | /** | 216 | /** |
208 | * Test is_session_id_valid with a valid ID - TEST ALL THE HASHES! | 217 | * Test generateSecretApi. |
209 | * | ||
210 | * This tests extensively covers all hash algorithms / bit representations | ||
211 | */ | 218 | */ |
212 | public function testIsAnyHashSessionIdValid() | 219 | public function testGenerateSecretApi() |
213 | { | 220 | { |
214 | foreach (self::$sidHashes as $algo => $bpcs) { | 221 | $this->assertEquals(12, strlen(generate_api_secret('foo', 'bar'))); |
215 | foreach ($bpcs as $bpc => $hash) { | ||
216 | $this->assertTrue(is_session_id_valid($hash)); | ||
217 | } | ||
218 | } | ||
219 | } | 222 | } |
220 | 223 | ||
221 | /** | 224 | /** |
222 | * Test is_session_id_valid with a valid ID - SHA-1 hashes | 225 | * Test generateSecretApi with invalid parameters. |
223 | */ | 226 | */ |
224 | public function testIsSha1SessionIdValid() | 227 | public function testGenerateSecretApiInvalid() |
225 | { | 228 | { |
226 | $this->assertTrue(is_session_id_valid(sha1('shaarli'))); | 229 | $this->assertFalse(generate_api_secret('', '')); |
230 | $this->assertFalse(generate_api_secret(false, false)); | ||
227 | } | 231 | } |
228 | 232 | ||
229 | /** | 233 | /** |
230 | * Test is_session_id_valid with a valid ID - SHA-256 hashes | 234 | * Test normalize_spaces. |
231 | */ | 235 | */ |
232 | public function testIsSha256SessionIdValid() | 236 | public function testNormalizeSpace() |
233 | { | 237 | { |
234 | $this->assertTrue(is_session_id_valid(hash('sha256', 'shaarli'))); | 238 | $str = ' foo bar is important '; |
239 | $this->assertEquals('foo bar is important', normalize_spaces($str)); | ||
240 | $this->assertEquals('foo', normalize_spaces('foo')); | ||
241 | $this->assertEquals('', normalize_spaces('')); | ||
242 | $this->assertEquals(null, normalize_spaces(null)); | ||
235 | } | 243 | } |
236 | 244 | ||
237 | /** | 245 | /** |
238 | * Test is_session_id_valid with a valid ID - SHA-512 hashes | 246 | * Test arrays_combine |
239 | */ | 247 | */ |
240 | public function testIsSha512SessionIdValid() | 248 | public function testCartesianProductGenerator() |
241 | { | 249 | { |
242 | $this->assertTrue(is_session_id_valid(hash('sha512', 'shaarli'))); | 250 | $arr = [['ab', 'cd'], ['ef', 'gh'], ['ij', 'kl'], ['m']]; |
251 | $expected = [ | ||
252 | ['ab', 'ef', 'ij', 'm'], | ||
253 | ['ab', 'ef', 'kl', 'm'], | ||
254 | ['ab', 'gh', 'ij', 'm'], | ||
255 | ['ab', 'gh', 'kl', 'm'], | ||
256 | ['cd', 'ef', 'ij', 'm'], | ||
257 | ['cd', 'ef', 'kl', 'm'], | ||
258 | ['cd', 'gh', 'ij', 'm'], | ||
259 | ['cd', 'gh', 'kl', 'm'], | ||
260 | ]; | ||
261 | $this->assertEquals($expected, iterator_to_array(cartesian_product_generator($arr))); | ||
243 | } | 262 | } |
244 | 263 | ||
245 | /** | 264 | /** |
246 | * Test is_session_id_valid with invalid IDs. | 265 | * Test date_format() with invalid parameter. |
247 | */ | 266 | */ |
248 | public function testIsSessionIdInvalid() | 267 | public function testDateFormatInvalid() |
249 | { | 268 | { |
250 | $this->assertFalse(is_session_id_valid('')); | 269 | $this->assertFalse(format_date([])); |
251 | $this->assertFalse(is_session_id_valid(array())); | 270 | $this->assertFalse(format_date(null)); |
252 | $this->assertFalse( | 271 | } |
253 | is_session_id_valid('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=') | 272 | |
254 | ); | 273 | /** |
274 | * Test is_integer_mixed with valid values | ||
275 | */ | ||
276 | public function testIsIntegerMixedValid() | ||
277 | { | ||
278 | $this->assertTrue(is_integer_mixed(12)); | ||
279 | $this->assertTrue(is_integer_mixed('12')); | ||
280 | $this->assertTrue(is_integer_mixed(-12)); | ||
281 | $this->assertTrue(is_integer_mixed('-12')); | ||
282 | $this->assertTrue(is_integer_mixed(0)); | ||
283 | $this->assertTrue(is_integer_mixed('0')); | ||
284 | $this->assertTrue(is_integer_mixed(0x0a)); | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * Test is_integer_mixed with invalid values | ||
289 | */ | ||
290 | public function testIsIntegerMixedInvalid() | ||
291 | { | ||
292 | $this->assertFalse(is_integer_mixed(true)); | ||
293 | $this->assertFalse(is_integer_mixed(false)); | ||
294 | $this->assertFalse(is_integer_mixed([])); | ||
295 | $this->assertFalse(is_integer_mixed(['test'])); | ||
296 | $this->assertFalse(is_integer_mixed([12])); | ||
297 | $this->assertFalse(is_integer_mixed(new DateTime())); | ||
298 | $this->assertFalse(is_integer_mixed('0x0a')); | ||
299 | $this->assertFalse(is_integer_mixed('12k')); | ||
300 | $this->assertFalse(is_integer_mixed('k12')); | ||
301 | $this->assertFalse(is_integer_mixed('')); | ||
302 | } | ||
303 | |||
304 | /** | ||
305 | * Test return_bytes | ||
306 | */ | ||
307 | public function testReturnBytes() | ||
308 | { | ||
309 | $this->assertEquals(2 * 1024, return_bytes('2k')); | ||
310 | $this->assertEquals(2 * 1024, return_bytes('2K')); | ||
311 | $this->assertEquals(2 * (pow(1024, 2)), return_bytes('2m')); | ||
312 | $this->assertEquals(2 * (pow(1024, 2)), return_bytes('2M')); | ||
313 | $this->assertEquals(2 * (pow(1024, 3)), return_bytes('2g')); | ||
314 | $this->assertEquals(2 * (pow(1024, 3)), return_bytes('2G')); | ||
315 | $this->assertEquals(374, return_bytes('374')); | ||
316 | $this->assertEquals(374, return_bytes(374)); | ||
317 | $this->assertEquals(0, return_bytes('0')); | ||
318 | $this->assertEquals(0, return_bytes(0)); | ||
319 | $this->assertEquals(-1, return_bytes('-1')); | ||
320 | $this->assertEquals(-1, return_bytes(-1)); | ||
321 | $this->assertEquals('', return_bytes('')); | ||
322 | } | ||
323 | |||
324 | /** | ||
325 | * Test human_bytes | ||
326 | */ | ||
327 | public function testHumanBytes() | ||
328 | { | ||
329 | $this->assertEquals('2'. t('kiB'), human_bytes(2 * 1024)); | ||
330 | $this->assertEquals('2'. t('kiB'), human_bytes(strval(2 * 1024))); | ||
331 | $this->assertEquals('2'. t('MiB'), human_bytes(2 * (pow(1024, 2)))); | ||
332 | $this->assertEquals('2'. t('MiB'), human_bytes(strval(2 * (pow(1024, 2))))); | ||
333 | $this->assertEquals('2'. t('GiB'), human_bytes(2 * (pow(1024, 3)))); | ||
334 | $this->assertEquals('2'. t('GiB'), human_bytes(strval(2 * (pow(1024, 3))))); | ||
335 | $this->assertEquals('374'. t('B'), human_bytes(374)); | ||
336 | $this->assertEquals('374'. t('B'), human_bytes('374')); | ||
337 | $this->assertEquals('232'. t('kiB'), human_bytes(237481)); | ||
338 | $this->assertEquals(t('Unlimited'), human_bytes('0')); | ||
339 | $this->assertEquals(t('Unlimited'), human_bytes(0)); | ||
340 | $this->assertEquals(t('Setting not set'), human_bytes('')); | ||
341 | } | ||
342 | |||
343 | /** | ||
344 | * Test get_max_upload_size with formatting | ||
345 | */ | ||
346 | public function testGetMaxUploadSize() | ||
347 | { | ||
348 | $this->assertEquals('1'. t('MiB'), get_max_upload_size(2097152, '1024k')); | ||
349 | $this->assertEquals('1'. t('MiB'), get_max_upload_size('1m', '2m')); | ||
350 | $this->assertEquals('100'. t('B'), get_max_upload_size(100, 100)); | ||
351 | } | ||
352 | |||
353 | /** | ||
354 | * Test get_max_upload_size without formatting | ||
355 | */ | ||
356 | public function testGetMaxUploadSizeRaw() | ||
357 | { | ||
358 | $this->assertEquals('1048576', get_max_upload_size(2097152, '1024k', false)); | ||
359 | $this->assertEquals('1048576', get_max_upload_size('1m', '2m', false)); | ||
360 | $this->assertEquals('100', get_max_upload_size(100, 100, false)); | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * Test alphabetical_sort by value, not reversed, with php-intl. | ||
365 | */ | ||
366 | public function testAlphabeticalSortByValue() | ||
367 | { | ||
368 | $arr = [ | ||
369 | 'zZz', | ||
370 | 'éee', | ||
371 | 'éae', | ||
372 | 'eee', | ||
373 | 'A', | ||
374 | 'a', | ||
375 | 'zzz', | ||
376 | ]; | ||
377 | $expected = [ | ||
378 | 'a', | ||
379 | 'A', | ||
380 | 'éae', | ||
381 | 'eee', | ||
382 | 'éee', | ||
383 | 'zzz', | ||
384 | 'zZz', | ||
385 | ]; | ||
386 | |||
387 | alphabetical_sort($arr); | ||
388 | $this->assertEquals($expected, $arr); | ||
389 | } | ||
390 | |||
391 | /** | ||
392 | * Test alphabetical_sort by value, reversed, with php-intl. | ||
393 | */ | ||
394 | public function testAlphabeticalSortByValueReversed() | ||
395 | { | ||
396 | $arr = [ | ||
397 | 'zZz', | ||
398 | 'éee', | ||
399 | 'éae', | ||
400 | 'eee', | ||
401 | 'A', | ||
402 | 'a', | ||
403 | 'zzz', | ||
404 | ]; | ||
405 | $expected = [ | ||
406 | 'zZz', | ||
407 | 'zzz', | ||
408 | 'éee', | ||
409 | 'eee', | ||
410 | 'éae', | ||
411 | 'A', | ||
412 | 'a', | ||
413 | ]; | ||
414 | |||
415 | alphabetical_sort($arr, true); | ||
416 | $this->assertEquals($expected, $arr); | ||
417 | } | ||
418 | |||
419 | /** | ||
420 | * Test alphabetical_sort by keys, not reversed, with php-intl. | ||
421 | */ | ||
422 | public function testAlphabeticalSortByKeys() | ||
423 | { | ||
424 | $arr = [ | ||
425 | 'zZz' => true, | ||
426 | 'éee' => true, | ||
427 | 'éae' => true, | ||
428 | 'eee' => true, | ||
429 | 'A' => true, | ||
430 | 'a' => true, | ||
431 | 'zzz' => true, | ||
432 | ]; | ||
433 | $expected = [ | ||
434 | 'a' => true, | ||
435 | 'A' => true, | ||
436 | 'éae' => true, | ||
437 | 'eee' => true, | ||
438 | 'éee' => true, | ||
439 | 'zzz' => true, | ||
440 | 'zZz' => true, | ||
441 | ]; | ||
442 | |||
443 | alphabetical_sort($arr, true, true); | ||
444 | $this->assertEquals($expected, $arr); | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * Test alphabetical_sort by keys, reversed, with php-intl. | ||
449 | */ | ||
450 | public function testAlphabeticalSortByKeysReversed() | ||
451 | { | ||
452 | $arr = [ | ||
453 | 'zZz' => true, | ||
454 | 'éee' => true, | ||
455 | 'éae' => true, | ||
456 | 'eee' => true, | ||
457 | 'A' => true, | ||
458 | 'a' => true, | ||
459 | 'zzz' => true, | ||
460 | ]; | ||
461 | $expected = [ | ||
462 | 'zZz' => true, | ||
463 | 'zzz' => true, | ||
464 | 'éee' => true, | ||
465 | 'eee' => true, | ||
466 | 'éae' => true, | ||
467 | 'A' => true, | ||
468 | 'a' => true, | ||
469 | ]; | ||
470 | |||
471 | alphabetical_sort($arr, true, true); | ||
472 | $this->assertEquals($expected, $arr); | ||
255 | } | 473 | } |
256 | } | 474 | } |
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 | ||
2 | namespace Shaarli\Api; | ||
3 | |||
4 | use Shaarli\Config\ConfigManager; | ||
5 | |||
6 | use Slim\Container; | ||
7 | use Slim\Http\Environment; | ||
8 | use Slim\Http\Request; | ||
9 | use 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 | */ | ||
21 | class 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 | |||
3 | namespace Shaarli\Api; | ||
4 | |||
5 | use Shaarli\Base64Url; | ||
6 | |||
7 | |||
8 | /** | ||
9 | * Class ApiUtilsTest | ||
10 | */ | ||
11 | class 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 | |||
4 | namespace Shaarli\Api\Controllers; | ||
5 | |||
6 | use Shaarli\Config\ConfigManager; | ||
7 | use Slim\Container; | ||
8 | use Slim\Http\Environment; | ||
9 | use Slim\Http\Request; | ||
10 | use Slim\Http\Response; | ||
11 | |||
12 | class 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 | |||
3 | namespace Shaarli\Api\Controllers; | ||
4 | |||
5 | use Shaarli\Config\ConfigManager; | ||
6 | |||
7 | use Slim\Container; | ||
8 | use Slim\Http\Environment; | ||
9 | use Slim\Http\Request; | ||
10 | use 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 | */ | ||
21 | class 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..d22ed3bf --- /dev/null +++ b/tests/api/controllers/GetLinksTest.php | |||
@@ -0,0 +1,472 @@ | |||
1 | <?php | ||
2 | namespace Shaarli\Api\Controllers; | ||
3 | |||
4 | use Shaarli\Config\ConfigManager; | ||
5 | |||
6 | use Slim\Container; | ||
7 | use Slim\Http\Environment; | ||
8 | use Slim\Http\Request; | ||
9 | use 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 | */ | ||
20 | class 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, 9, 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, 9, 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 | // wildcard: placeholder at the start | ||
372 | $env = Environment::mock([ | ||
373 | 'REQUEST_METHOD' => 'GET', | ||
374 | 'QUERY_STRING' => 'searchtags=*Tuff', | ||
375 | ]); | ||
376 | $request = Request::createFromEnvironment($env); | ||
377 | $response = $this->controller->getLinks($request, new Response()); | ||
378 | $this->assertEquals(200, $response->getStatusCode()); | ||
379 | $data = json_decode((string) $response->getBody(), true); | ||
380 | $this->assertEquals(2, count($data)); | ||
381 | $this->assertEquals(41, $data[0]['id']); | ||
382 | |||
383 | // wildcard: placeholder at the end | ||
384 | $env = Environment::mock([ | ||
385 | 'REQUEST_METHOD' => 'GET', | ||
386 | 'QUERY_STRING' => 'searchtags=c*', | ||
387 | ]); | ||
388 | $request = Request::createFromEnvironment($env); | ||
389 | $response = $this->controller->getLinks($request, new Response()); | ||
390 | $this->assertEquals(200, $response->getStatusCode()); | ||
391 | $data = json_decode((string) $response->getBody(), true); | ||
392 | $this->assertEquals(4, count($data)); | ||
393 | $this->assertEquals(6, $data[0]['id']); | ||
394 | |||
395 | // wildcard: placeholder at the middle | ||
396 | $env = Environment::mock([ | ||
397 | 'REQUEST_METHOD' => 'GET', | ||
398 | 'QUERY_STRING' => 'searchtags=w*b', | ||
399 | ]); | ||
400 | $request = Request::createFromEnvironment($env); | ||
401 | $response = $this->controller->getLinks($request, new Response()); | ||
402 | $this->assertEquals(200, $response->getStatusCode()); | ||
403 | $data = json_decode((string) $response->getBody(), true); | ||
404 | $this->assertEquals(4, count($data)); | ||
405 | $this->assertEquals(6, $data[0]['id']); | ||
406 | |||
407 | // wildcard: match all | ||
408 | $env = Environment::mock([ | ||
409 | 'REQUEST_METHOD' => 'GET', | ||
410 | 'QUERY_STRING' => 'searchtags=*', | ||
411 | ]); | ||
412 | $request = Request::createFromEnvironment($env); | ||
413 | $response = $this->controller->getLinks($request, new Response()); | ||
414 | $this->assertEquals(200, $response->getStatusCode()); | ||
415 | $data = json_decode((string) $response->getBody(), true); | ||
416 | $this->assertEquals(9, count($data)); | ||
417 | $this->assertEquals(41, $data[0]['id']); | ||
418 | |||
419 | // wildcard: optional ('*' does not need to expand) | ||
420 | $env = Environment::mock([ | ||
421 | 'REQUEST_METHOD' => 'GET', | ||
422 | 'QUERY_STRING' => 'searchtags=*stuff*', | ||
423 | ]); | ||
424 | $request = Request::createFromEnvironment($env); | ||
425 | $response = $this->controller->getLinks($request, new Response()); | ||
426 | $this->assertEquals(200, $response->getStatusCode()); | ||
427 | $data = json_decode((string) $response->getBody(), true); | ||
428 | $this->assertEquals(2, count($data)); | ||
429 | $this->assertEquals(41, $data[0]['id']); | ||
430 | |||
431 | // wildcard: exclusions | ||
432 | $env = Environment::mock([ | ||
433 | 'REQUEST_METHOD' => 'GET', | ||
434 | 'QUERY_STRING' => 'searchtags=*a*+-*e*', | ||
435 | ]); | ||
436 | $request = Request::createFromEnvironment($env); | ||
437 | $response = $this->controller->getLinks($request, new Response()); | ||
438 | $this->assertEquals(200, $response->getStatusCode()); | ||
439 | $data = json_decode((string) $response->getBody(), true); | ||
440 | $this->assertEquals(1, count($data)); | ||
441 | $this->assertEquals(41, $data[0]['id']); // finds '#hashtag' in descr. | ||
442 | |||
443 | // wildcard: exclude all | ||
444 | $env = Environment::mock([ | ||
445 | 'REQUEST_METHOD' => 'GET', | ||
446 | 'QUERY_STRING' => 'searchtags=-*', | ||
447 | ]); | ||
448 | $request = Request::createFromEnvironment($env); | ||
449 | $response = $this->controller->getLinks($request, new Response()); | ||
450 | $this->assertEquals(200, $response->getStatusCode()); | ||
451 | $data = json_decode((string) $response->getBody(), true); | ||
452 | $this->assertEquals(0, count($data)); | ||
453 | } | ||
454 | |||
455 | /** | ||
456 | * Test getLinks service with search tags+terms. | ||
457 | */ | ||
458 | public function testGetLinksSearchTermsAndTags() | ||
459 | { | ||
460 | $env = Environment::mock([ | ||
461 | 'REQUEST_METHOD' => 'GET', | ||
462 | 'QUERY_STRING' => 'searchterm=poke&searchtags=dev', | ||
463 | ]); | ||
464 | $request = Request::createFromEnvironment($env); | ||
465 | $response = $this->controller->getLinks($request, new Response()); | ||
466 | $this->assertEquals(200, $response->getStatusCode()); | ||
467 | $data = json_decode((string) $response->getBody(), true); | ||
468 | $this->assertEquals(1, count($data)); | ||
469 | $this->assertEquals(0, $data[0]['id']); | ||
470 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
471 | } | ||
472 | } | ||
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 | |||
4 | namespace Shaarli\Api\Controllers; | ||
5 | |||
6 | |||
7 | use Shaarli\Config\ConfigManager; | ||
8 | use Slim\Container; | ||
9 | use Slim\Http\Environment; | ||
10 | use Slim\Http\Request; | ||
11 | use Slim\Http\Response; | ||
12 | |||
13 | require_once 'tests/utils/ReferenceHistory.php'; | ||
14 | |||
15 | class 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..f7e63bfa --- /dev/null +++ b/tests/api/controllers/InfoTest.php | |||
@@ -0,0 +1,115 @@ | |||
1 | <?php | ||
2 | namespace Shaarli\Api\Controllers; | ||
3 | |||
4 | use Shaarli\Config\ConfigManager; | ||
5 | |||
6 | use Slim\Container; | ||
7 | use Slim\Http\Environment; | ||
8 | use Slim\Http\Request; | ||
9 | use Slim\Http\Response; | ||
10 | |||
11 | /** | ||
12 | * Class InfoTest | ||
13 | * | ||
14 | * Test REST API controller Info. | ||
15 | * | ||
16 | * @package Api\Controllers | ||
17 | */ | ||
18 | class 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(\ReferenceLinkDB::$NB_LINKS_TOTAL, $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(\ReferenceLinkDB::$NB_LINKS_TOTAL, $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 | |||
3 | namespace Shaarli\Api\Controllers; | ||
4 | |||
5 | |||
6 | use Shaarli\Config\ConfigManager; | ||
7 | use Slim\Container; | ||
8 | use Slim\Http\Environment; | ||
9 | use Slim\Http\Request; | ||
10 | use Slim\Http\Response; | ||
11 | |||
12 | /** | ||
13 | * Class PostLinkTest | ||
14 | * | ||
15 | * Test POST Link REST API service. | ||
16 | * | ||
17 | * @package Shaarli\Api\Controllers | ||
18 | */ | ||
19 | class 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 | |||
4 | namespace Shaarli\Api\Controllers; | ||
5 | |||
6 | |||
7 | use Shaarli\Config\ConfigManager; | ||
8 | use Slim\Container; | ||
9 | use Slim\Http\Environment; | ||
10 | use Slim\Http\Request; | ||
11 | use Slim\Http\Response; | ||
12 | |||
13 | class 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/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 00000000..d36d73cd --- /dev/null +++ b/tests/bootstrap.php | |||
@@ -0,0 +1,6 @@ | |||
1 | <?php | ||
2 | |||
3 | require_once 'vendor/autoload.php'; | ||
4 | |||
5 | $conf = new \Shaarli\Config\ConfigManager('tests/utils/config/configJson'); | ||
6 | new \Shaarli\Languages('en', $conf); | ||
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 | 2 | namespace Shaarli\Config; | |
3 | require_once 'application/config/ConfigJson.php'; | ||
4 | 3 | ||
5 | /** | 4 | /** |
6 | * Class ConfigJsonTest | 5 | * Class ConfigJsonTest |
7 | */ | 6 | */ |
8 | class ConfigJsonTest extends PHPUnit_Framework_TestCase | 7 | class 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 |
2 | namespace 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 | */ |
9 | class ConfigManagerTest extends PHPUnit_Framework_TestCase | 10 | class 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..be23eea1 100644 --- a/tests/config/ConfigPhpTest.php +++ b/tests/config/ConfigPhpTest.php | |||
@@ -1,11 +1,10 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | namespace Shaarli\Config; | |
3 | require_once 'application/config/ConfigPhp.php'; | ||
4 | 3 | ||
5 | /** | 4 | /** |
6 | * Class ConfigPhpTest | 5 | * Class ConfigPhpTest |
7 | */ | 6 | */ |
8 | class ConfigPhpTest extends PHPUnit_Framework_TestCase | 7 | class ConfigPhpTest extends \PHPUnit_Framework_TestCase |
9 | { | 8 | { |
10 | /** | 9 | /** |
11 | * @var ConfigPhp | 10 | * @var ConfigPhp |
@@ -38,6 +37,20 @@ class ConfigPhpTest extends PHPUnit_Framework_TestCase | |||
38 | } | 37 | } |
39 | 38 | ||
40 | /** | 39 | /** |
40 | * Read an empty existent config file -> array with blank default values. | ||
41 | */ | ||
42 | public function testReadEmpty() | ||
43 | { | ||
44 | $dataFile = 'tests/utils/config/emptyConfigPhp.php'; | ||
45 | $conf = $this->configIO->read($dataFile); | ||
46 | $this->assertEmpty($conf['login']); | ||
47 | $this->assertEmpty($conf['title']); | ||
48 | $this->assertEmpty($conf['titleLink']); | ||
49 | $this->assertEmpty($conf['config']); | ||
50 | $this->assertEmpty($conf['plugins']); | ||
51 | } | ||
52 | |||
53 | /** | ||
41 | * Write a new config file. | 54 | * Write a new config file. |
42 | */ | 55 | */ |
43 | public function testWriteNew() | 56 | public function testWriteNew() |
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 | /** | 2 | namespace Shaarli\Config; |
3 | * Config' tests | 3 | |
4 | */ | 4 | use Shaarli\Config\Exception\PluginConfigOrderException; |
5 | 5 | ||
6 | require_once 'application/config/ConfigPlugin.php'; | 6 | require_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 | */ |
11 | class ConfigPluginTest extends PHPUnit_Framework_TestCase | 11 | class 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/docker/alpine36/Dockerfile b/tests/docker/alpine36/Dockerfile new file mode 100644 index 00000000..fa84f6e2 --- /dev/null +++ b/tests/docker/alpine36/Dockerfile | |||
@@ -0,0 +1,34 @@ | |||
1 | FROM alpine:3.6 | ||
2 | MAINTAINER Shaarli Community | ||
3 | |||
4 | RUN apk --update --no-cache add \ | ||
5 | ca-certificates \ | ||
6 | curl \ | ||
7 | make \ | ||
8 | php7 \ | ||
9 | php7-ctype \ | ||
10 | php7-curl \ | ||
11 | php7-dom \ | ||
12 | php7-gd \ | ||
13 | php7-iconv \ | ||
14 | php7-intl \ | ||
15 | php7-json \ | ||
16 | php7-mbstring \ | ||
17 | php7-openssl \ | ||
18 | php7-phar \ | ||
19 | php7-session \ | ||
20 | php7-simplexml \ | ||
21 | php7-tokenizer \ | ||
22 | php7-xdebug \ | ||
23 | php7-xml \ | ||
24 | php7-zlib \ | ||
25 | rsync | ||
26 | |||
27 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer | ||
28 | |||
29 | RUN mkdir /shaarli | ||
30 | WORKDIR /shaarli | ||
31 | VOLUME /shaarli | ||
32 | |||
33 | ENTRYPOINT ["make"] | ||
34 | CMD [] | ||
diff --git a/tests/docker/debian8/Dockerfile b/tests/docker/debian8/Dockerfile new file mode 100644 index 00000000..eaa34e9b --- /dev/null +++ b/tests/docker/debian8/Dockerfile | |||
@@ -0,0 +1,35 @@ | |||
1 | FROM debian:jessie | ||
2 | MAINTAINER Shaarli Community | ||
3 | |||
4 | ENV TERM dumb | ||
5 | ENV DEBIAN_FRONTEND noninteractive | ||
6 | ENV LANG en_US.UTF-8 | ||
7 | ENV LANGUAGE en_US:en | ||
8 | |||
9 | RUN apt-get update \ | ||
10 | && apt-get install --no-install-recommends -y \ | ||
11 | ca-certificates \ | ||
12 | curl \ | ||
13 | locales \ | ||
14 | make \ | ||
15 | php5 \ | ||
16 | php5-curl \ | ||
17 | php5-gd \ | ||
18 | php5-intl \ | ||
19 | php5-xdebug \ | ||
20 | rsync \ | ||
21 | && apt-get clean | ||
22 | |||
23 | RUN locale-gen en_US.UTF-8 \ | ||
24 | && locale-gen de_DE.UTF-8 \ | ||
25 | && locale-gen fr_FR.UTF-8 | ||
26 | |||
27 | ADD https://getcomposer.org/composer.phar /usr/local/bin/composer | ||
28 | RUN chmod 755 /usr/local/bin/composer | ||
29 | |||
30 | RUN mkdir /shaarli | ||
31 | WORKDIR /shaarli | ||
32 | VOLUME /shaarli | ||
33 | |||
34 | ENTRYPOINT ["make"] | ||
35 | CMD [] | ||
diff --git a/tests/docker/debian9/Dockerfile b/tests/docker/debian9/Dockerfile new file mode 100644 index 00000000..3ab4b93d --- /dev/null +++ b/tests/docker/debian9/Dockerfile | |||
@@ -0,0 +1,36 @@ | |||
1 | FROM debian:stretch | ||
2 | MAINTAINER Shaarli Community | ||
3 | |||
4 | ENV TERM dumb | ||
5 | ENV DEBIAN_FRONTEND noninteractive | ||
6 | ENV LANG en_US.UTF-8 | ||
7 | ENV LANGUAGE en_US:en | ||
8 | |||
9 | RUN apt-get update \ | ||
10 | && apt-get install --no-install-recommends -y \ | ||
11 | ca-certificates \ | ||
12 | curl \ | ||
13 | locales \ | ||
14 | make \ | ||
15 | php7.0 \ | ||
16 | php7.0-curl \ | ||
17 | php7.0-gd \ | ||
18 | php7.0-intl \ | ||
19 | php7.0-xml \ | ||
20 | php-xdebug \ | ||
21 | rsync \ | ||
22 | && apt-get clean | ||
23 | |||
24 | RUN locale-gen en_US.UTF-8 \ | ||
25 | && locale-gen de_DE.UTF-8 \ | ||
26 | && locale-gen fr_FR.UTF-8 | ||
27 | |||
28 | ADD https://getcomposer.org/composer.phar /usr/local/bin/composer | ||
29 | RUN chmod 755 /usr/local/bin/composer | ||
30 | |||
31 | RUN mkdir /shaarli | ||
32 | WORKDIR /shaarli | ||
33 | VOLUME /shaarli | ||
34 | |||
35 | ENTRYPOINT ["make"] | ||
36 | CMD [] | ||
diff --git a/tests/docker/ubuntu16/Dockerfile b/tests/docker/ubuntu16/Dockerfile new file mode 100644 index 00000000..e53ed9e3 --- /dev/null +++ b/tests/docker/ubuntu16/Dockerfile | |||
@@ -0,0 +1,36 @@ | |||
1 | FROM ubuntu:16.04 | ||
2 | MAINTAINER Shaarli Community | ||
3 | |||
4 | ENV TERM dumb | ||
5 | ENV DEBIAN_FRONTEND noninteractive | ||
6 | ENV LANG en_US.UTF-8 | ||
7 | ENV LANGUAGE en_US:en | ||
8 | |||
9 | RUN apt-get update \ | ||
10 | && apt-get install --no-install-recommends -y \ | ||
11 | ca-certificates \ | ||
12 | curl \ | ||
13 | language-pack-de \ | ||
14 | language-pack-en \ | ||
15 | language-pack-fr \ | ||
16 | locales \ | ||
17 | make \ | ||
18 | php7.0 \ | ||
19 | php7.0-curl \ | ||
20 | php7.0-gd \ | ||
21 | php7.0-intl \ | ||
22 | php7.0-xml \ | ||
23 | php-xdebug \ | ||
24 | rsync \ | ||
25 | && apt-get clean | ||
26 | |||
27 | ADD https://getcomposer.org/composer.phar /usr/local/bin/composer | ||
28 | RUN chmod 755 /usr/local/bin/composer | ||
29 | |||
30 | RUN useradd -m dev \ | ||
31 | && mkdir /shaarli | ||
32 | USER dev | ||
33 | WORKDIR /shaarli | ||
34 | |||
35 | ENTRYPOINT ["make"] | ||
36 | CMD [] | ||
diff --git a/tests/languages/bootstrap.php b/tests/languages/bootstrap.php new file mode 100644 index 00000000..da6ac2e4 --- /dev/null +++ b/tests/languages/bootstrap.php | |||
@@ -0,0 +1,6 @@ | |||
1 | <?php | ||
2 | require_once 'tests/bootstrap.php'; | ||
3 | |||
4 | if (! empty(getenv('UT_LOCALE'))) { | ||
5 | setlocale(LC_ALL, getenv('UT_LOCALE')); | ||
6 | } | ||
diff --git a/tests/languages/de/UtilsDeTest.php b/tests/languages/de/UtilsDeTest.php new file mode 100644 index 00000000..4569c923 --- /dev/null +++ b/tests/languages/de/UtilsDeTest.php | |||
@@ -0,0 +1,119 @@ | |||
1 | <?php | ||
2 | |||
3 | require_once 'tests/UtilsTest.php'; | ||
4 | |||
5 | |||
6 | class 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 available | ||
85 | */ | ||
86 | public function testAutoLocaleMultipleSecondAvailable() | ||
87 | { | ||
88 | $current = setlocale(LC_ALL, 0); | ||
89 | $header = 'mag_IN,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 unavailable value: defaults to en_US. | ||
110 | */ | ||
111 | public function testAutoLocaleUnavailable() | ||
112 | { | ||
113 | $current = setlocale(LC_ALL, 0); | ||
114 | autoLocale('mag_IN'); | ||
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..a74063ae --- /dev/null +++ b/tests/languages/en/UtilsEnTest.php | |||
@@ -0,0 +1,119 @@ | |||
1 | <?php | ||
2 | |||
3 | require_once 'tests/UtilsTest.php'; | ||
4 | |||
5 | |||
6 | class 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 available | ||
85 | */ | ||
86 | public function testAutoLocaleMultipleSecondAvailable() | ||
87 | { | ||
88 | $current = setlocale(LC_ALL, 0); | ||
89 | $header = 'mag_IN,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 unavailable value: defaults to en_US. | ||
110 | */ | ||
111 | public function testAutoLocaleUnavailable() | ||
112 | { | ||
113 | $current = setlocale(LC_ALL, 0); | ||
114 | autoLocale('mag_IN'); | ||
115 | $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); | ||
116 | |||
117 | setlocale(LC_ALL, $current); | ||
118 | } | ||
119 | } | ||
diff --git a/tests/languages/fr/LanguagesFrTest.php b/tests/languages/fr/LanguagesFrTest.php new file mode 100644 index 00000000..79d05172 --- /dev/null +++ b/tests/languages/fr/LanguagesFrTest.php | |||
@@ -0,0 +1,175 @@ | |||
1 | <?php | ||
2 | |||
3 | |||
4 | namespace Shaarli; | ||
5 | |||
6 | |||
7 | use Shaarli\Config\ConfigManager; | ||
8 | |||
9 | /** | ||
10 | * Class LanguagesFrTest | ||
11 | * | ||
12 | * Test the translation system in PHP and gettext mode with French language. | ||
13 | * | ||
14 | * @package Shaarli | ||
15 | */ | ||
16 | class LanguagesFrTest extends \PHPUnit_Framework_TestCase | ||
17 | { | ||
18 | /** | ||
19 | * @var string Config file path (without extension). | ||
20 | */ | ||
21 | protected static $configFile = 'tests/utils/config/configJson'; | ||
22 | |||
23 | /** | ||
24 | * @var ConfigManager | ||
25 | */ | ||
26 | protected $conf; | ||
27 | |||
28 | /** | ||
29 | * Init: force French | ||
30 | */ | ||
31 | public function setUp() | ||
32 | { | ||
33 | $this->conf = new ConfigManager(self::$configFile); | ||
34 | $this->conf->set('translation.language', 'fr'); | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * Reset the locale since gettext seems to mess with it, making it too long | ||
39 | */ | ||
40 | public static function tearDownAfterClass() | ||
41 | { | ||
42 | if (! empty(getenv('UT_LOCALE'))) { | ||
43 | setlocale(LC_ALL, getenv('UT_LOCALE')); | ||
44 | } | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * Test t() with a simple non identified value. | ||
49 | */ | ||
50 | public function testTranslateSingleNotIDGettext() | ||
51 | { | ||
52 | $this->conf->set('translation.mode', 'gettext'); | ||
53 | new Languages('en', $this->conf); | ||
54 | $text = 'abcdé 564 fgK'; | ||
55 | $this->assertEquals($text, t($text)); | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * Test t() with a simple identified value in gettext mode. | ||
60 | */ | ||
61 | public function testTranslateSingleIDGettext() | ||
62 | { | ||
63 | $this->conf->set('translation.mode', 'gettext'); | ||
64 | new Languages('en', $this->conf); | ||
65 | $text = 'permalink'; | ||
66 | $this->assertEquals('permalien', t($text)); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * Test t() with a non identified plural form in gettext mode. | ||
71 | */ | ||
72 | public function testTranslatePluralNotIDGettext() | ||
73 | { | ||
74 | $this->conf->set('translation.mode', 'gettext'); | ||
75 | new Languages('en', $this->conf); | ||
76 | $text = 'sandwich'; | ||
77 | $nText = 'sandwiches'; | ||
78 | // Not ID, so English fallback, and in english, plural 0 | ||
79 | $this->assertEquals('sandwiches', t($text, $nText, 0)); | ||
80 | $this->assertEquals('sandwich', t($text, $nText, 1)); | ||
81 | $this->assertEquals('sandwiches', t($text, $nText, 2)); | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * Test t() with an identified plural form in gettext mode. | ||
86 | */ | ||
87 | public function testTranslatePluralIDGettext() | ||
88 | { | ||
89 | $this->conf->set('translation.mode', 'gettext'); | ||
90 | new Languages('en', $this->conf); | ||
91 | $text = 'shaare'; | ||
92 | $nText = 'shaares'; | ||
93 | $this->assertEquals('shaare', t($text, $nText, 0)); | ||
94 | $this->assertEquals('shaare', t($text, $nText, 1)); | ||
95 | $this->assertEquals('shaares', t($text, $nText, 2)); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * Test t() with a simple non identified value. | ||
100 | */ | ||
101 | public function testTranslateSingleNotIDPhp() | ||
102 | { | ||
103 | $this->conf->set('translation.mode', 'php'); | ||
104 | new Languages('en', $this->conf); | ||
105 | $text = 'abcdé 564 fgK'; | ||
106 | $this->assertEquals($text, t($text)); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * Test t() with a simple identified value in PHP mode. | ||
111 | */ | ||
112 | public function testTranslateSingleIDPhp() | ||
113 | { | ||
114 | $this->conf->set('translation.mode', 'php'); | ||
115 | new Languages('en', $this->conf); | ||
116 | $text = 'permalink'; | ||
117 | $this->assertEquals('permalien', t($text)); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * Test t() with a non identified plural form in PHP mode. | ||
122 | */ | ||
123 | public function testTranslatePluralNotIDPhp() | ||
124 | { | ||
125 | $this->conf->set('translation.mode', 'php'); | ||
126 | new Languages('en', $this->conf); | ||
127 | $text = 'sandwich'; | ||
128 | $nText = 'sandwiches'; | ||
129 | // Not ID, so English fallback, and in english, plural 0 | ||
130 | $this->assertEquals('sandwiches', t($text, $nText, 0)); | ||
131 | $this->assertEquals('sandwich', t($text, $nText, 1)); | ||
132 | $this->assertEquals('sandwiches', t($text, $nText, 2)); | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * Test t() with an identified plural form in PHP mode. | ||
137 | */ | ||
138 | public function testTranslatePluralIDPhp() | ||
139 | { | ||
140 | $this->conf->set('translation.mode', 'php'); | ||
141 | new Languages('en', $this->conf); | ||
142 | $text = 'shaare'; | ||
143 | $nText = 'shaares'; | ||
144 | // In english, zero is followed by plural form | ||
145 | $this->assertEquals('shaare', t($text, $nText, 0)); | ||
146 | $this->assertEquals('shaare', t($text, $nText, 1)); | ||
147 | $this->assertEquals('shaares', t($text, $nText, 2)); | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * Test t() with an extension language file in gettext mode | ||
152 | */ | ||
153 | public function testTranslationExtensionGettext() | ||
154 | { | ||
155 | $this->conf->set('translation.mode', 'gettext'); | ||
156 | $this->conf->set('translation.extensions.test', 'tests/utils/languages/'); | ||
157 | new Languages('en', $this->conf); | ||
158 | $txt = 'car'; // ignore me poedit | ||
159 | $this->assertEquals('voiture', t($txt, $txt, 1, 'test')); | ||
160 | $this->assertEquals('Fouille', t('Search', 'Search', 1, 'test')); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * Test t() with an extension language file in PHP mode | ||
165 | */ | ||
166 | public function testTranslationExtensionPhp() | ||
167 | { | ||
168 | $this->conf->set('translation.mode', 'php'); | ||
169 | $this->conf->set('translation.extensions.test', 'tests/utils/languages/'); | ||
170 | new Languages('en', $this->conf); | ||
171 | $txt = 'car'; // ignore me poedit | ||
172 | $this->assertEquals('voiture', t($txt, $txt, 1, 'test')); | ||
173 | $this->assertEquals('Fouille', t('Search', 'Search', 1, 'test')); | ||
174 | } | ||
175 | } | ||
diff --git a/tests/languages/fr/UtilsFrTest.php b/tests/languages/fr/UtilsFrTest.php new file mode 100644 index 00000000..3dbb126f --- /dev/null +++ b/tests/languages/fr/UtilsFrTest.php | |||
@@ -0,0 +1,119 @@ | |||
1 | <?php | ||
2 | |||
3 | require_once 'tests/UtilsTest.php'; | ||
4 | |||
5 | |||
6 | class 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 available | ||
85 | */ | ||
86 | public function testAutoLocaleMultipleSecondAvailable() | ||
87 | { | ||
88 | $current = setlocale(LC_ALL, 0); | ||
89 | $header = 'mag_IN,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 unavailable value: defaults to en_US. | ||
110 | */ | ||
111 | public function testAutoLocaleUnavailable() | ||
112 | { | ||
113 | $current = setlocale(LC_ALL, 0); | ||
114 | autoLocale('mag_IN'); | ||
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 |
2 | use Shaarli\Config\ConfigManager; | ||
2 | 3 | ||
3 | require_once 'plugins/isso/isso.php'; | 4 | require_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..96891f1f 100644 --- a/tests/plugins/PluginMarkdownTest.php +++ b/tests/plugins/PluginMarkdownTest.php | |||
@@ -1,4 +1,5 @@ | |||
1 | <?php | 1 | <?php |
2 | use Shaarli\Config\ConfigManager; | ||
2 | 3 | ||
3 | /** | 4 | /** |
4 | * PluginMarkdownTest.php | 5 | * PluginMarkdownTest.php |
@@ -21,17 +22,18 @@ 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'); |
29 | $this->conf->set('security.allowed_protocols', ['ftp', 'magnet']); | ||
28 | } | 30 | } |
29 | 31 | ||
30 | /** | 32 | /** |
31 | * Test render_linklist hook. | 33 | * Test render_linklist hook. |
32 | * Only check that there is basic markdown rendering. | 34 | * Only check that there is basic markdown rendering. |
33 | */ | 35 | */ |
34 | function testMarkdownLinklist() | 36 | public function testMarkdownLinklist() |
35 | { | 37 | { |
36 | $markdown = '# My title' . PHP_EOL . 'Very interesting content.'; | 38 | $markdown = '# My title' . PHP_EOL . 'Very interesting content.'; |
37 | $data = array( | 39 | $data = array( |
@@ -51,7 +53,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
51 | * Test render_daily hook. | 53 | * Test render_daily hook. |
52 | * Only check that there is basic markdown rendering. | 54 | * Only check that there is basic markdown rendering. |
53 | */ | 55 | */ |
54 | function testMarkdownDaily() | 56 | public function testMarkdownDaily() |
55 | { | 57 | { |
56 | $markdown = '# My title' . PHP_EOL . 'Very interesting content.'; | 58 | $markdown = '# My title' . PHP_EOL . 'Very interesting content.'; |
57 | $data = array( | 59 | $data = array( |
@@ -75,7 +77,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
75 | /** | 77 | /** |
76 | * Test reverse_text2clickable(). | 78 | * Test reverse_text2clickable(). |
77 | */ | 79 | */ |
78 | function testReverseText2clickable() | 80 | public function testReverseText2clickable() |
79 | { | 81 | { |
80 | $text = 'stuff http://hello.there/is=someone#here otherstuff'; | 82 | $text = 'stuff http://hello.there/is=someone#here otherstuff'; |
81 | $clickableText = text2clickable($text, ''); | 83 | $clickableText = text2clickable($text, ''); |
@@ -86,7 +88,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
86 | /** | 88 | /** |
87 | * Test reverse_nl2br(). | 89 | * Test reverse_nl2br(). |
88 | */ | 90 | */ |
89 | function testReverseNl2br() | 91 | public function testReverseNl2br() |
90 | { | 92 | { |
91 | $text = 'stuff' . PHP_EOL . 'otherstuff'; | 93 | $text = 'stuff' . PHP_EOL . 'otherstuff'; |
92 | $processedText = nl2br($text); | 94 | $processedText = nl2br($text); |
@@ -97,7 +99,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
97 | /** | 99 | /** |
98 | * Test reverse_space2nbsp(). | 100 | * Test reverse_space2nbsp(). |
99 | */ | 101 | */ |
100 | function testReverseSpace2nbsp() | 102 | public function testReverseSpace2nbsp() |
101 | { | 103 | { |
102 | $text = ' stuff' . PHP_EOL . ' otherstuff and another'; | 104 | $text = ' stuff' . PHP_EOL . ' otherstuff and another'; |
103 | $processedText = space2nbsp($text); | 105 | $processedText = space2nbsp($text); |
@@ -108,7 +110,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
108 | /** | 110 | /** |
109 | * Test sanitize_html(). | 111 | * Test sanitize_html(). |
110 | */ | 112 | */ |
111 | function testSanitizeHtml() | 113 | public function testSanitizeHtml() |
112 | { | 114 | { |
113 | $input = '< script src="js.js"/>'; | 115 | $input = '< script src="js.js"/>'; |
114 | $input .= '< script attr>alert(\'xss\');</script>'; | 116 | $input .= '< script attr>alert(\'xss\');</script>'; |
@@ -127,7 +129,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
127 | /** | 129 | /** |
128 | * Test the no markdown tag. | 130 | * Test the no markdown tag. |
129 | */ | 131 | */ |
130 | function testNoMarkdownTag() | 132 | public function testNoMarkdownTag() |
131 | { | 133 | { |
132 | $str = 'All _work_ and `no play` makes Jack a *dull* boy.'; | 134 | $str = 'All _work_ and `no play` makes Jack a *dull* boy.'; |
133 | $data = array( | 135 | $data = array( |
@@ -166,7 +168,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
166 | /** | 168 | /** |
167 | * Test that a close value to nomarkdown is not understand as nomarkdown (previous value `.nomarkdown`). | 169 | * Test that a close value to nomarkdown is not understand as nomarkdown (previous value `.nomarkdown`). |
168 | */ | 170 | */ |
169 | function testNoMarkdownNotExcactlyMatching() | 171 | public function testNoMarkdownNotExcactlyMatching() |
170 | { | 172 | { |
171 | $str = 'All _work_ and `no play` makes Jack a *dull* boy.'; | 173 | $str = 'All _work_ and `no play` makes Jack a *dull* boy.'; |
172 | $data = array( | 174 | $data = array( |
@@ -182,15 +184,19 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
182 | } | 184 | } |
183 | 185 | ||
184 | /** | 186 | /** |
185 | * Test hashtag links processed with markdown. | 187 | * Make sure that the generated HTML match the reference HTML file. |
186 | */ | 188 | */ |
187 | function testMarkdownHashtagLinks() | 189 | public function testMarkdownGlobalProcessDescription() |
188 | { | 190 | { |
189 | $md = file_get_contents('tests/plugins/resources/markdown.md'); | 191 | $md = file_get_contents('tests/plugins/resources/markdown.md'); |
190 | $md = format_description($md); | 192 | $md = format_description($md); |
191 | $html = file_get_contents('tests/plugins/resources/markdown.html'); | 193 | $html = file_get_contents('tests/plugins/resources/markdown.html'); |
192 | 194 | ||
193 | $data = process_markdown($md); | 195 | $data = process_markdown( |
196 | $md, | ||
197 | $this->conf->get('security.markdown_escape', true), | ||
198 | $this->conf->get('security.allowed_protocols') | ||
199 | ); | ||
194 | $this->assertEquals($html, $data); | 200 | $this->assertEquals($html, $data); |
195 | } | 201 | } |
196 | 202 | ||
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 | ||
2 | use Shaarli\Config\ConfigManager; | ||
3 | |||
4 | require_once 'plugins/pubsubhubbub/pubsubhubbub.php'; | ||
5 | require_once 'application/Router.php'; | ||
6 | |||
7 | /** | ||
8 | * Class PluginPubsubhubbubTest | ||
9 | * Unit test for the pubsubhubbub plugin | ||
10 | */ | ||
11 | class 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 | ||
7 | require_once 'plugins/qrcode/qrcode.php'; | 6 | require_once 'plugins/qrcode/qrcode.php'; |
8 | require_once 'application/Router.php'; | 7 | require_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 | */ |
14 | class PlugQrcodeTest extends PHPUnit_Framework_TestCase | 13 | class 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 | |||
7 | require_once 'plugins/readityourself/readityourself.php'; | ||
8 | |||
9 | /** | ||
10 | * Class PluginWallabagTest | ||
11 | * Unit test for the Wallabag plugin | ||
12 | */ | ||
13 | class 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 |
2 | use 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/plugins/resources/markdown.html b/tests/plugins/resources/markdown.html index 07a5a32e..844a6f31 100644 --- a/tests/plugins/resources/markdown.html +++ b/tests/plugins/resources/markdown.html | |||
@@ -21,4 +21,13 @@ | |||
21 | next #foo</code></pre> | 21 | next #foo</code></pre> |
22 | <p>Block:</p> | 22 | <p>Block:</p> |
23 | <pre><code>lorem ipsum #foobar http://link.tld | 23 | <pre><code>lorem ipsum #foobar http://link.tld |
24 | #foobar http://link.tld</code></pre></div> \ No newline at end of file | 24 | #foobar http://link.tld</code></pre> |
25 | <p><a href="?123456">link</a><br /> | ||
26 | <img src="/img/train.png" alt="link" /><br /> | ||
27 | <a href="http://test.tld/path/?query=value#hash">link</a><br /> | ||
28 | <a href="http://test.tld/path/?query=value#hash">link</a><br /> | ||
29 | <a href="https://test.tld/path/?query=value#hash">link</a><br /> | ||
30 | <a href="ftp://test.tld/path/?query=value#hash">link</a><br /> | ||
31 | <a href="magnet:test.tld/path/?query=value#hash">link</a><br /> | ||
32 | <a href="http://alert('xss')">link</a><br /> | ||
33 | <a href="http://test.tld/path/?query=value#hash">link</a></p></div> \ No newline at end of file | ||
diff --git a/tests/plugins/resources/markdown.md b/tests/plugins/resources/markdown.md index 0b8be7c5..b8ebd934 100644 --- a/tests/plugins/resources/markdown.md +++ b/tests/plugins/resources/markdown.md | |||
@@ -21,4 +21,14 @@ Block: | |||
21 | ``` | 21 | ``` |
22 | lorem ipsum #foobar http://link.tld | 22 | lorem ipsum #foobar http://link.tld |
23 | #foobar http://link.tld | 23 | #foobar http://link.tld |
24 | ``` \ No newline at end of file | 24 | ``` |
25 | |||
26 | [link](?123456) | ||
27 | ![link](/img/train.png) | ||
28 | [link](test.tld/path/?query=value#hash) | ||
29 | [link](http://test.tld/path/?query=value#hash) | ||
30 | [link](https://test.tld/path/?query=value#hash) | ||
31 | [link](ftp://test.tld/path/?query=value#hash) | ||
32 | [link](magnet:test.tld/path/?query=value#hash) | ||
33 | [link](javascript:alert('xss')) | ||
34 | [link](other://test.tld/path/?query=value#hash) \ No newline at end of file | ||
diff --git a/tests/utils/FakeConfigManager.php b/tests/utils/FakeConfigManager.php new file mode 100644 index 00000000..f29760cb --- /dev/null +++ b/tests/utils/FakeConfigManager.php | |||
@@ -0,0 +1,12 @@ | |||
1 | <?php | ||
2 | |||
3 | /** | ||
4 | * Fake ConfigManager | ||
5 | */ | ||
6 | class FakeConfigManager | ||
7 | { | ||
8 | public static function get($key) | ||
9 | { | ||
10 | return $key; | ||
11 | } | ||
12 | } | ||
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 | */ | ||
6 | class 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..e887aa78 100644 --- a/tests/utils/ReferenceLinkDB.php +++ b/tests/utils/ReferenceLinkDB.php | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | class ReferenceLinkDB | 5 | class ReferenceLinkDB |
6 | { | 6 | { |
7 | public static $NB_LINKS_TOTAL = 8; | 7 | public static $NB_LINKS_TOTAL = 9; |
8 | 8 | ||
9 | private $_links = array(); | 9 | private $_links = array(); |
10 | private $_publicCount = 0; | 10 | private $_publicCount = 0; |
@@ -38,6 +38,16 @@ class ReferenceLinkDB | |||
38 | ); | 38 | ); |
39 | 39 | ||
40 | $this->addLink( | 40 | $this->addLink( |
41 | 9, | ||
42 | 'PSR-2: Coding Style Guide', | ||
43 | 'http://www.php-fig.org/psr/psr-2/', | ||
44 | 'This guide extends and expands on PSR-1, the basic coding standard.', | ||
45 | 0, | ||
46 | DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_152312'), | ||
47 | '' | ||
48 | ); | ||
49 | |||
50 | $this->addLink( | ||
41 | 8, | 51 | 8, |
42 | 'Free as in Freedom 2.0 @website', | 52 | 'Free as in Freedom 2.0 @website', |
43 | 'https://static.fsf.org/nosvn/faif-2.0.pdf', | 53 | 'https://static.fsf.org/nosvn/faif-2.0.pdf', |
@@ -56,7 +66,7 @@ class ReferenceLinkDB | |||
56 | 0, | 66 | 0, |
57 | DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20130614_184135'), | 67 | DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20130614_184135'), |
58 | 'gnu media web .hidden hashtag', | 68 | 'gnu media web .hidden hashtag', |
59 | null, | 69 | DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20130615_184230'), |
60 | 'IuWvgA' | 70 | 'IuWvgA' |
61 | ); | 71 | ); |
62 | 72 | ||
@@ -131,6 +141,7 @@ class ReferenceLinkDB | |||
131 | */ | 141 | */ |
132 | public function write($filename) | 142 | public function write($filename) |
133 | { | 143 | { |
144 | $this->reorder(); | ||
134 | file_put_contents( | 145 | file_put_contents( |
135 | $filename, | 146 | $filename, |
136 | '<?php /* '.base64_encode(gzdeflate(serialize($this->_links))).' */ ?>' | 147 | '<?php /* '.base64_encode(gzdeflate(serialize($this->_links))).' */ ?>' |
@@ -138,6 +149,27 @@ class ReferenceLinkDB | |||
138 | } | 149 | } |
139 | 150 | ||
140 | /** | 151 | /** |
152 | * Reorder links by creation date (newest first). | ||
153 | * | ||
154 | * Also update the urls and ids mapping arrays. | ||
155 | * | ||
156 | * @param string $order ASC|DESC | ||
157 | */ | ||
158 | public function reorder($order = 'DESC') | ||
159 | { | ||
160 | // backward compatibility: ignore reorder if the the `created` field doesn't exist | ||
161 | if (! isset(array_values($this->_links)[0]['created'])) { | ||
162 | return; | ||
163 | } | ||
164 | |||
165 | $order = $order === 'ASC' ? -1 : 1; | ||
166 | // Reorder array by dates. | ||
167 | usort($this->_links, function($a, $b) use ($order) { | ||
168 | return $a['created'] < $b['created'] ? 1 * $order : -1 * $order; | ||
169 | }); | ||
170 | } | ||
171 | |||
172 | /** | ||
141 | * Returns the number of links in the reference data | 173 | * Returns the number of links in the reference data |
142 | */ | 174 | */ |
143 | public function countLinks() | 175 | public function countLinks() |
@@ -161,8 +193,23 @@ class ReferenceLinkDB | |||
161 | return $this->_privateCount; | 193 | return $this->_privateCount; |
162 | } | 194 | } |
163 | 195 | ||
196 | /** | ||
197 | * Returns the number of links without tag | ||
198 | */ | ||
199 | public function countUntaggedLinks() | ||
200 | { | ||
201 | $cpt = 0; | ||
202 | foreach ($this->_links as $link) { | ||
203 | if (empty($link['tags'])) { | ||
204 | ++$cpt; | ||
205 | } | ||
206 | } | ||
207 | return $cpt; | ||
208 | } | ||
209 | |||
164 | public function getLinks() | 210 | public function getLinks() |
165 | { | 211 | { |
212 | $this->reorder(); | ||
166 | return $this->_links; | 213 | return $this->_links; |
167 | } | 214 | } |
168 | 215 | ||
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 |
diff --git a/tests/utils/config/emptyConfigPhp.php b/tests/utils/config/emptyConfigPhp.php new file mode 100644 index 00000000..b3d9bbc7 --- /dev/null +++ b/tests/utils/config/emptyConfigPhp.php | |||
@@ -0,0 +1 @@ | |||
<?php | |||
diff --git a/tests/utils/languages/fr/LC_MESSAGES/test.mo b/tests/utils/languages/fr/LC_MESSAGES/test.mo new file mode 100644 index 00000000..416c7831 --- /dev/null +++ b/tests/utils/languages/fr/LC_MESSAGES/test.mo | |||
Binary files differ | |||
diff --git a/tests/utils/languages/fr/LC_MESSAGES/test.po b/tests/utils/languages/fr/LC_MESSAGES/test.po new file mode 100644 index 00000000..89a4fd9b --- /dev/null +++ b/tests/utils/languages/fr/LC_MESSAGES/test.po | |||
@@ -0,0 +1,19 @@ | |||
1 | msgid "" | ||
2 | msgstr "" | ||
3 | "Project-Id-Version: Extension test\n" | ||
4 | "POT-Creation-Date: 2017-05-20 13:54+0200\n" | ||
5 | "PO-Revision-Date: 2017-05-20 14:16+0200\n" | ||
6 | "Last-Translator: \n" | ||
7 | "Language-Team: Shaarli\n" | ||
8 | "Language: fr_FR\n" | ||
9 | "MIME-Version: 1.0\n" | ||
10 | "Content-Type: text/plain; charset=UTF-8\n" | ||
11 | "Content-Transfer-Encoding: 8bit\n" | ||
12 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" | ||
13 | "X-Generator: Poedit 2.0.1\n" | ||
14 | |||
15 | msgid "car" | ||
16 | msgstr "voiture" | ||
17 | |||
18 | msgid "Search" | ||
19 | msgstr "Fouille" | ||