]> git.mxchange.org Git - friendica.git/blob - tests/legacy/ApiTest.php
392ec5190ebff46569dc75d75d9ac57b0a7f25a4
[friendica.git] / tests / legacy / ApiTest.php
1 <?php
2 /**
3  * ApiTest class.
4  */
5
6 namespace Friendica\Test\legacy;
7
8 use Friendica\App;
9 use Friendica\Core\Config\Capability\IManageConfigValues;
10 use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
11 use Friendica\Core\Protocol;
12 use Friendica\DI;
13 use Friendica\Module\BaseApi;
14 use Friendica\Network\HTTPException;
15 use Friendica\Security\BasicAuth;
16 use Friendica\Test\FixtureTest;
17 use Friendica\Util\Arrays;
18 use Friendica\Util\DateTimeFormat;
19 use Friendica\Util\Temporal;
20 use Monolog\Handler\TestHandler;
21
22 require_once __DIR__ . '/../../include/api.php';
23
24 /**
25  * Tests for the API functions.
26  *
27  * Functions that use header() need to be tested in a separate process.
28  * @see https://phpunit.de/manual/5.7/en/appendixes.annotations.html#appendixes.annotations.runTestsInSeparateProcesses
29  *
30  * @backupGlobals enabled
31  */
32 class ApiTest extends FixtureTest
33 {
34         /**
35          * @var TestHandler Can handle log-outputs
36          */
37         protected $logOutput;
38
39         /** @var array */
40         protected $selfUser;
41         /** @var array */
42         protected $friendUser;
43         /** @var array */
44         protected $otherUser;
45
46         protected $wrongUserId;
47
48         /** @var App */
49         protected $app;
50
51         /** @var IManageConfigValues */
52         protected $config;
53
54         /**
55          * Create variables used by tests.
56          */
57         protected function setUp() : void
58         {
59                 global $API, $called_api;
60                 $API = [];
61                 $called_api = [];
62
63                 parent::setUp();
64
65                 /** @var IManageConfigValues $config */
66                 $this->config = $this->dice->create(IManageConfigValues::class);
67
68                 $this->config->set('system', 'url', 'http://localhost');
69                 $this->config->set('system', 'hostname', 'localhost');
70                 $this->config->set('system', 'worker_dont_fork', true);
71
72                 // Default config
73                 $this->config->set('config', 'hostname', 'localhost');
74                 $this->config->set('system', 'throttle_limit_day', 100);
75                 $this->config->set('system', 'throttle_limit_week', 100);
76                 $this->config->set('system', 'throttle_limit_month', 100);
77                 $this->config->set('system', 'theme', 'system_theme');
78
79
80                 /** @var App app */
81                 $this->app = DI::app();
82
83                 DI::args()->setArgc(1);
84
85                 // User data that the test database is populated with
86                 $this->selfUser   = [
87                         'id'   => 42,
88                         'name' => 'Self contact',
89                         'nick' => 'selfcontact',
90                         'nurl' => 'http://localhost/profile/selfcontact'
91                 ];
92                 $this->friendUser = [
93                         'id'   => 44,
94                         'name' => 'Friend contact',
95                         'nick' => 'friendcontact',
96                         'nurl' => 'http://localhost/profile/friendcontact'
97                 ];
98                 $this->otherUser  = [
99                         'id'   => 43,
100                         'name' => 'othercontact',
101                         'nick' => 'othercontact',
102                         'nurl' => 'http://localhost/profile/othercontact'
103                 ];
104
105                 // User ID that we know is not in the database
106                 $this->wrongUserId = 666;
107
108                 DI::session()->start();
109
110                 // Most API require login so we force the session
111                 $_SESSION = [
112                         'allow_api'     => true,
113                         'authenticated' => true,
114                         'uid'           => $this->selfUser['id']
115                 ];
116         }
117
118         /**
119          * Assert that an user array contains expected keys.
120          *
121          * @param array $user User array
122          *
123          * @return void
124          */
125         private function assertSelfUser(array $user)
126         {
127                 self::assertEquals($this->selfUser['id'], $user['uid']);
128                 self::assertEquals($this->selfUser['id'], $user['cid']);
129                 self::assertEquals(1, $user['self']);
130                 self::assertEquals('DFRN', $user['location']);
131                 self::assertEquals($this->selfUser['name'], $user['name']);
132                 self::assertEquals($this->selfUser['nick'], $user['screen_name']);
133                 self::assertEquals('dfrn', $user['network']);
134                 self::assertTrue($user['verified']);
135         }
136
137         /**
138          * Assert that an user array contains expected keys.
139          *
140          * @param array $user User array
141          *
142          * @return void
143          */
144         private function assertOtherUser(array $user = [])
145         {
146                 self::assertEquals($this->otherUser['id'], $user['id']);
147                 self::assertEquals($this->otherUser['id'], $user['id_str']);
148                 self::assertEquals(0, $user['self']);
149                 self::assertEquals($this->otherUser['name'], $user['name']);
150                 self::assertEquals($this->otherUser['nick'], $user['screen_name']);
151                 self::assertFalse($user['verified']);
152         }
153
154         /**
155          * Assert that a status array contains expected keys.
156          *
157          * @param array $status Status array
158          *
159          * @return void
160          */
161         private function assertStatus(array $status = [])
162         {
163                 self::assertIsString($status['text'] ?? '');
164                 self::assertIsInt($status['id'] ?? '');
165                 // We could probably do more checks here.
166         }
167
168         /**
169          * Assert that a list array contains expected keys.
170          *
171          * @param array $list List array
172          *
173          * @return void
174          */
175         private function assertList(array $list = [])
176         {
177                 self::assertIsString($list['name']);
178                 self::assertIsInt($list['id']);
179                 self::assertIsString('string', $list['id_str']);
180                 self::assertContains($list['mode'], ['public', 'private']);
181                 // We could probably do more checks here.
182         }
183
184         /**
185          * Assert that the string is XML and contain the root element.
186          *
187          * @param string $result       XML string
188          * @param string $root_element Root element name
189          *
190          * @return void
191          */
192         private function assertXml($result = '', $root_element = '')
193         {
194                 self::assertStringStartsWith('<?xml version="1.0"?>', $result);
195                 self::assertStringContainsString('<' . $root_element, $result);
196                 // We could probably do more checks here.
197         }
198
199         /**
200          * Get the path to a temporary empty PNG image.
201          *
202          * @return string Path
203          */
204         private function getTempImage()
205         {
206                 $tmpFile = tempnam(sys_get_temp_dir(), 'tmp_file');
207                 file_put_contents(
208                         $tmpFile,
209                         base64_decode(
210                         // Empty 1x1 px PNG image
211                                 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=='
212                         )
213                 );
214
215                 return $tmpFile;
216         }
217
218         /**
219          * Test the api_user() function.
220          *
221          * @return void
222          */
223         public function testApiUser()
224         {
225                 self::assertEquals($this->selfUser['id'], api_user());
226         }
227
228         /**
229          * Test the api_user() function with an unallowed user.
230          *
231          * @return void
232          */
233         public function testApiUserWithUnallowedUser()
234         {
235                 $_SESSION = ['allow_api' => false];
236                 self::assertEquals(false, api_user());
237         }
238
239         /**
240          * Test the api_source() function.
241          *
242          * @return void
243          */
244         public function testApiSource()
245         {
246                 self::assertEquals('api', api_source());
247         }
248
249         /**
250          * Test the api_source() function with a Twidere user agent.
251          *
252          * @return void
253          */
254         public function testApiSourceWithTwidere()
255         {
256                 $_SERVER['HTTP_USER_AGENT'] = 'Twidere';
257                 self::assertEquals('Twidere', api_source());
258         }
259
260         /**
261          * Test the api_source() function with a GET parameter.
262          *
263          * @return void
264          */
265         public function testApiSourceWithGet()
266         {
267                 $_GET['source'] = 'source_name';
268                 self::assertEquals('source_name', api_source());
269         }
270
271         /**
272          * Test the api_date() function.
273          *
274          * @return void
275          */
276         public function testApiDate()
277         {
278                 self::assertEquals('Wed Oct 10 00:00:00 +0000 1990', api_date('1990-10-10'));
279         }
280
281         /**
282          * Test the api_register_func() function.
283          *
284          * @return void
285          */
286         public function testApiRegisterFunc()
287         {
288                 global $API;
289                 self::assertNull(
290                         api_register_func(
291                                 'api_path',
292                                 function () {
293                                 },
294                                 true,
295                                 'method'
296                         )
297                 );
298                 self::assertTrue($API['api_path']['auth']);
299                 self::assertEquals('method', $API['api_path']['method']);
300                 self::assertTrue(is_callable($API['api_path']['func']));
301         }
302
303         /**
304          * Test the BasicAuth::getCurrentUserID() function without any login.
305          *
306          * @runInSeparateProcess
307          * @preserveGlobalState disabled
308          * @preserveGlobalState disabled
309          */
310         public function testApiLoginWithoutLogin()
311         {
312                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
313                 BasicAuth::getCurrentUserID(true);
314         }
315
316         /**
317          * Test the BasicAuth::getCurrentUserID() function with a bad login.
318          *
319          * @runInSeparateProcess
320          * @preserveGlobalState disabled
321          * @preserveGlobalState disabled
322          */
323         public function testApiLoginWithBadLogin()
324         {
325                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
326                 $_SERVER['PHP_AUTH_USER'] = 'user@server';
327                 BasicAuth::getCurrentUserID(true);
328         }
329
330         /**
331          * Test the BasicAuth::getCurrentUserID() function with oAuth.
332          *
333          * @return void
334          */
335         public function testApiLoginWithOauth()
336         {
337                 $this->markTestIncomplete('Can we test this easily?');
338         }
339
340         /**
341          * Test the BasicAuth::getCurrentUserID() function with authentication provided by an addon.
342          *
343          * @return void
344          */
345         public function testApiLoginWithAddonAuth()
346         {
347                 $this->markTestIncomplete('Can we test this easily?');
348         }
349
350         /**
351          * Test the BasicAuth::getCurrentUserID() function with a correct login.
352          *
353          * @runInSeparateProcess
354          * @preserveGlobalState disabled
355          * @doesNotPerformAssertions
356          */
357         public function testApiLoginWithCorrectLogin()
358         {
359                 $_SERVER['PHP_AUTH_USER'] = 'Test user';
360                 $_SERVER['PHP_AUTH_PW']   = 'password';
361                 BasicAuth::getCurrentUserID(true);
362         }
363
364         /**
365          * Test the BasicAuth::getCurrentUserID() function with a remote user.
366          *
367          * @runInSeparateProcess
368          * @preserveGlobalState disabled
369          */
370         public function testApiLoginWithRemoteUser()
371         {
372                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
373                 $_SERVER['REDIRECT_REMOTE_USER'] = '123456dXNlcjpwYXNzd29yZA==';
374                 BasicAuth::getCurrentUserID(true);
375         }
376
377         /**
378          * Test the api_check_method() function.
379          *
380          * @return void
381          */
382         public function testApiCheckMethod()
383         {
384                 self::assertFalse(api_check_method('method'));
385         }
386
387         /**
388          * Test the api_check_method() function with a correct method.
389          *
390          * @return void
391          */
392         public function testApiCheckMethodWithCorrectMethod()
393         {
394                 $_SERVER['REQUEST_METHOD'] = 'method';
395                 self::assertTrue(api_check_method('method'));
396         }
397
398         /**
399          * Test the api_check_method() function with a wildcard.
400          *
401          * @return void
402          */
403         public function testApiCheckMethodWithWildcard()
404         {
405                 self::assertTrue(api_check_method('*'));
406         }
407
408         /**
409          * Test the api_call() function.
410          *
411          * @runInSeparateProcess
412          * @preserveGlobalState disabled
413          */
414         public function testApiCall()
415         {
416                 global $API;
417                 $API['api_path']           = [
418                         'method' => 'method',
419                         'func'   => function () {
420                                 return ['data' => ['some_data']];
421                         }
422                 ];
423                 $_SERVER['REQUEST_METHOD'] = 'method';
424                 $_SERVER['QUERY_STRING'] = 'pagename=api_path';
425                 $_GET['callback']          = 'callback_name';
426
427                 $args = DI::args()->determine($_SERVER, $_GET);
428
429                 self::assertEquals(
430                         'callback_name(["some_data"])',
431                         api_call($this->app, $args)
432                 );
433         }
434
435         /**
436          * Test the api_call() function with the profiled enabled.
437          *
438          * @runInSeparateProcess
439          * @preserveGlobalState disabled
440          */
441         public function testApiCallWithProfiler()
442         {
443                 global $API;
444                 $API['api_path']           = [
445                         'method' => 'method',
446                         'func'   => function () {
447                                 return ['data' => ['some_data']];
448                         }
449                 ];
450
451                 $_SERVER['REQUEST_METHOD'] = 'method';
452                 $_SERVER['QUERY_STRING'] = 'pagename=api_path';
453
454                 $args = DI::args()->determine($_SERVER, $_GET);
455
456                 $this->config->set('system', 'profiler', true);
457                 $this->config->set('rendertime', 'callstack', true);
458                 $this->app->callstack = [
459                         'database'       => ['some_function' => 200],
460                         'database_write' => ['some_function' => 200],
461                         'cache'          => ['some_function' => 200],
462                         'cache_write'    => ['some_function' => 200],
463                         'network'        => ['some_function' => 200]
464                 ];
465
466                 self::assertEquals(
467                         '["some_data"]',
468                         api_call($this->app, $args)
469                 );
470         }
471
472         /**
473          * Test the api_call() function without any result.
474          *
475          * @runInSeparateProcess
476          * @preserveGlobalState disabled
477          */
478         public function testApiCallWithNoResult()
479         {
480                 global $API;
481                 $API['api_path']           = [
482                         'method' => 'method',
483                         'func'   => function () {
484                                 return false;
485                         }
486                 ];
487                 $_SERVER['REQUEST_METHOD'] = 'method';
488                 $_SERVER['QUERY_STRING'] = 'pagename=api_path';
489
490                 $args = DI::args()->determine($_SERVER, $_GET);
491
492                 self::assertEquals(
493                         '{"status":{"error":"Internal Server Error","code":"500 Internal Server Error","request":"api_path"}}',
494                         api_call($this->app, $args)
495                 );
496         }
497
498         /**
499          * Test the api_call() function with an unimplemented API.
500          *
501          * @runInSeparateProcess
502          * @preserveGlobalState disabled
503          */
504         public function testApiCallWithUninplementedApi()
505         {
506                 self::assertEquals(
507                         '{"status":{"error":"Not Found","code":"404 Not Found","request":""}}',
508                         api_call($this->app)
509                 );
510         }
511
512         /**
513          * Test the api_call() function with a JSON result.
514          *
515          * @runInSeparateProcess
516          * @preserveGlobalState disabled
517          */
518         public function testApiCallWithJson()
519         {
520                 global $API;
521                 $API['api_path']           = [
522                         'method' => 'method',
523                         'func'   => function () {
524                                 return ['data' => ['some_data']];
525                         }
526                 ];
527                 $_SERVER['REQUEST_METHOD'] = 'method';
528                 $_SERVER['QUERY_STRING'] = 'pagename=api_path.json';
529
530                 $args = DI::args()->determine($_SERVER, $_GET);
531
532                 self::assertEquals(
533                         '["some_data"]',
534                         api_call($this->app, $args)
535                 );
536         }
537
538         /**
539          * Test the api_call() function with an XML result.
540          *
541          * @runInSeparateProcess
542          * @preserveGlobalState disabled
543          */
544         public function testApiCallWithXml()
545         {
546                 global $API;
547                 $API['api_path']           = [
548                         'method' => 'method',
549                         'func'   => function () {
550                                 return 'some_data';
551                         }
552                 ];
553                 $_SERVER['REQUEST_METHOD'] = 'method';
554                 $_SERVER['QUERY_STRING'] = 'pagename=api_path.xml';
555
556                 $args = DI::args()->determine($_SERVER, $_GET);
557
558                 self::assertEquals(
559                         'some_data',
560                         api_call($this->app, $args)
561                 );
562         }
563
564         /**
565          * Test the api_call() function with an RSS result.
566          *
567          * @runInSeparateProcess
568          * @preserveGlobalState disabled
569          */
570         public function testApiCallWithRss()
571         {
572                 global $API;
573                 $API['api_path']           = [
574                         'method' => 'method',
575                         'func'   => function () {
576                                 return 'some_data';
577                         }
578                 ];
579                 $_SERVER['REQUEST_METHOD'] = 'method';
580                 $_SERVER['QUERY_STRING'] = 'pagename=api_path.rss';
581
582                 $args = DI::args()->determine($_SERVER, $_GET);
583
584                 self::assertEquals(
585                         '<?xml version="1.0" encoding="UTF-8"?>' . "\n" .
586                         'some_data',
587                         api_call($this->app, $args)
588                 );
589         }
590
591         /**
592          * Test the api_call() function with an Atom result.
593          *
594          * @runInSeparateProcess
595          * @preserveGlobalState disabled
596          */
597         public function testApiCallWithAtom()
598         {
599                 global $API;
600                 $API['api_path']           = [
601                         'method' => 'method',
602                         'func'   => function () {
603                                 return 'some_data';
604                         }
605                 ];
606                 $_SERVER['REQUEST_METHOD'] = 'method';
607                 $_SERVER['QUERY_STRING'] = 'pagename=api_path.atom';
608
609                 $args = DI::args()->determine($_SERVER, $_GET);
610
611                 self::assertEquals(
612                         '<?xml version="1.0" encoding="UTF-8"?>' . "\n" .
613                         'some_data',
614                         api_call($this->app, $args)
615                 );
616         }
617
618         /**
619          * Test the api_call() function with an unallowed method.
620          *
621          * @runInSeparateProcess
622          * @preserveGlobalState disabled
623          */
624         public function testApiCallWithWrongMethod()
625         {
626                 global $API;
627                 $API['api_path'] = ['method' => 'method'];
628
629                 $_SERVER['QUERY_STRING'] = 'pagename=api_path';
630
631                 $args = DI::args()->determine($_SERVER, $_GET);
632
633                 self::assertEquals(
634                         '{"status":{"error":"Method Not Allowed","code":"405 Method Not Allowed","request":"api_path"}}',
635                         api_call($this->app, $args)
636                 );
637         }
638
639         /**
640          * Test the api_call() function with an unauthorized user.
641          *
642          * @runInSeparateProcess
643          * @preserveGlobalState disabled
644          */
645         public function testApiCallWithWrongAuth()
646         {
647                 global $API;
648                 $API['api_path']           = [
649                         'method' => 'method',
650                         'auth'   => true
651                 ];
652                 $_SESSION['authenticated'] = false;
653                 $_SERVER['REQUEST_METHOD'] = 'method';
654                 $_SERVER['QUERY_STRING'] = 'pagename=api_path';
655
656                 $args = DI::args()->determine($_SERVER, $_GET);
657
658                 self::assertEquals(
659                         '{"status":{"error":"This API requires login","code":"401 Unauthorized","request":"api_path"}}',
660                         api_call($this->app, $args)
661                 );
662         }
663
664         /**
665          * Test the api_error() function with a JSON result.
666          *
667          * @runInSeparateProcess
668          * @preserveGlobalState disabled
669          */
670         public function testApiErrorWithJson()
671         {
672                 self::assertEquals(
673                         '{"status":{"error":"error_message","code":"200 OK","request":""}}',
674                         api_error('json', new HTTPException\OKException('error_message'), DI::args())
675                 );
676         }
677
678         /**
679          * Test the api_error() function with an XML result.
680          *
681          * @runInSeparateProcess
682          * @preserveGlobalState disabled
683          */
684         public function testApiErrorWithXml()
685         {
686                 self::assertEquals(
687                         '<?xml version="1.0"?>' . "\n" .
688                         '<status xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
689                         'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
690                         'xmlns:georss="http://www.georss.org/georss">' . "\n" .
691                         '  <error>error_message</error>' . "\n" .
692                         '  <code>200 OK</code>' . "\n" .
693                         '  <request/>' . "\n" .
694                         '</status>' . "\n",
695                         api_error('xml', new HTTPException\OKException('error_message'), DI::args())
696                 );
697         }
698
699         /**
700          * Test the api_error() function with an RSS result.
701          *
702          * @runInSeparateProcess
703          * @preserveGlobalState disabled
704          */
705         public function testApiErrorWithRss()
706         {
707                 self::assertEquals(
708                         '<?xml version="1.0"?>' . "\n" .
709                         '<status xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
710                         'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
711                         'xmlns:georss="http://www.georss.org/georss">' . "\n" .
712                         '  <error>error_message</error>' . "\n" .
713                         '  <code>200 OK</code>' . "\n" .
714                         '  <request/>' . "\n" .
715                         '</status>' . "\n",
716                         api_error('rss', new HTTPException\OKException('error_message'), DI::args())
717                 );
718         }
719
720         /**
721          * Test the api_error() function with an Atom result.
722          *
723          * @runInSeparateProcess
724          * @preserveGlobalState disabled
725          */
726         public function testApiErrorWithAtom()
727         {
728                 self::assertEquals(
729                         '<?xml version="1.0"?>' . "\n" .
730                         '<status xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
731                         'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
732                         'xmlns:georss="http://www.georss.org/georss">' . "\n" .
733                         '  <error>error_message</error>' . "\n" .
734                         '  <code>200 OK</code>' . "\n" .
735                         '  <request/>' . "\n" .
736                         '</status>' . "\n",
737                         api_error('atom', new HTTPException\OKException('error_message'), DI::args())
738                 );
739         }
740
741         /**
742          * Test the api_rss_extra() function.
743          *
744          * @return void
745          */
746         public function testApiRssExtra()
747         {
748                 $user_info = ['url' => 'user_url', 'lang' => 'en'];
749                 $result    = api_rss_extra($this->app, [], $user_info);
750                 self::assertEquals($user_info, $result['$user']);
751                 self::assertEquals($user_info['url'], $result['$rss']['alternate']);
752                 self::assertArrayHasKey('self', $result['$rss']);
753                 self::assertArrayHasKey('base', $result['$rss']);
754                 self::assertArrayHasKey('updated', $result['$rss']);
755                 self::assertArrayHasKey('atom_updated', $result['$rss']);
756                 self::assertArrayHasKey('language', $result['$rss']);
757                 self::assertArrayHasKey('logo', $result['$rss']);
758         }
759
760         /**
761          * Test the api_rss_extra() function without any user info.
762          *
763          * @return void
764          */
765         public function testApiRssExtraWithoutUserInfo()
766         {
767                 $result = api_rss_extra($this->app, [], null);
768                 self::assertIsArray($result['$user']);
769                 self::assertArrayHasKey('alternate', $result['$rss']);
770                 self::assertArrayHasKey('self', $result['$rss']);
771                 self::assertArrayHasKey('base', $result['$rss']);
772                 self::assertArrayHasKey('updated', $result['$rss']);
773                 self::assertArrayHasKey('atom_updated', $result['$rss']);
774                 self::assertArrayHasKey('language', $result['$rss']);
775                 self::assertArrayHasKey('logo', $result['$rss']);
776         }
777
778         /**
779          * Test the api_unique_id_to_nurl() function.
780          *
781          * @return void
782          */
783         public function testApiUniqueIdToNurl()
784         {
785                 self::assertFalse(api_unique_id_to_nurl($this->wrongUserId));
786         }
787
788         /**
789          * Test the api_unique_id_to_nurl() function with a correct ID.
790          *
791          * @return void
792          */
793         public function testApiUniqueIdToNurlWithCorrectId()
794         {
795                 self::assertEquals($this->otherUser['nurl'], api_unique_id_to_nurl($this->otherUser['id']));
796         }
797
798         /**
799          * Test the api_get_user() function.
800          *
801          * @return void
802          */
803         public function testApiGetUser()
804         {
805                 $user = api_get_user();
806                 self::assertSelfUser($user);
807                 self::assertEquals('708fa0', $user['profile_sidebar_fill_color']);
808                 self::assertEquals('6fdbe8', $user['profile_link_color']);
809                 self::assertEquals('ededed', $user['profile_background_color']);
810         }
811
812         /**
813          * Test the api_get_user() function with a Frio schema.
814          *
815          * @return void
816          */
817         public function testApiGetUserWithFrioSchema()
818         {
819                 $pConfig = $this->dice->create(IManagePersonalConfigValues::class);
820                 $pConfig->set($this->selfUser['id'], 'frio', 'schema', 'red');
821                 $user = api_get_user();
822                 self::assertSelfUser($user);
823                 self::assertEquals('708fa0', $user['profile_sidebar_fill_color']);
824                 self::assertEquals('6fdbe8', $user['profile_link_color']);
825                 self::assertEquals('ededed', $user['profile_background_color']);
826         }
827
828         /**
829          * Test the api_get_user() function with an empty Frio schema.
830          *
831          * @return void
832          */
833         public function testApiGetUserWithEmptyFrioSchema()
834         {
835                 $pConfig = $this->dice->create(IManagePersonalConfigValues::class);
836                 $pConfig->set($this->selfUser['id'], 'frio', 'schema', '---');
837                 $user = api_get_user();
838                 self::assertSelfUser($user);
839                 self::assertEquals('708fa0', $user['profile_sidebar_fill_color']);
840                 self::assertEquals('6fdbe8', $user['profile_link_color']);
841                 self::assertEquals('ededed', $user['profile_background_color']);
842         }
843
844         /**
845          * Test the api_get_user() function with a custom Frio schema.
846          *
847          * @return void
848          */
849         public function testApiGetUserWithCustomFrioSchema()
850         {
851                 $pConfig = $this->dice->create(IManagePersonalConfigValues::class);
852                 $pConfig->set($this->selfUser['id'], 'frio', 'schema', '---');
853                 $pConfig->set($this->selfUser['id'], 'frio', 'nav_bg', '#123456');
854                 $pConfig->set($this->selfUser['id'], 'frio', 'link_color', '#123456');
855                 $pConfig->set($this->selfUser['id'], 'frio', 'background_color', '#123456');
856                 $user = api_get_user();
857                 self::assertSelfUser($user);
858                 self::assertEquals('123456', $user['profile_sidebar_fill_color']);
859                 self::assertEquals('123456', $user['profile_link_color']);
860                 self::assertEquals('123456', $user['profile_background_color']);
861         }
862
863         /**
864          * Test the api_get_user() function with an user that is not allowed to use the API.
865          *
866          * @runInSeparateProcess
867          * @preserveGlobalState disabled
868          */
869         public function testApiGetUserWithoutApiUser()
870         {
871                 $_SERVER['PHP_AUTH_USER'] = 'Test user';
872                 $_SERVER['PHP_AUTH_PW']   = 'password';
873                 $_SESSION['allow_api']    = false;
874                 self::assertFalse(api_get_user());
875         }
876
877         /**
878          * Test the api_get_user() function with an user ID in a GET parameter.
879          *
880          * @return void
881          */
882         public function testApiGetUserWithGetId()
883         {
884                 $_GET['user_id'] = $this->otherUser['id'];
885                 self::assertOtherUser(api_get_user());
886         }
887
888         /**
889          * Test the api_get_user() function with a wrong user ID in a GET parameter.
890          *
891          * @return void
892          */
893         public function testApiGetUserWithWrongGetId()
894         {
895                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
896                 $_GET['user_id'] = $this->wrongUserId;
897                 self::assertOtherUser(api_get_user());
898         }
899
900         /**
901          * Test the api_get_user() function with an user name in a GET parameter.
902          *
903          * @return void
904          */
905         public function testApiGetUserWithGetName()
906         {
907                 $_GET['screen_name'] = $this->selfUser['nick'];
908                 self::assertSelfUser(api_get_user());
909         }
910
911         /**
912          * Test the api_get_user() function with a profile URL in a GET parameter.
913          *
914          * @return void
915          */
916         public function testApiGetUserWithGetUrl()
917         {
918                 $_GET['profileurl'] = $this->selfUser['nurl'];
919                 self::assertSelfUser(api_get_user());
920         }
921
922         /**
923          * Test the api_get_user() function with an user ID in the API path.
924          *
925          * @return void
926          */
927         public function testApiGetUserWithNumericCalledApi()
928         {
929                 global $called_api;
930                 $called_api         = ['api_path'];
931                 DI::args()->setArgv(['', $this->otherUser['id'] . '.json']);
932                 self::assertOtherUser(api_get_user());
933         }
934
935         /**
936          * Test the api_get_user() function with the $called_api global variable.
937          *
938          * @return void
939          */
940         public function testApiGetUserWithCalledApi()
941         {
942                 global $called_api;
943                 $called_api = ['api', 'api_path'];
944                 self::assertSelfUser(api_get_user());
945         }
946
947         /**
948          * Test the api_get_user() function with a valid user.
949          *
950          * @return void
951          */
952         public function testApiGetUserWithCorrectUser()
953         {
954                 self::assertOtherUser(api_get_user($this->otherUser['id']));
955         }
956
957         /**
958          * Test the api_get_user() function with a wrong user ID.
959          *
960          * @return void
961          */
962         public function testApiGetUserWithWrongUser()
963         {
964                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
965                 self::assertOtherUser(api_get_user($this->wrongUserId));
966         }
967
968         /**
969          * Test the api_get_user() function with a 0 user ID.
970          *
971          * @return void
972          */
973         public function testApiGetUserWithZeroUser()
974         {
975                 self::assertSelfUser(api_get_user(0));
976         }
977
978         /**
979          * Test the api_item_get_user() function.
980          *
981          * @return void
982          */
983         public function testApiItemGetUser()
984         {
985                 $users = api_item_get_user($this->app, []);
986                 self::assertSelfUser($users[0]);
987         }
988
989         /**
990          * Test the api_item_get_user() function with a different item parent.
991          *
992          * @return void
993          */
994         public function testApiItemGetUserWithDifferentParent()
995         {
996                 $users = api_item_get_user($this->app, ['thr-parent' => 'item_parent', 'uri' => 'item_uri']);
997                 self::assertSelfUser($users[0]);
998                 self::assertEquals($users[0], $users[1]);
999         }
1000
1001         /**
1002          * Test the Arrays::walkRecursive() function.
1003          *
1004          * @return void
1005          */
1006         public function testApiWalkRecursive()
1007         {
1008                 $array = ['item1'];
1009                 self::assertEquals(
1010                         $array,
1011                         Arrays::walkRecursive(
1012                                 $array,
1013                                 function () {
1014                                         // Should we test this with a callback that actually does something?
1015                                         return true;
1016                                 }
1017                         )
1018                 );
1019         }
1020
1021         /**
1022          * Test the Arrays::walkRecursive() function with an array.
1023          *
1024          * @return void
1025          */
1026         public function testApiWalkRecursiveWithArray()
1027         {
1028                 $array = [['item1'], ['item2']];
1029                 self::assertEquals(
1030                         $array,
1031                         Arrays::walkRecursive(
1032                                 $array,
1033                                 function () {
1034                                         // Should we test this with a callback that actually does something?
1035                                         return true;
1036                                 }
1037                         )
1038                 );
1039         }
1040
1041         /**
1042          * Test the BaseApi::reformatXML() function.
1043          *
1044          * @return void
1045          */
1046         public function testApiReformatXml()
1047         {
1048                 $item = true;
1049                 $key  = '';
1050                 self::assertTrue(BaseApi::reformatXML($item, $key));
1051                 self::assertEquals('true', $item);
1052         }
1053
1054         /**
1055          * Test the BaseApi::reformatXML() function with a statusnet_api key.
1056          *
1057          * @return void
1058          */
1059         public function testApiReformatXmlWithStatusnetKey()
1060         {
1061                 $item = '';
1062                 $key  = 'statusnet_api';
1063                 self::assertTrue(BaseApi::reformatXML($item, $key));
1064                 self::assertEquals('statusnet:api', $key);
1065         }
1066
1067         /**
1068          * Test the BaseApi::reformatXML() function with a friendica_api key.
1069          *
1070          * @return void
1071          */
1072         public function testApiReformatXmlWithFriendicaKey()
1073         {
1074                 $item = '';
1075                 $key  = 'friendica_api';
1076                 self::assertTrue(BaseApi::reformatXML($item, $key));
1077                 self::assertEquals('friendica:api', $key);
1078         }
1079
1080         /**
1081          * Test the BaseApi::createXML() function.
1082          *
1083          * @return void
1084          */
1085         public function testApiCreateXml()
1086         {
1087                 self::assertEquals(
1088                         '<?xml version="1.0"?>' . "\n" .
1089                         '<root_element xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
1090                         'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
1091                         'xmlns:georss="http://www.georss.org/georss">' . "\n" .
1092                         '  <data>some_data</data>' . "\n" .
1093                         '</root_element>' . "\n",
1094                         BaseApi::createXML(['data' => ['some_data']], 'root_element')
1095                 );
1096         }
1097
1098         /**
1099          * Test the BaseApi::createXML() function without any XML namespace.
1100          *
1101          * @return void
1102          */
1103         public function testApiCreateXmlWithoutNamespaces()
1104         {
1105                 self::assertEquals(
1106                         '<?xml version="1.0"?>' . "\n" .
1107                         '<ok>' . "\n" .
1108                         '  <data>some_data</data>' . "\n" .
1109                         '</ok>' . "\n",
1110                         BaseApi::createXML(['data' => ['some_data']], 'ok')
1111                 );
1112         }
1113
1114         /**
1115          * Test the BaseApi::formatData() function.
1116          *
1117          * @return void
1118          */
1119         public function testApiFormatData()
1120         {
1121                 $data = ['some_data'];
1122                 self::assertEquals($data, BaseApi::formatData('root_element', 'json', $data));
1123         }
1124
1125         /**
1126          * Test the BaseApi::formatData() function with an XML result.
1127          *
1128          * @return void
1129          */
1130         public function testApiFormatDataWithXml()
1131         {
1132                 self::assertEquals(
1133                         '<?xml version="1.0"?>' . "\n" .
1134                         '<root_element xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
1135                         'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
1136                         'xmlns:georss="http://www.georss.org/georss">' . "\n" .
1137                         '  <data>some_data</data>' . "\n" .
1138                         '</root_element>' . "\n",
1139                         BaseApi::formatData('root_element', 'xml', ['data' => ['some_data']])
1140                 );
1141         }
1142
1143         /**
1144          * Test the api_account_verify_credentials() function.
1145          *
1146          * @return void
1147          */
1148         public function testApiAccountVerifyCredentials()
1149         {
1150                 self::assertArrayHasKey('user', api_account_verify_credentials('json'));
1151         }
1152
1153         /**
1154          * Test the api_account_verify_credentials() function without an authenticated user.
1155          *
1156          * @return void
1157          */
1158         public function testApiAccountVerifyCredentialsWithoutAuthenticatedUser()
1159         {
1160                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1161                 $_SESSION['authenticated'] = false;
1162                 api_account_verify_credentials('json');
1163         }
1164
1165         /**
1166          * Test the requestdata() function.
1167          *
1168          * @return void
1169          */
1170         public function testRequestdata()
1171         {
1172                 self::assertNull(requestdata('variable_name'));
1173         }
1174
1175         /**
1176          * Test the requestdata() function with a POST parameter.
1177          *
1178          * @return void
1179          */
1180         public function testRequestdataWithPost()
1181         {
1182                 $_POST['variable_name'] = 'variable_value';
1183                 self::assertEquals('variable_value', requestdata('variable_name'));
1184         }
1185
1186         /**
1187          * Test the requestdata() function with a GET parameter.
1188          *
1189          * @return void
1190          */
1191         public function testRequestdataWithGet()
1192         {
1193                 $_GET['variable_name'] = 'variable_value';
1194                 self::assertEquals('variable_value', requestdata('variable_name'));
1195         }
1196
1197         /**
1198          * Test the api_statuses_mediap() function.
1199          *
1200          * @return void
1201          */
1202         public function testApiStatusesMediap()
1203         {
1204                 DI::args()->setArgc(2);
1205
1206                 $_FILES         = [
1207                         'media' => [
1208                                 'id'       => 666,
1209                                 'size'     => 666,
1210                                 'width'    => 666,
1211                                 'height'   => 666,
1212                                 'tmp_name' => $this->getTempImage(),
1213                                 'name'     => 'spacer.png',
1214                                 'type'     => 'image/png'
1215                         ]
1216                 ];
1217                 $_GET['status'] = '<b>Status content</b>';
1218
1219                 $result = api_statuses_mediap('json');
1220                 self::assertStatus($result['status']);
1221         }
1222
1223         /**
1224          * Test the api_statuses_mediap() function without an authenticated user.
1225          *
1226          * @return void
1227          */
1228         public function testApiStatusesMediapWithoutAuthenticatedUser()
1229         {
1230                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1231                 $_SESSION['authenticated'] = false;
1232                 api_statuses_mediap('json');
1233         }
1234
1235         /**
1236          * Test the api_statuses_update() function.
1237          *
1238          * @return void
1239          */
1240         public function testApiStatusesUpdate()
1241         {
1242                 $_GET['status']                = 'Status content #friendica';
1243                 $_GET['in_reply_to_status_id'] = -1;
1244                 $_GET['lat']                   = 48;
1245                 $_GET['long']                  = 7;
1246                 $_FILES                        = [
1247                         'media' => [
1248                                 'id'       => 666,
1249                                 'size'     => 666,
1250                                 'width'    => 666,
1251                                 'height'   => 666,
1252                                 'tmp_name' => $this->getTempImage(),
1253                                 'name'     => 'spacer.png',
1254                                 'type'     => 'image/png'
1255                         ]
1256                 ];
1257
1258                 $result = api_statuses_update('json');
1259                 self::assertStatus($result['status']);
1260         }
1261
1262         /**
1263          * Test the api_statuses_update() function with an HTML status.
1264          *
1265          * @return void
1266          */
1267         public function testApiStatusesUpdateWithHtml()
1268         {
1269                 $_GET['htmlstatus'] = '<b>Status content</b>';
1270
1271                 $result = api_statuses_update('json');
1272                 self::assertStatus($result['status']);
1273         }
1274
1275         /**
1276          * Test the api_statuses_update() function without an authenticated user.
1277          *
1278          * @return void
1279          */
1280         public function testApiStatusesUpdateWithoutAuthenticatedUser()
1281         {
1282                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1283                 $_SESSION['authenticated'] = false;
1284                 api_statuses_update('json');
1285         }
1286
1287         /**
1288          * Test the api_statuses_update() function with a parent status.
1289          *
1290          * @return void
1291          */
1292         public function testApiStatusesUpdateWithParent()
1293         {
1294                 $this->markTestIncomplete('This triggers an exit() somewhere and kills PHPUnit.');
1295         }
1296
1297         /**
1298          * Test the api_statuses_update() function with a media_ids parameter.
1299          *
1300          * @return void
1301          */
1302         public function testApiStatusesUpdateWithMediaIds()
1303         {
1304                 $this->markTestIncomplete();
1305         }
1306
1307         /**
1308          * Test the api_statuses_update() function with the throttle limit reached.
1309          *
1310          * @return void
1311          */
1312         public function testApiStatusesUpdateWithDayThrottleReached()
1313         {
1314                 $this->markTestIncomplete();
1315         }
1316
1317         /**
1318          * Test the api_media_upload() function.
1319          * @runInSeparateProcess
1320          * @preserveGlobalState disabled
1321          */
1322         public function testApiMediaUpload()
1323         {
1324                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
1325                 api_media_upload();
1326         }
1327
1328         /**
1329          * Test the api_media_upload() function without an authenticated user.
1330          *
1331          * @return void
1332          */
1333         public function testApiMediaUploadWithoutAuthenticatedUser()
1334         {
1335                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1336                 $_SESSION['authenticated'] = false;
1337                 api_media_upload();
1338         }
1339
1340         /**
1341          * Test the api_media_upload() function with an invalid uploaded media.
1342          *
1343          * @return void
1344          */
1345         public function testApiMediaUploadWithMedia()
1346         {
1347                 $this->expectException(\Friendica\Network\HTTPException\InternalServerErrorException::class);
1348                 $_FILES = [
1349                         'media' => [
1350                                 'id'       => 666,
1351                                 'tmp_name' => 'tmp_name'
1352                         ]
1353                 ];
1354                 api_media_upload();
1355         }
1356
1357         /**
1358          * Test the api_media_upload() function with an valid uploaded media.
1359          *
1360          * @return void
1361          */
1362         public function testApiMediaUploadWithValidMedia()
1363         {
1364                 $_FILES    = [
1365                         'media' => [
1366                                 'id'       => 666,
1367                                 'size'     => 666,
1368                                 'width'    => 666,
1369                                 'height'   => 666,
1370                                 'tmp_name' => $this->getTempImage(),
1371                                 'name'     => 'spacer.png',
1372                                 'type'     => 'image/png'
1373                         ]
1374                 ];
1375                 $app       = DI::app();
1376                 DI::args()->setArgc(2);
1377
1378                 $result = api_media_upload();
1379                 self::assertEquals('image/png', $result['media']['image']['image_type']);
1380                 self::assertEquals(1, $result['media']['image']['w']);
1381                 self::assertEquals(1, $result['media']['image']['h']);
1382                 self::assertNotEmpty($result['media']['image']['friendica_preview_url']);
1383         }
1384
1385         /**
1386          * Test the api_status_show() function.
1387          */
1388         public function testApiStatusShowWithJson()
1389         {
1390                 $result = api_status_show('json', 1);
1391                 self::assertStatus($result['status']);
1392         }
1393
1394         /**
1395          * Test the api_status_show() function with an XML result.
1396          */
1397         public function testApiStatusShowWithXml()
1398         {
1399                 $result = api_status_show('xml', 1);
1400                 self::assertXml($result, 'statuses');
1401         }
1402
1403         /**
1404          * Test the api_get_last_status() function
1405          */
1406         public function testApiGetLastStatus()
1407         {
1408                 $item = api_get_last_status($this->selfUser['id'], $this->selfUser['id']);
1409
1410                 self::assertNotNull($item);
1411         }
1412
1413         /**
1414          * Test the api_users_show() function.
1415          *
1416          * @return void
1417          */
1418         public function testApiUsersShow()
1419         {
1420                 $result = api_users_show('json');
1421                 // We can't use assertSelfUser() here because the user object is missing some properties.
1422                 self::assertEquals($this->selfUser['id'], $result['user']['cid']);
1423                 self::assertEquals('DFRN', $result['user']['location']);
1424                 self::assertEquals($this->selfUser['name'], $result['user']['name']);
1425                 self::assertEquals($this->selfUser['nick'], $result['user']['screen_name']);
1426                 self::assertEquals('dfrn', $result['user']['network']);
1427                 self::assertTrue($result['user']['verified']);
1428         }
1429
1430         /**
1431          * Test the api_users_show() function with an XML result.
1432          *
1433          * @return void
1434          */
1435         public function testApiUsersShowWithXml()
1436         {
1437                 $result = api_users_show('xml');
1438                 self::assertXml($result, 'statuses');
1439         }
1440
1441         /**
1442          * Test the api_users_search() function.
1443          *
1444          * @return void
1445          */
1446         public function testApiUsersSearch()
1447         {
1448                 $_GET['q'] = 'othercontact';
1449                 $result    = api_users_search('json');
1450                 self::assertOtherUser($result['users'][0]);
1451         }
1452
1453         /**
1454          * Test the api_users_search() function with an XML result.
1455          *
1456          * @return void
1457          */
1458         public function testApiUsersSearchWithXml()
1459         {
1460                 $_GET['q'] = 'othercontact';
1461                 $result    = api_users_search('xml');
1462                 self::assertXml($result, 'users');
1463         }
1464
1465         /**
1466          * Test the api_users_search() function without a GET q parameter.
1467          *
1468          * @return void
1469          */
1470         public function testApiUsersSearchWithoutQuery()
1471         {
1472                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
1473                 api_users_search('json');
1474         }
1475
1476         /**
1477          * Test the api_users_lookup() function.
1478          *
1479          * @return void
1480          */
1481         public function testApiUsersLookup()
1482         {
1483                 $this->expectException(\Friendica\Network\HTTPException\NotFoundException::class);
1484                 api_users_lookup('json');
1485         }
1486
1487         /**
1488          * Test the api_users_lookup() function with an user ID.
1489          *
1490          * @return void
1491          */
1492         public function testApiUsersLookupWithUserId()
1493         {
1494                 $_REQUEST['user_id'] = $this->otherUser['id'];
1495                 $result              = api_users_lookup('json');
1496                 self::assertOtherUser($result['users'][0]);
1497         }
1498
1499         /**
1500          * Test the api_search() function.
1501          *
1502          * @return void
1503          */
1504         public function testApiSearch()
1505         {
1506                 $_REQUEST['q']      = 'reply';
1507                 $_REQUEST['max_id'] = 10;
1508                 $result             = api_search('json');
1509                 foreach ($result['status'] as $status) {
1510                         self::assertStatus($status);
1511                         self::assertStringContainsStringIgnoringCase('reply', $status['text'], '', true);
1512                 }
1513         }
1514
1515         /**
1516          * Test the api_search() function a count parameter.
1517          *
1518          * @return void
1519          */
1520         public function testApiSearchWithCount()
1521         {
1522                 $_REQUEST['q']     = 'reply';
1523                 $_REQUEST['count'] = 20;
1524                 $result            = api_search('json');
1525                 foreach ($result['status'] as $status) {
1526                         self::assertStatus($status);
1527                         self::assertStringContainsStringIgnoringCase('reply', $status['text'], '', true);
1528                 }
1529         }
1530
1531         /**
1532          * Test the api_search() function with an rpp parameter.
1533          *
1534          * @return void
1535          */
1536         public function testApiSearchWithRpp()
1537         {
1538                 $_REQUEST['q']   = 'reply';
1539                 $_REQUEST['rpp'] = 20;
1540                 $result          = api_search('json');
1541                 foreach ($result['status'] as $status) {
1542                         self::assertStatus($status);
1543                         self::assertStringContainsStringIgnoringCase('reply', $status['text'], '', true);
1544                 }
1545         }
1546
1547         /**
1548          * Test the api_search() function with an q parameter contains hashtag.
1549          * @doesNotPerformAssertions
1550          */
1551         public function testApiSearchWithHashtag()
1552         {
1553                 $_REQUEST['q'] = '%23friendica';
1554                 $result        = api_search('json');
1555                 foreach ($result['status'] as $status) {
1556                         self::assertStatus($status);
1557                         self::assertStringContainsStringIgnoringCase('#friendica', $status['text'], '', true);
1558                 }
1559         }
1560
1561         /**
1562          * Test the api_search() function with an exclude_replies parameter.
1563          * @doesNotPerformAssertions
1564          */
1565         public function testApiSearchWithExcludeReplies()
1566         {
1567                 $_REQUEST['max_id']          = 10;
1568                 $_REQUEST['exclude_replies'] = true;
1569                 $_REQUEST['q']               = 'friendica';
1570                 $result                      = api_search('json');
1571                 foreach ($result['status'] as $status) {
1572                         self::assertStatus($status);
1573                 }
1574         }
1575
1576         /**
1577          * Test the api_search() function without an authenticated user.
1578          *
1579          * @return void
1580          */
1581         public function testApiSearchWithUnallowedUser()
1582         {
1583                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1584                 $_SESSION['allow_api'] = false;
1585                 $_GET['screen_name']   = $this->selfUser['nick'];
1586                 api_search('json');
1587         }
1588
1589         /**
1590          * Test the api_search() function without any GET query parameter.
1591          *
1592          * @return void
1593          */
1594         public function testApiSearchWithoutQuery()
1595         {
1596                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
1597                 api_search('json');
1598         }
1599
1600         /**
1601          * Test the api_statuses_home_timeline() function.
1602          *
1603          * @return void
1604          */
1605         public function testApiStatusesHomeTimeline()
1606         {
1607                 $_REQUEST['max_id']          = 10;
1608                 $_REQUEST['exclude_replies'] = true;
1609                 $_REQUEST['conversation_id'] = 1;
1610                 $result                      = api_statuses_home_timeline('json');
1611                 self::assertNotEmpty($result['status']);
1612                 foreach ($result['status'] as $status) {
1613                         self::assertStatus($status);
1614                 }
1615         }
1616
1617         /**
1618          * Test the api_statuses_home_timeline() function with a negative page parameter.
1619          *
1620          * @return void
1621          */
1622         public function testApiStatusesHomeTimelineWithNegativePage()
1623         {
1624                 $_REQUEST['page'] = -2;
1625                 $result           = api_statuses_home_timeline('json');
1626                 self::assertNotEmpty($result['status']);
1627                 foreach ($result['status'] as $status) {
1628                         self::assertStatus($status);
1629                 }
1630         }
1631
1632         /**
1633          * Test the api_statuses_home_timeline() with an unallowed user.
1634          *
1635          * @return void
1636          */
1637         public function testApiStatusesHomeTimelineWithUnallowedUser()
1638         {
1639                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1640                 $_SESSION['allow_api'] = false;
1641                 $_GET['screen_name']   = $this->selfUser['nick'];
1642                 api_statuses_home_timeline('json');
1643         }
1644
1645         /**
1646          * Test the api_statuses_home_timeline() function with an RSS result.
1647          *
1648          * @return void
1649          */
1650         public function testApiStatusesHomeTimelineWithRss()
1651         {
1652                 $result = api_statuses_home_timeline('rss');
1653                 self::assertXml($result, 'statuses');
1654         }
1655
1656         /**
1657          * Test the api_statuses_public_timeline() function.
1658          *
1659          * @return void
1660          */
1661         public function testApiStatusesPublicTimeline()
1662         {
1663                 $_REQUEST['max_id']          = 10;
1664                 $_REQUEST['conversation_id'] = 1;
1665                 $result                      = api_statuses_public_timeline('json');
1666                 self::assertNotEmpty($result['status']);
1667                 foreach ($result['status'] as $status) {
1668                         self::assertStatus($status);
1669                 }
1670         }
1671
1672         /**
1673          * Test the api_statuses_public_timeline() function with the exclude_replies parameter.
1674          *
1675          * @return void
1676          */
1677         public function testApiStatusesPublicTimelineWithExcludeReplies()
1678         {
1679                 $_REQUEST['max_id']          = 10;
1680                 $_REQUEST['exclude_replies'] = true;
1681                 $result                      = api_statuses_public_timeline('json');
1682                 self::assertNotEmpty($result['status']);
1683                 foreach ($result['status'] as $status) {
1684                         self::assertStatus($status);
1685                 }
1686         }
1687
1688         /**
1689          * Test the api_statuses_public_timeline() function with a negative page parameter.
1690          *
1691          * @return void
1692          */
1693         public function testApiStatusesPublicTimelineWithNegativePage()
1694         {
1695                 $_REQUEST['page'] = -2;
1696                 $result           = api_statuses_public_timeline('json');
1697                 self::assertNotEmpty($result['status']);
1698                 foreach ($result['status'] as $status) {
1699                         self::assertStatus($status);
1700                 }
1701         }
1702
1703         /**
1704          * Test the api_statuses_public_timeline() function with an unallowed user.
1705          *
1706          * @return void
1707          */
1708         public function testApiStatusesPublicTimelineWithUnallowedUser()
1709         {
1710                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1711                 $_SESSION['allow_api'] = false;
1712                 $_GET['screen_name']   = $this->selfUser['nick'];
1713                 api_statuses_public_timeline('json');
1714         }
1715
1716         /**
1717          * Test the api_statuses_public_timeline() function with an RSS result.
1718          *
1719          * @return void
1720          */
1721         public function testApiStatusesPublicTimelineWithRss()
1722         {
1723                 $result = api_statuses_public_timeline('rss');
1724                 self::assertXml($result, 'statuses');
1725         }
1726
1727         /**
1728          * Test the api_statuses_networkpublic_timeline() function.
1729          *
1730          * @return void
1731          */
1732         public function testApiStatusesNetworkpublicTimeline()
1733         {
1734                 $_REQUEST['max_id'] = 10;
1735                 $result             = api_statuses_networkpublic_timeline('json');
1736                 self::assertNotEmpty($result['status']);
1737                 foreach ($result['status'] as $status) {
1738                         self::assertStatus($status);
1739                 }
1740         }
1741
1742         /**
1743          * Test the api_statuses_networkpublic_timeline() function with a negative page parameter.
1744          *
1745          * @return void
1746          */
1747         public function testApiStatusesNetworkpublicTimelineWithNegativePage()
1748         {
1749                 $_REQUEST['page'] = -2;
1750                 $result           = api_statuses_networkpublic_timeline('json');
1751                 self::assertNotEmpty($result['status']);
1752                 foreach ($result['status'] as $status) {
1753                         self::assertStatus($status);
1754                 }
1755         }
1756
1757         /**
1758          * Test the api_statuses_networkpublic_timeline() function with an unallowed user.
1759          *
1760          * @return void
1761          */
1762         public function testApiStatusesNetworkpublicTimelineWithUnallowedUser()
1763         {
1764                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1765                 $_SESSION['allow_api'] = false;
1766                 $_GET['screen_name']   = $this->selfUser['nick'];
1767                 api_statuses_networkpublic_timeline('json');
1768         }
1769
1770         /**
1771          * Test the api_statuses_networkpublic_timeline() function with an RSS result.
1772          *
1773          * @return void
1774          */
1775         public function testApiStatusesNetworkpublicTimelineWithRss()
1776         {
1777                 $result = api_statuses_networkpublic_timeline('rss');
1778                 self::assertXml($result, 'statuses');
1779         }
1780
1781         /**
1782          * Test the api_statuses_show() function.
1783          *
1784          * @return void
1785          */
1786         public function testApiStatusesShow()
1787         {
1788                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
1789                 api_statuses_show('json');
1790         }
1791
1792         /**
1793          * Test the api_statuses_show() function with an ID.
1794          *
1795          * @return void
1796          */
1797         public function testApiStatusesShowWithId()
1798         {
1799                 DI::args()->setArgv(['', '', '', 1]);
1800                 $result = api_statuses_show('json');
1801                 self::assertStatus($result['status']);
1802         }
1803
1804         /**
1805          * Test the api_statuses_show() function with the conversation parameter.
1806          *
1807          * @return void
1808          */
1809         public function testApiStatusesShowWithConversation()
1810         {
1811                 DI::args()->setArgv(['', '', '', 1]);
1812                 $_REQUEST['conversation'] = 1;
1813                 $result                   = api_statuses_show('json');
1814                 self::assertNotEmpty($result['status']);
1815                 foreach ($result['status'] as $status) {
1816                         self::assertStatus($status);
1817                 }
1818         }
1819
1820         /**
1821          * Test the api_statuses_show() function with an unallowed user.
1822          *
1823          * @return void
1824          */
1825         public function testApiStatusesShowWithUnallowedUser()
1826         {
1827                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1828                 $_SESSION['allow_api'] = false;
1829                 $_GET['screen_name']   = $this->selfUser['nick'];
1830                 api_statuses_show('json');
1831         }
1832
1833         /**
1834          * Test the api_conversation_show() function.
1835          *
1836          * @return void
1837          */
1838         public function testApiConversationShow()
1839         {
1840                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
1841                 api_conversation_show('json');
1842         }
1843
1844         /**
1845          * Test the api_conversation_show() function with an ID.
1846          *
1847          * @return void
1848          */
1849         public function testApiConversationShowWithId()
1850         {
1851                 DI::args()->setArgv(['', '', '', 1]);
1852                 $_REQUEST['max_id'] = 10;
1853                 $_REQUEST['page']   = -2;
1854                 $result             = api_conversation_show('json');
1855                 self::assertNotEmpty($result['status']);
1856                 foreach ($result['status'] as $status) {
1857                         self::assertStatus($status);
1858                 }
1859         }
1860
1861         /**
1862          * Test the api_conversation_show() function with an unallowed user.
1863          *
1864          * @return void
1865          */
1866         public function testApiConversationShowWithUnallowedUser()
1867         {
1868                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1869                 $_SESSION['allow_api'] = false;
1870                 $_GET['screen_name']   = $this->selfUser['nick'];
1871                 api_conversation_show('json');
1872         }
1873
1874         /**
1875          * Test the api_statuses_repeat() function.
1876          *
1877          * @return void
1878          */
1879         public function testApiStatusesRepeat()
1880         {
1881                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1882                 api_statuses_repeat('json');
1883         }
1884
1885         /**
1886          * Test the api_statuses_repeat() function without an authenticated user.
1887          *
1888          * @return void
1889          */
1890         public function testApiStatusesRepeatWithoutAuthenticatedUser()
1891         {
1892                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1893                 $_SESSION['authenticated'] = false;
1894                 api_statuses_repeat('json');
1895         }
1896
1897         /**
1898          * Test the api_statuses_repeat() function with an ID.
1899          *
1900          * @return void
1901          */
1902         public function testApiStatusesRepeatWithId()
1903         {
1904                 DI::args()->setArgv(['', '', '', 1]);
1905                 $result = api_statuses_repeat('json');
1906                 self::assertStatus($result['status']);
1907
1908                 // Also test with a shared status
1909                 DI::args()->setArgv(['', '', '', 5]);
1910                 $result = api_statuses_repeat('json');
1911                 self::assertStatus($result['status']);
1912         }
1913
1914         /**
1915          * Test the api_statuses_destroy() function.
1916          *
1917          * @return void
1918          */
1919         public function testApiStatusesDestroy()
1920         {
1921                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
1922                 api_statuses_destroy('json');
1923         }
1924
1925         /**
1926          * Test the api_statuses_destroy() function without an authenticated user.
1927          *
1928          * @return void
1929          */
1930         public function testApiStatusesDestroyWithoutAuthenticatedUser()
1931         {
1932                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1933                 $_SESSION['authenticated'] = false;
1934                 api_statuses_destroy('json');
1935         }
1936
1937         /**
1938          * Test the api_statuses_destroy() function with an ID.
1939          *
1940          * @return void
1941          */
1942         public function testApiStatusesDestroyWithId()
1943         {
1944                 DI::args()->setArgv(['', '', '', 1]);
1945                 $result = api_statuses_destroy('json');
1946                 self::assertStatus($result['status']);
1947         }
1948
1949         /**
1950          * Test the api_statuses_mentions() function.
1951          *
1952          * @return void
1953          */
1954         public function testApiStatusesMentions()
1955         {
1956                 $this->app->setLoggedInUserNickname($this->selfUser['nick']);
1957                 $_REQUEST['max_id'] = 10;
1958                 $result             = api_statuses_mentions('json');
1959                 self::assertEmpty($result['status']);
1960                 // We should test with mentions in the database.
1961         }
1962
1963         /**
1964          * Test the api_statuses_mentions() function with a negative page parameter.
1965          *
1966          * @return void
1967          */
1968         public function testApiStatusesMentionsWithNegativePage()
1969         {
1970                 $_REQUEST['page'] = -2;
1971                 $result           = api_statuses_mentions('json');
1972                 self::assertEmpty($result['status']);
1973         }
1974
1975         /**
1976          * Test the api_statuses_mentions() function with an unallowed user.
1977          *
1978          * @return void
1979          */
1980         public function testApiStatusesMentionsWithUnallowedUser()
1981         {
1982                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
1983                 $_SESSION['allow_api'] = false;
1984                 $_GET['screen_name']   = $this->selfUser['nick'];
1985                 api_statuses_mentions('json');
1986         }
1987
1988         /**
1989          * Test the api_statuses_mentions() function with an RSS result.
1990          *
1991          * @return void
1992          */
1993         public function testApiStatusesMentionsWithRss()
1994         {
1995                 $result = api_statuses_mentions('rss');
1996                 self::assertXml($result, 'statuses');
1997         }
1998
1999         /**
2000          * Test the api_statuses_user_timeline() function.
2001          *
2002          * @return void
2003          */
2004         public function testApiStatusesUserTimeline()
2005         {
2006                 $_REQUEST['max_id']          = 10;
2007                 $_REQUEST['exclude_replies'] = true;
2008                 $_REQUEST['conversation_id'] = 1;
2009                 $result                      = api_statuses_user_timeline('json');
2010                 self::assertNotEmpty($result['status']);
2011                 foreach ($result['status'] as $status) {
2012                         self::assertStatus($status);
2013                 }
2014         }
2015
2016         /**
2017          * Test the api_statuses_user_timeline() function with a negative page parameter.
2018          *
2019          * @return void
2020          */
2021         public function testApiStatusesUserTimelineWithNegativePage()
2022         {
2023                 $_REQUEST['page'] = -2;
2024                 $result           = api_statuses_user_timeline('json');
2025                 self::assertNotEmpty($result['status']);
2026                 foreach ($result['status'] as $status) {
2027                         self::assertStatus($status);
2028                 }
2029         }
2030
2031         /**
2032          * Test the api_statuses_user_timeline() function with an RSS result.
2033          *
2034          * @return void
2035          */
2036         public function testApiStatusesUserTimelineWithRss()
2037         {
2038                 $result = api_statuses_user_timeline('rss');
2039                 self::assertXml($result, 'statuses');
2040         }
2041
2042         /**
2043          * Test the api_statuses_user_timeline() function with an unallowed user.
2044          *
2045          * @return void
2046          */
2047         public function testApiStatusesUserTimelineWithUnallowedUser()
2048         {
2049                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2050                 $_SESSION['allow_api'] = false;
2051                 $_GET['screen_name']   = $this->selfUser['nick'];
2052                 api_statuses_user_timeline('json');
2053         }
2054
2055         /**
2056          * Test the api_favorites_create_destroy() function.
2057          *
2058          * @return void
2059          */
2060         public function testApiFavoritesCreateDestroy()
2061         {
2062                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2063                 DI::args()->setArgv(['api', '1.1', 'favorites', 'create']);
2064                 api_favorites_create_destroy('json');
2065         }
2066
2067         /**
2068          * Test the api_favorites_create_destroy() function with an invalid ID.
2069          *
2070          * @return void
2071          */
2072         public function testApiFavoritesCreateDestroyWithInvalidId()
2073         {
2074                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2075                 DI::args()->setArgv(['api', '1.1', 'favorites', 'create', '12.json']);
2076                 api_favorites_create_destroy('json');
2077         }
2078
2079         /**
2080          * Test the api_favorites_create_destroy() function with an invalid action.
2081          *
2082          * @return void
2083          */
2084         public function testApiFavoritesCreateDestroyWithInvalidAction()
2085         {
2086                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2087                 DI::args()->setArgv(['api', '1.1', 'favorites', 'change.json']);
2088                 $_REQUEST['id'] = 1;
2089                 api_favorites_create_destroy('json');
2090         }
2091
2092         /**
2093          * Test the api_favorites_create_destroy() function with the create action.
2094          *
2095          * @return void
2096          */
2097         public function testApiFavoritesCreateDestroyWithCreateAction()
2098         {
2099                 DI::args()->setArgv(['api', '1.1', 'favorites', 'create.json']);
2100                 $_REQUEST['id'] = 3;
2101                 $result         = api_favorites_create_destroy('json');
2102                 self::assertStatus($result['status']);
2103         }
2104
2105         /**
2106          * Test the api_favorites_create_destroy() function with the create action and an RSS result.
2107          *
2108          * @return void
2109          */
2110         public function testApiFavoritesCreateDestroyWithCreateActionAndRss()
2111         {
2112                 DI::args()->setArgv(['api', '1.1', 'favorites', 'create.rss']);
2113                 $_REQUEST['id'] = 3;
2114                 $result         = api_favorites_create_destroy('rss');
2115                 self::assertXml($result, 'status');
2116         }
2117
2118         /**
2119          * Test the api_favorites_create_destroy() function with the destroy action.
2120          *
2121          * @return void
2122          */
2123         public function testApiFavoritesCreateDestroyWithDestroyAction()
2124         {
2125                 DI::args()->setArgv(['api', '1.1', 'favorites', 'destroy.json']);
2126                 $_REQUEST['id'] = 3;
2127                 $result         = api_favorites_create_destroy('json');
2128                 self::assertStatus($result['status']);
2129         }
2130
2131         /**
2132          * Test the api_favorites_create_destroy() function without an authenticated user.
2133          *
2134          * @return void
2135          */
2136         public function testApiFavoritesCreateDestroyWithoutAuthenticatedUser()
2137         {
2138                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2139                 DI::args()->setArgv(['api', '1.1', 'favorites', 'create.json']);
2140                 $_SESSION['authenticated'] = false;
2141                 api_favorites_create_destroy('json');
2142         }
2143
2144         /**
2145          * Test the api_favorites() function.
2146          *
2147          * @return void
2148          */
2149         public function testApiFavorites()
2150         {
2151                 $_REQUEST['page']   = -1;
2152                 $_REQUEST['max_id'] = 10;
2153                 $result             = api_favorites('json');
2154                 foreach ($result['status'] as $status) {
2155                         self::assertStatus($status);
2156                 }
2157         }
2158
2159         /**
2160          * Test the api_favorites() function with an RSS result.
2161          *
2162          * @return void
2163          */
2164         public function testApiFavoritesWithRss()
2165         {
2166                 $result = api_favorites('rss');
2167                 self::assertXml($result, 'statuses');
2168         }
2169
2170         /**
2171          * Test the api_favorites() function with an unallowed user.
2172          *
2173          * @return void
2174          */
2175         public function testApiFavoritesWithUnallowedUser()
2176         {
2177                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2178                 $_SESSION['allow_api'] = false;
2179                 $_GET['screen_name']   = $this->selfUser['nick'];
2180                 api_favorites('json');
2181         }
2182
2183         /**
2184          * Test the api_format_messages() function.
2185          *
2186          * @return void
2187          */
2188         public function testApiFormatMessages()
2189         {
2190                 $result = api_format_messages(
2191                         ['id' => 1, 'uri-id' => 1, 'title' => 'item_title', 'body' => '[b]item_body[/b]'],
2192                         ['id' => 2, 'uri-id' => 2, 'screen_name' => 'recipient_name'],
2193                         ['id' => 3, 'uri-id' => 2, 'screen_name' => 'sender_name']
2194                 );
2195                 self::assertEquals('item_title' . "\n" . 'item_body', $result['text']);
2196                 self::assertEquals(1, $result['id']);
2197                 self::assertEquals(2, $result['recipient_id']);
2198                 self::assertEquals(3, $result['sender_id']);
2199                 self::assertEquals('recipient_name', $result['recipient_screen_name']);
2200                 self::assertEquals('sender_name', $result['sender_screen_name']);
2201         }
2202
2203         /**
2204          * Test the api_format_messages() function with HTML.
2205          *
2206          * @return void
2207          */
2208         public function testApiFormatMessagesWithHtmlText()
2209         {
2210                 $_GET['getText'] = 'html';
2211                 $result          = api_format_messages(
2212                         ['id' => 1, 'uri-id' => 1, 'title' => 'item_title', 'body' => '[b]item_body[/b]'],
2213                         ['id' => 2, 'uri-id' => 2, 'screen_name' => 'recipient_name'],
2214                         ['id' => 3, 'uri-id' => 3, 'screen_name' => 'sender_name']
2215                 );
2216                 self::assertEquals('item_title', $result['title']);
2217                 self::assertEquals('<strong>item_body</strong>', $result['text']);
2218         }
2219
2220         /**
2221          * Test the api_format_messages() function with plain text.
2222          *
2223          * @return void
2224          */
2225         public function testApiFormatMessagesWithPlainText()
2226         {
2227                 $_GET['getText'] = 'plain';
2228                 $result          = api_format_messages(
2229                         ['id' => 1, 'uri-id' => 1, 'title' => 'item_title', 'body' => '[b]item_body[/b]'],
2230                         ['id' => 2, 'uri-id' => 2, 'screen_name' => 'recipient_name'],
2231                         ['id' => 3, 'uri-id' => 3, 'screen_name' => 'sender_name']
2232                 );
2233                 self::assertEquals('item_title', $result['title']);
2234                 self::assertEquals('item_body', $result['text']);
2235         }
2236
2237         /**
2238          * Test the api_format_messages() function with the getUserObjects GET parameter set to false.
2239          *
2240          * @return void
2241          */
2242         public function testApiFormatMessagesWithoutUserObjects()
2243         {
2244                 $_GET['getUserObjects'] = 'false';
2245                 $result                 = api_format_messages(
2246                         ['id' => 1, 'uri-id' => 1, 'title' => 'item_title', 'body' => '[b]item_body[/b]'],
2247                         ['id' => 2, 'uri-id' => 2, 'screen_name' => 'recipient_name'],
2248                         ['id' => 3, 'uri-id' => 3, 'screen_name' => 'sender_name']
2249                 );
2250                 self::assertTrue(!isset($result['sender']));
2251                 self::assertTrue(!isset($result['recipient']));
2252         }
2253
2254         /**
2255          * Test the api_convert_item() function.
2256          *
2257          * @return void
2258          */
2259         public function testApiConvertItem()
2260         {
2261                 $result = api_convert_item(
2262                         [
2263                                 'network' => 'feed',
2264                                 'title'   => 'item_title',
2265                                 'uri-id'  => 1,
2266                                 // We need a long string to test that it is correctly cut
2267                                 'body'    => 'perspiciatis impedit voluptatem quis molestiae ea qui ' .
2268                                              'reiciendis dolorum aut ducimus sunt consequatur inventore dolor ' .
2269                                              'officiis pariatur doloremque nemo culpa aut quidem qui dolore ' .
2270                                              'laudantium atque commodi alias voluptatem non possimus aperiam ' .
2271                                              'ipsum rerum consequuntur aut amet fugit quia aliquid praesentium ' .
2272                                              'repellendus quibusdam et et inventore mollitia rerum sit autem ' .
2273                                              'pariatur maiores ipsum accusantium perferendis vel sit possimus ' .
2274                                              'veritatis nihil distinctio qui eum repellat officia illum quos ' .
2275                                              'impedit quam iste esse unde qui suscipit aut facilis ut inventore ' .
2276                                              'omnis exercitationem quo magnam consequatur maxime aut illum ' .
2277                                              'soluta quaerat natus unde aspernatur et sed beatae nihil ullam ' .
2278                                              'temporibus corporis ratione blanditiis perspiciatis impedit ' .
2279                                              'voluptatem quis molestiae ea qui reiciendis dolorum aut ducimus ' .
2280                                              'sunt consequatur inventore dolor officiis pariatur doloremque ' .
2281                                              'nemo culpa aut quidem qui dolore laudantium atque commodi alias ' .
2282                                              'voluptatem non possimus aperiam ipsum rerum consequuntur aut ' .
2283                                              'amet fugit quia aliquid praesentium repellendus quibusdam et et ' .
2284                                              'inventore mollitia rerum sit autem pariatur maiores ipsum accusantium ' .
2285                                              'perferendis vel sit possimus veritatis nihil distinctio qui eum ' .
2286                                              'repellat officia illum quos impedit quam iste esse unde qui ' .
2287                                              'suscipit aut facilis ut inventore omnis exercitationem quo magnam ' .
2288                                              'consequatur maxime aut illum soluta quaerat natus unde aspernatur ' .
2289                                              'et sed beatae nihil ullam temporibus corporis ratione blanditiis',
2290                                 'plink'   => 'item_plink'
2291                         ]
2292                 );
2293                 self::assertStringStartsWith('item_title', $result['text']);
2294                 self::assertStringStartsWith('<h4>item_title</h4><br>perspiciatis impedit voluptatem', $result['html']);
2295         }
2296
2297         /**
2298          * Test the api_convert_item() function with an empty item body.
2299          *
2300          * @return void
2301          */
2302         public function testApiConvertItemWithoutBody()
2303         {
2304                 $result = api_convert_item(
2305                         [
2306                                 'network' => 'feed',
2307                                 'title'   => 'item_title',
2308                                 'uri-id'  => -1,
2309                                 'body'    => '',
2310                                 'plink'   => 'item_plink'
2311                         ]
2312                 );
2313                 self::assertEquals("item_title", $result['text']);
2314                 self::assertEquals('<h4>item_title</h4><br>item_plink', $result['html']);
2315         }
2316
2317         /**
2318          * Test the api_convert_item() function with the title in the body.
2319          *
2320          * @return void
2321          */
2322         public function testApiConvertItemWithTitleInBody()
2323         {
2324                 $result = api_convert_item(
2325                         [
2326                                 'title'  => 'item_title',
2327                                 'body'   => 'item_title item_body',
2328                                 'uri-id' => 1,
2329                         ]
2330                 );
2331                 self::assertEquals('item_title item_body', $result['text']);
2332                 self::assertEquals('<h4>item_title</h4><br>item_title item_body', $result['html']);
2333         }
2334
2335         /**
2336          * Test the api_get_attachments() function.
2337          *
2338          * @return void
2339          */
2340         public function testApiGetAttachments()
2341         {
2342                 $body = 'body';
2343                 self::assertEmpty(api_get_attachments($body, 0));
2344         }
2345
2346         /**
2347          * Test the api_get_attachments() function with an img tag.
2348          *
2349          * @return void
2350          */
2351         public function testApiGetAttachmentsWithImage()
2352         {
2353                 $body = '[img]http://via.placeholder.com/1x1.png[/img]';
2354                 self::assertIsArray(api_get_attachments($body, 0));
2355         }
2356
2357         /**
2358          * Test the api_get_attachments() function with an img tag and an AndStatus user agent.
2359          *
2360          * @return void
2361          */
2362         public function testApiGetAttachmentsWithImageAndAndStatus()
2363         {
2364                 $_SERVER['HTTP_USER_AGENT'] = 'AndStatus';
2365                 $body                       = '[img]http://via.placeholder.com/1x1.png[/img]';
2366                 self::assertIsArray(api_get_attachments($body, 0));
2367         }
2368
2369         /**
2370          * Test the api_get_entitities() function.
2371          *
2372          * @return void
2373          */
2374         public function testApiGetEntitities()
2375         {
2376                 $text = 'text';
2377                 self::assertIsArray(api_get_entitities($text, 'bbcode', 0));
2378         }
2379
2380         /**
2381          * Test the api_get_entitities() function with the include_entities parameter.
2382          *
2383          * @return void
2384          */
2385         public function testApiGetEntititiesWithIncludeEntities()
2386         {
2387                 $_REQUEST['include_entities'] = 'true';
2388                 $text                         = 'text';
2389                 $result                       = api_get_entitities($text, 'bbcode', 0);
2390                 self::assertIsArray($result['hashtags']);
2391                 self::assertIsArray($result['symbols']);
2392                 self::assertIsArray($result['urls']);
2393                 self::assertIsArray($result['user_mentions']);
2394         }
2395
2396         /**
2397          * Test the api_format_items_embeded_images() function.
2398          *
2399          * @return void
2400          */
2401         public function testApiFormatItemsEmbededImages()
2402         {
2403                 self::assertEquals(
2404                         'text ' . DI::baseUrl() . '/display/item_guid',
2405                         api_format_items_embeded_images(['guid' => 'item_guid'], 'text data:image/foo')
2406                 );
2407         }
2408
2409         /**
2410          * Test the api_contactlink_to_array() function.
2411          *
2412          * @return void
2413          */
2414         public function testApiContactlinkToArray()
2415         {
2416                 self::assertEquals(
2417                         [
2418                                 'name' => 'text',
2419                                 'url'  => '',
2420                         ],
2421                         api_contactlink_to_array('text')
2422                 );
2423         }
2424
2425         /**
2426          * Test the api_contactlink_to_array() function with an URL.
2427          *
2428          * @return void
2429          */
2430         public function testApiContactlinkToArrayWithUrl()
2431         {
2432                 self::assertEquals(
2433                         [
2434                                 'name' => ['link_text'],
2435                                 'url'  => ['url'],
2436                         ],
2437                         api_contactlink_to_array('text <a href="url">link_text</a>')
2438                 );
2439         }
2440
2441         /**
2442          * Test the api_format_items_activities() function.
2443          *
2444          * @return void
2445          */
2446         public function testApiFormatItemsActivities()
2447         {
2448                 $item   = ['uid' => 0, 'uri' => ''];
2449                 $result = api_format_items_activities($item);
2450                 self::assertArrayHasKey('like', $result);
2451                 self::assertArrayHasKey('dislike', $result);
2452                 self::assertArrayHasKey('attendyes', $result);
2453                 self::assertArrayHasKey('attendno', $result);
2454                 self::assertArrayHasKey('attendmaybe', $result);
2455         }
2456
2457         /**
2458          * Test the api_format_items_activities() function with an XML result.
2459          *
2460          * @return void
2461          */
2462         public function testApiFormatItemsActivitiesWithXml()
2463         {
2464                 $item   = ['uid' => 0, 'uri' => ''];
2465                 $result = api_format_items_activities($item, 'xml');
2466                 self::assertArrayHasKey('friendica:like', $result);
2467                 self::assertArrayHasKey('friendica:dislike', $result);
2468                 self::assertArrayHasKey('friendica:attendyes', $result);
2469                 self::assertArrayHasKey('friendica:attendno', $result);
2470                 self::assertArrayHasKey('friendica:attendmaybe', $result);
2471         }
2472
2473         /**
2474          * Test the api_format_items() function.
2475          * @doesNotPerformAssertions
2476          */
2477         public function testApiFormatItems()
2478         {
2479                 $items  = [
2480                         [
2481                                 'item_network'   => 'item_network',
2482                                 'source'         => 'web',
2483                                 'coord'          => '5 7',
2484                                 'body'           => '',
2485                                 'verb'           => '',
2486                                 'author-id'      => 43,
2487                                 'author-network' => Protocol::DFRN,
2488                                 'author-link'    => 'http://localhost/profile/othercontact',
2489                                 'plink'          => '',
2490                         ]
2491                 ];
2492                 $result = api_format_items($items, ['id' => 0], true);
2493                 foreach ($result as $status) {
2494                         self::assertStatus($status);
2495                 }
2496         }
2497
2498         /**
2499          * Test the api_format_items() function with an XML result.
2500          * @doesNotPerformAssertions
2501          */
2502         public function testApiFormatItemsWithXml()
2503         {
2504                 $items  = [
2505                         [
2506                                 'coord'          => '5 7',
2507                                 'body'           => '',
2508                                 'verb'           => '',
2509                                 'author-id'      => 43,
2510                                 'author-network' => Protocol::DFRN,
2511                                 'author-link'    => 'http://localhost/profile/othercontact',
2512                                 'plink'          => '',
2513                         ]
2514                 ];
2515                 $result = api_format_items($items, ['id' => 0], true, 'xml');
2516                 foreach ($result as $status) {
2517                         self::assertStatus($status);
2518                 }
2519         }
2520
2521         /**
2522          * Test the api_format_items() function.
2523          *
2524          * @return void
2525          */
2526         public function testApiAccountRateLimitStatus()
2527         {
2528                 // @todo How to test the new API?
2529                 // $result = api_account_rate_limit_status('json');
2530                 // self::assertEquals(150, $result['hash']['remaining_hits']);
2531                 // self::assertEquals(150, $result['hash']['hourly_limit']);
2532                 // self::assertIsInt($result['hash']['reset_time_in_seconds']);
2533         }
2534
2535         /**
2536          * Test the api_format_items() function with an XML result.
2537          *
2538          * @return void
2539          */
2540         public function testApiAccountRateLimitStatusWithXml()
2541         {
2542                 // @todo How to test the new API?
2543                 // $result = api_account_rate_limit_status('xml');
2544                 // self::assertXml($result, 'hash');
2545         }
2546
2547         /**
2548          * Test the api_help_test() function.
2549          *
2550          * @return void
2551          */
2552         public function testApiHelpTest()
2553         {
2554                 // @todo How to test the new API?
2555                 // $result = \Friendica\Module\Api\Friendica\Help\Test::rawcontent(['extension' => 'json']);
2556                 // self::assertEquals(['ok' => 'ok'], $result);
2557         }
2558
2559         /**
2560          * Test the api_help_test() function with an XML result.
2561          *
2562          * @return void
2563          */
2564         public function testApiHelpTestWithXml()
2565         {
2566                 // @todo How to test the new API?
2567                 // $result = api_help_test('xml');
2568                 // self::assertXml($result, 'ok');
2569         }
2570
2571         /**
2572          * Test the api_lists_list() function.
2573          *
2574          * @return void
2575          */
2576         public function testApiListsList()
2577         {
2578                 $result = api_lists_list('json');
2579                 self::assertEquals(['lists_list' => []], $result);
2580         }
2581
2582         /**
2583          * Test the api_lists_ownerships() function.
2584          *
2585          * @return void
2586          */
2587         public function testApiListsOwnerships()
2588         {
2589                 $result = api_lists_ownerships('json');
2590                 foreach ($result['lists']['lists'] as $list) {
2591                         self::assertList($list);
2592                 }
2593         }
2594
2595         /**
2596          * Test the api_lists_ownerships() function without an authenticated user.
2597          *
2598          * @return void
2599          */
2600         public function testApiListsOwnershipsWithoutAuthenticatedUser()
2601         {
2602                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2603                 $_SESSION['authenticated'] = false;
2604                 api_lists_ownerships('json');
2605         }
2606
2607         /**
2608          * Test the api_lists_statuses() function.
2609          *
2610          * @return void
2611          */
2612         public function testApiListsStatuses()
2613         {
2614                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2615                 api_lists_statuses('json');
2616         }
2617
2618         /**
2619          * Test the api_lists_statuses() function with a list ID.
2620          * @doesNotPerformAssertions
2621          */
2622         public function testApiListsStatusesWithListId()
2623         {
2624                 $_REQUEST['list_id'] = 1;
2625                 $_REQUEST['page']    = -1;
2626                 $_REQUEST['max_id']  = 10;
2627                 $result              = api_lists_statuses('json');
2628                 foreach ($result['status'] as $status) {
2629                         self::assertStatus($status);
2630                 }
2631         }
2632
2633         /**
2634          * Test the api_lists_statuses() function with a list ID and a RSS result.
2635          *
2636          * @return void
2637          */
2638         public function testApiListsStatusesWithListIdAndRss()
2639         {
2640                 $_REQUEST['list_id'] = 1;
2641                 $result              = api_lists_statuses('rss');
2642                 self::assertXml($result, 'statuses');
2643         }
2644
2645         /**
2646          * Test the api_lists_statuses() function with an unallowed user.
2647          *
2648          * @return void
2649          */
2650         public function testApiListsStatusesWithUnallowedUser()
2651         {
2652                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2653                 $_SESSION['allow_api'] = false;
2654                 $_GET['screen_name']   = $this->selfUser['nick'];
2655                 api_lists_statuses('json');
2656         }
2657
2658         /**
2659          * Test the api_statuses_f() function.
2660          *
2661          * @return void
2662          */
2663         public function testApiStatusesFWithFriends()
2664         {
2665                 $_GET['page'] = -1;
2666                 $result       = api_statuses_f('friends');
2667                 self::assertArrayHasKey('user', $result);
2668         }
2669
2670         /**
2671          * Test the api_statuses_f() function.
2672          *
2673          * @return void
2674          */
2675         public function testApiStatusesFWithFollowers()
2676         {
2677                 $result = api_statuses_f('followers');
2678                 self::assertArrayHasKey('user', $result);
2679         }
2680
2681         /**
2682          * Test the api_statuses_f() function.
2683          *
2684          * @return void
2685          */
2686         public function testApiStatusesFWithBlocks()
2687         {
2688                 $result = api_statuses_f('blocks');
2689                 self::assertArrayHasKey('user', $result);
2690         }
2691
2692         /**
2693          * Test the api_statuses_f() function.
2694          *
2695          * @return void
2696          */
2697         public function testApiStatusesFWithIncoming()
2698         {
2699                 $result = api_statuses_f('incoming');
2700                 self::assertArrayHasKey('user', $result);
2701         }
2702
2703         /**
2704          * Test the api_statuses_f() function an undefined cursor GET variable.
2705          *
2706          * @return void
2707          */
2708         public function testApiStatusesFWithUndefinedCursor()
2709         {
2710                 $_GET['cursor'] = 'undefined';
2711                 self::assertFalse(api_statuses_f('friends'));
2712         }
2713
2714         /**
2715          * Test the api_statuses_friends() function.
2716          *
2717          * @return void
2718          */
2719         public function testApiStatusesFriends()
2720         {
2721                 $result = api_statuses_friends('json');
2722                 self::assertArrayHasKey('user', $result);
2723         }
2724
2725         /**
2726          * Test the api_statuses_friends() function an undefined cursor GET variable.
2727          *
2728          * @return void
2729          */
2730         public function testApiStatusesFriendsWithUndefinedCursor()
2731         {
2732                 $_GET['cursor'] = 'undefined';
2733                 self::assertFalse(api_statuses_friends('json'));
2734         }
2735
2736         /**
2737          * Test the api_statuses_followers() function.
2738          *
2739          * @return void
2740          */
2741         public function testApiStatusesFollowers()
2742         {
2743                 $result = api_statuses_followers('json');
2744                 self::assertArrayHasKey('user', $result);
2745         }
2746
2747         /**
2748          * Test the api_statuses_followers() function an undefined cursor GET variable.
2749          *
2750          * @return void
2751          */
2752         public function testApiStatusesFollowersWithUndefinedCursor()
2753         {
2754                 $_GET['cursor'] = 'undefined';
2755                 self::assertFalse(api_statuses_followers('json'));
2756         }
2757
2758         /**
2759          * Test the api_blocks_list() function.
2760          *
2761          * @return void
2762          */
2763         public function testApiBlocksList()
2764         {
2765                 $result = api_blocks_list('json');
2766                 self::assertArrayHasKey('user', $result);
2767         }
2768
2769         /**
2770          * Test the api_blocks_list() function an undefined cursor GET variable.
2771          *
2772          * @return void
2773          */
2774         public function testApiBlocksListWithUndefinedCursor()
2775         {
2776                 $_GET['cursor'] = 'undefined';
2777                 self::assertFalse(api_blocks_list('json'));
2778         }
2779
2780         /**
2781          * Test the api_friendships_incoming() function.
2782          *
2783          * @return void
2784          */
2785         public function testApiFriendshipsIncoming()
2786         {
2787                 $result = api_friendships_incoming('json');
2788                 self::assertArrayHasKey('id', $result);
2789         }
2790
2791         /**
2792          * Test the api_friendships_incoming() function an undefined cursor GET variable.
2793          *
2794          * @return void
2795          */
2796         public function testApiFriendshipsIncomingWithUndefinedCursor()
2797         {
2798                 $_GET['cursor'] = 'undefined';
2799                 self::assertFalse(api_friendships_incoming('json'));
2800         }
2801
2802         /**
2803          * Test the api_statusnet_config() function.
2804          *
2805          * @return void
2806          */
2807         public function testApiStatusnetConfig()
2808         {
2809                 $result = api_statusnet_config('json');
2810                 self::assertEquals('localhost', $result['config']['site']['server']);
2811                 self::assertEquals('default', $result['config']['site']['theme']);
2812                 self::assertEquals(DI::baseUrl() . '/images/friendica-64.png', $result['config']['site']['logo']);
2813                 self::assertTrue($result['config']['site']['fancy']);
2814                 self::assertEquals('en', $result['config']['site']['language']);
2815                 self::assertEquals('UTC', $result['config']['site']['timezone']);
2816                 self::assertEquals(200000, $result['config']['site']['textlimit']);
2817                 self::assertEquals('false', $result['config']['site']['private']);
2818                 self::assertEquals('false', $result['config']['site']['ssl']);
2819                 self::assertEquals(30, $result['config']['site']['shorturllength']);
2820         }
2821
2822         /**
2823          * Test the api_statusnet_version() function.
2824          *
2825          * @return void
2826          */
2827         public function testApiStatusnetVersion()
2828         {
2829                 // @todo How to test the new API?
2830                 // $result = api_statusnet_version('json');
2831                 // self::assertEquals('0.9.7', $result['version']);
2832         }
2833
2834         /**
2835          * Test the api_direct_messages_new() function.
2836          *
2837          * @return void
2838          */
2839         public function testApiDirectMessagesNew()
2840         {
2841                 $result = api_direct_messages_new('json');
2842                 self::assertNull($result);
2843         }
2844
2845         /**
2846          * Test the api_direct_messages_new() function without an authenticated user.
2847          *
2848          * @return void
2849          */
2850         public function testApiDirectMessagesNewWithoutAuthenticatedUser()
2851         {
2852                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2853                 $_SESSION['authenticated'] = false;
2854                 api_direct_messages_new('json');
2855         }
2856
2857         /**
2858          * Test the api_direct_messages_new() function with an user ID.
2859          *
2860          * @return void
2861          */
2862         public function testApiDirectMessagesNewWithUserId()
2863         {
2864                 $_POST['text']    = 'message_text';
2865                 $_POST['user_id'] = $this->otherUser['id'];
2866                 $result           = api_direct_messages_new('json');
2867                 self::assertEquals(['direct_message' => ['error' => -1]], $result);
2868         }
2869
2870         /**
2871          * Test the api_direct_messages_new() function with a screen name.
2872          *
2873          * @return void
2874          */
2875         public function testApiDirectMessagesNewWithScreenName()
2876         {
2877                 $this->app->setLoggedInUserNickname($this->selfUser['nick']);
2878                 $_POST['text']        = 'message_text';
2879                 $_POST['screen_name'] = $this->friendUser['nick'];
2880                 $result               = api_direct_messages_new('json');
2881                 self::assertStringContainsString('message_text', $result['direct_message']['text']);
2882                 self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']);
2883                 self::assertEquals(1, $result['direct_message']['friendica_seen']);
2884         }
2885
2886         /**
2887          * Test the api_direct_messages_new() function with a title.
2888          *
2889          * @return void
2890          */
2891         public function testApiDirectMessagesNewWithTitle()
2892         {
2893                 $this->app->setLoggedInUserNickname($this->selfUser['nick']);
2894                 $_POST['text']        = 'message_text';
2895                 $_POST['screen_name'] = $this->friendUser['nick'];
2896                 $_REQUEST['title']    = 'message_title';
2897                 $result               = api_direct_messages_new('json');
2898                 self::assertStringContainsString('message_text', $result['direct_message']['text']);
2899                 self::assertStringContainsString('message_title', $result['direct_message']['text']);
2900                 self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']);
2901                 self::assertEquals(1, $result['direct_message']['friendica_seen']);
2902         }
2903
2904         /**
2905          * Test the api_direct_messages_new() function with an RSS result.
2906          *
2907          * @return void
2908          */
2909         public function testApiDirectMessagesNewWithRss()
2910         {
2911                 $this->app->setLoggedInUserNickname($this->selfUser['nick']);
2912                 $_POST['text']        = 'message_text';
2913                 $_POST['screen_name'] = $this->friendUser['nick'];
2914                 $result               = api_direct_messages_new('rss');
2915                 self::assertXml($result, 'direct-messages');
2916         }
2917
2918         /**
2919          * Test the api_direct_messages_destroy() function.
2920          *
2921          * @return void
2922          */
2923         public function testApiDirectMessagesDestroy()
2924         {
2925                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2926                 api_direct_messages_destroy('json');
2927         }
2928
2929         /**
2930          * Test the api_direct_messages_destroy() function with the friendica_verbose GET param.
2931          *
2932          * @return void
2933          */
2934         public function testApiDirectMessagesDestroyWithVerbose()
2935         {
2936                 $_GET['friendica_verbose'] = 'true';
2937                 $result                    = api_direct_messages_destroy('json');
2938                 self::assertEquals(
2939                         [
2940                                 '$result' => [
2941                                         'result'  => 'error',
2942                                         'message' => 'message id or parenturi not specified'
2943                                 ]
2944                         ],
2945                         $result
2946                 );
2947         }
2948
2949         /**
2950          * Test the api_direct_messages_destroy() function without an authenticated user.
2951          *
2952          * @return void
2953          */
2954         public function testApiDirectMessagesDestroyWithoutAuthenticatedUser()
2955         {
2956                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2957                 $_SESSION['authenticated'] = false;
2958                 api_direct_messages_destroy('json');
2959         }
2960
2961         /**
2962          * Test the api_direct_messages_destroy() function with a non-zero ID.
2963          *
2964          * @return void
2965          */
2966         public function testApiDirectMessagesDestroyWithId()
2967         {
2968                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2969                 $_REQUEST['id'] = 1;
2970                 api_direct_messages_destroy('json');
2971         }
2972
2973         /**
2974          * Test the api_direct_messages_destroy() with a non-zero ID and the friendica_verbose GET param.
2975          *
2976          * @return void
2977          */
2978         public function testApiDirectMessagesDestroyWithIdAndVerbose()
2979         {
2980                 $_REQUEST['id']                  = 1;
2981                 $_REQUEST['friendica_parenturi'] = 'parent_uri';
2982                 $_GET['friendica_verbose']       = 'true';
2983                 $result                          = api_direct_messages_destroy('json');
2984                 self::assertEquals(
2985                         [
2986                                 '$result' => [
2987                                         'result'  => 'error',
2988                                         'message' => 'message id not in database'
2989                                 ]
2990                         ],
2991                         $result
2992                 );
2993         }
2994
2995         /**
2996          * Test the api_direct_messages_destroy() function with a non-zero ID.
2997          *
2998          * @return void
2999          */
3000         public function testApiDirectMessagesDestroyWithCorrectId()
3001         {
3002                 $this->markTestIncomplete('We need to add a dataset for this.');
3003         }
3004
3005         /**
3006          * Test the api_direct_messages_box() function.
3007          *
3008          * @return void
3009          */
3010         public function testApiDirectMessagesBoxWithSentbox()
3011         {
3012                 $_REQUEST['page']   = -1;
3013                 $_REQUEST['max_id'] = 10;
3014                 $result             = api_direct_messages_box('json', 'sentbox', 'false');
3015                 self::assertArrayHasKey('direct_message', $result);
3016         }
3017
3018         /**
3019          * Test the api_direct_messages_box() function.
3020          *
3021          * @return void
3022          */
3023         public function testApiDirectMessagesBoxWithConversation()
3024         {
3025                 $result = api_direct_messages_box('json', 'conversation', 'false');
3026                 self::assertArrayHasKey('direct_message', $result);
3027         }
3028
3029         /**
3030          * Test the api_direct_messages_box() function.
3031          *
3032          * @return void
3033          */
3034         public function testApiDirectMessagesBoxWithAll()
3035         {
3036                 $result = api_direct_messages_box('json', 'all', 'false');
3037                 self::assertArrayHasKey('direct_message', $result);
3038         }
3039
3040         /**
3041          * Test the api_direct_messages_box() function.
3042          *
3043          * @return void
3044          */
3045         public function testApiDirectMessagesBoxWithInbox()
3046         {
3047                 $result = api_direct_messages_box('json', 'inbox', 'false');
3048                 self::assertArrayHasKey('direct_message', $result);
3049         }
3050
3051         /**
3052          * Test the api_direct_messages_box() function.
3053          *
3054          * @return void
3055          */
3056         public function testApiDirectMessagesBoxWithVerbose()
3057         {
3058                 $result = api_direct_messages_box('json', 'sentbox', 'true');
3059                 self::assertEquals(
3060                         [
3061                                 '$result' => [
3062                                         'result'  => 'error',
3063                                         'message' => 'no mails available'
3064                                 ]
3065                         ],
3066                         $result
3067                 );
3068         }
3069
3070         /**
3071          * Test the api_direct_messages_box() function with a RSS result.
3072          *
3073          * @return void
3074          */
3075         public function testApiDirectMessagesBoxWithRss()
3076         {
3077                 $result = api_direct_messages_box('rss', 'sentbox', 'false');
3078                 self::assertXml($result, 'direct-messages');
3079         }
3080
3081         /**
3082          * Test the api_direct_messages_box() function without an authenticated user.
3083          *
3084          * @return void
3085          */
3086         public function testApiDirectMessagesBoxWithUnallowedUser()
3087         {
3088                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3089                 $_SESSION['allow_api'] = false;
3090                 $_GET['screen_name']   = $this->selfUser['nick'];
3091                 api_direct_messages_box('json', 'sentbox', 'false');
3092         }
3093
3094         /**
3095          * Test the api_direct_messages_sentbox() function.
3096          *
3097          * @return void
3098          */
3099         public function testApiDirectMessagesSentbox()
3100         {
3101                 $result = api_direct_messages_sentbox('json');
3102                 self::assertArrayHasKey('direct_message', $result);
3103         }
3104
3105         /**
3106          * Test the api_direct_messages_inbox() function.
3107          *
3108          * @return void
3109          */
3110         public function testApiDirectMessagesInbox()
3111         {
3112                 $result = api_direct_messages_inbox('json');
3113                 self::assertArrayHasKey('direct_message', $result);
3114         }
3115
3116         /**
3117          * Test the api_direct_messages_all() function.
3118          *
3119          * @return void
3120          */
3121         public function testApiDirectMessagesAll()
3122         {
3123                 $result = api_direct_messages_all('json');
3124                 self::assertArrayHasKey('direct_message', $result);
3125         }
3126
3127         /**
3128          * Test the api_direct_messages_conversation() function.
3129          *
3130          * @return void
3131          */
3132         public function testApiDirectMessagesConversation()
3133         {
3134                 $result = api_direct_messages_conversation('json');
3135                 self::assertArrayHasKey('direct_message', $result);
3136         }
3137
3138         /**
3139          * Test the api_oauth_request_token() function.
3140          *
3141          * @return void
3142          */
3143         public function testApiOauthRequestToken()
3144         {
3145                 $this->markTestIncomplete('exit() kills phpunit as well');
3146         }
3147
3148         /**
3149          * Test the api_oauth_access_token() function.
3150          *
3151          * @return void
3152          */
3153         public function testApiOauthAccessToken()
3154         {
3155                 $this->markTestIncomplete('exit() kills phpunit as well');
3156         }
3157
3158         /**
3159          * Test the api_fr_photoalbum_delete() function.
3160          *
3161          * @return void
3162          */
3163         public function testApiFrPhotoalbumDelete()
3164         {
3165                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3166                 api_fr_photoalbum_delete('json');
3167         }
3168
3169         /**
3170          * Test the api_fr_photoalbum_delete() function with an album name.
3171          *
3172          * @return void
3173          */
3174         public function testApiFrPhotoalbumDeleteWithAlbum()
3175         {
3176                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3177                 $_REQUEST['album'] = 'album_name';
3178                 api_fr_photoalbum_delete('json');
3179         }
3180
3181         /**
3182          * Test the api_fr_photoalbum_delete() function with an album name.
3183          *
3184          * @return void
3185          */
3186         public function testApiFrPhotoalbumDeleteWithValidAlbum()
3187         {
3188                 $this->markTestIncomplete('We need to add a dataset for this.');
3189         }
3190
3191         /**
3192          * Test the api_fr_photoalbum_delete() function.
3193          *
3194          * @return void
3195          */
3196         public function testApiFrPhotoalbumUpdate()
3197         {
3198                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3199                 api_fr_photoalbum_update('json');
3200         }
3201
3202         /**
3203          * Test the api_fr_photoalbum_delete() function with an album name.
3204          *
3205          * @return void
3206          */
3207         public function testApiFrPhotoalbumUpdateWithAlbum()
3208         {
3209                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3210                 $_REQUEST['album'] = 'album_name';
3211                 api_fr_photoalbum_update('json');
3212         }
3213
3214         /**
3215          * Test the api_fr_photoalbum_delete() function with an album name.
3216          *
3217          * @return void
3218          */
3219         public function testApiFrPhotoalbumUpdateWithAlbumAndNewAlbum()
3220         {
3221                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3222                 $_REQUEST['album']     = 'album_name';
3223                 $_REQUEST['album_new'] = 'album_name';
3224                 api_fr_photoalbum_update('json');
3225         }
3226
3227         /**
3228          * Test the api_fr_photoalbum_update() function without an authenticated user.
3229          *
3230          * @return void
3231          */
3232         public function testApiFrPhotoalbumUpdateWithoutAuthenticatedUser()
3233         {
3234                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3235                 $_SESSION['authenticated'] = false;
3236                 api_fr_photoalbum_update('json');
3237         }
3238
3239         /**
3240          * Test the api_fr_photoalbum_delete() function with an album name.
3241          *
3242          * @return void
3243          */
3244         public function testApiFrPhotoalbumUpdateWithValidAlbum()
3245         {
3246                 $this->markTestIncomplete('We need to add a dataset for this.');
3247         }
3248
3249         /**
3250          * Test the api_fr_photos_list() function.
3251          *
3252          * @return void
3253          */
3254         public function testApiFrPhotosList()
3255         {
3256                 $result = api_fr_photos_list('json');
3257                 self::assertArrayHasKey('photo', $result);
3258         }
3259
3260         /**
3261          * Test the api_fr_photos_list() function without an authenticated user.
3262          *
3263          * @return void
3264          */
3265         public function testApiFrPhotosListWithoutAuthenticatedUser()
3266         {
3267                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3268                 $_SESSION['authenticated'] = false;
3269                 api_fr_photos_list('json');
3270         }
3271
3272         /**
3273          * Test the api_fr_photo_create_update() function.
3274          */
3275         public function testApiFrPhotoCreateUpdate()
3276         {
3277                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3278                 api_fr_photo_create_update('json');
3279         }
3280
3281         /**
3282          * Test the api_fr_photo_create_update() function without an authenticated user.
3283          *
3284          * @return void
3285          */
3286         public function testApiFrPhotoCreateUpdateWithoutAuthenticatedUser()
3287         {
3288                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3289                 $_SESSION['authenticated'] = false;
3290                 api_fr_photo_create_update('json');
3291         }
3292
3293         /**
3294          * Test the api_fr_photo_create_update() function with an album name.
3295          *
3296          * @return void
3297          */
3298         public function testApiFrPhotoCreateUpdateWithAlbum()
3299         {
3300                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3301                 $_REQUEST['album'] = 'album_name';
3302                 api_fr_photo_create_update('json');
3303         }
3304
3305         /**
3306          * Test the api_fr_photo_create_update() function with the update mode.
3307          *
3308          * @return void
3309          */
3310         public function testApiFrPhotoCreateUpdateWithUpdate()
3311         {
3312                 $this->markTestIncomplete('We need to create a dataset for this');
3313         }
3314
3315         /**
3316          * Test the api_fr_photo_create_update() function with an uploaded file.
3317          *
3318          * @return void
3319          */
3320         public function testApiFrPhotoCreateUpdateWithFile()
3321         {
3322                 $this->markTestIncomplete();
3323         }
3324
3325         /**
3326          * Test the api_fr_photo_delete() function.
3327          *
3328          * @return void
3329          */
3330         public function testApiFrPhotoDelete()
3331         {
3332                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3333                 api_fr_photo_delete('json');
3334         }
3335
3336         /**
3337          * Test the api_fr_photo_delete() function without an authenticated user.
3338          *
3339          * @return void
3340          */
3341         public function testApiFrPhotoDeleteWithoutAuthenticatedUser()
3342         {
3343                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3344                 $_SESSION['authenticated'] = false;
3345                 api_fr_photo_delete('json');
3346         }
3347
3348         /**
3349          * Test the api_fr_photo_delete() function with a photo ID.
3350          *
3351          * @return void
3352          */
3353         public function testApiFrPhotoDeleteWithPhotoId()
3354         {
3355                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3356                 $_REQUEST['photo_id'] = 1;
3357                 api_fr_photo_delete('json');
3358         }
3359
3360         /**
3361          * Test the api_fr_photo_delete() function with a correct photo ID.
3362          *
3363          * @return void
3364          */
3365         public function testApiFrPhotoDeleteWithCorrectPhotoId()
3366         {
3367                 $this->markTestIncomplete('We need to create a dataset for this.');
3368         }
3369
3370         /**
3371          * Test the api_fr_photo_detail() function.
3372          *
3373          * @return void
3374          */
3375         public function testApiFrPhotoDetail()
3376         {
3377                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3378                 api_fr_photo_detail('json');
3379         }
3380
3381         /**
3382          * Test the api_fr_photo_detail() function without an authenticated user.
3383          *
3384          * @return void
3385          */
3386         public function testApiFrPhotoDetailWithoutAuthenticatedUser()
3387         {
3388                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3389                 $_SESSION['authenticated'] = false;
3390                 api_fr_photo_detail('json');
3391         }
3392
3393         /**
3394          * Test the api_fr_photo_detail() function with a photo ID.
3395          *
3396          * @return void
3397          */
3398         public function testApiFrPhotoDetailWithPhotoId()
3399         {
3400                 $this->expectException(\Friendica\Network\HTTPException\NotFoundException::class);
3401                 $_REQUEST['photo_id'] = 1;
3402                 api_fr_photo_detail('json');
3403         }
3404
3405         /**
3406          * Test the api_fr_photo_detail() function with a correct photo ID.
3407          *
3408          * @return void
3409          */
3410         public function testApiFrPhotoDetailCorrectPhotoId()
3411         {
3412                 $this->markTestIncomplete('We need to create a dataset for this.');
3413         }
3414
3415         /**
3416          * Test the api_account_update_profile_image() function.
3417          *
3418          * @return void
3419          */
3420         public function testApiAccountUpdateProfileImage()
3421         {
3422                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3423                 api_account_update_profile_image('json');
3424         }
3425
3426         /**
3427          * Test the api_account_update_profile_image() function without an authenticated user.
3428          *
3429          * @return void
3430          */
3431         public function testApiAccountUpdateProfileImageWithoutAuthenticatedUser()
3432         {
3433                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3434                 $_SESSION['authenticated'] = false;
3435                 api_account_update_profile_image('json');
3436         }
3437
3438         /**
3439          * Test the api_account_update_profile_image() function with an uploaded file.
3440          *
3441          * @return void
3442          */
3443         public function testApiAccountUpdateProfileImageWithUpload()
3444         {
3445                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3446                 $this->markTestIncomplete();
3447         }
3448
3449
3450         /**
3451          * Test the api_account_update_profile() function.
3452          *
3453          * @return void
3454          */
3455         public function testApiAccountUpdateProfile()
3456         {
3457                 $_POST['name']        = 'new_name';
3458                 $_POST['description'] = 'new_description';
3459                 $result               = api_account_update_profile('json');
3460                 // We can't use assertSelfUser() here because the user object is missing some properties.
3461                 self::assertEquals($this->selfUser['id'], $result['user']['cid']);
3462                 self::assertEquals('DFRN', $result['user']['location']);
3463                 self::assertEquals($this->selfUser['nick'], $result['user']['screen_name']);
3464                 self::assertEquals('dfrn', $result['user']['network']);
3465                 self::assertEquals('new_name', $result['user']['name']);
3466                 self::assertEquals('new_description', $result['user']['description']);
3467         }
3468
3469         /**
3470          * Test the check_acl_input() function.
3471          *
3472          * @return void
3473          */
3474         public function testCheckAclInput()
3475         {
3476                 $result = check_acl_input('<aclstring>');
3477                 // Where does this result come from?
3478                 self::assertEquals(1, $result);
3479         }
3480
3481         /**
3482          * Test the check_acl_input() function with an empty ACL string.
3483          *
3484          * @return void
3485          */
3486         public function testCheckAclInputWithEmptyAclString()
3487         {
3488                 $result = check_acl_input(' ');
3489                 self::assertFalse($result);
3490         }
3491
3492         /**
3493          * Test the save_media_to_database() function.
3494          *
3495          * @return void
3496          */
3497         public function testSaveMediaToDatabase()
3498         {
3499                 $this->markTestIncomplete();
3500         }
3501
3502         /**
3503          * Test the post_photo_item() function.
3504          *
3505          * @return void
3506          */
3507         public function testPostPhotoItem()
3508         {
3509                 $this->markTestIncomplete();
3510         }
3511
3512         /**
3513          * Test the prepare_photo_data() function.
3514          *
3515          * @return void
3516          */
3517         public function testPreparePhotoData()
3518         {
3519                 $this->markTestIncomplete();
3520         }
3521
3522         /**
3523          * Test the api_share_as_retweet() function with a valid item.
3524          *
3525          * @return void
3526          */
3527         public function testApiShareAsRetweetWithValidItem()
3528         {
3529                 $this->markTestIncomplete();
3530         }
3531
3532         /**
3533          * Test the api_in_reply_to() function.
3534          *
3535          * @return void
3536          */
3537         public function testApiInReplyTo()
3538         {
3539                 $result = api_in_reply_to(['id' => 0, 'parent' => 0, 'uri' => '', 'thr-parent' => '']);
3540                 self::assertArrayHasKey('status_id', $result);
3541                 self::assertArrayHasKey('user_id', $result);
3542                 self::assertArrayHasKey('status_id_str', $result);
3543                 self::assertArrayHasKey('user_id_str', $result);
3544                 self::assertArrayHasKey('screen_name', $result);
3545         }
3546
3547         /**
3548          * Test the api_in_reply_to() function with a valid item.
3549          *
3550          * @return void
3551          */
3552         public function testApiInReplyToWithValidItem()
3553         {
3554                 $this->markTestIncomplete();
3555         }
3556
3557         /**
3558          * Test the api_clean_plain_items() function.
3559          *
3560          * @return void
3561          */
3562         public function testApiCleanPlainItems()
3563         {
3564                 $_REQUEST['include_entities'] = 'true';
3565                 $result                       = api_clean_plain_items('some_text [url="some_url"]some_text[/url]');
3566                 self::assertEquals('some_text [url="some_url"]"some_url"[/url]', $result);
3567         }
3568
3569         /**
3570          * Test the api_best_nickname() function.
3571          *
3572          * @return void
3573          */
3574         public function testApiBestNickname()
3575         {
3576                 $contacts = [];
3577                 $result   = api_best_nickname($contacts);
3578                 self::assertNull($result);
3579         }
3580
3581         /**
3582          * Test the api_best_nickname() function with contacts.
3583          *
3584          * @return void
3585          */
3586         public function testApiBestNicknameWithContacts()
3587         {
3588                 $this->markTestIncomplete();
3589         }
3590
3591         /**
3592          * Test the api_friendica_group_show() function.
3593          *
3594          * @return void
3595          */
3596         public function testApiFriendicaGroupShow()
3597         {
3598                 $this->markTestIncomplete();
3599         }
3600
3601         /**
3602          * Test the api_friendica_group_delete() function.
3603          *
3604          * @return void
3605          */
3606         public function testApiFriendicaGroupDelete()
3607         {
3608                 $this->markTestIncomplete();
3609         }
3610
3611         /**
3612          * Test the api_lists_destroy() function.
3613          *
3614          * @return void
3615          */
3616         public function testApiListsDestroy()
3617         {
3618                 $this->markTestIncomplete();
3619         }
3620
3621         /**
3622          * Test the group_create() function.
3623          *
3624          * @return void
3625          */
3626         public function testGroupCreate()
3627         {
3628                 $this->markTestIncomplete();
3629         }
3630
3631         /**
3632          * Test the api_friendica_group_create() function.
3633          *
3634          * @return void
3635          */
3636         public function testApiFriendicaGroupCreate()
3637         {
3638                 $this->markTestIncomplete();
3639         }
3640
3641         /**
3642          * Test the api_lists_create() function.
3643          *
3644          * @return void
3645          */
3646         public function testApiListsCreate()
3647         {
3648                 $this->markTestIncomplete();
3649         }
3650
3651         /**
3652          * Test the api_friendica_group_update() function.
3653          *
3654          * @return void
3655          */
3656         public function testApiFriendicaGroupUpdate()
3657         {
3658                 $this->markTestIncomplete();
3659         }
3660
3661         /**
3662          * Test the api_lists_update() function.
3663          *
3664          * @return void
3665          */
3666         public function testApiListsUpdate()
3667         {
3668                 $this->markTestIncomplete();
3669         }
3670
3671         /**
3672          * Test the api_friendica_activity() function.
3673          *
3674          * @return void
3675          */
3676         public function testApiFriendicaActivity()
3677         {
3678                 $this->markTestIncomplete();
3679         }
3680
3681         /**
3682          * Test the api_friendica_notification() function.
3683          *
3684          * @return void
3685          */
3686         public function testApiFriendicaNotification()
3687         {
3688                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3689                 api_friendica_notification('json');
3690         }
3691
3692         /**
3693          * Test the api_friendica_notification() function without an authenticated user.
3694          *
3695          * @return void
3696          */
3697         public function testApiFriendicaNotificationWithoutAuthenticatedUser()
3698         {
3699                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3700                 $_SESSION['authenticated'] = false;
3701                 api_friendica_notification('json');
3702         }
3703
3704         /**
3705          * Test the api_friendica_notification() function with empty result
3706          *
3707          * @return void
3708          */
3709         public function testApiFriendicaNotificationWithEmptyResult()
3710         {
3711                 DI::args()->setArgv(['api', 'friendica', 'notification']);
3712                 $_SESSION['uid'] = 41;
3713                 $result          = api_friendica_notification('json');
3714                 self::assertEquals(['note' => false], $result);
3715         }
3716
3717         /**
3718          * Test the api_friendica_notification() function with an XML result.
3719          *
3720          * @return void
3721          */
3722         public function testApiFriendicaNotificationWithXmlResult()
3723         {
3724                 DI::args()->setArgv(['api', 'friendica', 'notification']);
3725                 $result  = api_friendica_notification('xml');
3726                 $date = DateTimeFormat::local('2020-01-01 12:12:02');
3727                 $dateRel = Temporal::getRelativeDate('2020-01-01 07:12:02');
3728
3729                 $assertXml=<<<XML
3730 <?xml version="1.0"?>
3731 <notes>
3732   <note date="$date" date_rel="$dateRel" id="1" iid="4" link="http://localhost/notification/1" msg="A test reply from an item" msg_cache="A test reply from an item" msg_html="A test reply from an item" msg_plain="A test reply from an item" name="Reply to" name_cache="Reply to" otype="item" parent="" photo="http://localhost/" seen="false" timestamp="1577880722" type="8" uid="42" url="http://localhost/display/1" verb="http://activitystrea.ms/schema/1.0/post"/>
3733 </notes>
3734 XML;
3735                 self::assertXmlStringEqualsXmlString($assertXml, $result);
3736         }
3737
3738         /**
3739          * Test the api_friendica_notification() function with an JSON result.
3740          *
3741          * @return void
3742          */
3743         public function testApiFriendicaNotificationWithJsonResult()
3744         {
3745                 DI::args()->setArgv(['api', 'friendica', 'notification']);
3746                 $result = json_encode(api_friendica_notification('json'));
3747                 self::assertJson($result);
3748         }
3749
3750         /**
3751          * Test the api_friendica_notification_seen() function.
3752          *
3753          * @return void
3754          */
3755         public function testApiFriendicaNotificationSeen()
3756         {
3757                 $this->markTestIncomplete();
3758         }
3759
3760         /**
3761          * Test the api_friendica_direct_messages_setseen() function.
3762          *
3763          * @return void
3764          */
3765         public function testApiFriendicaDirectMessagesSetseen()
3766         {
3767                 $this->markTestIncomplete();
3768         }
3769
3770         /**
3771          * Test the api_friendica_direct_messages_search() function.
3772          *
3773          * @return void
3774          */
3775         public function testApiFriendicaDirectMessagesSearch()
3776         {
3777                 $this->markTestIncomplete();
3778         }
3779
3780         /**
3781          * Test the api_saved_searches_list() function.
3782          *
3783          * @return void
3784          */
3785         public function testApiSavedSearchesList()
3786         {
3787                 $result = api_saved_searches_list('json');
3788                 self::assertEquals(1, $result['terms'][0]['id']);
3789                 self::assertEquals(1, $result['terms'][0]['id_str']);
3790                 self::assertEquals('Saved search', $result['terms'][0]['name']);
3791                 self::assertEquals('Saved search', $result['terms'][0]['query']);
3792         }
3793 }