diff options
author | yude <yudesleepy@gmail.com> | 2021-01-04 18:51:10 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-04 18:51:10 +0900 |
commit | e6754f2154a79abd8e5e64bd923f6984aa9ad44b (patch) | |
tree | f074119530bb59ef155938ea367f719f1e4b70f1 /tests/helper | |
parent | 5256b4287021342a9f8868967b2a77e481314331 (diff) | |
parent | ed4ee8f0297941ac83300389b7de6a293312d20e (diff) | |
download | Shaarli-e6754f2154a79abd8e5e64bd923f6984aa9ad44b.tar.gz Shaarli-e6754f2154a79abd8e5e64bd923f6984aa9ad44b.tar.zst Shaarli-e6754f2154a79abd8e5e64bd923f6984aa9ad44b.zip |
Merge pull request #2 from shaarli/master
Merge fork source
Diffstat (limited to 'tests/helper')
-rw-r--r-- | tests/helper/ApplicationUtilsTest.php | 415 | ||||
-rw-r--r-- | tests/helper/DailyPageHelperTest.php | 341 | ||||
-rw-r--r-- | tests/helper/FileUtilsTest.php | 197 |
3 files changed, 953 insertions, 0 deletions
diff --git a/tests/helper/ApplicationUtilsTest.php b/tests/helper/ApplicationUtilsTest.php new file mode 100644 index 00000000..654857b9 --- /dev/null +++ b/tests/helper/ApplicationUtilsTest.php | |||
@@ -0,0 +1,415 @@ | |||
1 | <?php | ||
2 | namespace Shaarli\Helper; | ||
3 | |||
4 | use Shaarli\Config\ConfigManager; | ||
5 | use Shaarli\FakeApplicationUtils; | ||
6 | |||
7 | require_once 'tests/utils/FakeApplicationUtils.php'; | ||
8 | |||
9 | /** | ||
10 | * Unitary tests for Shaarli utilities | ||
11 | */ | ||
12 | class ApplicationUtilsTest extends \Shaarli\TestCase | ||
13 | { | ||
14 | protected static $testUpdateFile = 'sandbox/update.txt'; | ||
15 | protected static $testVersion = '0.5.0'; | ||
16 | protected static $versionPattern = '/^\d+\.\d+\.\d+$/'; | ||
17 | |||
18 | /** | ||
19 | * Reset test data for each test | ||
20 | */ | ||
21 | protected function setUp(): void | ||
22 | { | ||
23 | FakeApplicationUtils::$VERSION_CODE = ''; | ||
24 | if (file_exists(self::$testUpdateFile)) { | ||
25 | unlink(self::$testUpdateFile); | ||
26 | } | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * Remove test version file if it exists | ||
31 | */ | ||
32 | protected function tearDown(): void | ||
33 | { | ||
34 | if (is_file('sandbox/version.php')) { | ||
35 | unlink('sandbox/version.php'); | ||
36 | } | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * Retrieve the latest version code available on Git | ||
41 | * | ||
42 | * Expected format: Semantic Versioning - major.minor.patch | ||
43 | */ | ||
44 | public function testGetVersionCode() | ||
45 | { | ||
46 | $testTimeout = 10; | ||
47 | |||
48 | $this->assertEquals( | ||
49 | '0.5.4', | ||
50 | ApplicationUtils::getVersion( | ||
51 | 'https://raw.githubusercontent.com/shaarli/Shaarli/' | ||
52 | .'v0.5.4/shaarli_version.php', | ||
53 | $testTimeout | ||
54 | ) | ||
55 | ); | ||
56 | $this->assertRegExp( | ||
57 | self::$versionPattern, | ||
58 | ApplicationUtils::getVersion( | ||
59 | 'https://raw.githubusercontent.com/shaarli/Shaarli/' | ||
60 | .'latest/shaarli_version.php', | ||
61 | $testTimeout | ||
62 | ) | ||
63 | ); | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * Attempt to retrieve the latest version from an invalid File | ||
68 | */ | ||
69 | public function testGetVersionCodeFromFile() | ||
70 | { | ||
71 | file_put_contents('sandbox/version.php', '<?php /* 1.2.3 */ ?>'. PHP_EOL); | ||
72 | $this->assertEquals( | ||
73 | '1.2.3', | ||
74 | ApplicationUtils::getVersion('sandbox/version.php', 1) | ||
75 | ); | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * Attempt to retrieve the latest version from an invalid File | ||
80 | */ | ||
81 | public function testGetVersionCodeInvalidFile() | ||
82 | { | ||
83 | $oldlog = ini_get('error_log'); | ||
84 | ini_set('error_log', '/dev/null'); | ||
85 | $this->assertFalse( | ||
86 | ApplicationUtils::getVersion('idontexist', 1) | ||
87 | ); | ||
88 | ini_set('error_log', $oldlog); | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * Test update checks - the user is logged off | ||
93 | */ | ||
94 | public function testCheckUpdateLoggedOff() | ||
95 | { | ||
96 | $this->assertFalse( | ||
97 | ApplicationUtils::checkUpdate(self::$testVersion, 'null', 0, false, false) | ||
98 | ); | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * Test update checks - the user has disabled updates | ||
103 | */ | ||
104 | public function testCheckUpdateUserDisabled() | ||
105 | { | ||
106 | $this->assertFalse( | ||
107 | ApplicationUtils::checkUpdate(self::$testVersion, 'null', 0, false, true) | ||
108 | ); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * A newer version is available | ||
113 | */ | ||
114 | public function testCheckUpdateNewVersionAvailable() | ||
115 | { | ||
116 | $newVersion = '1.8.3'; | ||
117 | FakeApplicationUtils::$VERSION_CODE = $newVersion; | ||
118 | |||
119 | $version = FakeApplicationUtils::checkUpdate( | ||
120 | self::$testVersion, | ||
121 | self::$testUpdateFile, | ||
122 | 100, | ||
123 | true, | ||
124 | true | ||
125 | ); | ||
126 | |||
127 | $this->assertEquals($newVersion, $version); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * No available information about versions | ||
132 | */ | ||
133 | public function testCheckUpdateNewVersionUnavailable() | ||
134 | { | ||
135 | $version = FakeApplicationUtils::checkUpdate( | ||
136 | self::$testVersion, | ||
137 | self::$testUpdateFile, | ||
138 | 100, | ||
139 | true, | ||
140 | true | ||
141 | ); | ||
142 | |||
143 | $this->assertFalse($version); | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * Test update checks - invalid Git branch | ||
148 | */ | ||
149 | public function testCheckUpdateInvalidGitBranch() | ||
150 | { | ||
151 | $this->expectException(\Exception::class); | ||
152 | $this->expectExceptionMessageRegExp('/Invalid branch selected for updates/'); | ||
153 | |||
154 | ApplicationUtils::checkUpdate('', 'null', 0, true, true, 'unstable'); | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * Shaarli is up-to-date | ||
159 | */ | ||
160 | public function testCheckUpdateNewVersionUpToDate() | ||
161 | { | ||
162 | FakeApplicationUtils::$VERSION_CODE = self::$testVersion; | ||
163 | |||
164 | $version = FakeApplicationUtils::checkUpdate( | ||
165 | self::$testVersion, | ||
166 | self::$testUpdateFile, | ||
167 | 100, | ||
168 | true, | ||
169 | true | ||
170 | ); | ||
171 | |||
172 | $this->assertFalse($version); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * Time-traveller's Shaarli | ||
177 | */ | ||
178 | public function testCheckUpdateNewVersionMaartiMcFly() | ||
179 | { | ||
180 | FakeApplicationUtils::$VERSION_CODE = '0.4.1'; | ||
181 | |||
182 | $version = FakeApplicationUtils::checkUpdate( | ||
183 | self::$testVersion, | ||
184 | self::$testUpdateFile, | ||
185 | 100, | ||
186 | true, | ||
187 | true | ||
188 | ); | ||
189 | |||
190 | $this->assertFalse($version); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * The version has been checked recently and Shaarli is up-to-date | ||
195 | */ | ||
196 | public function testCheckUpdateNewVersionTwiceUpToDate() | ||
197 | { | ||
198 | FakeApplicationUtils::$VERSION_CODE = self::$testVersion; | ||
199 | |||
200 | // Create the update file | ||
201 | $version = FakeApplicationUtils::checkUpdate( | ||
202 | self::$testVersion, | ||
203 | self::$testUpdateFile, | ||
204 | 100, | ||
205 | true, | ||
206 | true | ||
207 | ); | ||
208 | |||
209 | $this->assertFalse($version); | ||
210 | |||
211 | // Reuse the update file | ||
212 | $version = FakeApplicationUtils::checkUpdate( | ||
213 | self::$testVersion, | ||
214 | self::$testUpdateFile, | ||
215 | 100, | ||
216 | true, | ||
217 | true | ||
218 | ); | ||
219 | |||
220 | $this->assertFalse($version); | ||
221 | } | ||
222 | |||
223 | /** | ||
224 | * The version has been checked recently and Shaarli is outdated | ||
225 | */ | ||
226 | public function testCheckUpdateNewVersionTwiceOutdated() | ||
227 | { | ||
228 | $newVersion = '1.8.3'; | ||
229 | FakeApplicationUtils::$VERSION_CODE = $newVersion; | ||
230 | |||
231 | // Create the update file | ||
232 | $version = FakeApplicationUtils::checkUpdate( | ||
233 | self::$testVersion, | ||
234 | self::$testUpdateFile, | ||
235 | 100, | ||
236 | true, | ||
237 | true | ||
238 | ); | ||
239 | $this->assertEquals($newVersion, $version); | ||
240 | |||
241 | // Reuse the update file | ||
242 | $version = FakeApplicationUtils::checkUpdate( | ||
243 | self::$testVersion, | ||
244 | self::$testUpdateFile, | ||
245 | 100, | ||
246 | true, | ||
247 | true | ||
248 | ); | ||
249 | $this->assertEquals($newVersion, $version); | ||
250 | } | ||
251 | |||
252 | /** | ||
253 | * Check supported PHP versions | ||
254 | */ | ||
255 | public function testCheckSupportedPHPVersion() | ||
256 | { | ||
257 | $minVersion = '5.3'; | ||
258 | $this->assertTrue(ApplicationUtils::checkPHPVersion($minVersion, '5.4.32')); | ||
259 | $this->assertTrue(ApplicationUtils::checkPHPVersion($minVersion, '5.5')); | ||
260 | $this->assertTrue(ApplicationUtils::checkPHPVersion($minVersion, '5.6.10')); | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * Check a unsupported PHP version | ||
265 | */ | ||
266 | public function testCheckSupportedPHPVersion51() | ||
267 | { | ||
268 | $this->expectException(\Exception::class); | ||
269 | $this->expectExceptionMessageRegExp('/Your PHP version is obsolete/'); | ||
270 | |||
271 | $this->assertTrue(ApplicationUtils::checkPHPVersion('5.3', '5.1.0')); | ||
272 | } | ||
273 | |||
274 | /** | ||
275 | * Check another unsupported PHP version | ||
276 | */ | ||
277 | public function testCheckSupportedPHPVersion52() | ||
278 | { | ||
279 | $this->expectException(\Exception::class); | ||
280 | $this->expectExceptionMessageRegExp('/Your PHP version is obsolete/'); | ||
281 | |||
282 | $this->assertTrue(ApplicationUtils::checkPHPVersion('5.3', '5.2')); | ||
283 | } | ||
284 | |||
285 | /** | ||
286 | * Checks resource permissions for the current Shaarli installation | ||
287 | */ | ||
288 | public function testCheckCurrentResourcePermissions() | ||
289 | { | ||
290 | $conf = new ConfigManager(''); | ||
291 | $conf->set('resource.thumbnails_cache', 'cache'); | ||
292 | $conf->set('resource.config', 'data/config.php'); | ||
293 | $conf->set('resource.data_dir', 'data'); | ||
294 | $conf->set('resource.datastore', 'data/datastore.php'); | ||
295 | $conf->set('resource.ban_file', 'data/ipbans.php'); | ||
296 | $conf->set('resource.log', 'data/log.txt'); | ||
297 | $conf->set('resource.page_cache', 'pagecache'); | ||
298 | $conf->set('resource.raintpl_tmp', 'tmp'); | ||
299 | $conf->set('resource.raintpl_tpl', 'tpl'); | ||
300 | $conf->set('resource.theme', 'default'); | ||
301 | $conf->set('resource.update_check', 'data/lastupdatecheck.txt'); | ||
302 | |||
303 | $this->assertEquals( | ||
304 | array(), | ||
305 | ApplicationUtils::checkResourcePermissions($conf) | ||
306 | ); | ||
307 | } | ||
308 | |||
309 | /** | ||
310 | * Checks resource permissions for a non-existent Shaarli installation | ||
311 | */ | ||
312 | public function testCheckCurrentResourcePermissionsErrors() | ||
313 | { | ||
314 | $conf = new ConfigManager(''); | ||
315 | $conf->set('resource.thumbnails_cache', 'null/cache'); | ||
316 | $conf->set('resource.config', 'null/data/config.php'); | ||
317 | $conf->set('resource.data_dir', 'null/data'); | ||
318 | $conf->set('resource.datastore', 'null/data/store.php'); | ||
319 | $conf->set('resource.ban_file', 'null/data/ipbans.php'); | ||
320 | $conf->set('resource.log', 'null/data/log.txt'); | ||
321 | $conf->set('resource.page_cache', 'null/pagecache'); | ||
322 | $conf->set('resource.raintpl_tmp', 'null/tmp'); | ||
323 | $conf->set('resource.raintpl_tpl', 'null/tpl'); | ||
324 | $conf->set('resource.raintpl_theme', 'null/tpl/default'); | ||
325 | $conf->set('resource.update_check', 'null/data/lastupdatecheck.txt'); | ||
326 | $this->assertEquals( | ||
327 | array( | ||
328 | '"null/tpl" directory is not readable', | ||
329 | '"null/tpl/default" directory is not readable', | ||
330 | '"null/cache" directory is not readable', | ||
331 | '"null/cache" directory is not writable', | ||
332 | '"null/data" directory is not readable', | ||
333 | '"null/data" directory is not writable', | ||
334 | '"null/pagecache" directory is not readable', | ||
335 | '"null/pagecache" directory is not writable', | ||
336 | '"null/tmp" directory is not readable', | ||
337 | '"null/tmp" directory is not writable' | ||
338 | ), | ||
339 | ApplicationUtils::checkResourcePermissions($conf) | ||
340 | ); | ||
341 | } | ||
342 | |||
343 | /** | ||
344 | * Checks resource permissions in minimal mode. | ||
345 | */ | ||
346 | public function testCheckCurrentResourcePermissionsErrorsMinimalMode(): void | ||
347 | { | ||
348 | $conf = new ConfigManager(''); | ||
349 | $conf->set('resource.thumbnails_cache', 'null/cache'); | ||
350 | $conf->set('resource.config', 'null/data/config.php'); | ||
351 | $conf->set('resource.data_dir', 'null/data'); | ||
352 | $conf->set('resource.datastore', 'null/data/store.php'); | ||
353 | $conf->set('resource.ban_file', 'null/data/ipbans.php'); | ||
354 | $conf->set('resource.log', 'null/data/log.txt'); | ||
355 | $conf->set('resource.page_cache', 'null/pagecache'); | ||
356 | $conf->set('resource.raintpl_tmp', 'null/tmp'); | ||
357 | $conf->set('resource.raintpl_tpl', 'null/tpl'); | ||
358 | $conf->set('resource.raintpl_theme', 'null/tpl/default'); | ||
359 | $conf->set('resource.update_check', 'null/data/lastupdatecheck.txt'); | ||
360 | |||
361 | static::assertSame( | ||
362 | [ | ||
363 | '"null/tpl" directory is not readable', | ||
364 | '"null/tpl/default" directory is not readable', | ||
365 | '"null/tmp" directory is not readable', | ||
366 | '"null/tmp" directory is not writable' | ||
367 | ], | ||
368 | ApplicationUtils::checkResourcePermissions($conf, true) | ||
369 | ); | ||
370 | } | ||
371 | |||
372 | /** | ||
373 | * Check update with 'dev' as curent version (master branch). | ||
374 | * It should always return false. | ||
375 | */ | ||
376 | public function testCheckUpdateDev() | ||
377 | { | ||
378 | $this->assertFalse( | ||
379 | ApplicationUtils::checkUpdate('dev', self::$testUpdateFile, 100, true, true) | ||
380 | ); | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * Basic test of getPhpExtensionsRequirement() | ||
385 | */ | ||
386 | public function testGetPhpExtensionsRequirementSimple(): void | ||
387 | { | ||
388 | static::assertCount(8, ApplicationUtils::getPhpExtensionsRequirement()); | ||
389 | static::assertSame([ | ||
390 | 'name' => 'json', | ||
391 | 'required' => true, | ||
392 | 'desc' => 'Configuration parsing', | ||
393 | 'loaded' => true, | ||
394 | ], ApplicationUtils::getPhpExtensionsRequirement()[0]); | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * Test getPhpEol with a known version: 7.4 -> 2022 | ||
399 | */ | ||
400 | public function testGetKnownPhpEol(): void | ||
401 | { | ||
402 | static::assertSame('2022-11-28', ApplicationUtils::getPhpEol('7.4.7')); | ||
403 | } | ||
404 | |||
405 | /** | ||
406 | * Test getPhpEol with an unknown version: 7.4 -> 2022 | ||
407 | */ | ||
408 | public function testGetUnknownPhpEol(): void | ||
409 | { | ||
410 | static::assertSame( | ||
411 | (((int) (new \DateTime())->format('Y')) + 2) . (new \DateTime())->format('-m-d'), | ||
412 | ApplicationUtils::getPhpEol('7.51.34') | ||
413 | ); | ||
414 | } | ||
415 | } | ||
diff --git a/tests/helper/DailyPageHelperTest.php b/tests/helper/DailyPageHelperTest.php new file mode 100644 index 00000000..2d745800 --- /dev/null +++ b/tests/helper/DailyPageHelperTest.php | |||
@@ -0,0 +1,341 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Helper; | ||
6 | |||
7 | use DateTimeImmutable; | ||
8 | use DateTimeInterface; | ||
9 | use Shaarli\Bookmark\Bookmark; | ||
10 | use Shaarli\TestCase; | ||
11 | use Slim\Http\Request; | ||
12 | |||
13 | class DailyPageHelperTest extends TestCase | ||
14 | { | ||
15 | /** | ||
16 | * @dataProvider getRequestedTypes | ||
17 | */ | ||
18 | public function testExtractRequestedType(array $queryParams, string $expectedType): void | ||
19 | { | ||
20 | $request = $this->createMock(Request::class); | ||
21 | $request->method('getQueryParam')->willReturnCallback(function ($key) use ($queryParams): ?string { | ||
22 | return $queryParams[$key] ?? null; | ||
23 | }); | ||
24 | |||
25 | $type = DailyPageHelper::extractRequestedType($request); | ||
26 | |||
27 | static::assertSame($type, $expectedType); | ||
28 | } | ||
29 | |||
30 | /** | ||
31 | * @dataProvider getRequestedDateTimes | ||
32 | */ | ||
33 | public function testExtractRequestedDateTime( | ||
34 | string $type, | ||
35 | string $input, | ||
36 | ?Bookmark $bookmark, | ||
37 | DateTimeInterface $expectedDateTime, | ||
38 | string $compareFormat = 'Ymd' | ||
39 | ): void { | ||
40 | $dateTime = DailyPageHelper::extractRequestedDateTime($type, $input, $bookmark); | ||
41 | |||
42 | static::assertSame($dateTime->format($compareFormat), $expectedDateTime->format($compareFormat)); | ||
43 | } | ||
44 | |||
45 | public function testExtractRequestedDateTimeExceptionUnknownType(): void | ||
46 | { | ||
47 | $this->expectException(\Exception::class); | ||
48 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
49 | |||
50 | DailyPageHelper::extractRequestedDateTime('nope', null, null); | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * @dataProvider getFormatsByType | ||
55 | */ | ||
56 | public function testGetFormatByType(string $type, string $expectedFormat): void | ||
57 | { | ||
58 | $format = DailyPageHelper::getFormatByType($type); | ||
59 | |||
60 | static::assertSame($expectedFormat, $format); | ||
61 | } | ||
62 | |||
63 | public function testGetFormatByTypeExceptionUnknownType(): void | ||
64 | { | ||
65 | $this->expectException(\Exception::class); | ||
66 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
67 | |||
68 | DailyPageHelper::getFormatByType('nope'); | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * @dataProvider getStartDatesByType | ||
73 | */ | ||
74 | public function testGetStartDatesByType( | ||
75 | string $type, | ||
76 | DateTimeImmutable $dateTime, | ||
77 | DateTimeInterface $expectedDateTime | ||
78 | ): void { | ||
79 | $startDateTime = DailyPageHelper::getStartDateTimeByType($type, $dateTime); | ||
80 | |||
81 | static::assertEquals($expectedDateTime, $startDateTime); | ||
82 | } | ||
83 | |||
84 | public function testGetStartDatesByTypeExceptionUnknownType(): void | ||
85 | { | ||
86 | $this->expectException(\Exception::class); | ||
87 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
88 | |||
89 | DailyPageHelper::getStartDateTimeByType('nope', new DateTimeImmutable()); | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * @dataProvider getEndDatesByType | ||
94 | */ | ||
95 | public function testGetEndDatesByType( | ||
96 | string $type, | ||
97 | DateTimeImmutable $dateTime, | ||
98 | DateTimeInterface $expectedDateTime | ||
99 | ): void { | ||
100 | $endDateTime = DailyPageHelper::getEndDateTimeByType($type, $dateTime); | ||
101 | |||
102 | static::assertEquals($expectedDateTime, $endDateTime); | ||
103 | } | ||
104 | |||
105 | public function testGetEndDatesByTypeExceptionUnknownType(): void | ||
106 | { | ||
107 | $this->expectException(\Exception::class); | ||
108 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
109 | |||
110 | DailyPageHelper::getEndDateTimeByType('nope', new DateTimeImmutable()); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * @dataProvider getDescriptionsByType | ||
115 | */ | ||
116 | public function testGeDescriptionsByType( | ||
117 | string $type, | ||
118 | DateTimeImmutable $dateTime, | ||
119 | string $expectedDescription | ||
120 | ): void { | ||
121 | $description = DailyPageHelper::getDescriptionByType($type, $dateTime); | ||
122 | |||
123 | static::assertEquals($expectedDescription, $description); | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * @dataProvider getDescriptionsByTypeNotIncludeRelative | ||
128 | */ | ||
129 | public function testGeDescriptionsByTypeNotIncludeRelative( | ||
130 | string $type, | ||
131 | \DateTimeImmutable $dateTime, | ||
132 | string $expectedDescription | ||
133 | ): void { | ||
134 | $description = DailyPageHelper::getDescriptionByType($type, $dateTime, false); | ||
135 | |||
136 | static::assertEquals($expectedDescription, $description); | ||
137 | } | ||
138 | |||
139 | public function getDescriptionByTypeExceptionUnknownType(): void | ||
140 | { | ||
141 | $this->expectException(\Exception::class); | ||
142 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
143 | |||
144 | DailyPageHelper::getDescriptionByType('nope', new DateTimeImmutable()); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * @dataProvider getRssLengthsByType | ||
149 | */ | ||
150 | public function testGeRssLengthsByType(string $type): void { | ||
151 | $length = DailyPageHelper::getRssLengthByType($type); | ||
152 | |||
153 | static::assertIsInt($length); | ||
154 | } | ||
155 | |||
156 | public function testGeRssLengthsByTypeExceptionUnknownType(): void | ||
157 | { | ||
158 | $this->expectException(\Exception::class); | ||
159 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
160 | |||
161 | DailyPageHelper::getRssLengthByType('nope'); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * @dataProvider getCacheDatePeriodByType | ||
166 | */ | ||
167 | public function testGetCacheDatePeriodByType( | ||
168 | string $type, | ||
169 | DateTimeImmutable $requested, | ||
170 | DateTimeInterface $start, | ||
171 | DateTimeInterface $end | ||
172 | ): void { | ||
173 | $period = DailyPageHelper::getCacheDatePeriodByType($type, $requested); | ||
174 | |||
175 | static::assertEquals($start, $period->getStartDate()); | ||
176 | static::assertEquals($end, $period->getEndDate()); | ||
177 | } | ||
178 | |||
179 | public function testGetCacheDatePeriodByTypeExceptionUnknownType(): void | ||
180 | { | ||
181 | $this->expectException(\Exception::class); | ||
182 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
183 | |||
184 | DailyPageHelper::getCacheDatePeriodByType('nope'); | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * Data provider for testExtractRequestedType() test method. | ||
189 | */ | ||
190 | public function getRequestedTypes(): array | ||
191 | { | ||
192 | return [ | ||
193 | [['month' => null], DailyPageHelper::DAY], | ||
194 | [['month' => ''], DailyPageHelper::MONTH], | ||
195 | [['month' => 'content'], DailyPageHelper::MONTH], | ||
196 | [['week' => null], DailyPageHelper::DAY], | ||
197 | [['week' => ''], DailyPageHelper::WEEK], | ||
198 | [['week' => 'content'], DailyPageHelper::WEEK], | ||
199 | [['day' => null], DailyPageHelper::DAY], | ||
200 | [['day' => ''], DailyPageHelper::DAY], | ||
201 | [['day' => 'content'], DailyPageHelper::DAY], | ||
202 | ]; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * Data provider for testExtractRequestedDateTime() test method. | ||
207 | */ | ||
208 | public function getRequestedDateTimes(): array | ||
209 | { | ||
210 | return [ | ||
211 | [DailyPageHelper::DAY, '20201013', null, new \DateTime('2020-10-13')], | ||
212 | [ | ||
213 | DailyPageHelper::DAY, | ||
214 | '', | ||
215 | (new Bookmark())->setCreated($date = new \DateTime('2020-10-13 12:05:31')), | ||
216 | $date, | ||
217 | ], | ||
218 | [DailyPageHelper::DAY, '', null, new \DateTime()], | ||
219 | [DailyPageHelper::WEEK, '202030', null, new \DateTime('2020-07-20')], | ||
220 | [ | ||
221 | DailyPageHelper::WEEK, | ||
222 | '', | ||
223 | (new Bookmark())->setCreated($date = new \DateTime('2020-10-13 12:05:31')), | ||
224 | new \DateTime('2020-10-13'), | ||
225 | ], | ||
226 | [DailyPageHelper::WEEK, '', null, new \DateTime(), 'Ym'], | ||
227 | [DailyPageHelper::MONTH, '202008', null, new \DateTime('2020-08-01'), 'Ym'], | ||
228 | [ | ||
229 | DailyPageHelper::MONTH, | ||
230 | '', | ||
231 | (new Bookmark())->setCreated($date = new \DateTime('2020-10-13 12:05:31')), | ||
232 | new \DateTime('2020-10-13'), | ||
233 | 'Ym' | ||
234 | ], | ||
235 | [DailyPageHelper::MONTH, '', null, new \DateTime(), 'Ym'], | ||
236 | ]; | ||
237 | } | ||
238 | |||
239 | /** | ||
240 | * Data provider for testGetFormatByType() test method. | ||
241 | */ | ||
242 | public function getFormatsByType(): array | ||
243 | { | ||
244 | return [ | ||
245 | [DailyPageHelper::DAY, 'Ymd'], | ||
246 | [DailyPageHelper::WEEK, 'YW'], | ||
247 | [DailyPageHelper::MONTH, 'Ym'], | ||
248 | ]; | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * Data provider for testGetStartDatesByType() test method. | ||
253 | */ | ||
254 | public function getStartDatesByType(): array | ||
255 | { | ||
256 | return [ | ||
257 | [DailyPageHelper::DAY, new DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-09 00:00:00')], | ||
258 | [DailyPageHelper::WEEK, new DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-05 00:00:00')], | ||
259 | [DailyPageHelper::MONTH, new DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-01 00:00:00')], | ||
260 | ]; | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * Data provider for testGetEndDatesByType() test method. | ||
265 | */ | ||
266 | public function getEndDatesByType(): array | ||
267 | { | ||
268 | return [ | ||
269 | [DailyPageHelper::DAY, new DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-09 23:59:59')], | ||
270 | [DailyPageHelper::WEEK, new DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-11 23:59:59')], | ||
271 | [DailyPageHelper::MONTH, new DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-31 23:59:59')], | ||
272 | ]; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * Data provider for testGetDescriptionsByType() test method. | ||
277 | */ | ||
278 | public function getDescriptionsByType(): array | ||
279 | { | ||
280 | return [ | ||
281 | [DailyPageHelper::DAY, $date = new DateTimeImmutable(), 'Today - ' . $date->format('F j, Y')], | ||
282 | [DailyPageHelper::DAY, $date = new DateTimeImmutable('-1 day'), 'Yesterday - ' . $date->format('F j, Y')], | ||
283 | [DailyPageHelper::DAY, new DateTimeImmutable('2020-10-09 04:05:06'), 'October 9, 2020'], | ||
284 | [DailyPageHelper::WEEK, new DateTimeImmutable('2020-10-09 04:05:06'), 'Week 41 (October 5, 2020)'], | ||
285 | [DailyPageHelper::MONTH, new DateTimeImmutable('2020-10-09 04:05:06'), 'October, 2020'], | ||
286 | ]; | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * Data provider for testGeDescriptionsByTypeNotIncludeRelative() test method. | ||
291 | */ | ||
292 | public function getDescriptionsByTypeNotIncludeRelative(): array | ||
293 | { | ||
294 | return [ | ||
295 | [DailyPageHelper::DAY, $date = new \DateTimeImmutable(), $date->format('F j, Y')], | ||
296 | [DailyPageHelper::DAY, $date = new \DateTimeImmutable('-1 day'), $date->format('F j, Y')], | ||
297 | [DailyPageHelper::DAY, new \DateTimeImmutable('2020-10-09 04:05:06'), 'October 9, 2020'], | ||
298 | [DailyPageHelper::WEEK, new \DateTimeImmutable('2020-10-09 04:05:06'), 'Week 41 (October 5, 2020)'], | ||
299 | [DailyPageHelper::MONTH, new \DateTimeImmutable('2020-10-09 04:05:06'), 'October, 2020'], | ||
300 | ]; | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * Data provider for testGetRssLengthsByType() test method. | ||
305 | */ | ||
306 | public function getRssLengthsByType(): array | ||
307 | { | ||
308 | return [ | ||
309 | [DailyPageHelper::DAY], | ||
310 | [DailyPageHelper::WEEK], | ||
311 | [DailyPageHelper::MONTH], | ||
312 | ]; | ||
313 | } | ||
314 | |||
315 | /** | ||
316 | * Data provider for testGetCacheDatePeriodByType() test method. | ||
317 | */ | ||
318 | public function getCacheDatePeriodByType(): array | ||
319 | { | ||
320 | return [ | ||
321 | [ | ||
322 | DailyPageHelper::DAY, | ||
323 | new DateTimeImmutable('2020-10-09 04:05:06'), | ||
324 | new \DateTime('2020-10-09 00:00:00'), | ||
325 | new \DateTime('2020-10-09 23:59:59'), | ||
326 | ], | ||
327 | [ | ||
328 | DailyPageHelper::WEEK, | ||
329 | new DateTimeImmutable('2020-10-09 04:05:06'), | ||
330 | new \DateTime('2020-10-05 00:00:00'), | ||
331 | new \DateTime('2020-10-11 23:59:59'), | ||
332 | ], | ||
333 | [ | ||
334 | DailyPageHelper::MONTH, | ||
335 | new DateTimeImmutable('2020-10-09 04:05:06'), | ||
336 | new \DateTime('2020-10-01 00:00:00'), | ||
337 | new \DateTime('2020-10-31 23:59:59'), | ||
338 | ], | ||
339 | ]; | ||
340 | } | ||
341 | } | ||
diff --git a/tests/helper/FileUtilsTest.php b/tests/helper/FileUtilsTest.php new file mode 100644 index 00000000..8035f79c --- /dev/null +++ b/tests/helper/FileUtilsTest.php | |||
@@ -0,0 +1,197 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Shaarli\Helper; | ||
4 | |||
5 | use Exception; | ||
6 | use Shaarli\Exceptions\IOException; | ||
7 | use Shaarli\TestCase; | ||
8 | |||
9 | /** | ||
10 | * Class FileUtilsTest | ||
11 | * | ||
12 | * Test file utility class. | ||
13 | */ | ||
14 | class FileUtilsTest extends TestCase | ||
15 | { | ||
16 | /** | ||
17 | * @var string Test file path. | ||
18 | */ | ||
19 | protected static $file = 'sandbox/flat.db'; | ||
20 | |||
21 | protected function setUp(): void | ||
22 | { | ||
23 | @mkdir('sandbox'); | ||
24 | mkdir('sandbox/folder2'); | ||
25 | touch('sandbox/file1'); | ||
26 | touch('sandbox/file2'); | ||
27 | mkdir('sandbox/folder1'); | ||
28 | touch('sandbox/folder1/file1'); | ||
29 | touch('sandbox/folder1/file2'); | ||
30 | mkdir('sandbox/folder3'); | ||
31 | mkdir('/tmp/shaarli-to-delete'); | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * Delete test file after every test. | ||
36 | */ | ||
37 | protected function tearDown(): void | ||
38 | { | ||
39 | @unlink(self::$file); | ||
40 | |||
41 | @unlink('sandbox/folder1/file1'); | ||
42 | @unlink('sandbox/folder1/file2'); | ||
43 | @rmdir('sandbox/folder1'); | ||
44 | @unlink('sandbox/file1'); | ||
45 | @unlink('sandbox/file2'); | ||
46 | @rmdir('sandbox/folder2'); | ||
47 | @rmdir('sandbox/folder3'); | ||
48 | @rmdir('/tmp/shaarli-to-delete'); | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * Test writeDB, then readDB with different data. | ||
53 | */ | ||
54 | public function testSimpleWriteRead() | ||
55 | { | ||
56 | $data = ['blue', 'red']; | ||
57 | $this->assertTrue(FileUtils::writeFlatDB(self::$file, $data) > 0); | ||
58 | $this->assertTrue(startsWith(file_get_contents(self::$file), '<?php /*')); | ||
59 | $this->assertEquals($data, FileUtils::readFlatDB(self::$file)); | ||
60 | |||
61 | $data = 0; | ||
62 | $this->assertTrue(FileUtils::writeFlatDB(self::$file, $data) > 0); | ||
63 | $this->assertEquals($data, FileUtils::readFlatDB(self::$file)); | ||
64 | |||
65 | $data = null; | ||
66 | $this->assertTrue(FileUtils::writeFlatDB(self::$file, $data) > 0); | ||
67 | $this->assertEquals($data, FileUtils::readFlatDB(self::$file)); | ||
68 | |||
69 | $data = false; | ||
70 | $this->assertTrue(FileUtils::writeFlatDB(self::$file, $data) > 0); | ||
71 | $this->assertEquals($data, FileUtils::readFlatDB(self::$file)); | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * File not writable: raise an exception. | ||
76 | */ | ||
77 | public function testWriteWithoutPermission() | ||
78 | { | ||
79 | $this->expectException(\Shaarli\Exceptions\IOException::class); | ||
80 | $this->expectExceptionMessage('Error accessing "sandbox/flat.db"'); | ||
81 | |||
82 | touch(self::$file); | ||
83 | chmod(self::$file, 0440); | ||
84 | FileUtils::writeFlatDB(self::$file, null); | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * Folder non existent: raise an exception. | ||
89 | */ | ||
90 | public function testWriteFolderDoesNotExist() | ||
91 | { | ||
92 | $this->expectException(\Shaarli\Exceptions\IOException::class); | ||
93 | $this->expectExceptionMessage('Error accessing "nopefolder"'); | ||
94 | |||
95 | FileUtils::writeFlatDB('nopefolder/file', null); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * Folder non writable: raise an exception. | ||
100 | */ | ||
101 | public function testWriteFolderPermission() | ||
102 | { | ||
103 | $this->expectException(\Shaarli\Exceptions\IOException::class); | ||
104 | $this->expectExceptionMessage('Error accessing "sandbox"'); | ||
105 | |||
106 | chmod(dirname(self::$file), 0555); | ||
107 | try { | ||
108 | FileUtils::writeFlatDB(self::$file, null); | ||
109 | } catch (Exception $e) { | ||
110 | chmod(dirname(self::$file), 0755); | ||
111 | throw $e; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * Read non existent file, use default parameter. | ||
117 | */ | ||
118 | public function testReadNotExistentFile() | ||
119 | { | ||
120 | $this->assertEquals(null, FileUtils::readFlatDB(self::$file)); | ||
121 | $this->assertEquals(['test'], FileUtils::readFlatDB(self::$file, ['test'])); | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * Read non readable file, use default parameter. | ||
126 | */ | ||
127 | public function testReadNotReadable() | ||
128 | { | ||
129 | touch(self::$file); | ||
130 | chmod(self::$file, 0220); | ||
131 | $this->assertEquals(null, FileUtils::readFlatDB(self::$file)); | ||
132 | $this->assertEquals(['test'], FileUtils::readFlatDB(self::$file, ['test'])); | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * Test clearFolder with self delete and excluded files | ||
137 | */ | ||
138 | public function testClearFolderSelfDeleteWithExclusion(): void | ||
139 | { | ||
140 | FileUtils::clearFolder('sandbox', true, ['file2']); | ||
141 | |||
142 | static::assertFileExists('sandbox/folder1/file2'); | ||
143 | static::assertFileExists('sandbox/folder1'); | ||
144 | static::assertFileExists('sandbox/file2'); | ||
145 | static::assertFileExists('sandbox'); | ||
146 | |||
147 | static::assertFileNotExists('sandbox/folder1/file1'); | ||
148 | static::assertFileNotExists('sandbox/file1'); | ||
149 | static::assertFileNotExists('sandbox/folder3'); | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * Test clearFolder with self delete and excluded files | ||
154 | */ | ||
155 | public function testClearFolderSelfDeleteWithoutExclusion(): void | ||
156 | { | ||
157 | FileUtils::clearFolder('sandbox', true); | ||
158 | |||
159 | static::assertFileNotExists('sandbox'); | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * Test clearFolder with self delete and excluded files | ||
164 | */ | ||
165 | public function testClearFolderNoSelfDeleteWithoutExclusion(): void | ||
166 | { | ||
167 | FileUtils::clearFolder('sandbox', false); | ||
168 | |||
169 | static::assertFileExists('sandbox'); | ||
170 | |||
171 | // 2 because '.' and '..' | ||
172 | static::assertCount(2, new \DirectoryIterator('sandbox')); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * Test clearFolder on a file instead of a folder | ||
177 | */ | ||
178 | public function testClearFolderOnANonDirectory(): void | ||
179 | { | ||
180 | $this->expectException(IOException::class); | ||
181 | $this->expectExceptionMessage('Provided path is not a directory.'); | ||
182 | |||
183 | FileUtils::clearFolder('sandbox/file1', false); | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * Test clearFolder on a file instead of a folder | ||
188 | */ | ||
189 | public function testClearFolderOutsideOfShaarliDirectory(): void | ||
190 | { | ||
191 | $this->expectException(IOException::class); | ||
192 | $this->expectExceptionMessage('Trying to delete a folder outside of Shaarli path.'); | ||
193 | |||
194 | |||
195 | FileUtils::clearFolder('/tmp/shaarli-to-delete', true); | ||
196 | } | ||
197 | } | ||