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