]> git.mxchange.org Git - friendica.git/blob - tests/legacy/ApiTest.php
Merge remote-tracking branch 'upstream/develop' into error-handling
[friendica.git] / tests / legacy / ApiTest.php
1 <?php
2 /**
3  * ApiTest class.
4  */
5
6 namespace Friendica\Test\legacy;
7
8 use Friendica\App;
9 use Friendica\Core\Config\Capability\IManageConfigValues;
10 use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
11 use Friendica\Core\Protocol;
12 use Friendica\DI;
13 use Friendica\Network\HTTPException;
14 use Friendica\Test\FixtureTest;
15 use Friendica\Util\DateTimeFormat;
16 use Friendica\Util\Temporal;
17 use Monolog\Handler\TestHandler;
18
19 require_once __DIR__ . '/../../include/api.php';
20
21 /**
22  * Tests for the API functions.
23  *
24  * Functions that use header() need to be tested in a separate process.
25  * @see https://phpunit.de/manual/5.7/en/appendixes.annotations.html#appendixes.annotations.runTestsInSeparateProcesses
26  *
27  * @backupGlobals enabled
28  */
29 class ApiTest extends FixtureTest
30 {
31         /**
32          * @var TestHandler Can handle log-outputs
33          */
34         protected $logOutput;
35
36         /** @var array */
37         protected $selfUser;
38         /** @var array */
39         protected $friendUser;
40         /** @var array */
41         protected $otherUser;
42
43         protected $wrongUserId;
44
45         /** @var App */
46         protected $app;
47
48         /** @var IManageConfigValues */
49         protected $config;
50
51         /**
52          * Create variables used by tests.
53          */
54         protected function setUp() : void
55         {
56                 global $API, $called_api;
57                 $API = [];
58                 $called_api = [];
59
60                 parent::setUp();
61
62                 /** @var IManageConfigValues $config */
63                 $this->config = $this->dice->create(IManageConfigValues::class);
64
65                 $this->config->set('system', 'url', 'http://localhost');
66                 $this->config->set('system', 'hostname', 'localhost');
67                 $this->config->set('system', 'worker_dont_fork', true);
68
69                 // Default config
70                 $this->config->set('config', 'hostname', 'localhost');
71                 $this->config->set('system', 'throttle_limit_day', 100);
72                 $this->config->set('system', 'throttle_limit_week', 100);
73                 $this->config->set('system', 'throttle_limit_month', 100);
74                 $this->config->set('system', 'theme', 'system_theme');
75
76
77                 /** @var App app */
78                 $this->app = DI::app();
79
80                 DI::args()->setArgc(1);
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::assertIsString($status['text'] ?? '');
161                 self::assertIsInt($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::assertIsString($list['name']);
175                 self::assertIsInt($list['id']);
176                 self::assertIsString('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::assertStringContainsString('<' . $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::assertIsArray($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(IManagePersonalConfigValues::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(IManagePersonalConfigValues::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(IManagePersonalConfigValues::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                 DI::args()->setArgv(['', $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                 DI::args()->setArgc(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                 DI::args()->setArgc(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::assertStringContainsStringIgnoringCase('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::assertStringContainsStringIgnoringCase('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::assertStringContainsStringIgnoringCase('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::assertStringContainsStringIgnoringCase('#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                 DI::args()->setArgv(['', '', '', 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                 DI::args()->setArgv(['', '', '', 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                 DI::args()->setArgv(['', '', '', 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                 DI::args()->setArgv(['', '', '', 1]);
1902                 $result = api_statuses_repeat('json');
1903                 self::assertStatus($result['status']);
1904
1905                 // Also test with a shared status
1906                 DI::args()->setArgv(['', '', '', 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                 DI::args()->setArgv(['', '', '', 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->setLoggedInUserNickname($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                 DI::args()->setArgv(['api', '1.1', 'favorites', 'create']);
2061                 api_favorites_create_destroy('json');
2062         }
2063
2064         /**
2065          * Test the api_favorites_create_destroy() function with an invalid ID.
2066          *
2067          * @return void
2068          */
2069         public function testApiFavoritesCreateDestroyWithInvalidId()
2070         {
2071                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2072                 DI::args()->setArgv(['api', '1.1', 'favorites', 'create', '12.json']);
2073                 api_favorites_create_destroy('json');
2074         }
2075
2076         /**
2077          * Test the api_favorites_create_destroy() function with an invalid action.
2078          *
2079          * @return void
2080          */
2081         public function testApiFavoritesCreateDestroyWithInvalidAction()
2082         {
2083                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2084                 DI::args()->setArgv(['api', '1.1', 'favorites', 'change.json']);
2085                 $_REQUEST['id'] = 1;
2086                 api_favorites_create_destroy('json');
2087         }
2088
2089         /**
2090          * Test the api_favorites_create_destroy() function with the create action.
2091          *
2092          * @return void
2093          */
2094         public function testApiFavoritesCreateDestroyWithCreateAction()
2095         {
2096                 DI::args()->setArgv(['api', '1.1', 'favorites', 'create.json']);
2097                 $_REQUEST['id'] = 3;
2098                 $result         = api_favorites_create_destroy('json');
2099                 self::assertStatus($result['status']);
2100         }
2101
2102         /**
2103          * Test the api_favorites_create_destroy() function with the create action and an RSS result.
2104          *
2105          * @return void
2106          */
2107         public function testApiFavoritesCreateDestroyWithCreateActionAndRss()
2108         {
2109                 DI::args()->setArgv(['api', '1.1', 'favorites', 'create.rss']);
2110                 $_REQUEST['id'] = 3;
2111                 $result         = api_favorites_create_destroy('rss');
2112                 self::assertXml($result, 'status');
2113         }
2114
2115         /**
2116          * Test the api_favorites_create_destroy() function with the destroy action.
2117          *
2118          * @return void
2119          */
2120         public function testApiFavoritesCreateDestroyWithDestroyAction()
2121         {
2122                 DI::args()->setArgv(['api', '1.1', 'favorites', 'destroy.json']);
2123                 $_REQUEST['id'] = 3;
2124                 $result         = api_favorites_create_destroy('json');
2125                 self::assertStatus($result['status']);
2126         }
2127
2128         /**
2129          * Test the api_favorites_create_destroy() function without an authenticated user.
2130          *
2131          * @return void
2132          */
2133         public function testApiFavoritesCreateDestroyWithoutAuthenticatedUser()
2134         {
2135                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2136                 DI::args()->setArgv(['api', '1.1', 'favorites', 'create.json']);
2137                 $_SESSION['authenticated'] = false;
2138                 api_favorites_create_destroy('json');
2139         }
2140
2141         /**
2142          * Test the api_favorites() function.
2143          *
2144          * @return void
2145          */
2146         public function testApiFavorites()
2147         {
2148                 $_REQUEST['page']   = -1;
2149                 $_REQUEST['max_id'] = 10;
2150                 $result             = api_favorites('json');
2151                 foreach ($result['status'] as $status) {
2152                         self::assertStatus($status);
2153                 }
2154         }
2155
2156         /**
2157          * Test the api_favorites() function with an RSS result.
2158          *
2159          * @return void
2160          */
2161         public function testApiFavoritesWithRss()
2162         {
2163                 $result = api_favorites('rss');
2164                 self::assertXml($result, 'statuses');
2165         }
2166
2167         /**
2168          * Test the api_favorites() function with an unallowed user.
2169          *
2170          * @return void
2171          */
2172         public function testApiFavoritesWithUnallowedUser()
2173         {
2174                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2175                 $_SESSION['allow_api'] = false;
2176                 $_GET['screen_name']   = $this->selfUser['nick'];
2177                 api_favorites('json');
2178         }
2179
2180         /**
2181          * Test the api_format_messages() function.
2182          *
2183          * @return void
2184          */
2185         public function testApiFormatMessages()
2186         {
2187                 $result = api_format_messages(
2188                         ['id' => 1, 'uri-id' => 1, 'title' => 'item_title', 'body' => '[b]item_body[/b]'],
2189                         ['id' => 2, 'uri-id' => 2, 'screen_name' => 'recipient_name'],
2190                         ['id' => 3, 'uri-id' => 2, 'screen_name' => 'sender_name']
2191                 );
2192                 self::assertEquals('item_title' . "\n" . 'item_body', $result['text']);
2193                 self::assertEquals(1, $result['id']);
2194                 self::assertEquals(2, $result['recipient_id']);
2195                 self::assertEquals(3, $result['sender_id']);
2196                 self::assertEquals('recipient_name', $result['recipient_screen_name']);
2197                 self::assertEquals('sender_name', $result['sender_screen_name']);
2198         }
2199
2200         /**
2201          * Test the api_format_messages() function with HTML.
2202          *
2203          * @return void
2204          */
2205         public function testApiFormatMessagesWithHtmlText()
2206         {
2207                 $_GET['getText'] = 'html';
2208                 $result          = api_format_messages(
2209                         ['id' => 1, 'uri-id' => 1, 'title' => 'item_title', 'body' => '[b]item_body[/b]'],
2210                         ['id' => 2, 'uri-id' => 2, 'screen_name' => 'recipient_name'],
2211                         ['id' => 3, 'uri-id' => 3, 'screen_name' => 'sender_name']
2212                 );
2213                 self::assertEquals('item_title', $result['title']);
2214                 self::assertEquals('<strong>item_body</strong>', $result['text']);
2215         }
2216
2217         /**
2218          * Test the api_format_messages() function with plain text.
2219          *
2220          * @return void
2221          */
2222         public function testApiFormatMessagesWithPlainText()
2223         {
2224                 $_GET['getText'] = 'plain';
2225                 $result          = api_format_messages(
2226                         ['id' => 1, 'uri-id' => 1, 'title' => 'item_title', 'body' => '[b]item_body[/b]'],
2227                         ['id' => 2, 'uri-id' => 2, 'screen_name' => 'recipient_name'],
2228                         ['id' => 3, 'uri-id' => 3, 'screen_name' => 'sender_name']
2229                 );
2230                 self::assertEquals('item_title', $result['title']);
2231                 self::assertEquals('item_body', $result['text']);
2232         }
2233
2234         /**
2235          * Test the api_format_messages() function with the getUserObjects GET parameter set to false.
2236          *
2237          * @return void
2238          */
2239         public function testApiFormatMessagesWithoutUserObjects()
2240         {
2241                 $_GET['getUserObjects'] = 'false';
2242                 $result                 = api_format_messages(
2243                         ['id' => 1, 'uri-id' => 1, 'title' => 'item_title', 'body' => '[b]item_body[/b]'],
2244                         ['id' => 2, 'uri-id' => 2, 'screen_name' => 'recipient_name'],
2245                         ['id' => 3, 'uri-id' => 3, 'screen_name' => 'sender_name']
2246                 );
2247                 self::assertTrue(!isset($result['sender']));
2248                 self::assertTrue(!isset($result['recipient']));
2249         }
2250
2251         /**
2252          * Test the api_convert_item() function.
2253          *
2254          * @return void
2255          */
2256         public function testApiConvertItem()
2257         {
2258                 $result = api_convert_item(
2259                         [
2260                                 'network' => 'feed',
2261                                 'title'   => 'item_title',
2262                                 'uri-id'  => 1,
2263                                 // We need a long string to test that it is correctly cut
2264                                 'body'    => 'perspiciatis impedit voluptatem quis molestiae ea qui ' .
2265                                              'reiciendis dolorum aut ducimus sunt consequatur inventore dolor ' .
2266                                              'officiis pariatur doloremque nemo culpa aut quidem qui dolore ' .
2267                                              'laudantium atque commodi alias voluptatem non possimus aperiam ' .
2268                                              'ipsum rerum consequuntur aut amet fugit quia aliquid praesentium ' .
2269                                              'repellendus quibusdam et et inventore mollitia rerum sit autem ' .
2270                                              'pariatur maiores ipsum accusantium perferendis vel sit possimus ' .
2271                                              'veritatis nihil distinctio qui eum repellat officia illum quos ' .
2272                                              'impedit quam iste esse unde qui suscipit aut facilis ut inventore ' .
2273                                              'omnis exercitationem quo magnam consequatur maxime aut illum ' .
2274                                              'soluta quaerat natus unde aspernatur et sed beatae nihil ullam ' .
2275                                              'temporibus corporis ratione blanditiis perspiciatis impedit ' .
2276                                              'voluptatem quis molestiae ea qui reiciendis dolorum aut ducimus ' .
2277                                              'sunt consequatur inventore dolor officiis pariatur doloremque ' .
2278                                              'nemo culpa aut quidem qui dolore laudantium atque commodi alias ' .
2279                                              'voluptatem non possimus aperiam ipsum rerum consequuntur aut ' .
2280                                              'amet fugit quia aliquid praesentium repellendus quibusdam et et ' .
2281                                              'inventore mollitia rerum sit autem pariatur maiores ipsum accusantium ' .
2282                                              'perferendis vel sit possimus veritatis nihil distinctio qui eum ' .
2283                                              'repellat officia illum quos impedit quam iste esse unde qui ' .
2284                                              'suscipit aut facilis ut inventore omnis exercitationem quo magnam ' .
2285                                              'consequatur maxime aut illum soluta quaerat natus unde aspernatur ' .
2286                                              'et sed beatae nihil ullam temporibus corporis ratione blanditiis',
2287                                 'plink'   => 'item_plink'
2288                         ]
2289                 );
2290                 self::assertStringStartsWith('item_title', $result['text']);
2291                 self::assertStringStartsWith('<h4>item_title</h4><br>perspiciatis impedit voluptatem', $result['html']);
2292         }
2293
2294         /**
2295          * Test the api_convert_item() function with an empty item body.
2296          *
2297          * @return void
2298          */
2299         public function testApiConvertItemWithoutBody()
2300         {
2301                 $result = api_convert_item(
2302                         [
2303                                 'network' => 'feed',
2304                                 'title'   => 'item_title',
2305                                 'uri-id'  => -1,
2306                                 'body'    => '',
2307                                 'plink'   => 'item_plink'
2308                         ]
2309                 );
2310                 self::assertEquals("item_title", $result['text']);
2311                 self::assertEquals('<h4>item_title</h4><br>item_plink', $result['html']);
2312         }
2313
2314         /**
2315          * Test the api_convert_item() function with the title in the body.
2316          *
2317          * @return void
2318          */
2319         public function testApiConvertItemWithTitleInBody()
2320         {
2321                 $result = api_convert_item(
2322                         [
2323                                 'title'  => 'item_title',
2324                                 'body'   => 'item_title item_body',
2325                                 'uri-id' => 1,
2326                         ]
2327                 );
2328                 self::assertEquals('item_title item_body', $result['text']);
2329                 self::assertEquals('<h4>item_title</h4><br>item_title item_body', $result['html']);
2330         }
2331
2332         /**
2333          * Test the api_get_attachments() function.
2334          *
2335          * @return void
2336          */
2337         public function testApiGetAttachments()
2338         {
2339                 $body = 'body';
2340                 self::assertEmpty(api_get_attachments($body, 0));
2341         }
2342
2343         /**
2344          * Test the api_get_attachments() function with an img tag.
2345          *
2346          * @return void
2347          */
2348         public function testApiGetAttachmentsWithImage()
2349         {
2350                 $body = '[img]http://via.placeholder.com/1x1.png[/img]';
2351                 self::assertIsArray(api_get_attachments($body, 0));
2352         }
2353
2354         /**
2355          * Test the api_get_attachments() function with an img tag and an AndStatus user agent.
2356          *
2357          * @return void
2358          */
2359         public function testApiGetAttachmentsWithImageAndAndStatus()
2360         {
2361                 $_SERVER['HTTP_USER_AGENT'] = 'AndStatus';
2362                 $body                       = '[img]http://via.placeholder.com/1x1.png[/img]';
2363                 self::assertIsArray(api_get_attachments($body, 0));
2364         }
2365
2366         /**
2367          * Test the api_get_entitities() function.
2368          *
2369          * @return void
2370          */
2371         public function testApiGetEntitities()
2372         {
2373                 $text = 'text';
2374                 self::assertIsArray(api_get_entitities($text, 'bbcode', 0));
2375         }
2376
2377         /**
2378          * Test the api_get_entitities() function with the include_entities parameter.
2379          *
2380          * @return void
2381          */
2382         public function testApiGetEntititiesWithIncludeEntities()
2383         {
2384                 $_REQUEST['include_entities'] = 'true';
2385                 $text                         = 'text';
2386                 $result                       = api_get_entitities($text, 'bbcode', 0);
2387                 self::assertIsArray($result['hashtags']);
2388                 self::assertIsArray($result['symbols']);
2389                 self::assertIsArray($result['urls']);
2390                 self::assertIsArray($result['user_mentions']);
2391         }
2392
2393         /**
2394          * Test the api_format_items_embeded_images() function.
2395          *
2396          * @return void
2397          */
2398         public function testApiFormatItemsEmbededImages()
2399         {
2400                 self::assertEquals(
2401                         'text ' . DI::baseUrl() . '/display/item_guid',
2402                         api_format_items_embeded_images(['guid' => 'item_guid'], 'text data:image/foo')
2403                 );
2404         }
2405
2406         /**
2407          * Test the api_contactlink_to_array() function.
2408          *
2409          * @return void
2410          */
2411         public function testApiContactlinkToArray()
2412         {
2413                 self::assertEquals(
2414                         [
2415                                 'name' => 'text',
2416                                 'url'  => '',
2417                         ],
2418                         api_contactlink_to_array('text')
2419                 );
2420         }
2421
2422         /**
2423          * Test the api_contactlink_to_array() function with an URL.
2424          *
2425          * @return void
2426          */
2427         public function testApiContactlinkToArrayWithUrl()
2428         {
2429                 self::assertEquals(
2430                         [
2431                                 'name' => ['link_text'],
2432                                 'url'  => ['url'],
2433                         ],
2434                         api_contactlink_to_array('text <a href="url">link_text</a>')
2435                 );
2436         }
2437
2438         /**
2439          * Test the api_format_items_activities() function.
2440          *
2441          * @return void
2442          */
2443         public function testApiFormatItemsActivities()
2444         {
2445                 $item   = ['uid' => 0, 'uri' => ''];
2446                 $result = api_format_items_activities($item);
2447                 self::assertArrayHasKey('like', $result);
2448                 self::assertArrayHasKey('dislike', $result);
2449                 self::assertArrayHasKey('attendyes', $result);
2450                 self::assertArrayHasKey('attendno', $result);
2451                 self::assertArrayHasKey('attendmaybe', $result);
2452         }
2453
2454         /**
2455          * Test the api_format_items_activities() function with an XML result.
2456          *
2457          * @return void
2458          */
2459         public function testApiFormatItemsActivitiesWithXml()
2460         {
2461                 $item   = ['uid' => 0, 'uri' => ''];
2462                 $result = api_format_items_activities($item, 'xml');
2463                 self::assertArrayHasKey('friendica:like', $result);
2464                 self::assertArrayHasKey('friendica:dislike', $result);
2465                 self::assertArrayHasKey('friendica:attendyes', $result);
2466                 self::assertArrayHasKey('friendica:attendno', $result);
2467                 self::assertArrayHasKey('friendica:attendmaybe', $result);
2468         }
2469
2470         /**
2471          * Test the api_format_items() function.
2472          * @doesNotPerformAssertions
2473          */
2474         public function testApiFormatItems()
2475         {
2476                 $items  = [
2477                         [
2478                                 'item_network'   => 'item_network',
2479                                 'source'         => 'web',
2480                                 'coord'          => '5 7',
2481                                 'body'           => '',
2482                                 'verb'           => '',
2483                                 'author-id'      => 43,
2484                                 'author-network' => Protocol::DFRN,
2485                                 'author-link'    => 'http://localhost/profile/othercontact',
2486                                 'plink'          => '',
2487                         ]
2488                 ];
2489                 $result = api_format_items($items, ['id' => 0], true);
2490                 foreach ($result as $status) {
2491                         self::assertStatus($status);
2492                 }
2493         }
2494
2495         /**
2496          * Test the api_format_items() function with an XML result.
2497          * @doesNotPerformAssertions
2498          */
2499         public function testApiFormatItemsWithXml()
2500         {
2501                 $items  = [
2502                         [
2503                                 'coord'          => '5 7',
2504                                 'body'           => '',
2505                                 'verb'           => '',
2506                                 'author-id'      => 43,
2507                                 'author-network' => Protocol::DFRN,
2508                                 'author-link'    => 'http://localhost/profile/othercontact',
2509                                 'plink'          => '',
2510                         ]
2511                 ];
2512                 $result = api_format_items($items, ['id' => 0], true, 'xml');
2513                 foreach ($result as $status) {
2514                         self::assertStatus($status);
2515                 }
2516         }
2517
2518         /**
2519          * Test the api_format_items() function.
2520          *
2521          * @return void
2522          */
2523         public function testApiAccountRateLimitStatus()
2524         {
2525                 $result = api_account_rate_limit_status('json');
2526                 self::assertEquals(150, $result['hash']['remaining_hits']);
2527                 self::assertEquals(150, $result['hash']['hourly_limit']);
2528                 self::assertIsInt($result['hash']['reset_time_in_seconds']);
2529         }
2530
2531         /**
2532          * Test the api_format_items() function with an XML result.
2533          *
2534          * @return void
2535          */
2536         public function testApiAccountRateLimitStatusWithXml()
2537         {
2538                 $result = api_account_rate_limit_status('xml');
2539                 self::assertXml($result, 'hash');
2540         }
2541
2542         /**
2543          * Test the api_help_test() function.
2544          *
2545          * @return void
2546          */
2547         public function testApiHelpTest()
2548         {
2549                 $result = api_help_test('json');
2550                 self::assertEquals(['ok' => 'ok'], $result);
2551         }
2552
2553         /**
2554          * Test the api_help_test() function with an XML result.
2555          *
2556          * @return void
2557          */
2558         public function testApiHelpTestWithXml()
2559         {
2560                 $result = api_help_test('xml');
2561                 self::assertXml($result, 'ok');
2562         }
2563
2564         /**
2565          * Test the api_lists_list() function.
2566          *
2567          * @return void
2568          */
2569         public function testApiListsList()
2570         {
2571                 $result = api_lists_list('json');
2572                 self::assertEquals(['lists_list' => []], $result);
2573         }
2574
2575         /**
2576          * Test the api_lists_ownerships() function.
2577          *
2578          * @return void
2579          */
2580         public function testApiListsOwnerships()
2581         {
2582                 $result = api_lists_ownerships('json');
2583                 foreach ($result['lists']['lists'] as $list) {
2584                         self::assertList($list);
2585                 }
2586         }
2587
2588         /**
2589          * Test the api_lists_ownerships() function without an authenticated user.
2590          *
2591          * @return void
2592          */
2593         public function testApiListsOwnershipsWithoutAuthenticatedUser()
2594         {
2595                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2596                 $_SESSION['authenticated'] = false;
2597                 api_lists_ownerships('json');
2598         }
2599
2600         /**
2601          * Test the api_lists_statuses() function.
2602          *
2603          * @return void
2604          */
2605         public function testApiListsStatuses()
2606         {
2607                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2608                 api_lists_statuses('json');
2609         }
2610
2611         /**
2612          * Test the api_lists_statuses() function with a list ID.
2613          * @doesNotPerformAssertions
2614          */
2615         public function testApiListsStatusesWithListId()
2616         {
2617                 $_REQUEST['list_id'] = 1;
2618                 $_REQUEST['page']    = -1;
2619                 $_REQUEST['max_id']  = 10;
2620                 $result              = api_lists_statuses('json');
2621                 foreach ($result['status'] as $status) {
2622                         self::assertStatus($status);
2623                 }
2624         }
2625
2626         /**
2627          * Test the api_lists_statuses() function with a list ID and a RSS result.
2628          *
2629          * @return void
2630          */
2631         public function testApiListsStatusesWithListIdAndRss()
2632         {
2633                 $_REQUEST['list_id'] = 1;
2634                 $result              = api_lists_statuses('rss');
2635                 self::assertXml($result, 'statuses');
2636         }
2637
2638         /**
2639          * Test the api_lists_statuses() function with an unallowed user.
2640          *
2641          * @return void
2642          */
2643         public function testApiListsStatusesWithUnallowedUser()
2644         {
2645                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2646                 $_SESSION['allow_api'] = false;
2647                 $_GET['screen_name']   = $this->selfUser['nick'];
2648                 api_lists_statuses('json');
2649         }
2650
2651         /**
2652          * Test the api_statuses_f() function.
2653          *
2654          * @return void
2655          */
2656         public function testApiStatusesFWithFriends()
2657         {
2658                 $_GET['page'] = -1;
2659                 $result       = api_statuses_f('friends');
2660                 self::assertArrayHasKey('user', $result);
2661         }
2662
2663         /**
2664          * Test the api_statuses_f() function.
2665          *
2666          * @return void
2667          */
2668         public function testApiStatusesFWithFollowers()
2669         {
2670                 $result = api_statuses_f('followers');
2671                 self::assertArrayHasKey('user', $result);
2672         }
2673
2674         /**
2675          * Test the api_statuses_f() function.
2676          *
2677          * @return void
2678          */
2679         public function testApiStatusesFWithBlocks()
2680         {
2681                 $result = api_statuses_f('blocks');
2682                 self::assertArrayHasKey('user', $result);
2683         }
2684
2685         /**
2686          * Test the api_statuses_f() function.
2687          *
2688          * @return void
2689          */
2690         public function testApiStatusesFWithIncoming()
2691         {
2692                 $result = api_statuses_f('incoming');
2693                 self::assertArrayHasKey('user', $result);
2694         }
2695
2696         /**
2697          * Test the api_statuses_f() function an undefined cursor GET variable.
2698          *
2699          * @return void
2700          */
2701         public function testApiStatusesFWithUndefinedCursor()
2702         {
2703                 $_GET['cursor'] = 'undefined';
2704                 self::assertFalse(api_statuses_f('friends'));
2705         }
2706
2707         /**
2708          * Test the api_statuses_friends() function.
2709          *
2710          * @return void
2711          */
2712         public function testApiStatusesFriends()
2713         {
2714                 $result = api_statuses_friends('json');
2715                 self::assertArrayHasKey('user', $result);
2716         }
2717
2718         /**
2719          * Test the api_statuses_friends() function an undefined cursor GET variable.
2720          *
2721          * @return void
2722          */
2723         public function testApiStatusesFriendsWithUndefinedCursor()
2724         {
2725                 $_GET['cursor'] = 'undefined';
2726                 self::assertFalse(api_statuses_friends('json'));
2727         }
2728
2729         /**
2730          * Test the api_statuses_followers() function.
2731          *
2732          * @return void
2733          */
2734         public function testApiStatusesFollowers()
2735         {
2736                 $result = api_statuses_followers('json');
2737                 self::assertArrayHasKey('user', $result);
2738         }
2739
2740         /**
2741          * Test the api_statuses_followers() function an undefined cursor GET variable.
2742          *
2743          * @return void
2744          */
2745         public function testApiStatusesFollowersWithUndefinedCursor()
2746         {
2747                 $_GET['cursor'] = 'undefined';
2748                 self::assertFalse(api_statuses_followers('json'));
2749         }
2750
2751         /**
2752          * Test the api_blocks_list() function.
2753          *
2754          * @return void
2755          */
2756         public function testApiBlocksList()
2757         {
2758                 $result = api_blocks_list('json');
2759                 self::assertArrayHasKey('user', $result);
2760         }
2761
2762         /**
2763          * Test the api_blocks_list() function an undefined cursor GET variable.
2764          *
2765          * @return void
2766          */
2767         public function testApiBlocksListWithUndefinedCursor()
2768         {
2769                 $_GET['cursor'] = 'undefined';
2770                 self::assertFalse(api_blocks_list('json'));
2771         }
2772
2773         /**
2774          * Test the api_friendships_incoming() function.
2775          *
2776          * @return void
2777          */
2778         public function testApiFriendshipsIncoming()
2779         {
2780                 $result = api_friendships_incoming('json');
2781                 self::assertArrayHasKey('id', $result);
2782         }
2783
2784         /**
2785          * Test the api_friendships_incoming() function an undefined cursor GET variable.
2786          *
2787          * @return void
2788          */
2789         public function testApiFriendshipsIncomingWithUndefinedCursor()
2790         {
2791                 $_GET['cursor'] = 'undefined';
2792                 self::assertFalse(api_friendships_incoming('json'));
2793         }
2794
2795         /**
2796          * Test the api_statusnet_config() function.
2797          *
2798          * @return void
2799          */
2800         public function testApiStatusnetConfig()
2801         {
2802                 $result = api_statusnet_config('json');
2803                 self::assertEquals('localhost', $result['config']['site']['server']);
2804                 self::assertEquals('default', $result['config']['site']['theme']);
2805                 self::assertEquals(DI::baseUrl() . '/images/friendica-64.png', $result['config']['site']['logo']);
2806                 self::assertTrue($result['config']['site']['fancy']);
2807                 self::assertEquals('en', $result['config']['site']['language']);
2808                 self::assertEquals('UTC', $result['config']['site']['timezone']);
2809                 self::assertEquals(200000, $result['config']['site']['textlimit']);
2810                 self::assertEquals('false', $result['config']['site']['private']);
2811                 self::assertEquals('false', $result['config']['site']['ssl']);
2812                 self::assertEquals(30, $result['config']['site']['shorturllength']);
2813         }
2814
2815         /**
2816          * Test the api_statusnet_version() function.
2817          *
2818          * @return void
2819          */
2820         public function testApiStatusnetVersion()
2821         {
2822                 $result = api_statusnet_version('json');
2823                 self::assertEquals('0.9.7', $result['version']);
2824         }
2825
2826         /**
2827          * Test the api_direct_messages_new() function.
2828          *
2829          * @return void
2830          */
2831         public function testApiDirectMessagesNew()
2832         {
2833                 $result = api_direct_messages_new('json');
2834                 self::assertNull($result);
2835         }
2836
2837         /**
2838          * Test the api_direct_messages_new() function without an authenticated user.
2839          *
2840          * @return void
2841          */
2842         public function testApiDirectMessagesNewWithoutAuthenticatedUser()
2843         {
2844                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2845                 $_SESSION['authenticated'] = false;
2846                 api_direct_messages_new('json');
2847         }
2848
2849         /**
2850          * Test the api_direct_messages_new() function with an user ID.
2851          *
2852          * @return void
2853          */
2854         public function testApiDirectMessagesNewWithUserId()
2855         {
2856                 $_POST['text']    = 'message_text';
2857                 $_POST['user_id'] = $this->otherUser['id'];
2858                 $result           = api_direct_messages_new('json');
2859                 self::assertEquals(['direct_message' => ['error' => -1]], $result);
2860         }
2861
2862         /**
2863          * Test the api_direct_messages_new() function with a screen name.
2864          *
2865          * @return void
2866          */
2867         public function testApiDirectMessagesNewWithScreenName()
2868         {
2869                 $this->app->setLoggedInUserNickname($this->selfUser['nick']);
2870                 $_POST['text']        = 'message_text';
2871                 $_POST['screen_name'] = $this->friendUser['nick'];
2872                 $result               = api_direct_messages_new('json');
2873                 self::assertStringContainsString('message_text', $result['direct_message']['text']);
2874                 self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']);
2875                 self::assertEquals(1, $result['direct_message']['friendica_seen']);
2876         }
2877
2878         /**
2879          * Test the api_direct_messages_new() function with a title.
2880          *
2881          * @return void
2882          */
2883         public function testApiDirectMessagesNewWithTitle()
2884         {
2885                 $this->app->setLoggedInUserNickname($this->selfUser['nick']);
2886                 $_POST['text']        = 'message_text';
2887                 $_POST['screen_name'] = $this->friendUser['nick'];
2888                 $_REQUEST['title']    = 'message_title';
2889                 $result               = api_direct_messages_new('json');
2890                 self::assertStringContainsString('message_text', $result['direct_message']['text']);
2891                 self::assertStringContainsString('message_title', $result['direct_message']['text']);
2892                 self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']);
2893                 self::assertEquals(1, $result['direct_message']['friendica_seen']);
2894         }
2895
2896         /**
2897          * Test the api_direct_messages_new() function with an RSS result.
2898          *
2899          * @return void
2900          */
2901         public function testApiDirectMessagesNewWithRss()
2902         {
2903                 $this->app->setLoggedInUserNickname($this->selfUser['nick']);
2904                 $_POST['text']        = 'message_text';
2905                 $_POST['screen_name'] = $this->friendUser['nick'];
2906                 $result               = api_direct_messages_new('rss');
2907                 self::assertXml($result, 'direct-messages');
2908         }
2909
2910         /**
2911          * Test the api_direct_messages_destroy() function.
2912          *
2913          * @return void
2914          */
2915         public function testApiDirectMessagesDestroy()
2916         {
2917                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2918                 api_direct_messages_destroy('json');
2919         }
2920
2921         /**
2922          * Test the api_direct_messages_destroy() function with the friendica_verbose GET param.
2923          *
2924          * @return void
2925          */
2926         public function testApiDirectMessagesDestroyWithVerbose()
2927         {
2928                 $_GET['friendica_verbose'] = 'true';
2929                 $result                    = api_direct_messages_destroy('json');
2930                 self::assertEquals(
2931                         [
2932                                 '$result' => [
2933                                         'result'  => 'error',
2934                                         'message' => 'message id or parenturi not specified'
2935                                 ]
2936                         ],
2937                         $result
2938                 );
2939         }
2940
2941         /**
2942          * Test the api_direct_messages_destroy() function without an authenticated user.
2943          *
2944          * @return void
2945          */
2946         public function testApiDirectMessagesDestroyWithoutAuthenticatedUser()
2947         {
2948                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
2949                 $_SESSION['authenticated'] = false;
2950                 api_direct_messages_destroy('json');
2951         }
2952
2953         /**
2954          * Test the api_direct_messages_destroy() function with a non-zero ID.
2955          *
2956          * @return void
2957          */
2958         public function testApiDirectMessagesDestroyWithId()
2959         {
2960                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
2961                 $_REQUEST['id'] = 1;
2962                 api_direct_messages_destroy('json');
2963         }
2964
2965         /**
2966          * Test the api_direct_messages_destroy() with a non-zero ID and the friendica_verbose GET param.
2967          *
2968          * @return void
2969          */
2970         public function testApiDirectMessagesDestroyWithIdAndVerbose()
2971         {
2972                 $_REQUEST['id']                  = 1;
2973                 $_REQUEST['friendica_parenturi'] = 'parent_uri';
2974                 $_GET['friendica_verbose']       = 'true';
2975                 $result                          = api_direct_messages_destroy('json');
2976                 self::assertEquals(
2977                         [
2978                                 '$result' => [
2979                                         'result'  => 'error',
2980                                         'message' => 'message id not in database'
2981                                 ]
2982                         ],
2983                         $result
2984                 );
2985         }
2986
2987         /**
2988          * Test the api_direct_messages_destroy() function with a non-zero ID.
2989          *
2990          * @return void
2991          */
2992         public function testApiDirectMessagesDestroyWithCorrectId()
2993         {
2994                 $this->markTestIncomplete('We need to add a dataset for this.');
2995         }
2996
2997         /**
2998          * Test the api_direct_messages_box() function.
2999          *
3000          * @return void
3001          */
3002         public function testApiDirectMessagesBoxWithSentbox()
3003         {
3004                 $_REQUEST['page']   = -1;
3005                 $_REQUEST['max_id'] = 10;
3006                 $result             = api_direct_messages_box('json', 'sentbox', 'false');
3007                 self::assertArrayHasKey('direct_message', $result);
3008         }
3009
3010         /**
3011          * Test the api_direct_messages_box() function.
3012          *
3013          * @return void
3014          */
3015         public function testApiDirectMessagesBoxWithConversation()
3016         {
3017                 $result = api_direct_messages_box('json', 'conversation', 'false');
3018                 self::assertArrayHasKey('direct_message', $result);
3019         }
3020
3021         /**
3022          * Test the api_direct_messages_box() function.
3023          *
3024          * @return void
3025          */
3026         public function testApiDirectMessagesBoxWithAll()
3027         {
3028                 $result = api_direct_messages_box('json', 'all', 'false');
3029                 self::assertArrayHasKey('direct_message', $result);
3030         }
3031
3032         /**
3033          * Test the api_direct_messages_box() function.
3034          *
3035          * @return void
3036          */
3037         public function testApiDirectMessagesBoxWithInbox()
3038         {
3039                 $result = api_direct_messages_box('json', 'inbox', 'false');
3040                 self::assertArrayHasKey('direct_message', $result);
3041         }
3042
3043         /**
3044          * Test the api_direct_messages_box() function.
3045          *
3046          * @return void
3047          */
3048         public function testApiDirectMessagesBoxWithVerbose()
3049         {
3050                 $result = api_direct_messages_box('json', 'sentbox', 'true');
3051                 self::assertEquals(
3052                         [
3053                                 '$result' => [
3054                                         'result'  => 'error',
3055                                         'message' => 'no mails available'
3056                                 ]
3057                         ],
3058                         $result
3059                 );
3060         }
3061
3062         /**
3063          * Test the api_direct_messages_box() function with a RSS result.
3064          *
3065          * @return void
3066          */
3067         public function testApiDirectMessagesBoxWithRss()
3068         {
3069                 $result = api_direct_messages_box('rss', 'sentbox', 'false');
3070                 self::assertXml($result, 'direct-messages');
3071         }
3072
3073         /**
3074          * Test the api_direct_messages_box() function without an authenticated user.
3075          *
3076          * @return void
3077          */
3078         public function testApiDirectMessagesBoxWithUnallowedUser()
3079         {
3080                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3081                 $_SESSION['allow_api'] = false;
3082                 $_GET['screen_name']   = $this->selfUser['nick'];
3083                 api_direct_messages_box('json', 'sentbox', 'false');
3084         }
3085
3086         /**
3087          * Test the api_direct_messages_sentbox() function.
3088          *
3089          * @return void
3090          */
3091         public function testApiDirectMessagesSentbox()
3092         {
3093                 $result = api_direct_messages_sentbox('json');
3094                 self::assertArrayHasKey('direct_message', $result);
3095         }
3096
3097         /**
3098          * Test the api_direct_messages_inbox() function.
3099          *
3100          * @return void
3101          */
3102         public function testApiDirectMessagesInbox()
3103         {
3104                 $result = api_direct_messages_inbox('json');
3105                 self::assertArrayHasKey('direct_message', $result);
3106         }
3107
3108         /**
3109          * Test the api_direct_messages_all() function.
3110          *
3111          * @return void
3112          */
3113         public function testApiDirectMessagesAll()
3114         {
3115                 $result = api_direct_messages_all('json');
3116                 self::assertArrayHasKey('direct_message', $result);
3117         }
3118
3119         /**
3120          * Test the api_direct_messages_conversation() function.
3121          *
3122          * @return void
3123          */
3124         public function testApiDirectMessagesConversation()
3125         {
3126                 $result = api_direct_messages_conversation('json');
3127                 self::assertArrayHasKey('direct_message', $result);
3128         }
3129
3130         /**
3131          * Test the api_oauth_request_token() function.
3132          *
3133          * @return void
3134          */
3135         public function testApiOauthRequestToken()
3136         {
3137                 $this->markTestIncomplete('exit() kills phpunit as well');
3138         }
3139
3140         /**
3141          * Test the api_oauth_access_token() function.
3142          *
3143          * @return void
3144          */
3145         public function testApiOauthAccessToken()
3146         {
3147                 $this->markTestIncomplete('exit() kills phpunit as well');
3148         }
3149
3150         /**
3151          * Test the api_fr_photoalbum_delete() function.
3152          *
3153          * @return void
3154          */
3155         public function testApiFrPhotoalbumDelete()
3156         {
3157                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3158                 api_fr_photoalbum_delete('json');
3159         }
3160
3161         /**
3162          * Test the api_fr_photoalbum_delete() function with an album name.
3163          *
3164          * @return void
3165          */
3166         public function testApiFrPhotoalbumDeleteWithAlbum()
3167         {
3168                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3169                 $_REQUEST['album'] = 'album_name';
3170                 api_fr_photoalbum_delete('json');
3171         }
3172
3173         /**
3174          * Test the api_fr_photoalbum_delete() function with an album name.
3175          *
3176          * @return void
3177          */
3178         public function testApiFrPhotoalbumDeleteWithValidAlbum()
3179         {
3180                 $this->markTestIncomplete('We need to add a dataset for this.');
3181         }
3182
3183         /**
3184          * Test the api_fr_photoalbum_delete() function.
3185          *
3186          * @return void
3187          */
3188         public function testApiFrPhotoalbumUpdate()
3189         {
3190                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3191                 api_fr_photoalbum_update('json');
3192         }
3193
3194         /**
3195          * Test the api_fr_photoalbum_delete() function with an album name.
3196          *
3197          * @return void
3198          */
3199         public function testApiFrPhotoalbumUpdateWithAlbum()
3200         {
3201                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3202                 $_REQUEST['album'] = 'album_name';
3203                 api_fr_photoalbum_update('json');
3204         }
3205
3206         /**
3207          * Test the api_fr_photoalbum_delete() function with an album name.
3208          *
3209          * @return void
3210          */
3211         public function testApiFrPhotoalbumUpdateWithAlbumAndNewAlbum()
3212         {
3213                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3214                 $_REQUEST['album']     = 'album_name';
3215                 $_REQUEST['album_new'] = 'album_name';
3216                 api_fr_photoalbum_update('json');
3217         }
3218
3219         /**
3220          * Test the api_fr_photoalbum_update() function without an authenticated user.
3221          *
3222          * @return void
3223          */
3224         public function testApiFrPhotoalbumUpdateWithoutAuthenticatedUser()
3225         {
3226                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3227                 $_SESSION['authenticated'] = false;
3228                 api_fr_photoalbum_update('json');
3229         }
3230
3231         /**
3232          * Test the api_fr_photoalbum_delete() function with an album name.
3233          *
3234          * @return void
3235          */
3236         public function testApiFrPhotoalbumUpdateWithValidAlbum()
3237         {
3238                 $this->markTestIncomplete('We need to add a dataset for this.');
3239         }
3240
3241         /**
3242          * Test the api_fr_photos_list() function.
3243          *
3244          * @return void
3245          */
3246         public function testApiFrPhotosList()
3247         {
3248                 $result = api_fr_photos_list('json');
3249                 self::assertArrayHasKey('photo', $result);
3250         }
3251
3252         /**
3253          * Test the api_fr_photos_list() function without an authenticated user.
3254          *
3255          * @return void
3256          */
3257         public function testApiFrPhotosListWithoutAuthenticatedUser()
3258         {
3259                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3260                 $_SESSION['authenticated'] = false;
3261                 api_fr_photos_list('json');
3262         }
3263
3264         /**
3265          * Test the api_fr_photo_create_update() function.
3266          */
3267         public function testApiFrPhotoCreateUpdate()
3268         {
3269                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3270                 api_fr_photo_create_update('json');
3271         }
3272
3273         /**
3274          * Test the api_fr_photo_create_update() function without an authenticated user.
3275          *
3276          * @return void
3277          */
3278         public function testApiFrPhotoCreateUpdateWithoutAuthenticatedUser()
3279         {
3280                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3281                 $_SESSION['authenticated'] = false;
3282                 api_fr_photo_create_update('json');
3283         }
3284
3285         /**
3286          * Test the api_fr_photo_create_update() function with an album name.
3287          *
3288          * @return void
3289          */
3290         public function testApiFrPhotoCreateUpdateWithAlbum()
3291         {
3292                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3293                 $_REQUEST['album'] = 'album_name';
3294                 api_fr_photo_create_update('json');
3295         }
3296
3297         /**
3298          * Test the api_fr_photo_create_update() function with the update mode.
3299          *
3300          * @return void
3301          */
3302         public function testApiFrPhotoCreateUpdateWithUpdate()
3303         {
3304                 $this->markTestIncomplete('We need to create a dataset for this');
3305         }
3306
3307         /**
3308          * Test the api_fr_photo_create_update() function with an uploaded file.
3309          *
3310          * @return void
3311          */
3312         public function testApiFrPhotoCreateUpdateWithFile()
3313         {
3314                 $this->markTestIncomplete();
3315         }
3316
3317         /**
3318          * Test the api_fr_photo_delete() function.
3319          *
3320          * @return void
3321          */
3322         public function testApiFrPhotoDelete()
3323         {
3324                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3325                 api_fr_photo_delete('json');
3326         }
3327
3328         /**
3329          * Test the api_fr_photo_delete() function without an authenticated user.
3330          *
3331          * @return void
3332          */
3333         public function testApiFrPhotoDeleteWithoutAuthenticatedUser()
3334         {
3335                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3336                 $_SESSION['authenticated'] = false;
3337                 api_fr_photo_delete('json');
3338         }
3339
3340         /**
3341          * Test the api_fr_photo_delete() function with a photo ID.
3342          *
3343          * @return void
3344          */
3345         public function testApiFrPhotoDeleteWithPhotoId()
3346         {
3347                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3348                 $_REQUEST['photo_id'] = 1;
3349                 api_fr_photo_delete('json');
3350         }
3351
3352         /**
3353          * Test the api_fr_photo_delete() function with a correct photo ID.
3354          *
3355          * @return void
3356          */
3357         public function testApiFrPhotoDeleteWithCorrectPhotoId()
3358         {
3359                 $this->markTestIncomplete('We need to create a dataset for this.');
3360         }
3361
3362         /**
3363          * Test the api_fr_photo_detail() function.
3364          *
3365          * @return void
3366          */
3367         public function testApiFrPhotoDetail()
3368         {
3369                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3370                 api_fr_photo_detail('json');
3371         }
3372
3373         /**
3374          * Test the api_fr_photo_detail() function without an authenticated user.
3375          *
3376          * @return void
3377          */
3378         public function testApiFrPhotoDetailWithoutAuthenticatedUser()
3379         {
3380                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3381                 $_SESSION['authenticated'] = false;
3382                 api_fr_photo_detail('json');
3383         }
3384
3385         /**
3386          * Test the api_fr_photo_detail() function with a photo ID.
3387          *
3388          * @return void
3389          */
3390         public function testApiFrPhotoDetailWithPhotoId()
3391         {
3392                 $this->expectException(\Friendica\Network\HTTPException\NotFoundException::class);
3393                 $_REQUEST['photo_id'] = 1;
3394                 api_fr_photo_detail('json');
3395         }
3396
3397         /**
3398          * Test the api_fr_photo_detail() function with a correct photo ID.
3399          *
3400          * @return void
3401          */
3402         public function testApiFrPhotoDetailCorrectPhotoId()
3403         {
3404                 $this->markTestIncomplete('We need to create a dataset for this.');
3405         }
3406
3407         /**
3408          * Test the api_account_update_profile_image() function.
3409          *
3410          * @return void
3411          */
3412         public function testApiAccountUpdateProfileImage()
3413         {
3414                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3415                 api_account_update_profile_image('json');
3416         }
3417
3418         /**
3419          * Test the api_account_update_profile_image() function without an authenticated user.
3420          *
3421          * @return void
3422          */
3423         public function testApiAccountUpdateProfileImageWithoutAuthenticatedUser()
3424         {
3425                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3426                 $_SESSION['authenticated'] = false;
3427                 api_account_update_profile_image('json');
3428         }
3429
3430         /**
3431          * Test the api_account_update_profile_image() function with an uploaded file.
3432          *
3433          * @return void
3434          */
3435         public function testApiAccountUpdateProfileImageWithUpload()
3436         {
3437                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3438                 $this->markTestIncomplete();
3439         }
3440
3441
3442         /**
3443          * Test the api_account_update_profile() function.
3444          *
3445          * @return void
3446          */
3447         public function testApiAccountUpdateProfile()
3448         {
3449                 $_POST['name']        = 'new_name';
3450                 $_POST['description'] = 'new_description';
3451                 $result               = api_account_update_profile('json');
3452                 // We can't use assertSelfUser() here because the user object is missing some properties.
3453                 self::assertEquals($this->selfUser['id'], $result['user']['cid']);
3454                 self::assertEquals('DFRN', $result['user']['location']);
3455                 self::assertEquals($this->selfUser['nick'], $result['user']['screen_name']);
3456                 self::assertEquals('dfrn', $result['user']['network']);
3457                 self::assertEquals('new_name', $result['user']['name']);
3458                 self::assertEquals('new_description', $result['user']['description']);
3459         }
3460
3461         /**
3462          * Test the check_acl_input() function.
3463          *
3464          * @return void
3465          */
3466         public function testCheckAclInput()
3467         {
3468                 $result = check_acl_input('<aclstring>');
3469                 // Where does this result come from?
3470                 self::assertEquals(1, $result);
3471         }
3472
3473         /**
3474          * Test the check_acl_input() function with an empty ACL string.
3475          *
3476          * @return void
3477          */
3478         public function testCheckAclInputWithEmptyAclString()
3479         {
3480                 $result = check_acl_input(' ');
3481                 self::assertFalse($result);
3482         }
3483
3484         /**
3485          * Test the save_media_to_database() function.
3486          *
3487          * @return void
3488          */
3489         public function testSaveMediaToDatabase()
3490         {
3491                 $this->markTestIncomplete();
3492         }
3493
3494         /**
3495          * Test the post_photo_item() function.
3496          *
3497          * @return void
3498          */
3499         public function testPostPhotoItem()
3500         {
3501                 $this->markTestIncomplete();
3502         }
3503
3504         /**
3505          * Test the prepare_photo_data() function.
3506          *
3507          * @return void
3508          */
3509         public function testPreparePhotoData()
3510         {
3511                 $this->markTestIncomplete();
3512         }
3513
3514         /**
3515          * Test the api_share_as_retweet() function with a valid item.
3516          *
3517          * @return void
3518          */
3519         public function testApiShareAsRetweetWithValidItem()
3520         {
3521                 $this->markTestIncomplete();
3522         }
3523
3524         /**
3525          * Test the api_in_reply_to() function.
3526          *
3527          * @return void
3528          */
3529         public function testApiInReplyTo()
3530         {
3531                 $result = api_in_reply_to(['id' => 0, 'parent' => 0, 'uri' => '', 'thr-parent' => '']);
3532                 self::assertArrayHasKey('status_id', $result);
3533                 self::assertArrayHasKey('user_id', $result);
3534                 self::assertArrayHasKey('status_id_str', $result);
3535                 self::assertArrayHasKey('user_id_str', $result);
3536                 self::assertArrayHasKey('screen_name', $result);
3537         }
3538
3539         /**
3540          * Test the api_in_reply_to() function with a valid item.
3541          *
3542          * @return void
3543          */
3544         public function testApiInReplyToWithValidItem()
3545         {
3546                 $this->markTestIncomplete();
3547         }
3548
3549         /**
3550          * Test the api_clean_plain_items() function.
3551          *
3552          * @return void
3553          */
3554         public function testApiCleanPlainItems()
3555         {
3556                 $_REQUEST['include_entities'] = 'true';
3557                 $result                       = api_clean_plain_items('some_text [url="some_url"]some_text[/url]');
3558                 self::assertEquals('some_text [url="some_url"]"some_url"[/url]', $result);
3559         }
3560
3561         /**
3562          * Test the api_best_nickname() function.
3563          *
3564          * @return void
3565          */
3566         public function testApiBestNickname()
3567         {
3568                 $contacts = [];
3569                 $result   = api_best_nickname($contacts);
3570                 self::assertNull($result);
3571         }
3572
3573         /**
3574          * Test the api_best_nickname() function with contacts.
3575          *
3576          * @return void
3577          */
3578         public function testApiBestNicknameWithContacts()
3579         {
3580                 $this->markTestIncomplete();
3581         }
3582
3583         /**
3584          * Test the api_friendica_group_show() function.
3585          *
3586          * @return void
3587          */
3588         public function testApiFriendicaGroupShow()
3589         {
3590                 $this->markTestIncomplete();
3591         }
3592
3593         /**
3594          * Test the api_friendica_group_delete() function.
3595          *
3596          * @return void
3597          */
3598         public function testApiFriendicaGroupDelete()
3599         {
3600                 $this->markTestIncomplete();
3601         }
3602
3603         /**
3604          * Test the api_lists_destroy() function.
3605          *
3606          * @return void
3607          */
3608         public function testApiListsDestroy()
3609         {
3610                 $this->markTestIncomplete();
3611         }
3612
3613         /**
3614          * Test the group_create() function.
3615          *
3616          * @return void
3617          */
3618         public function testGroupCreate()
3619         {
3620                 $this->markTestIncomplete();
3621         }
3622
3623         /**
3624          * Test the api_friendica_group_create() function.
3625          *
3626          * @return void
3627          */
3628         public function testApiFriendicaGroupCreate()
3629         {
3630                 $this->markTestIncomplete();
3631         }
3632
3633         /**
3634          * Test the api_lists_create() function.
3635          *
3636          * @return void
3637          */
3638         public function testApiListsCreate()
3639         {
3640                 $this->markTestIncomplete();
3641         }
3642
3643         /**
3644          * Test the api_friendica_group_update() function.
3645          *
3646          * @return void
3647          */
3648         public function testApiFriendicaGroupUpdate()
3649         {
3650                 $this->markTestIncomplete();
3651         }
3652
3653         /**
3654          * Test the api_lists_update() function.
3655          *
3656          * @return void
3657          */
3658         public function testApiListsUpdate()
3659         {
3660                 $this->markTestIncomplete();
3661         }
3662
3663         /**
3664          * Test the api_friendica_activity() function.
3665          *
3666          * @return void
3667          */
3668         public function testApiFriendicaActivity()
3669         {
3670                 $this->markTestIncomplete();
3671         }
3672
3673         /**
3674          * Test the api_friendica_notification() function.
3675          *
3676          * @return void
3677          */
3678         public function testApiFriendicaNotification()
3679         {
3680                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
3681                 api_friendica_notification('json');
3682         }
3683
3684         /**
3685          * Test the api_friendica_notification() function without an authenticated user.
3686          *
3687          * @return void
3688          */
3689         public function testApiFriendicaNotificationWithoutAuthenticatedUser()
3690         {
3691                 $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
3692                 $_SESSION['authenticated'] = false;
3693                 api_friendica_notification('json');
3694         }
3695
3696         /**
3697          * Test the api_friendica_notification() function with empty result
3698          *
3699          * @return void
3700          */
3701         public function testApiFriendicaNotificationWithEmptyResult()
3702         {
3703                 DI::args()->setArgv(['api', 'friendica', 'notification']);
3704                 $_SESSION['uid'] = 41;
3705                 $result          = api_friendica_notification('json');
3706                 self::assertEquals(['note' => false], $result);
3707         }
3708
3709         /**
3710          * Test the api_friendica_notification() function with an XML result.
3711          *
3712          * @return void
3713          */
3714         public function testApiFriendicaNotificationWithXmlResult()
3715         {
3716                 DI::args()->setArgv(['api', 'friendica', 'notification']);
3717                 $result  = api_friendica_notification('xml');
3718                 $date = DateTimeFormat::local('2020-01-01 12:12:02');
3719                 $dateRel = Temporal::getRelativeDate('2020-01-01 07:12:02');
3720
3721                 $assertXml=<<<XML
3722 <?xml version="1.0"?>
3723 <notes>
3724   <note date="$date" date_rel="$dateRel" id="1" iid="4" link="http://localhost/notification/1" msg="A test reply from an item" msg_cache="A test reply from an item" msg_html="A test reply from an item" msg_plain="A test reply from an item" name="Reply to" name_cache="Reply to" otype="item" parent="" photo="http://localhost/" seen="false" timestamp="1577880722" type="8" uid="42" url="http://localhost/display/1" verb="http://activitystrea.ms/schema/1.0/post"/>
3725 </notes>
3726 XML;
3727                 self::assertXmlStringEqualsXmlString($assertXml, $result);
3728         }
3729
3730         /**
3731          * Test the api_friendica_notification() function with an JSON result.
3732          *
3733          * @return void
3734          */
3735         public function testApiFriendicaNotificationWithJsonResult()
3736         {
3737                 DI::args()->setArgv(['api', 'friendica', 'notification']);
3738                 $result = json_encode(api_friendica_notification('json'));
3739                 self::assertJson($result);
3740         }
3741
3742         /**
3743          * Test the api_friendica_notification_seen() function.
3744          *
3745          * @return void
3746          */
3747         public function testApiFriendicaNotificationSeen()
3748         {
3749                 $this->markTestIncomplete();
3750         }
3751
3752         /**
3753          * Test the api_friendica_direct_messages_setseen() function.
3754          *
3755          * @return void
3756          */
3757         public function testApiFriendicaDirectMessagesSetseen()
3758         {
3759                 $this->markTestIncomplete();
3760         }
3761
3762         /**
3763          * Test the api_friendica_direct_messages_search() function.
3764          *
3765          * @return void
3766          */
3767         public function testApiFriendicaDirectMessagesSearch()
3768         {
3769                 $this->markTestIncomplete();
3770         }
3771
3772         /**
3773          * Test the api_saved_searches_list() function.
3774          *
3775          * @return void
3776          */
3777         public function testApiSavedSearchesList()
3778         {
3779                 $result = api_saved_searches_list('json');
3780                 self::assertEquals(1, $result['terms'][0]['id']);
3781                 self::assertEquals(1, $result['terms'][0]['id_str']);
3782                 self::assertEquals('Saved search', $result['terms'][0]['name']);
3783                 self::assertEquals('Saved search', $result['terms'][0]['query']);
3784         }
3785 }