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