]> git.mxchange.org Git - friendica.git/blob - tests/legacy/ApiTest.php
Add missing Twitter API routes for IDs
[friendica.git] / tests / legacy / ApiTest.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2022, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  * ApiTest class.
21  */
22
23 namespace Friendica\Test\legacy;
24
25 use Friendica\App;
26 use Friendica\Core\ACL;
27 use Friendica\Core\Config\Capability\IManageConfigValues;
28 use Friendica\DI;
29 use Friendica\Module\BaseApi;
30 use Friendica\Security\BasicAuth;
31 use Friendica\Test\FixtureTest;
32 use Friendica\Util\Arrays;
33 use Friendica\Util\DateTimeFormat;
34 use Monolog\Handler\TestHandler;
35
36 require_once __DIR__ . '/../../include/api.php';
37
38 /**
39  * Tests for the API functions.
40  *
41  * Functions that use header() need to be tested in a separate process.
42  * @see https://phpunit.de/manual/5.7/en/appendixes.annotations.html#appendixes.annotations.runTestsInSeparateProcesses
43  *
44  * @backupGlobals enabled
45  */
46 class ApiTest extends FixtureTest
47 {
48         /**
49          * @var TestHandler Can handle log-outputs
50          */
51         protected $logOutput;
52
53         /** @var array */
54         protected $selfUser;
55         /** @var array */
56         protected $friendUser;
57         /** @var array */
58         protected $otherUser;
59
60         protected $wrongUserId;
61
62         /** @var App */
63         protected $app;
64
65         /** @var IManageConfigValues */
66         protected $config;
67
68         /**
69          * Create variables used by tests.
70          */
71         protected function setUp() : void
72         {
73                 global $API, $called_api;
74                 $API = [];
75                 $called_api = [];
76
77                 parent::setUp();
78
79                 /** @var IManageConfigValues $config */
80                 $this->config = $this->dice->create(IManageConfigValues::class);
81
82                 $this->config->set('system', 'url', 'http://localhost');
83                 $this->config->set('system', 'hostname', 'localhost');
84                 $this->config->set('system', 'worker_dont_fork', true);
85
86                 // Default config
87                 $this->config->set('config', 'hostname', 'localhost');
88                 $this->config->set('system', 'throttle_limit_day', 100);
89                 $this->config->set('system', 'throttle_limit_week', 100);
90                 $this->config->set('system', 'throttle_limit_month', 100);
91                 $this->config->set('system', 'theme', 'system_theme');
92
93
94                 /** @var App app */
95                 $this->app = DI::app();
96
97                 DI::args()->setArgc(1);
98
99                 // User data that the test database is populated with
100                 $this->selfUser   = [
101                         'id'   => 42,
102                         'name' => 'Self contact',
103                         'nick' => 'selfcontact',
104                         'nurl' => 'http://localhost/profile/selfcontact'
105                 ];
106                 $this->friendUser = [
107                         'id'   => 44,
108                         'name' => 'Friend contact',
109                         'nick' => 'friendcontact',
110                         'nurl' => 'http://localhost/profile/friendcontact'
111                 ];
112                 $this->otherUser  = [
113                         'id'   => 43,
114                         'name' => 'othercontact',
115                         'nick' => 'othercontact',
116                         'nurl' => 'http://localhost/profile/othercontact'
117                 ];
118
119                 // User ID that we know is not in the database
120                 $this->wrongUserId = 666;
121
122                 DI::session()->start();
123
124                 // Most API require login so we force the session
125                 $_SESSION = [
126                         'authenticated' => true,
127                         'uid'           => $this->selfUser['id']
128                 ];
129                 BasicAuth::setCurrentUserID($this->selfUser['id']);
130         }
131
132         /**
133          * Assert that a list array contains expected keys.
134          *
135          * @param array $list List array
136          *
137          * @return void
138          */
139         private function assertList(array $list = [])
140         {
141                 self::assertIsString($list['name']);
142                 self::assertIsInt($list['id']);
143                 self::assertIsString('string', $list['id_str']);
144                 self::assertContains($list['mode'], ['public', 'private']);
145                 // We could probably do more checks here.
146         }
147
148         /**
149          * Assert that the string is XML and contain the root element.
150          *
151          * @param string $result       XML string
152          * @param string $root_element Root element name
153          *
154          * @return void
155          */
156         private function assertXml($result = '', $root_element = '')
157         {
158                 self::assertStringStartsWith('<?xml version="1.0"?>', $result);
159                 self::assertStringContainsString('<' . $root_element, $result);
160                 // We could probably do more checks here.
161         }
162
163         /**
164          * Test the api_user() function.
165          *
166          * @return void
167          */
168         public function testApiUser()
169         {
170                 self::assertEquals($this->selfUser['id'], BaseApi::getCurrentUserID());
171         }
172
173
174
175         /**
176          * Test the api_source() function.
177          *
178          * @return void
179          */
180         public function testApiSource()
181         {
182                 self::assertEquals('api', BasicAuth::getCurrentApplicationToken()['name']);
183         }
184
185         /**
186          * Test the api_source() function with a Twidere user agent.
187          *
188          * @return void
189          */
190         public function testApiSourceWithTwidere()
191         {
192                 $_SERVER['HTTP_USER_AGENT'] = 'Twidere';
193                 self::assertEquals('Twidere', BasicAuth::getCurrentApplicationToken()['name']);
194         }
195
196         /**
197          * Test the api_source() function with a GET parameter.
198          *
199          * @return void
200          */
201         public function testApiSourceWithGet()
202         {
203                 $_REQUEST['source'] = 'source_name';
204                 self::assertEquals('source_name', BasicAuth::getCurrentApplicationToken()['name']);
205         }
206
207         /**
208          * Test the api_date() function.
209          *
210          * @return void
211          */
212         public function testApiDate()
213         {
214                 self::assertEquals('Wed Oct 10 00:00:00 +0000 1990', DateTimeFormat::utc('1990-10-10', DateTimeFormat::API));
215         }
216
217         /**
218          * Test the api_register_func() function.
219          *
220          * @return void
221          */
222         public function testApiRegisterFunc()
223         {
224                 global $API;
225                 self::assertNull(
226                         api_register_func(
227                                 'api_path',
228                                 function () {
229                                 },
230                                 true,
231                                 'method'
232                         )
233                 );
234                 self::assertTrue(is_callable($API['api_path']['func']));
235         }
236
237         /**
238          * Test the BasicAuth::getCurrentUserID() function without any login.
239          *
240          * @runInSeparateProcess
241          * @preserveGlobalState disabled
242          * @preserveGlobalState disabled
243          */
244         public function testApiLoginWithoutLogin()
245         {
246                 BasicAuth::setCurrentUserID();
247                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
248                 BasicAuth::getCurrentUserID(true);
249         }
250
251         /**
252          * Test the BasicAuth::getCurrentUserID() function with a bad login.
253          *
254          * @runInSeparateProcess
255          * @preserveGlobalState disabled
256          * @preserveGlobalState disabled
257          */
258         public function testApiLoginWithBadLogin()
259         {
260                 BasicAuth::setCurrentUserID();
261                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
262                 $_SERVER['PHP_AUTH_USER'] = 'user@server';
263                 BasicAuth::getCurrentUserID(true);
264         }
265
266         /**
267          * Test the BasicAuth::getCurrentUserID() function with oAuth.
268          *
269          * @return void
270          */
271         public function testApiLoginWithOauth()
272         {
273                 $this->markTestIncomplete('Can we test this easily?');
274         }
275
276         /**
277          * Test the BasicAuth::getCurrentUserID() function with authentication provided by an addon.
278          *
279          * @return void
280          */
281         public function testApiLoginWithAddonAuth()
282         {
283                 $this->markTestIncomplete('Can we test this easily?');
284         }
285
286         /**
287          * Test the BasicAuth::getCurrentUserID() function with a correct login.
288          *
289          * @runInSeparateProcess
290          * @preserveGlobalState disabled
291          * @doesNotPerformAssertions
292          */
293         public function testApiLoginWithCorrectLogin()
294         {
295                 BasicAuth::setCurrentUserID();
296                 $_SERVER['PHP_AUTH_USER'] = 'Test user';
297                 $_SERVER['PHP_AUTH_PW']   = 'password';
298                 BasicAuth::getCurrentUserID(true);
299         }
300
301         /**
302          * Test the BasicAuth::getCurrentUserID() function with a remote user.
303          *
304          * @runInSeparateProcess
305          * @preserveGlobalState disabled
306          */
307         public function testApiLoginWithRemoteUser()
308         {
309                 BasicAuth::setCurrentUserID();
310                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
311                 $_SERVER['REDIRECT_REMOTE_USER'] = '123456dXNlcjpwYXNzd29yZA==';
312                 BasicAuth::getCurrentUserID(true);
313         }
314
315         /**
316          * Test the api_call() function.
317          *
318          * @runInSeparateProcess
319          * @preserveGlobalState disabled
320          */
321         public function testApiCall()
322         {
323                 global $API;
324                 $API['api_path']           = [
325                         'method' => 'method',
326                         'func'   => function () {
327                                 return ['data' => ['some_data']];
328                         }
329                 ];
330                 $_SERVER['REQUEST_METHOD'] = 'method';
331                 $_SERVER['QUERY_STRING'] = 'pagename=api_path';
332                 $_GET['callback']          = 'callback_name';
333
334                 self::assertEquals(
335                         'callback_name(["some_data"])',
336                         api_call('api_path', 'json')
337                 );
338         }
339
340         /**
341          * Test the api_call() function with the profiled enabled.
342          *
343          * @runInSeparateProcess
344          * @preserveGlobalState disabled
345          */
346         public function testApiCallWithProfiler()
347         {
348                 global $API;
349                 $API['api_path']           = [
350                         'method' => 'method',
351                         'func'   => function () {
352                                 return ['data' => ['some_data']];
353                         }
354                 ];
355
356                 $_SERVER['REQUEST_METHOD'] = 'method';
357                 $_SERVER['QUERY_STRING'] = 'pagename=api_path';
358
359                 $this->config->set('system', 'profiler', true);
360                 $this->config->set('rendertime', 'callstack', true);
361                 $this->app->callstack = [
362                         'database'       => ['some_function' => 200],
363                         'database_write' => ['some_function' => 200],
364                         'cache'          => ['some_function' => 200],
365                         'cache_write'    => ['some_function' => 200],
366                         'network'        => ['some_function' => 200]
367                 ];
368
369                 self::assertEquals(
370                         '["some_data"]',
371                         api_call('api_path', 'json')
372                 );
373         }
374
375         /**
376          * Test the api_call() function with a JSON result.
377          *
378          * @runInSeparateProcess
379          * @preserveGlobalState disabled
380          */
381         public function testApiCallWithJson()
382         {
383                 global $API;
384                 $API['api_path']           = [
385                         'method' => 'method',
386                         'func'   => function () {
387                                 return ['data' => ['some_data']];
388                         }
389                 ];
390                 $_SERVER['REQUEST_METHOD'] = 'method';
391                 $_SERVER['QUERY_STRING'] = 'pagename=api_path.json';
392
393                 self::assertEquals(
394                         '["some_data"]',
395                         api_call('api_path.json', 'json')
396                 );
397         }
398
399         /**
400          * Test the api_call() function with an XML result.
401          *
402          * @runInSeparateProcess
403          * @preserveGlobalState disabled
404          */
405         public function testApiCallWithXml()
406         {
407                 global $API;
408                 $API['api_path']           = [
409                         'method' => 'method',
410                         'func'   => function () {
411                                 return 'some_data';
412                         }
413                 ];
414                 $_SERVER['REQUEST_METHOD'] = 'method';
415                 $_SERVER['QUERY_STRING'] = 'pagename=api_path.xml';
416
417                 $args = DI::args()->determine($_SERVER, $_GET);
418
419                 self::assertEquals(
420                         'some_data',
421                         api_call('api_path.xml', 'xml')
422                 );
423         }
424
425         /**
426          * Test the api_call() function with an RSS result.
427          *
428          * @runInSeparateProcess
429          * @preserveGlobalState disabled
430          */
431         public function testApiCallWithRss()
432         {
433                 global $API;
434                 $API['api_path']           = [
435                         'method' => 'method',
436                         'func'   => function () {
437                                 return 'some_data';
438                         }
439                 ];
440                 $_SERVER['REQUEST_METHOD'] = 'method';
441                 $_SERVER['QUERY_STRING'] = 'pagename=api_path.rss';
442
443                 self::assertEquals(
444                         '<?xml version="1.0" encoding="UTF-8"?>' . "\n" .
445                         'some_data',
446                         api_call('api_path.rss', 'rss')
447                 );
448         }
449
450         /**
451          * Test the api_call() function with an Atom result.
452          *
453          * @runInSeparateProcess
454          * @preserveGlobalState disabled
455          */
456         public function testApiCallWithAtom()
457         {
458                 global $API;
459                 $API['api_path']           = [
460                         'method' => 'method',
461                         'func'   => function () {
462                                 return 'some_data';
463                         }
464                 ];
465                 $_SERVER['REQUEST_METHOD'] = 'method';
466                 $_SERVER['QUERY_STRING'] = 'pagename=api_path.atom';
467
468                 self::assertEquals(
469                         '<?xml version="1.0" encoding="UTF-8"?>' . "\n" .
470                         'some_data',
471                         api_call('api_path.atom', 'atom')
472                 );
473         }
474
475         /**
476          * Test the Arrays::walkRecursive() function.
477          *
478          * @return void
479          */
480         public function testApiWalkRecursive()
481         {
482                 $array = ['item1'];
483                 self::assertEquals(
484                         $array,
485                         Arrays::walkRecursive(
486                                 $array,
487                                 function () {
488                                         // Should we test this with a callback that actually does something?
489                                         return true;
490                                 }
491                         )
492                 );
493         }
494
495         /**
496          * Test the Arrays::walkRecursive() function with an array.
497          *
498          * @return void
499          */
500         public function testApiWalkRecursiveWithArray()
501         {
502                 $array = [['item1'], ['item2']];
503                 self::assertEquals(
504                         $array,
505                         Arrays::walkRecursive(
506                                 $array,
507                                 function () {
508                                         // Should we test this with a callback that actually does something?
509                                         return true;
510                                 }
511                         )
512                 );
513         }
514
515         /**
516          * Test the api_lists_list() function.
517          *
518          * @return void
519          */
520         public function testApiListsList()
521         {
522                 $result = api_lists_list('json');
523                 self::assertEquals(['lists_list' => []], $result);
524         }
525
526         /**
527          * Test the api_lists_ownerships() function.
528          *
529          * @return void
530          */
531         public function testApiListsOwnerships()
532         {
533                 $result = api_lists_ownerships('json');
534                 foreach ($result['lists']['lists'] as $list) {
535                         self::assertList($list);
536                 }
537         }
538
539         /**
540          * Test the api_lists_ownerships() function without an authenticated user.
541          *
542          * @return void
543          */
544         public function testApiListsOwnershipsWithoutAuthenticatedUser()
545         {
546                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
547                 BasicAuth::setCurrentUserID();
548                 $_SESSION['authenticated'] = false;
549                 api_lists_ownerships('json');
550         }
551
552         /**
553          * Test the api_fr_photos_list() function.
554          *
555          * @return void
556          */
557         public function testApiFrPhotosList()
558         {
559                 $result = api_fr_photos_list('json');
560                 self::assertArrayHasKey('photo', $result);
561         }
562
563         /**
564          * Test the api_fr_photos_list() function without an authenticated user.
565          *
566          * @return void
567          */
568         public function testApiFrPhotosListWithoutAuthenticatedUser()
569         {
570                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
571                 BasicAuth::setCurrentUserID();
572                 $_SESSION['authenticated'] = false;
573                 api_fr_photos_list('json');
574         }
575
576         /**
577          * Test the api_fr_photo_create_update() function.
578          */
579         public function testApiFrPhotoCreateUpdate()
580         {
581                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
582                 api_fr_photo_create_update('json');
583         }
584
585         /**
586          * Test the api_fr_photo_create_update() function without an authenticated user.
587          *
588          * @return void
589          */
590         public function testApiFrPhotoCreateUpdateWithoutAuthenticatedUser()
591         {
592                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
593                 BasicAuth::setCurrentUserID();
594                 $_SESSION['authenticated'] = false;
595                 api_fr_photo_create_update('json');
596         }
597
598         /**
599          * Test the api_fr_photo_create_update() function with an album name.
600          *
601          * @return void
602          */
603         public function testApiFrPhotoCreateUpdateWithAlbum()
604         {
605                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
606                 $_REQUEST['album'] = 'album_name';
607                 api_fr_photo_create_update('json');
608         }
609
610         /**
611          * Test the api_fr_photo_create_update() function with the update mode.
612          *
613          * @return void
614          */
615         public function testApiFrPhotoCreateUpdateWithUpdate()
616         {
617                 $this->markTestIncomplete('We need to create a dataset for this');
618         }
619
620         /**
621          * Test the api_fr_photo_create_update() function with an uploaded file.
622          *
623          * @return void
624          */
625         public function testApiFrPhotoCreateUpdateWithFile()
626         {
627                 $this->markTestIncomplete();
628         }
629
630         /**
631          * Test the api_fr_photo_detail() function.
632          *
633          * @return void
634          */
635         public function testApiFrPhotoDetail()
636         {
637                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
638                 api_fr_photo_detail('json');
639         }
640
641         /**
642          * Test the api_fr_photo_detail() function without an authenticated user.
643          *
644          * @return void
645          */
646         public function testApiFrPhotoDetailWithoutAuthenticatedUser()
647         {
648                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
649                 BasicAuth::setCurrentUserID();
650                 $_SESSION['authenticated'] = false;
651                 api_fr_photo_detail('json');
652         }
653
654         /**
655          * Test the api_fr_photo_detail() function with a photo ID.
656          *
657          * @return void
658          */
659         public function testApiFrPhotoDetailWithPhotoId()
660         {
661                 $this->expectException(\Friendica\Network\HTTPException\NotFoundException::class);
662                 $_REQUEST['photo_id'] = 1;
663                 api_fr_photo_detail('json');
664         }
665
666         /**
667          * Test the api_fr_photo_detail() function with a correct photo ID.
668          *
669          * @return void
670          */
671         public function testApiFrPhotoDetailCorrectPhotoId()
672         {
673                 $this->markTestIncomplete('We need to create a dataset for this.');
674         }
675
676         /**
677          * Test the api_account_update_profile_image() function.
678          *
679          * @return void
680          */
681         public function testApiAccountUpdateProfileImage()
682         {
683                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
684                 api_account_update_profile_image('json');
685         }
686
687         /**
688          * Test the api_account_update_profile_image() function without an authenticated user.
689          *
690          * @return void
691          */
692         public function testApiAccountUpdateProfileImageWithoutAuthenticatedUser()
693         {
694                 $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
695                 BasicAuth::setCurrentUserID();
696                 $_SESSION['authenticated'] = false;
697                 api_account_update_profile_image('json');
698         }
699
700         /**
701          * Test the api_account_update_profile_image() function with an uploaded file.
702          *
703          * @return void
704          */
705         public function testApiAccountUpdateProfileImageWithUpload()
706         {
707                 $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
708                 $this->markTestIncomplete();
709         }
710
711         /**
712          * Test the save_media_to_database() function.
713          *
714          * @return void
715          */
716         public function testSaveMediaToDatabase()
717         {
718                 $this->markTestIncomplete();
719         }
720
721         /**
722          * Test the post_photo_item() function.
723          *
724          * @return void
725          */
726         public function testPostPhotoItem()
727         {
728                 $this->markTestIncomplete();
729         }
730
731         /**
732          * Test the prepare_photo_data() function.
733          *
734          * @return void
735          */
736         public function testPreparePhotoData()
737         {
738                 $this->markTestIncomplete();
739         }
740
741         /**
742          * Test the api_friendica_group_show() function.
743          *
744          * @return void
745          */
746         public function testApiFriendicaGroupShow()
747         {
748                 $this->markTestIncomplete();
749         }
750
751         /**
752          * Test the api_lists_destroy() function.
753          *
754          * @return void
755          */
756         public function testApiListsDestroy()
757         {
758                 $this->markTestIncomplete();
759         }
760
761         /**
762          * Test the group_create() function.
763          *
764          * @return void
765          */
766         public function testGroupCreate()
767         {
768                 $this->markTestIncomplete();
769         }
770
771         /**
772          * Test the api_friendica_group_create() function.
773          *
774          * @return void
775          */
776         public function testApiFriendicaGroupCreate()
777         {
778                 $this->markTestIncomplete();
779         }
780
781         /**
782          * Test the api_lists_create() function.
783          *
784          * @return void
785          */
786         public function testApiListsCreate()
787         {
788                 $this->markTestIncomplete();
789         }
790
791         /**
792          * Test the api_lists_update() function.
793          *
794          * @return void
795          */
796         public function testApiListsUpdate()
797         {
798                 $this->markTestIncomplete();
799         }
800 }