2017-04-02 03:06:52 +00:00
< ? php
2017-11-17 01:23:18 +00:00
/** @ license MIT
* Copyright 2017 J . King , Dustin Wilson et al .
* See LICENSE and AUTHORS files for details */
2017-04-02 03:06:52 +00:00
declare ( strict_types = 1 );
2019-12-05 18:02:02 +00:00
namespace JKingWeb\Arsse\TestCase\REST\NextcloudNews ;
2017-08-29 14:50:31 +00:00
2017-12-22 16:41:54 +00:00
use JKingWeb\Arsse\Arsse ;
use JKingWeb\Arsse\User ;
use JKingWeb\Arsse\Database ;
2017-04-02 03:06:52 +00:00
use JKingWeb\Arsse\Test\Result ;
2017-07-19 22:07:36 +00:00
use JKingWeb\Arsse\Misc\Date ;
2022-08-05 02:04:39 +00:00
use JKingWeb\Arsse\Misc\HTTP ;
2019-02-26 03:41:12 +00:00
use JKingWeb\Arsse\Context\Context ;
2017-07-09 21:57:18 +00:00
use JKingWeb\Arsse\Db\ExceptionInput ;
use JKingWeb\Arsse\Db\Transaction ;
2019-12-05 18:02:02 +00:00
use JKingWeb\Arsse\REST\NextcloudNews\V1_2 ;
2018-01-05 04:08:53 +00:00
use Psr\Http\Message\ResponseInterface ;
2017-04-02 03:06:52 +00:00
2019-12-05 18:02:02 +00:00
/** @covers \JKingWeb\Arsse\REST\NextcloudNews\V1_2<extended> */
2017-12-22 16:41:54 +00:00
class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
2017-04-07 01:41:21 +00:00
protected $h ;
2020-01-08 17:02:43 +00:00
protected $transaction ;
2021-03-01 15:03:52 +00:00
protected $userId ;
2017-05-21 14:10:36 +00:00
protected $feeds = [ // expected sample output of a feed list from the database, and the resultant expected transformation by the REST handler
'db' => [
[
2020-03-01 20:16:50 +00:00
'id' => 2112 ,
'url' => 'http://example.com/news.atom' ,
2021-01-16 04:15:22 +00:00
'icon_url' => 'http://example.com/favicon.png' ,
2020-03-01 20:16:50 +00:00
'source' => 'http://example.com/' ,
'folder' => null ,
2017-06-01 22:12:08 +00:00
'top_folder' => null ,
2020-03-01 20:16:50 +00:00
'pinned' => 0 ,
'err_count' => 0 ,
'err_msg' => '' ,
2017-05-21 14:10:36 +00:00
'order_type' => 0 ,
2020-03-01 20:16:50 +00:00
'added' => '2017-05-20 13:35:54' ,
'title' => 'First example feed' ,
'unread' => 50048 ,
2017-05-21 14:10:36 +00:00
],
[
2020-03-01 20:16:50 +00:00
'id' => 42 ,
'url' => 'http://example.org/news.atom' ,
2021-01-16 04:15:22 +00:00
'icon_url' => 'http://example.org/favicon.png' ,
2020-03-01 20:16:50 +00:00
'source' => 'http://example.org/' ,
'folder' => 12 ,
2017-06-01 22:12:08 +00:00
'top_folder' => 8 ,
2020-03-01 20:16:50 +00:00
'pinned' => 1 ,
'err_count' => 0 ,
'err_msg' => '' ,
2017-05-21 14:10:36 +00:00
'order_type' => 2 ,
2020-03-01 20:16:50 +00:00
'added' => '2017-05-20 13:35:54' ,
'title' => 'Second example feed' ,
'unread' => 23 ,
2017-05-21 14:10:36 +00:00
],
2017-09-28 02:25:45 +00:00
[
2020-03-01 20:16:50 +00:00
'id' => 47 ,
'url' => 'http://example.net/news.atom' ,
2021-01-16 04:15:22 +00:00
'icon_url' => 'http://example.net/favicon.png' ,
2020-03-01 20:16:50 +00:00
'source' => 'http://example.net/' ,
'folder' => null ,
2017-09-28 02:25:45 +00:00
'top_folder' => null ,
2020-03-01 20:16:50 +00:00
'pinned' => 0 ,
'err_count' => 0 ,
'err_msg' => null ,
2017-09-28 02:25:45 +00:00
'order_type' => 1 ,
2020-03-01 20:16:50 +00:00
'added' => '2017-05-20 13:35:54' ,
'title' => 'Third example feed' ,
'unread' => 0 ,
2017-09-28 02:25:45 +00:00
],
2017-05-21 14:10:36 +00:00
],
'rest' => [
[
2020-03-01 20:16:50 +00:00
'id' => 2112 ,
'url' => 'http://example.com/news.atom' ,
'title' => 'First example feed' ,
'added' => 1495287354 ,
'pinned' => false ,
'link' => 'http://example.com/' ,
'faviconLink' => 'http://example.com/favicon.png' ,
'folderId' => 0 ,
'unreadCount' => 50048 ,
'ordering' => 0 ,
2017-05-21 14:10:36 +00:00
'updateErrorCount' => 0 ,
2020-03-01 20:16:50 +00:00
'lastUpdateError' => '' ,
2017-05-21 14:10:36 +00:00
],
[
2020-03-01 20:16:50 +00:00
'id' => 42 ,
'url' => 'http://example.org/news.atom' ,
'title' => 'Second example feed' ,
'added' => 1495287354 ,
'pinned' => true ,
'link' => 'http://example.org/' ,
'faviconLink' => 'http://example.org/favicon.png' ,
'folderId' => 8 ,
'unreadCount' => 23 ,
'ordering' => 2 ,
2017-05-21 14:10:36 +00:00
'updateErrorCount' => 0 ,
2020-03-01 20:16:50 +00:00
'lastUpdateError' => '' ,
2017-05-21 14:10:36 +00:00
],
2017-09-28 02:25:45 +00:00
[
2020-03-01 20:16:50 +00:00
'id' => 47 ,
'url' => 'http://example.net/news.atom' ,
'title' => 'Third example feed' ,
'added' => 1495287354 ,
'pinned' => false ,
'link' => 'http://example.net/' ,
'faviconLink' => 'http://example.net/favicon.png' ,
'folderId' => 0 ,
'unreadCount' => 0 ,
'ordering' => 1 ,
2017-09-28 02:25:45 +00:00
'updateErrorCount' => 0 ,
2020-03-01 20:16:50 +00:00
'lastUpdateError' => '' ,
2017-09-28 02:25:45 +00:00
],
2017-05-21 14:10:36 +00:00
],
];
2017-07-09 21:57:18 +00:00
protected $articles = [
'db' => [
[
2020-03-01 20:16:50 +00:00
'id' => 101 ,
'url' => 'http://example.com/1' ,
'title' => 'Article title 1' ,
'author' => '' ,
'content' => '<p>Article content 1</p>' ,
'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda' ,
2017-07-09 21:57:18 +00:00
'published_date' => '2000-01-01 00:00:00' ,
2020-03-01 20:16:50 +00:00
'edited_date' => '2000-01-01 00:00:01' ,
'modified_date' => '2000-01-01 01:00:00' ,
'unread' => 1 ,
'starred' => 0 ,
'edition' => 101 ,
'subscription' => 8 ,
'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207' ,
'media_url' => null ,
'media_type' => null ,
2017-07-09 21:57:18 +00:00
],
[
2020-03-01 20:16:50 +00:00
'id' => 102 ,
'url' => 'http://example.com/2' ,
'title' => 'Article title 2' ,
'author' => '' ,
'content' => '<p>Article content 2</p>' ,
'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7' ,
2017-07-09 21:57:18 +00:00
'published_date' => '2000-01-02 00:00:00' ,
2020-03-01 20:16:50 +00:00
'edited_date' => '2000-01-02 00:00:02' ,
'modified_date' => '2000-01-02 02:00:00' ,
'unread' => 0 ,
'starred' => 0 ,
'edition' => 202 ,
'subscription' => 8 ,
'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e' ,
'media_url' => " http://example.com/text " ,
'media_type' => " text/plain " ,
2017-07-09 21:57:18 +00:00
],
[
2020-03-01 20:16:50 +00:00
'id' => 103 ,
'url' => 'http://example.com/3' ,
'title' => 'Article title 3' ,
'author' => '' ,
'content' => '<p>Article content 3</p>' ,
'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92' ,
2017-07-09 21:57:18 +00:00
'published_date' => '2000-01-03 00:00:00' ,
2020-03-01 20:16:50 +00:00
'edited_date' => '2000-01-03 00:00:03' ,
'modified_date' => '2000-01-03 03:00:00' ,
'unread' => 1 ,
'starred' => 1 ,
'edition' => 203 ,
'subscription' => 9 ,
'fingerprint' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b:b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406:ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b' ,
'media_url' => " http://example.com/video " ,
'media_type' => " video/webm " ,
2017-07-09 21:57:18 +00:00
],
[
2020-03-01 20:16:50 +00:00
'id' => 104 ,
'url' => 'http://example.com/4' ,
'title' => 'Article title 4' ,
'author' => '' ,
'content' => '<p>Article content 4</p>' ,
'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180' ,
2017-07-09 21:57:18 +00:00
'published_date' => '2000-01-04 00:00:00' ,
2020-03-01 20:16:50 +00:00
'edited_date' => '2000-01-04 00:00:04' ,
'modified_date' => '2000-01-04 04:00:00' ,
'unread' => 0 ,
'starred' => 1 ,
'edition' => 204 ,
'subscription' => 9 ,
'fingerprint' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8:f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3:ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9' ,
'media_url' => " http://example.com/image " ,
'media_type' => " image/svg+xml " ,
2017-07-09 21:57:18 +00:00
],
[
2020-03-01 20:16:50 +00:00
'id' => 105 ,
'url' => 'http://example.com/5' ,
'title' => 'Article title 5' ,
'author' => '' ,
'content' => '<p>Article content 5</p>' ,
'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41' ,
2017-07-09 21:57:18 +00:00
'published_date' => '2000-01-05 00:00:00' ,
2020-03-01 20:16:50 +00:00
'edited_date' => '2000-01-05 00:00:05' ,
'modified_date' => '2000-01-05 05:00:00' ,
'unread' => 1 ,
'starred' => 0 ,
'edition' => 305 ,
'subscription' => 10 ,
'fingerprint' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022:834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900:43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba' ,
'media_url' => " http://example.com/audio " ,
'media_type' => " audio/ogg " ,
2017-07-09 21:57:18 +00:00
],
],
'rest' => [
[
2020-03-01 20:16:50 +00:00
'id' => 101 ,
'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda' ,
'guidHash' => " 101 " ,
'url' => 'http://example.com/1' ,
'title' => 'Article title 1' ,
'author' => '' ,
'pubDate' => 946684801 ,
'body' => '<p>Article content 1</p>' ,
2017-11-30 19:47:39 +00:00
'enclosureMime' => " " ,
'enclosureLink' => " " ,
2020-03-01 20:16:50 +00:00
'feedId' => 8 ,
'unread' => true ,
'starred' => false ,
'lastModified' => 946688400 ,
'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207' ,
2017-07-09 21:57:18 +00:00
],
[
2020-03-01 20:16:50 +00:00
'id' => 202 ,
'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7' ,
'guidHash' => " 102 " ,
'url' => 'http://example.com/2' ,
'title' => 'Article title 2' ,
'author' => '' ,
'pubDate' => 946771202 ,
'body' => '<p>Article content 2</p>' ,
2017-11-30 19:47:39 +00:00
'enclosureMime' => " text/plain " ,
'enclosureLink' => " http://example.com/text " ,
2020-03-01 20:16:50 +00:00
'feedId' => 8 ,
'unread' => false ,
'starred' => false ,
'lastModified' => 946778400 ,
'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e' ,
2017-07-09 21:57:18 +00:00
],
[
2020-03-01 20:16:50 +00:00
'id' => 203 ,
'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92' ,
'guidHash' => " 103 " ,
'url' => 'http://example.com/3' ,
'title' => 'Article title 3' ,
'author' => '' ,
'pubDate' => 946857603 ,
'body' => '<p>Article content 3</p>' ,
2017-11-30 19:47:39 +00:00
'enclosureMime' => " video/webm " ,
'enclosureLink' => " http://example.com/video " ,
2020-03-01 20:16:50 +00:00
'feedId' => 9 ,
'unread' => true ,
'starred' => true ,
'lastModified' => 946868400 ,
'fingerprint' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b:b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406:ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b' ,
2017-07-09 21:57:18 +00:00
],
[
2020-03-01 20:16:50 +00:00
'id' => 204 ,
'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180' ,
'guidHash' => " 104 " ,
'url' => 'http://example.com/4' ,
'title' => 'Article title 4' ,
'author' => '' ,
'pubDate' => 946944004 ,
'body' => '<p>Article content 4</p>' ,
2017-11-30 19:47:39 +00:00
'enclosureMime' => " image/svg+xml " ,
'enclosureLink' => " http://example.com/image " ,
2020-03-01 20:16:50 +00:00
'feedId' => 9 ,
'unread' => false ,
'starred' => true ,
'lastModified' => 946958400 ,
'fingerprint' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8:f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3:ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9' ,
2017-07-09 21:57:18 +00:00
],
[
2020-03-01 20:16:50 +00:00
'id' => 305 ,
'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41' ,
'guidHash' => " 105 " ,
'url' => 'http://example.com/5' ,
'title' => 'Article title 5' ,
'author' => '' ,
'pubDate' => 947030405 ,
'body' => '<p>Article content 5</p>' ,
2017-11-30 19:47:39 +00:00
'enclosureMime' => " audio/ogg " ,
'enclosureLink' => " http://example.com/audio " ,
2020-03-01 20:16:50 +00:00
'feedId' => 10 ,
'unread' => true ,
'starred' => false ,
'lastModified' => 947048400 ,
'fingerprint' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022:834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900:43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba' ,
2017-07-09 21:57:18 +00:00
],
],
];
2017-04-02 03:06:52 +00:00
2020-01-08 17:02:43 +00:00
protected function req ( string $method , string $target , $data = " " , array $headers = [], bool $authenticated = true , bool $body = true ) : ResponseInterface {
2021-03-01 15:03:52 +00:00
Arsse :: $obj = $this -> objMock -> get ();
Arsse :: $db = $this -> dbMock -> get ();
Arsse :: $user = $this -> userMock -> get ();
Arsse :: $user -> id = $this -> userId ;
2019-09-25 22:30:53 +00:00
$prefix = " /index.php/apps/news/api/v1-2 " ;
$url = $prefix . $target ;
2020-01-08 17:02:43 +00:00
if ( $body ) {
$params = [];
} else {
$params = $data ;
$data = [];
}
$req = $this -> serverRequest ( $method , $url , $prefix , $headers , [], $data , " application/json " , $params , $authenticated ? " john.doe@example.com " : " " );
2018-01-05 04:08:53 +00:00
return $this -> h -> dispatch ( $req );
}
2019-10-16 18:42:43 +00:00
public function setUp () : void {
2021-02-27 20:24:02 +00:00
parent :: setUp ();
2018-11-23 00:55:54 +00:00
self :: setConf ();
2017-04-02 03:06:52 +00:00
// create a mock user manager
2021-03-01 15:03:52 +00:00
$this -> userId = " john.doe@example.com " ;
$this -> userMock = $this -> mock ( User :: class );
$this -> userMock -> auth -> returns ( true );
$this -> userMock -> propertiesGet -> returns ([ 'admin' => true ]);
2017-04-07 01:41:21 +00:00
// create a mock database interface
2021-03-01 15:03:52 +00:00
$this -> dbMock = $this -> mock ( Database :: class );
$this -> dbMock -> begin -> returns ( $this -> mock ( Transaction :: class ));
2020-01-08 17:02:43 +00:00
//initialize a handler
2022-06-01 03:55:04 +00:00
$this -> h = new V1_2 ;
2017-04-07 01:41:21 +00:00
}
2017-04-02 03:06:52 +00:00
2017-12-31 18:58:37 +00:00
protected function v ( $value ) {
return $value ;
}
2020-01-20 18:52:48 +00:00
public function testSendAuthenticationChallenge () : void {
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 401 );
2019-09-25 22:30:53 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " / " , " " , [], false ));
2017-11-29 20:28:33 +00:00
}
2020-01-08 17:02:43 +00:00
/** @dataProvider provideInvalidPaths */
2020-01-20 18:52:48 +00:00
public function testRespondToInvalidPaths ( $path , $method , $code , $allow = null ) : void {
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( $code , $allow ? [ 'Allow' => $allow ] : []);
2020-01-08 17:02:43 +00:00
$this -> assertMessage ( $exp , $this -> req ( $method , $path ));
}
2020-01-20 18:34:03 +00:00
public function provideInvalidPaths () : array {
2020-01-08 17:02:43 +00:00
return [
[ " / " , " GET " , 404 ],
[ " / " , " POST " , 404 ],
[ " / " , " PUT " , 404 ],
[ " / " , " DELETE " , 404 ],
[ " / " , " OPTIONS " , 404 ],
[ " /version/invalid " , " GET " , 404 ],
[ " /version/invalid " , " POST " , 404 ],
[ " /version/invalid " , " PUT " , 404 ],
[ " /version/invalid " , " DELETE " , 404 ],
[ " /version/invalid " , " OPTIONS " , 404 ],
[ " /folders/1/invalid " , " GET " , 404 ],
[ " /folders/1/invalid " , " POST " , 404 ],
[ " /folders/1/invalid " , " PUT " , 404 ],
[ " /folders/1/invalid " , " DELETE " , 404 ],
[ " /folders/1/invalid " , " OPTIONS " , 404 ],
[ " /version " , " POST " , 405 , " GET " ],
[ " /version " , " PUT " , 405 , " GET " ],
[ " /version " , " DELETE " , 405 , " GET " ],
[ " /folders " , " PUT " , 405 , " GET, POST " ],
[ " /folders " , " DELETE " , 405 , " GET, POST " ],
[ " /folders/1 " , " GET " , 405 , " PUT, DELETE " ],
[ " /folders/1 " , " POST " , 405 , " PUT, DELETE " ],
2017-04-07 01:41:21 +00:00
];
}
2017-04-03 01:34:30 +00:00
2020-01-20 18:52:48 +00:00
public function testRespondToInvalidInputTypes () : void {
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 415 , [ 'Accept' => " application/json " ]);
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /folders/1 " , '<data/>' , [ 'Content-Type' => " application/xml " ]));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 400 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /folders/1 " , '<data/>' ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /folders/1 " , '<data/>' , [ 'Content-Type' => null ]));
2017-07-24 12:15:37 +00:00
}
2020-01-08 17:02:43 +00:00
/** @dataProvider provideOptionsRequests */
2020-01-20 18:52:48 +00:00
public function testRespondToOptionsRequests ( string $url , string $allow , string $accept ) : void {
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 , [
2020-01-08 17:02:43 +00:00
'Allow' => $allow ,
'Accept' => $accept ,
2017-11-29 20:28:33 +00:00
]);
2020-01-08 17:02:43 +00:00
$this -> assertMessage ( $exp , $this -> req ( " OPTIONS " , $url ));
}
2020-01-20 18:34:03 +00:00
public function provideOptionsRequests () : array {
2020-01-08 17:02:43 +00:00
return [
[ " /feeds " , " HEAD,GET,POST " , " application/json " ],
[ " /feeds/2112 " , " DELETE " , " application/json " ],
[ " /user " , " HEAD,GET " , " application/json " ],
];
2017-06-03 21:34:37 +00:00
}
2020-01-20 18:52:48 +00:00
public function testListFolders () : void {
2017-04-07 01:41:21 +00:00
$list = [
[ 'id' => 1 , 'name' => " Software " , 'parent' => null ],
2017-12-31 18:58:37 +00:00
[ 'id' => 12 , 'name' => " Hardware " , 'parent' => null ],
2017-11-30 19:47:39 +00:00
];
$out = [
[ 'id' => 1 , 'name' => " Software " ],
[ 'id' => 12 , 'name' => " Hardware " ],
2017-04-07 01:41:21 +00:00
];
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderList -> with ( $this -> userId , null , false ) -> returns ( new Result ( $this -> v ( $list )));
2022-08-06 02:08:36 +00:00
$exp = HTTP :: respJson ([ 'folders' => $out ]);
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /folders " ));
2017-04-07 01:41:21 +00:00
}
2017-04-02 16:14:15 +00:00
2020-01-08 17:02:43 +00:00
/** @dataProvider provideFolderCreations */
2020-01-20 18:52:48 +00:00
public function testAddAFolder ( array $input , bool $body , $output , ResponseInterface $exp ) : void {
2020-01-08 17:02:43 +00:00
if ( $output instanceof ExceptionInput ) {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderAdd -> throws ( $output );
2020-01-08 17:02:43 +00:00
} else {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderAdd -> returns ( $output );
$this -> dbMock -> folderPropertiesGet -> returns ( $this -> v ([ 'id' => $output , 'name' => $input [ 'name' ], 'parent' => null ]));
2020-01-08 17:02:43 +00:00
}
$act = $this -> req ( " POST " , " /folders " , $input , [], true , $body );
$this -> assertMessage ( $exp , $act );
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderAdd -> calledWith ( $this -> userId , $input );
2020-01-08 17:02:43 +00:00
if ( $output instanceof ExceptionInput ) {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderPropertiesGet -> never () -> called ();
2020-01-08 17:02:43 +00:00
} else {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderPropertiesGet -> calledWith ( $this -> userId , $this -> equalTo ( $output ));
2020-01-08 17:02:43 +00:00
}
}
2020-01-20 18:34:03 +00:00
public function provideFolderCreations () : array {
2020-01-08 17:02:43 +00:00
return [
2022-08-06 02:08:36 +00:00
[[ 'name' => " Software " ], true , 1 , HTTP :: respJson ([ 'folders' => [[ 'id' => 1 , 'name' => " Software " ]]])],
[[ 'name' => " Software " ], false , 1 , HTTP :: respJson ([ 'folders' => [[ 'id' => 1 , 'name' => " Software " ]]])],
[[ 'name' => " Hardware " ], true , " 2 " , HTTP :: respJson ([ 'folders' => [[ 'id' => 2 , 'name' => " Hardware " ]]])],
[[ 'name' => " Hardware " ], false , " 2 " , HTTP :: respJson ([ 'folders' => [[ 'id' => 2 , 'name' => " Hardware " ]]])],
2022-08-05 02:04:39 +00:00
[[ 'name' => " Software " ], true , new ExceptionInput ( " constraintViolation " ), HTTP :: respEmpty ( 409 )],
[[ 'name' => " " ], true , new ExceptionInput ( " whitespace " ), HTTP :: respEmpty ( 422 )],
[[ 'name' => " " ], true , new ExceptionInput ( " whitespace " ), HTTP :: respEmpty ( 422 )],
[[ 'name' => null ], true , new ExceptionInput ( " missing " ), HTTP :: respEmpty ( 422 )],
2017-04-07 01:41:21 +00:00
];
}
2017-04-03 01:34:30 +00:00
2020-01-20 18:52:48 +00:00
public function testRemoveAFolder () : void {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderRemove -> with ( $this -> userId , 1 ) -> returns ( true ) -> throws ( new ExceptionInput ( " subjectMissing " ));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " DELETE " , " /folders/1 " ));
2017-04-07 01:41:21 +00:00
// fail on the second invocation because it no longer exists
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 404 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " DELETE " , " /folders/1 " ));
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderRemove -> times ( 2 ) -> calledWith ( $this -> userId , 1 );
2017-04-07 01:41:21 +00:00
}
2017-04-03 01:34:30 +00:00
2020-01-08 17:02:43 +00:00
/** @dataProvider provideFolderRenamings */
2020-01-20 18:52:48 +00:00
public function testRenameAFolder ( array $input , int $id , $output , ResponseInterface $exp ) : void {
2020-01-08 17:02:43 +00:00
if ( $output instanceof ExceptionInput ) {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderPropertiesSet -> throws ( $output );
2020-01-08 17:02:43 +00:00
} else {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderPropertiesSet -> returns ( $output );
2020-01-08 17:02:43 +00:00
}
$act = $this -> req ( " PUT " , " /folders/ $id " , $input );
$this -> assertMessage ( $exp , $act );
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderPropertiesSet -> calledWith ( $this -> userId , $id , $input );
2020-01-08 17:02:43 +00:00
}
2020-01-19 23:13:32 +00:00
2020-01-20 18:34:03 +00:00
public function provideFolderRenamings () : array {
2020-01-08 17:02:43 +00:00
return [
2022-08-05 02:04:39 +00:00
[[ 'name' => " Software " ], 1 , true , HTTP :: respEmpty ( 204 )],
[[ 'name' => " Software " ], 2 , new ExceptionInput ( " constraintViolation " ), HTTP :: respEmpty ( 409 )],
[[ 'name' => " Software " ], 3 , new ExceptionInput ( " subjectMissing " ), HTTP :: respEmpty ( 404 )],
[[ 'name' => " " ], 2 , new ExceptionInput ( " whitespace " ), HTTP :: respEmpty ( 422 )],
[[ 'name' => " " ], 2 , new ExceptionInput ( " whitespace " ), HTTP :: respEmpty ( 422 )],
[[ 'name' => null ], 2 , new ExceptionInput ( " missing " ), HTTP :: respEmpty ( 422 )],
2017-04-07 01:41:21 +00:00
];
}
2017-04-03 01:49:37 +00:00
2020-01-20 18:52:48 +00:00
public function testRetrieveServerVersion () : void {
2022-08-06 02:08:36 +00:00
$exp = HTTP :: respJson ([
2020-03-01 20:16:50 +00:00
'version' => V1_2 :: VERSION ,
2017-11-30 19:47:39 +00:00
'arsse_version' => Arsse :: VERSION ,
2017-07-16 15:51:18 +00:00
]);
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /version " ));
2017-04-07 01:41:21 +00:00
}
2017-05-21 14:10:36 +00:00
2020-01-20 18:52:48 +00:00
public function testListSubscriptions () : void {
2017-05-21 14:10:36 +00:00
$exp1 = [
2020-03-01 20:16:50 +00:00
'feeds' => [],
2017-05-21 14:10:36 +00:00
'starredCount' => 0 ,
];
$exp2 = [
'feeds' => $this -> feeds [ 'rest' ],
'starredCount' => 5 ,
'newestItemId' => 4758915 ,
];
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionList -> with ( $this -> userId ) -> returns ( new Result ([])) -> returns ( new Result ( $this -> v ( $this -> feeds [ 'db' ])));
$this -> dbMock -> articleStarred -> with ( $this -> userId ) -> returns ( $this -> v ([ 'total' => 0 ])) -> returns ( $this -> v ([ 'total' => 5 ]));
$this -> dbMock -> editionLatest -> with ( $this -> userId ) -> returns ( 0 ) -> returns ( 4758915 );
2022-08-06 02:08:36 +00:00
$exp = HTTP :: respJson ( $exp1 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /feeds " ));
2022-08-06 02:08:36 +00:00
$exp = HTTP :: respJson ( $exp2 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /feeds " ));
2017-05-21 14:10:36 +00:00
}
2020-01-08 17:02:43 +00:00
/** @dataProvider provideNewSubscriptions */
2020-01-20 18:52:48 +00:00
public function testAddASubscription ( array $input , $id , int $latestEdition , array $output , $moveOutcome , ResponseInterface $exp ) : void {
2020-01-08 17:02:43 +00:00
if ( $id instanceof \Exception ) {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionAdd -> throws ( $id );
2020-01-08 17:02:43 +00:00
} else {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionAdd -> returns ( $id );
2020-01-08 17:02:43 +00:00
}
if ( $moveOutcome instanceof \Exception ) {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionPropertiesSet -> throws ( $moveOutcome );
2020-01-08 17:02:43 +00:00
} else {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionPropertiesSet -> returns ( $moveOutcome );
2020-01-08 17:02:43 +00:00
}
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionPropertiesGet -> returns ( $this -> v ( $output ));
$this -> dbMock -> editionLatest -> returns ( $latestEdition );
2020-01-08 17:02:43 +00:00
$act = $this -> req ( " POST " , " /feeds " , $input );
$this -> assertMessage ( $exp , $act );
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionAdd -> calledWith ( $this -> userId , $input [ 'url' ] ? ? " " );
2020-01-08 17:02:43 +00:00
if ( $id instanceof \Exception ) {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionPropertiesSet -> never () -> called ();
$this -> dbMock -> subscriptionPropertiesGet -> never () -> called ();
$this -> dbMock -> editionLatest -> never () -> called ();
2020-01-08 17:02:43 +00:00
} else {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionPropertiesGet -> calledWith ( $this -> userId , $id );
$this -> dbMock -> editionLatest -> calledWith ( $this -> userId , $this -> equalTo (( new Context ) -> subscription ( $id ) -> hidden ( false )));
2020-01-08 17:02:43 +00:00
if ( $input [ 'folderId' ] ? ? 0 ) {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionPropertiesSet -> calledWith ( $this -> userId , $id , [ 'folder' => ( int ) $input [ 'folderId' ]]);
2020-01-08 17:02:43 +00:00
} else {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionPropertiesSet -> never () -> called ();
2020-01-08 17:02:43 +00:00
}
}
}
2020-01-20 18:34:03 +00:00
public function provideNewSubscriptions () : array {
2021-01-22 03:44:22 +00:00
$feedException = new \JKingWeb\Arsse\Feed\Exception ( " " , [], new \PicoFeed\Reader\SubscriptionNotFoundException );
2020-01-08 17:02:43 +00:00
return [
2022-08-06 02:08:36 +00:00
[[ 'url' => " http://example.com/news.atom " , 'folderId' => 3 ], 2112 , 0 , $this -> feeds [ 'db' ][ 0 ], new ExceptionInput ( " idMissing " ), HTTP :: respJson ([ 'feeds' => [ $this -> feeds [ 'rest' ][ 0 ]]])],
[[ 'url' => " http://example.org/news.atom " , 'folderId' => 8 ], 42 , 4758915 , $this -> feeds [ 'db' ][ 1 ], true , HTTP :: respJson ([ 'feeds' => [ $this -> feeds [ 'rest' ][ 1 ]], 'newestItemId' => 4758915 ])],
2022-08-05 02:04:39 +00:00
[[ 'url' => " http://example.com/news.atom " , 'folderId' => 3 ], new ExceptionInput ( " constraintViolation " ), 0 , $this -> feeds [ 'db' ][ 0 ], new ExceptionInput ( " idMissing " ), HTTP :: respEmpty ( 409 )],
[[ 'url' => " http://example.org/news.atom " , 'folderId' => 8 ], new ExceptionInput ( " constraintViolation " ), 4758915 , $this -> feeds [ 'db' ][ 1 ], true , HTTP :: respEmpty ( 409 )],
[[], $feedException , 0 , [], false , HTTP :: respEmpty ( 422 )],
2022-08-06 02:08:36 +00:00
[[ 'url' => " http://example.net/news.atom " , 'folderId' => - 1 ], 47 , 2112 , $this -> feeds [ 'db' ][ 2 ], new ExceptionInput ( " typeViolation " ), HTTP :: respJson ([ 'feeds' => [ $this -> feeds [ 'rest' ][ 2 ]], 'newestItemId' => 2112 ])],
2017-05-21 14:10:36 +00:00
];
}
2020-01-20 18:52:48 +00:00
public function testRemoveASubscription () : void {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionRemove -> with ( $this -> userId , 1 ) -> returns ( true ) -> throws ( new ExceptionInput ( " subjectMissing " ));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " DELETE " , " /feeds/1 " ));
2017-05-21 14:10:36 +00:00
// fail on the second invocation because it no longer exists
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 404 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " DELETE " , " /feeds/1 " ));
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionRemove -> times ( 2 ) -> calledWith ( $this -> userId , 1 );
2017-05-21 14:10:36 +00:00
}
2020-01-20 18:52:48 +00:00
public function testMoveASubscription () : void {
2017-05-21 14:10:36 +00:00
$in = [
[ 'folderId' => 0 ],
2020-03-01 20:16:50 +00:00
[ 'folderId' => 42 ],
2017-05-21 14:10:36 +00:00
[ 'folderId' => 2112 ],
2020-03-01 20:16:50 +00:00
[ 'folderId' => 42 ],
[ 'folderId' => - 1 ],
2017-07-24 12:15:37 +00:00
[],
2017-05-21 14:10:36 +00:00
];
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 1 , [ 'folder' => 42 ]) -> returns ( true );
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 1 , [ 'folder' => null ]) -> returns ( true );
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 1 , [ 'folder' => 2112 ]) -> throws ( new ExceptionInput ( " idMissing " )); // folder does not exist
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 1 , [ 'folder' => - 1 ]) -> throws ( new ExceptionInput ( " typeViolation " )); // folder is invalid
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 42 , $this -> anything ()) -> throws ( new ExceptionInput ( " subjectMissing " )); // subscription does not exist
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/move " , json_encode ( $in [ 0 ])));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/move " , json_encode ( $in [ 1 ])));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 422 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/move " , json_encode ( $in [ 2 ])));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 404 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/42/move " , json_encode ( $in [ 3 ])));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 422 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/move " , json_encode ( $in [ 4 ])));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 422 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/move " , json_encode ( $in [ 5 ])));
2017-05-21 14:10:36 +00:00
}
2020-01-20 18:52:48 +00:00
public function testRenameASubscription () : void {
2017-05-21 14:10:36 +00:00
$in = [
[ 'feedTitle' => null ],
[ 'feedTitle' => " Ook " ],
[ 'feedTitle' => " " ],
[ 'feedTitle' => " " ],
[ 'feedTitle' => false ],
[ 'feedTitle' => " Feed does not exist " ],
2017-07-24 12:15:37 +00:00
[],
2017-05-21 14:10:36 +00:00
];
2021-03-01 15:03:52 +00:00
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 1 , $this -> identicalTo ([ 'title' => null ])) -> returns ( true );
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 1 , $this -> identicalTo ([ 'title' => " Ook " ])) -> returns ( true );
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 1 , $this -> identicalTo ([ 'title' => " " ])) -> throws ( new ExceptionInput ( " whitespace " ));
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 1 , $this -> identicalTo ([ 'title' => " " ])) -> throws ( new ExceptionInput ( " missing " ));
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 1 , $this -> identicalTo ([ 'title' => false ])) -> throws ( new ExceptionInput ( " missing " ));
$this -> dbMock -> subscriptionPropertiesSet -> with ( $this -> userId , 42 , $this -> anything ()) -> throws ( new ExceptionInput ( " subjectMissing " ));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 422 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/rename " , json_encode ( $in [ 0 ])));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/rename " , json_encode ( $in [ 1 ])));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 422 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/rename " , json_encode ( $in [ 2 ])));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 422 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/rename " , json_encode ( $in [ 3 ])));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 404 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/42/rename " , json_encode ( $in [ 4 ])));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 422 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/rename " , json_encode ( $in [ 6 ])));
2017-05-21 14:10:36 +00:00
}
2017-06-03 21:34:37 +00:00
2020-01-20 18:52:48 +00:00
public function testListStaleFeeds () : void {
2017-06-03 21:34:37 +00:00
$out = [
[
2020-03-01 20:16:50 +00:00
'id' => 42 ,
2017-06-03 21:34:37 +00:00
'userId' => " " ,
],
[
2020-03-01 20:16:50 +00:00
'id' => 2112 ,
2017-06-03 21:34:37 +00:00
'userId' => " " ,
],
];
2021-03-01 15:03:52 +00:00
$this -> dbMock -> feedListStale -> returns ( $this -> v ( array_column ( $out , " id " )));
2022-08-06 02:08:36 +00:00
$exp = HTTP :: respJson ([ 'feeds' => $out ]);
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /feeds/all " ));
2017-06-03 21:34:37 +00:00
}
2021-02-09 15:05:44 +00:00
public function testListStaleFeedsWithoutAuthority () : void {
2021-03-01 15:03:52 +00:00
$this -> userMock -> propertiesGet -> returns ([ 'admin' => false ]);
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 403 );
2021-02-09 15:05:44 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /feeds/all " ));
2021-03-01 15:03:52 +00:00
$this -> dbMock -> feedListStale -> never () -> called ();
2021-02-09 15:05:44 +00:00
}
2022-12-30 17:41:12 +00:00
/** @dataProvider provideFeedUpdates */
public function testUpdateAFeed ( array $in , int $exp ) : void {
$this -> dbMock -> subscriptionUpdate -> with ( " ook " , 42 ) -> returns ( true );
$this -> dbMock -> subscriptionUpdate -> with ( " eek " , 2112 ) -> throws ( new ExceptionInput ( " subjectMissing " ));
$this -> dbMock -> subscriptionUpdate -> with ( null , $this -> anything ()) -> throws ( new ExceptionInput ( " subjectMissing " ));
$this -> dbMock -> subscriptionUpdate -> with ( $this -> anything (), $this -> lessThan ( 1 )) -> throws ( new ExceptionInput ( " typeViolation " ));
$exp = HTTP :: respEmpty ( $exp );
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /feeds/update " , json_encode ( $in )));
}
public function provideFeedUpdates () : iterable {
return [
'Valid input' => [[ 'userId' => " ook " , 'feedId' => 42 ], 204 ],
'Missing feed' => [[ 'userId' => " eek " , 'feedId' => 2112 ], 404 ],
'String ID' => [[ 'userId' => " ook " , 'feedId' => " ook " ], 422 ],
'Negative ID' => [[ 'userId' => " ook " , 'feedId' => - 1 ], 422 ],
'Bad input 1' => [[ 'userId' => " ook " , 'feed' => 42 ], 422 ],
'Bad input 2' => [[ 'user' => " ook " , 'feedId' => 42 ], 404 ],
2017-06-03 21:34:37 +00:00
];
}
2017-07-09 21:57:18 +00:00
2021-02-09 15:05:44 +00:00
public function testUpdateAFeedWithoutAuthority () : void {
2021-03-01 15:03:52 +00:00
$this -> userMock -> propertiesGet -> returns ([ 'admin' => false ]);
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 403 );
2021-02-09 15:05:44 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /feeds/update " , [ 'feedId' => 42 ]));
2022-12-30 17:41:12 +00:00
$this -> dbMock -> subscriptionUpdate -> never () -> called ();
2021-02-09 15:05:44 +00:00
}
2020-12-20 22:42:28 +00:00
/** @dataProvider provideArticleQueries */
public function testListArticles ( string $url , array $in , Context $c , $out , ResponseInterface $exp ) : void {
if ( $out instanceof \Exception ) {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleList -> throws ( $out );
2020-12-20 22:42:28 +00:00
} else {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleList -> returns ( $out );
2020-12-20 22:42:28 +00:00
}
$this -> assertMessage ( $exp , $this -> req ( " GET " , $url , $in ));
$columns = [ " edition " , " guid " , " id " , " url " , " title " , " author " , " edited_date " , " content " , " media_type " , " media_url " , " subscription " , " unread " , " starred " , " modified_date " , " fingerprint " ];
$order = ( $in [ 'oldestFirst' ] ? ? false ) ? " edition " : " edition desc " ;
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleList -> calledWith ( $this -> userId , $this -> equalTo ( $c ), $columns , [ $order ]);
2020-12-20 22:42:28 +00:00
}
public function provideArticleQueries () : iterable {
$c = ( new Context ) -> hidden ( false );
$t = Date :: normalize ( time ());
$out = new Result ( $this -> v ( $this -> articles [ 'db' ]));
2022-08-06 02:08:36 +00:00
$r200 = HTTP :: respJson ([ 'items' => $this -> articles [ 'rest' ]]);
2022-08-05 02:04:39 +00:00
$r422 = HTTP :: respEmpty ( 422 );
2020-12-20 22:42:28 +00:00
return [
2022-04-20 02:53:36 +00:00
[ " /items " , [], clone $c , $out , $r200 ],
[ " /items " , [ 'type' => 0 , 'id' => 42 ], ( clone $c ) -> subscription ( 42 ), new ExceptionInput ( " idMissing " ), $r422 ],
[ " /items " , [ 'type' => 1 , 'id' => 2112 ], ( clone $c ) -> folder ( 2112 ), new ExceptionInput ( " idMissing " ), $r422 ],
[ " /items " , [ 'type' => 0 , 'id' => - 1 ], ( clone $c ) -> subscription ( - 1 ), new ExceptionInput ( " typeViolation " ), $r422 ],
[ " /items " , [ 'type' => 1 , 'id' => - 1 ], ( clone $c ) -> folder ( - 1 ), new ExceptionInput ( " typeViolation " ), $r422 ],
[ " /items " , [ 'type' => 2 , 'id' => 0 ], ( clone $c ) -> starred ( true ), $out , $r200 ],
[ " /items " , [ 'type' => 3 , 'id' => 0 ], clone $c , $out , $r200 ],
[ " /items " , [ 'getRead' => true ], clone $c , $out , $r200 ],
[ " /items " , [ 'getRead' => false ], ( clone $c ) -> unread ( true ), $out , $r200 ],
[ " /items " , [ 'lastModified' => $t -> getTimestamp ()], ( clone $c ) -> markedRange ( $t , null ), $out , $r200 ],
[ " /items " , [ 'oldestFirst' => true , 'batchSize' => 10 , 'offset' => 5 ], ( clone $c ) -> editionRange ( 6 , null ) -> limit ( 10 ), $out , $r200 ],
[ " /items " , [ 'oldestFirst' => false , 'batchSize' => 5 , 'offset' => 5 ], ( clone $c ) -> editionRange ( null , 4 ) -> limit ( 5 ), $out , $r200 ],
[ " /items " , [ 'oldestFirst' => false , 'batchSize' => 5 , 'offset' => 0 ], ( clone $c ) -> limit ( 5 ), $out , $r200 ],
[ " /items/updated " , [], clone $c , $out , $r200 ],
[ " /items/updated " , [ 'type' => 0 , 'id' => 42 ], ( clone $c ) -> subscription ( 42 ), new ExceptionInput ( " idMissing " ), $r422 ],
[ " /items/updated " , [ 'type' => 1 , 'id' => 2112 ], ( clone $c ) -> folder ( 2112 ), new ExceptionInput ( " idMissing " ), $r422 ],
[ " /items/updated " , [ 'type' => 0 , 'id' => - 1 ], ( clone $c ) -> subscription ( - 1 ), new ExceptionInput ( " typeViolation " ), $r422 ],
[ " /items/updated " , [ 'type' => 1 , 'id' => - 1 ], ( clone $c ) -> folder ( - 1 ), new ExceptionInput ( " typeViolation " ), $r422 ],
[ " /items/updated " , [ 'type' => 2 , 'id' => 0 ], ( clone $c ) -> starred ( true ), $out , $r200 ],
[ " /items/updated " , [ 'type' => 3 , 'id' => 0 ], clone $c , $out , $r200 ],
[ " /items/updated " , [ 'getRead' => true ], clone $c , $out , $r200 ],
[ " /items/updated " , [ 'getRead' => false ], ( clone $c ) -> unread ( true ), $out , $r200 ],
[ " /items/updated " , [ 'lastModified' => $t -> getTimestamp ()], ( clone $c ) -> markedRange ( $t , null ), $out , $r200 ],
[ " /items/updated " , [ 'oldestFirst' => true , 'batchSize' => 10 , 'offset' => 5 ], ( clone $c ) -> editionRange ( 6 , null ) -> limit ( 10 ), $out , $r200 ],
[ " /items/updated " , [ 'oldestFirst' => false , 'batchSize' => 5 , 'offset' => 5 ], ( clone $c ) -> editionRange ( null , 4 ) -> limit ( 5 ), $out , $r200 ],
[ " /items/updated " , [ 'oldestFirst' => false , 'batchSize' => 5 , 'offset' => 0 ], ( clone $c ) -> limit ( 5 ), $out , $r200 ],
2017-07-09 21:57:18 +00:00
];
}
2020-01-20 18:52:48 +00:00
public function testMarkAFolderRead () : void {
2017-07-09 21:57:18 +00:00
$read = [ 'read' => true ];
$in = json_encode ([ 'newestItemId' => 2112 ]);
2022-04-20 02:53:36 +00:00
$this -> dbMock -> articleMark -> with ( $this -> userId , $read , $this -> equalTo (( new Context ) -> folder ( 1 ) -> editionRange ( null , 2112 ) -> hidden ( false ))) -> returns ( 42 );
$this -> dbMock -> articleMark -> with ( $this -> userId , $read , $this -> equalTo (( new Context ) -> folder ( 42 ) -> editionRange ( null , 2112 ) -> hidden ( false ))) -> throws ( new ExceptionInput ( " idMissing " )); // folder doesn't exist
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /folders/1/read " , $in ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /folders/1/read?newestItemId=2112 " ));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 422 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /folders/1/read " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /folders/1/read?newestItemId=ook " ));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 404 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /folders/42/read " , $in ));
2017-07-09 21:57:18 +00:00
}
2020-01-20 18:52:48 +00:00
public function testMarkASubscriptionRead () : void {
2017-07-09 21:57:18 +00:00
$read = [ 'read' => true ];
$in = json_encode ([ 'newestItemId' => 2112 ]);
2022-04-20 02:53:36 +00:00
$this -> dbMock -> articleMark -> with ( $this -> userId , $read , $this -> equalTo (( new Context ) -> subscription ( 1 ) -> editionRange ( null , 2112 ) -> hidden ( false ))) -> returns ( 42 );
$this -> dbMock -> articleMark -> with ( $this -> userId , $read , $this -> equalTo (( new Context ) -> subscription ( 42 ) -> editionRange ( null , 2112 ) -> hidden ( false ))) -> throws ( new ExceptionInput ( " idMissing " )); // subscription doesn't exist
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/read " , $in ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/read?newestItemId=2112 " ));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 422 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/read " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/1/read?newestItemId=ook " ));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 404 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /feeds/42/read " , $in ));
2017-07-09 21:57:18 +00:00
}
2020-01-20 18:52:48 +00:00
public function testMarkAllItemsRead () : void {
2017-07-09 21:57:18 +00:00
$read = [ 'read' => true ];
$in = json_encode ([ 'newestItemId' => 2112 ]);
2022-04-20 02:53:36 +00:00
$this -> dbMock -> articleMark -> with ( $this -> userId , $read , $this -> equalTo (( new Context ) -> editionRange ( null , 2112 ))) -> returns ( 42 );
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/read " , $in ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/read?newestItemId=2112 " ));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 422 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/read " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/read?newestItemId=ook " ));
2017-07-09 21:57:18 +00:00
}
2020-01-20 18:52:48 +00:00
public function testChangeMarksOfASingleArticle () : void {
2017-07-09 21:57:18 +00:00
$read = [ 'read' => true ];
$unread = [ 'read' => false ];
$star = [ 'starred' => true ];
$unstar = [ 'starred' => false ];
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleMark -> with ( $this -> userId , $read , $this -> equalTo (( new Context ) -> edition ( 1 ))) -> returns ( 42 );
$this -> dbMock -> articleMark -> with ( $this -> userId , $read , $this -> equalTo (( new Context ) -> edition ( 42 ))) -> throws ( new ExceptionInput ( " subjectMissing " )); // edition doesn't exist doesn't exist
$this -> dbMock -> articleMark -> with ( $this -> userId , $unread , $this -> equalTo (( new Context ) -> edition ( 2 ))) -> returns ( 42 );
$this -> dbMock -> articleMark -> with ( $this -> userId , $unread , $this -> equalTo (( new Context ) -> edition ( 47 ))) -> throws ( new ExceptionInput ( " subjectMissing " )); // edition doesn't exist doesn't exist
$this -> dbMock -> articleMark -> with ( $this -> userId , $star , $this -> equalTo (( new Context ) -> article ( 3 ))) -> returns ( 42 );
$this -> dbMock -> articleMark -> with ( $this -> userId , $star , $this -> equalTo (( new Context ) -> article ( 2112 ))) -> throws ( new ExceptionInput ( " subjectMissing " )); // article doesn't exist doesn't exist
$this -> dbMock -> articleMark -> with ( $this -> userId , $unstar , $this -> equalTo (( new Context ) -> article ( 4 ))) -> returns ( 42 );
$this -> dbMock -> articleMark -> with ( $this -> userId , $unstar , $this -> equalTo (( new Context ) -> article ( 1337 ))) -> throws ( new ExceptionInput ( " subjectMissing " )); // article doesn't exist doesn't exist
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/1/read " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/2/unread " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/1/3/star " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/4400/4/unstar " ));
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 404 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/42/read " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/47/unread " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/1/2112/star " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/4400/1337/unstar " ));
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleMark -> times ( 8 ) -> calledWith ( $this -> userId , $this -> anything (), $this -> anything ());
2017-07-09 21:57:18 +00:00
}
2020-01-20 18:52:48 +00:00
public function testChangeMarksOfMultipleArticles () : void {
2017-07-09 21:57:18 +00:00
$read = [ 'read' => true ];
$unread = [ 'read' => false ];
$star = [ 'starred' => true ];
$unstar = [ 'starred' => false ];
$in = [
[ " ook " , " eek " , " ack " ],
2017-08-29 14:50:31 +00:00
range ( 100 , 199 ),
2017-07-09 21:57:18 +00:00
];
$inStar = $in ;
2017-08-29 14:50:31 +00:00
for ( $a = 0 ; $a < sizeof ( $inStar ); $a ++ ) {
for ( $b = 0 ; $b < sizeof ( $inStar [ $a ]); $b ++ ) {
2017-07-09 21:57:18 +00:00
$inStar [ $a ][ $b ] = [ 'feedId' => 2112 , 'guidHash' => $inStar [ $a ][ $b ]];
}
}
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleMark -> with ( $this -> userId , $this -> anything (), $this -> anything ()) -> returns ( 42 );
$this -> dbMock -> articleMark -> with ( $this -> userId , $this -> anything (), $this -> equalTo (( new Context ) -> editions ([]))) -> throws ( new ExceptionInput ( " tooShort " )); // data model function requires one valid integer for multiples
$this -> dbMock -> articleMark -> with ( $this -> userId , $this -> anything (), $this -> equalTo (( new Context ) -> articles ([]))) -> throws ( new ExceptionInput ( " tooShort " )); // data model function requires one valid integer for multiples
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/read/multiple " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/unread/multiple " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/star/multiple " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/unstar/multiple " ));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/read/multiple " , json_encode ([ 'items' => " ook " ])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/unread/multiple " , json_encode ([ 'items' => " ook " ])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/star/multiple " , json_encode ([ 'items' => " ook " ])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/unstar/multiple " , json_encode ([ 'items' => " ook " ])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/read/multiple " , json_encode ([ 'items' => []])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/unread/multiple " , json_encode ([ 'items' => []])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/read/multiple " , json_encode ([ 'items' => $in [ 0 ]])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/unread/multiple " , json_encode ([ 'items' => $in [ 0 ]])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/read/multiple " , json_encode ([ 'items' => $in [ 1 ]])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/unread/multiple " , json_encode ([ 'items' => $in [ 1 ]])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/star/multiple " , json_encode ([ 'items' => []])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/unstar/multiple " , json_encode ([ 'items' => []])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/star/multiple " , json_encode ([ 'items' => $inStar [ 0 ]])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/unstar/multiple " , json_encode ([ 'items' => $inStar [ 0 ]])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/star/multiple " , json_encode ([ 'items' => $inStar [ 1 ]])));
$this -> assertMessage ( $exp , $this -> req ( " PUT " , " /items/unstar/multiple " , json_encode ([ 'items' => $inStar [ 1 ]])));
2017-07-09 21:57:18 +00:00
// ensure the data model was queried appropriately for read/unread
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $read , $this -> equalTo (( new Context ) -> editions ([])));
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $read , $this -> equalTo (( new Context ) -> editions ( $in [ 0 ])));
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $read , $this -> equalTo (( new Context ) -> editions ( $in [ 1 ])));
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $unread , $this -> equalTo (( new Context ) -> editions ([])));
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $unread , $this -> equalTo (( new Context ) -> editions ( $in [ 0 ])));
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $unread , $this -> equalTo (( new Context ) -> editions ( $in [ 1 ])));
2017-07-09 21:57:18 +00:00
// ensure the data model was queried appropriately for star/unstar
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $star , $this -> equalTo (( new Context ) -> articles ([])));
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $star , $this -> equalTo (( new Context ) -> articles ( $in [ 0 ])));
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $star , $this -> equalTo (( new Context ) -> articles ( $in [ 1 ])));
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $unstar , $this -> equalTo (( new Context ) -> articles ([])));
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $unstar , $this -> equalTo (( new Context ) -> articles ( $in [ 0 ])));
$this -> dbMock -> articleMark -> atLeast ( 1 ) -> calledWith ( $this -> userId , $unstar , $this -> equalTo (( new Context ) -> articles ( $in [ 1 ])));
2017-07-09 21:57:18 +00:00
}
2017-07-19 22:07:36 +00:00
2020-01-20 18:52:48 +00:00
public function testQueryTheServerStatus () : void {
2019-01-21 03:40:49 +00:00
$interval = Arsse :: $conf -> serviceFrequency ;
2017-07-19 22:07:36 +00:00
$valid = ( new \DateTimeImmutable ( " now " , new \DateTimezone ( " UTC " ))) -> sub ( $interval );
$invalid = $valid -> sub ( $interval ) -> sub ( $interval );
2021-03-01 15:03:52 +00:00
$this -> dbMock -> metaGet -> with ( " service_last_checkin " ) -> returns ( Date :: transform ( $valid , " sql " )) -> returns ( Date :: transform ( $invalid , " sql " ));
$this -> dbMock -> driverCharsetAcceptable -> returns ( true ) -> returns ( false );
2017-07-19 22:07:36 +00:00
$arr1 = $arr2 = [
2020-03-01 20:16:50 +00:00
'version' => V1_2 :: VERSION ,
2017-10-01 13:33:49 +00:00
'arsse_version' => Arsse :: VERSION ,
2020-03-01 20:16:50 +00:00
'warnings' => [
2017-07-19 22:07:36 +00:00
'improperlyConfiguredCron' => false ,
2020-03-01 20:16:50 +00:00
'incorrectDbCharset' => false ,
],
2017-07-19 22:07:36 +00:00
];
$arr2 [ 'warnings' ][ 'improperlyConfiguredCron' ] = true ;
2017-11-29 23:14:59 +00:00
$arr2 [ 'warnings' ][ 'incorrectDbCharset' ] = true ;
2022-08-06 02:08:36 +00:00
$exp = HTTP :: respJson ( $arr1 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /status " ));
2017-07-19 22:07:36 +00:00
}
2017-08-02 22:27:04 +00:00
2020-01-20 18:52:48 +00:00
public function testCleanUpBeforeUpdate () : void {
2023-03-14 23:58:33 +00:00
$this -> dbMock -> subscriptionCleanup -> with () -> returns ( true );
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /cleanup/before-update " ));
2023-03-14 23:58:33 +00:00
$this -> dbMock -> subscriptionCleanup -> calledWith ();
2017-08-02 22:27:04 +00:00
}
2018-10-26 18:58:04 +00:00
2021-02-09 15:05:44 +00:00
public function testCleanUpBeforeUpdateWithoutAuthority () : void {
2021-03-01 15:03:52 +00:00
$this -> userMock -> propertiesGet -> returns ([ 'admin' => false ]);
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 403 );
2021-02-09 15:05:44 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /cleanup/before-update " ));
2023-03-14 23:58:33 +00:00
$this -> dbMock -> subscriptionCleanup -> never () -> called ();
2021-02-09 15:05:44 +00:00
}
2020-01-20 18:52:48 +00:00
public function testCleanUpAfterUpdate () : void {
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleCleanup -> with () -> returns ( true );
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 204 );
2018-01-11 16:09:25 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /cleanup/after-update " ));
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleCleanup -> calledWith ();
2017-08-18 02:36:15 +00:00
}
2018-11-06 18:21:53 +00:00
2021-02-09 15:05:44 +00:00
public function testCleanUpAfterUpdateWithoutAuthority () : void {
2021-03-01 15:03:52 +00:00
$this -> userMock -> propertiesGet -> returns ([ 'admin' => false ]);
2022-08-05 02:04:39 +00:00
$exp = HTTP :: respEmpty ( 403 );
2021-02-09 15:05:44 +00:00
$this -> assertMessage ( $exp , $this -> req ( " GET " , " /cleanup/after-update " ));
2023-03-14 23:58:33 +00:00
$this -> dbMock -> subscriptionCleanup -> never () -> called ();
2021-02-09 15:05:44 +00:00
}
2020-01-20 18:52:48 +00:00
public function testQueryTheUserStatus () : void {
2018-11-06 18:21:53 +00:00
$act = $this -> req ( " GET " , " /user " );
2022-08-06 02:08:36 +00:00
$exp = HTTP :: respJson ([
2021-03-01 15:03:52 +00:00
'userId' => $this -> userId ,
'displayName' => $this -> userId ,
2022-08-06 02:08:36 +00:00
'lastLoginTimestamp' => $this -> approximateTime ( json_decode (( string ) $act -> getBody (), true )[ 'lastLoginTimestamp' ], new \DateTimeImmutable ),
2020-03-01 20:16:50 +00:00
'avatar' => null ,
2018-11-06 18:21:53 +00:00
]);
$this -> assertMessage ( $exp , $act );
2017-08-18 02:36:15 +00:00
}
2020-03-01 20:16:50 +00:00
2020-01-20 18:52:48 +00:00
public function testPreferJsonOverQueryParameters () : void {
2018-11-07 18:01:46 +00:00
$in = [ 'name' => " Software " ];
$url = " /folders?name=Hardware " ;
$out1 = [ 'id' => 1 , 'name' => " Software " ];
$out2 = [ 'id' => 2 , 'name' => " Hardware " ];
2021-03-01 15:03:52 +00:00
$this -> dbMock -> folderAdd -> with ( $this -> anything (), $this -> anything ()) -> returns ( 2 );
$this -> dbMock -> folderAdd -> with ( $this -> anything (), $in ) -> returns ( 1 );
$this -> dbMock -> folderPropertiesGet -> with ( $this -> userId , 1 ) -> returns ( $this -> v ( $out1 ));
$this -> dbMock -> folderPropertiesGet -> with ( $this -> userId , 2 ) -> returns ( $this -> v ( $out2 ));
2022-08-06 02:08:36 +00:00
$exp = HTTP :: respJson ([ 'folders' => [ $out1 ]]);
2022-08-06 02:10:36 +00:00
$this -> assertMessage ( $exp , $this -> req ( " POST " , $url , json_encode ( $in )));
2018-11-07 18:01:46 +00:00
}
2020-03-01 20:16:50 +00:00
2020-01-20 18:52:48 +00:00
public function testMeldJsonAndQueryParameters () : void {
2018-11-07 18:01:46 +00:00
$in = [ 'oldestFirst' => true ];
$url = " /items?type=2 " ;
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleList -> returns ( new Result ([]));
2018-11-07 18:01:46 +00:00
$this -> req ( " GET " , $url , json_encode ( $in ));
2021-03-01 15:03:52 +00:00
$this -> dbMock -> articleList -> calledWith ( $this -> userId , $this -> equalTo (( new Context ) -> starred ( true ) -> hidden ( false )), $this -> anything (), [ " edition " ]);
2018-11-07 18:01:46 +00:00
}
2017-08-29 14:50:31 +00:00
}