mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 21:22:40 +00:00
Tests and fixed for Fever feeds and groups
This commit is contained in:
parent
7faec3b0db
commit
de615c671a
2 changed files with 96 additions and 28 deletions
|
@ -30,8 +30,8 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
}
|
||||
|
||||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
$inR = $req->getQueryParams();
|
||||
$inW = $req->getParsedBody();
|
||||
$inR = $req->getQueryParams() ?? [];
|
||||
$inW = $req->getParsedBody() ?? [];
|
||||
if (!array_key_exists("api", $inR)) {
|
||||
// the original would have shown the Fever UI in the absence of the "api" parameter, but we'll return 404
|
||||
return new EmptyResponse(404);
|
||||
|
@ -57,14 +57,13 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// otherwise if HTTP authentication failed or is required, deny access at the HTTP level
|
||||
return new EmptyResponse(401);
|
||||
}
|
||||
// check that the user specified credentials
|
||||
// produce a full response if authenticated or a basic response otherwise
|
||||
if ($this->logIn(strtolower($inW['api_key'] ?? ""))) {
|
||||
$out['auth'] = 1;
|
||||
$out = $this->processRequest($out, $inR, $inW);
|
||||
$out = $this->processRequest($this->baseResponse(true), $inR, $inW);
|
||||
} else {
|
||||
$out['auth'] = 0;
|
||||
$out = $this->baseResponse(false);
|
||||
}
|
||||
// return the result
|
||||
// return the result, possibly formatted as XML
|
||||
return $this->formatResponse($out, $xml);
|
||||
break;
|
||||
default:
|
||||
|
@ -73,9 +72,6 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
}
|
||||
|
||||
protected function processRequest(array $out, array $G, array $P): array {
|
||||
// add base metadata
|
||||
$out['last_refreshed_on_time'] = Date::transform(Arsse::$db->subscriptionRefreshed(Arsse::$user->id), "unix");
|
||||
// handle each possible parameter
|
||||
if (array_key_exists("feeds", $G) || array_key_exists("groups", $G)) {
|
||||
if (array_key_exists("groups", $G)) {
|
||||
$out['groups'] = $this->getGroups();
|
||||
|
@ -91,6 +87,18 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
return $out;
|
||||
}
|
||||
|
||||
protected function baseResponse(bool $authenticated): array {
|
||||
$out = [
|
||||
'api_version' => self::LEVEL,
|
||||
'auth' => (int) $authenticated,
|
||||
];
|
||||
if ($authenticated) {
|
||||
// authenticated requests always include the most recent feed refresh
|
||||
$out['last_refreshed_on_time'] = $this->getRefreshTime();
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
protected function formatResponse(array $data, bool $xml): ResponseInterface {
|
||||
if ($xml) {
|
||||
throw \Exception("Not implemented yet");
|
||||
|
@ -115,6 +123,10 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
return true;
|
||||
}
|
||||
|
||||
protected function getRefreshTime() {
|
||||
return Date::transform(Arsse::$db->subscriptionRefreshed(Arsse::$user->id), "unix");
|
||||
}
|
||||
|
||||
protected function getFeeds(): array {
|
||||
$out = [];
|
||||
foreach (arsse::$db->subscriptionList(Arsse::$user->id) as $sub) {
|
||||
|
@ -125,7 +137,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
'url' => $sub['url'],
|
||||
'site_url' => $sub['source'],
|
||||
'is_spark' => 0,
|
||||
'lat_updated_on_time' => Date::transform($sub['edited'], "unix", "sql"),
|
||||
'last_updated_on_time' => Date::transform($sub['edited'], "unix", "sql"),
|
||||
];
|
||||
}
|
||||
return $out;
|
||||
|
|
|
@ -31,7 +31,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
return $value;
|
||||
}
|
||||
|
||||
protected function req($dataGet, $dataPost, string $method = "POST", string $type = null, string $url = "", string $user = null): ResponseInterface {
|
||||
protected function req($dataGet, $dataPost = "", string $method = "POST", string $type = null, string $url = "", string $user = null): ResponseInterface {
|
||||
$url = "/fever/".$url;
|
||||
$server = [
|
||||
'REQUEST_METHOD' => $method,
|
||||
|
@ -39,11 +39,10 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
'HTTP_CONTENT_TYPE' => $type ?? "application/x-www-form-urlencoded",
|
||||
];
|
||||
$req = new ServerRequest($server, [], $url, $method, "php://memory");
|
||||
if (is_array($dataGet)) {
|
||||
$req = $req->withRequestTarget($url)->withQueryParams($dataGet);
|
||||
} else {
|
||||
$req = $req->withRequestTarget($url."?".http_build_query((string) $dataGet, "", "&", \PHP_QUERY_RFC3986));
|
||||
if (!is_array($dataGet)) {
|
||||
parse_str($dataGet, $dataGet);
|
||||
}
|
||||
$req = $req->withRequestTarget($url)->withQueryParams($dataGet);
|
||||
if (is_array($dataPost)) {
|
||||
$req = $req->withParsedBody($dataPost);
|
||||
} else {
|
||||
|
@ -72,8 +71,9 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Arsse::$db = \Phake::mock(Database::class);
|
||||
\Phake::when(Arsse::$db)->begin->thenReturn(\Phake::mock(Transaction::class));
|
||||
\Phake::when(Arsse::$db)->tokenLookup->thenReturn(['user' => "john.doe@example.com"]);
|
||||
// instantiate the handler
|
||||
$this->h = new API();
|
||||
// instantiate the handler as a partial mock to simplify testing
|
||||
$this->h = \Phake::partialMock(API::class);
|
||||
\Phake::when($this->h)->baseResponse->thenReturn([]);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
|
@ -89,8 +89,10 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Arsse::$user->id = null;
|
||||
\Phake::when(Arsse::$db)->tokenLookup->thenThrow(new ExceptionInput("subjectMissing"));
|
||||
\Phake::when(Arsse::$db)->tokenLookup("fever.login", "validtoken")->thenReturn(['user' => "jane.doe@example.com"]);
|
||||
// use a partial mock to test only the authentication process
|
||||
$this->h = \Phake::partialMock(API::class);
|
||||
// test only the authentication process
|
||||
\Phake::when($this->h)->baseResponse->thenReturnCallback(function(bool $authenticated) {
|
||||
return ['auth' => (int) $authenticated];
|
||||
});
|
||||
\Phake::when($this->h)->processRequest->thenReturnCallback(function($out, $G, $P) {
|
||||
return $out;
|
||||
});
|
||||
|
@ -99,8 +101,8 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
public function provideTokenAuthenticationRequests() {
|
||||
$success = new JsonResponse(['api_version' => API::LEVEL, 'auth' => 1]);
|
||||
$failure = new JsonResponse(['api_version' => API::LEVEL, 'auth' => 0]);
|
||||
$success = new JsonResponse(['auth' => 1]);
|
||||
$failure = new JsonResponse(['auth' => 0]);
|
||||
$denied = new EmptyResponse(401);
|
||||
return [
|
||||
[false, true, null, [], ['api' => null], $failure],
|
||||
|
@ -149,4 +151,58 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
[true, false, "validUser", ['api_key' => "invalidToken"], ['api' => null], $success],
|
||||
];
|
||||
}
|
||||
|
||||
public function testListGroups() {
|
||||
\Phake::when(Arsse::$db)->tagList(Arsse::$user->id)->thenReturn(new Result([
|
||||
['id' => 1, 'name' => "Fascinating", 'subscriptions' => 2],
|
||||
['id' => 2, 'name' => "Interesting", 'subscriptions' => 2],
|
||||
['id' => 3, 'name' => "Boring", 'subscriptions' => 0],
|
||||
]));
|
||||
\Phake::when(Arsse::$db)->tagSummarize(Arsse::$user->id)->thenReturn(new Result([
|
||||
['id' => 1, 'name' => "Fascinating", 'subscription' => 1],
|
||||
['id' => 1, 'name' => "Fascinating", 'subscription' => 2],
|
||||
['id' => 2, 'name' => "Interesting", 'subscription' => 1],
|
||||
['id' => 2, 'name' => "Interesting", 'subscription' => 3],
|
||||
]));
|
||||
$exp = new JsonResponse([
|
||||
'groups' => [
|
||||
['id' => 1, 'title' => "Fascinating"],
|
||||
['id' => 2, 'title' => "Interesting"],
|
||||
['id' => 3, 'title' => "Boring"],
|
||||
],
|
||||
'feeds_groups' => [
|
||||
['group_id' => 1, 'feed_ids' => "1,2"],
|
||||
['group_id' => 2, 'feed_ids' => "1,3"],
|
||||
],
|
||||
]);
|
||||
$act = $this->req("api&groups");
|
||||
$this->assertMessage($exp, $act);
|
||||
}
|
||||
|
||||
public function testListFeeds() {
|
||||
\Phake::when(Arsse::$db)->subscriptionList(Arsse::$user->id)->thenReturn(new Result([
|
||||
['id' => 1, 'feed' => 5, 'title' => "Ankh-Morpork News", 'url' => "http://example.com/feed", 'source' => "http://example.com/", 'edited' => "2019-01-01 21:12:00", 'favicon' => "http://example.com/favicon.ico"],
|
||||
['id' => 2, 'feed' => 9, 'title' => "Ook, Ook Eek Ook!", 'url' => "http://example.net/feed", 'source' => "http://example.net/", 'edited' => "1988-06-24 12:21:00", 'favicon' => ""],
|
||||
['id' => 3, 'feed' => 1, 'title' => "The Last Soul", 'url' => "http://example.org/feed", 'source' => "http://example.org/", 'edited' => "1991-08-12 03:22:00", 'favicon' => "http://example.org/favicon.ico"],
|
||||
]));
|
||||
\Phake::when(Arsse::$db)->tagSummarize(Arsse::$user->id)->thenReturn(new Result([
|
||||
['id' => 1, 'name' => "Fascinating", 'subscription' => 1],
|
||||
['id' => 1, 'name' => "Fascinating", 'subscription' => 2],
|
||||
['id' => 2, 'name' => "Interesting", 'subscription' => 1],
|
||||
['id' => 2, 'name' => "Interesting", 'subscription' => 3],
|
||||
]));
|
||||
$exp = new JsonResponse([
|
||||
'feeds' => [
|
||||
['id' => 1, 'favicon_id' => 5, 'title' => "Ankh-Morpork News", 'url' => "http://example.com/feed", 'site_url' => "http://example.com/", 'is_spark' => 0, 'last_updated_on_time' => strtotime("2019-01-01T21:12:00Z")],
|
||||
['id' => 2, 'favicon_id' => 0, 'title' => "Ook, Ook Eek Ook!", 'url' => "http://example.net/feed", 'site_url' => "http://example.net/", 'is_spark' => 0, 'last_updated_on_time' => strtotime("1988-06-24T12:21:00Z")],
|
||||
['id' => 3, 'favicon_id' => 1, 'title' => "The Last Soul", 'url' => "http://example.org/feed", 'site_url' => "http://example.org/", 'is_spark' => 0, 'last_updated_on_time' => strtotime("1991-08-12T03:22:00Z")],
|
||||
],
|
||||
'feeds_groups' => [
|
||||
['group_id' => 1, 'feed_ids' => "1,2"],
|
||||
['group_id' => 2, 'feed_ids' => "1,3"],
|
||||
],
|
||||
]);
|
||||
$act = $this->req("api&feeds");
|
||||
$this->assertMessage($exp, $act);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue