mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +00:00
Replace Resquest objects with PSR-7 request messages; improves #53
This commit is contained in:
parent
9ad0b47201
commit
890f9b07d4
12 changed files with 327 additions and 329 deletions
|
@ -8,10 +8,12 @@ namespace JKingWeb\Arsse\REST;
|
|||
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\ValueInfo;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
abstract class AbstractHandler implements Handler {
|
||||
abstract public function __construct();
|
||||
abstract public function dispatch(Request $req): \Psr\Http\Message\ResponseInterface;
|
||||
abstract public function dispatch(ServerRequestInterface $req): ResponseInterface;
|
||||
|
||||
protected function fieldMapNames(array $data, array $map): array {
|
||||
$out = [];
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\REST;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
interface Handler {
|
||||
public function __construct();
|
||||
public function dispatch(Request $req): \Psr\Http\Message\ResponseInterface;
|
||||
public function dispatch(ServerRequestInterface $req): ResponseInterface;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@ use JKingWeb\Arsse\Misc\ValueInfo;
|
|||
use JKingWeb\Arsse\AbstractException;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
||||
use \Psr\Http\Message\ResponseInterface;
|
||||
use JKingWeb\Arsse\REST\Target;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Diactoros\Response\JsonResponse as Response;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
|
||||
|
@ -43,53 +45,61 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
'items' => ValueInfo::T_MIXED | ValueInfo::M_ARRAY,
|
||||
];
|
||||
protected $paths = [
|
||||
'folders' => ['GET' => "folderList", 'POST' => "folderAdd"],
|
||||
'folders/1' => ['PUT' => "folderRename", 'DELETE' => "folderRemove"],
|
||||
'folders/1/read' => ['PUT' => "folderMarkRead"],
|
||||
'feeds' => ['GET' => "subscriptionList", 'POST' => "subscriptionAdd"],
|
||||
'feeds/1' => ['DELETE' => "subscriptionRemove"],
|
||||
'feeds/1/move' => ['PUT' => "subscriptionMove"],
|
||||
'feeds/1/rename' => ['PUT' => "subscriptionRename"],
|
||||
'feeds/1/read' => ['PUT' => "subscriptionMarkRead"],
|
||||
'feeds/all' => ['GET' => "feedListStale"],
|
||||
'feeds/update' => ['GET' => "feedUpdate"],
|
||||
'items' => ['GET' => "articleList"],
|
||||
'items/updated' => ['GET' => "articleList"],
|
||||
'items/read' => ['PUT' => "articleMarkReadAll"],
|
||||
'items/1/read' => ['PUT' => "articleMarkRead"],
|
||||
'items/1/unread' => ['PUT' => "articleMarkRead"],
|
||||
'items/read/multiple' => ['PUT' => "articleMarkReadMulti"],
|
||||
'items/unread/multiple' => ['PUT' => "articleMarkReadMulti"],
|
||||
'items/1/1/star' => ['PUT' => "articleMarkStarred"],
|
||||
'items/1/1/unstar' => ['PUT' => "articleMarkStarred"],
|
||||
'items/star/multiple' => ['PUT' => "articleMarkStarredMulti"],
|
||||
'items/unstar/multiple' => ['PUT' => "articleMarkStarredMulti"],
|
||||
'cleanup/before-update' => ['GET' => "cleanupBefore"],
|
||||
'cleanup/after-update' => ['GET' => "cleanupAfter"],
|
||||
'version' => ['GET' => "serverVersion"],
|
||||
'status' => ['GET' => "serverStatus"],
|
||||
'user' => ['GET' => "userStatus"],
|
||||
'/folders' => ['GET' => "folderList", 'POST' => "folderAdd"],
|
||||
'/folders/1' => ['PUT' => "folderRename", 'DELETE' => "folderRemove"],
|
||||
'/folders/1/read' => ['PUT' => "folderMarkRead"],
|
||||
'/feeds' => ['GET' => "subscriptionList", 'POST' => "subscriptionAdd"],
|
||||
'/feeds/1' => ['DELETE' => "subscriptionRemove"],
|
||||
'/feeds/1/move' => ['PUT' => "subscriptionMove"],
|
||||
'/feeds/1/rename' => ['PUT' => "subscriptionRename"],
|
||||
'/feeds/1/read' => ['PUT' => "subscriptionMarkRead"],
|
||||
'/feeds/all' => ['GET' => "feedListStale"],
|
||||
'/feeds/update' => ['GET' => "feedUpdate"],
|
||||
'/items' => ['GET' => "articleList"],
|
||||
'/items/updated' => ['GET' => "articleList"],
|
||||
'/items/read' => ['PUT' => "articleMarkReadAll"],
|
||||
'/items/1/read' => ['PUT' => "articleMarkRead"],
|
||||
'/items/1/unread' => ['PUT' => "articleMarkRead"],
|
||||
'/items/read/multiple' => ['PUT' => "articleMarkReadMulti"],
|
||||
'/items/unread/multiple' => ['PUT' => "articleMarkReadMulti"],
|
||||
'/items/1/1/star' => ['PUT' => "articleMarkStarred"],
|
||||
'/items/1/1/unstar' => ['PUT' => "articleMarkStarred"],
|
||||
'/items/star/multiple' => ['PUT' => "articleMarkStarredMulti"],
|
||||
'/items/unstar/multiple' => ['PUT' => "articleMarkStarredMulti"],
|
||||
'/cleanup/before-update' => ['GET' => "cleanupBefore"],
|
||||
'/cleanup/after-update' => ['GET' => "cleanupAfter"],
|
||||
'/version' => ['GET' => "serverVersion"],
|
||||
'/status' => ['GET' => "serverStatus"],
|
||||
'/user' => ['GET' => "userStatus"],
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
public function dispatch(\JKingWeb\Arsse\REST\Request $req): ResponseInterface {
|
||||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
// try to authenticate
|
||||
if (!Arsse::$user->authHTTP()) {
|
||||
return new EmptyResponse(401, ['WWW-Authenticate' => 'Basic realm="'.self::REALM.'"']);
|
||||
}
|
||||
// explode and normalize the URL path
|
||||
$target = new Target($req->getRequestTarget());
|
||||
// handle HTTP OPTIONS requests
|
||||
if ($req->method=="OPTIONS") {
|
||||
return $this->handleHTTPOptions($req->paths);
|
||||
if ($req->getMethod()=="OPTIONS") {
|
||||
return $this->handleHTTPOptions((string) $target);
|
||||
}
|
||||
// normalize the input
|
||||
if ($req->body) {
|
||||
$data = (string) $req->getBody();
|
||||
$type = "";
|
||||
if ($req->hasHeader("Content-Type")) {
|
||||
$type = $req->getHeader("Content-Type");
|
||||
$type = array_pop($type);
|
||||
}
|
||||
if ($data) {
|
||||
// if the entity body is not JSON according to content type, return "415 Unsupported Media Type"
|
||||
if (!preg_match("<^application/json\b|^$>", $req->type)) {
|
||||
if (!preg_match("<^application/json\b|^$>", $type)) {
|
||||
return new EmptyResponse(415, ['Accept' => "application/json"]);
|
||||
}
|
||||
$data = @json_decode($req->body, true);
|
||||
$data = @json_decode($data, true);
|
||||
if (json_last_error() != \JSON_ERROR_NONE) {
|
||||
// if the body could not be parsed as JSON, return "400 Bad Request"
|
||||
return new EmptyResponse(400);
|
||||
|
@ -98,10 +108,10 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$data = [];
|
||||
}
|
||||
// FIXME: Do query parameters take precedence in NextCloud? Is there a conflict error when values differ?
|
||||
$data = $this->normalizeInput(array_merge($data, $req->query), $this->validInput, "unix");
|
||||
$data = $this->normalizeInput(array_merge($data, $req->getQueryParams()), $this->validInput, "unix");
|
||||
// check to make sure the requested function is implemented
|
||||
try {
|
||||
$func = $this->chooseCall($req->paths, $req->method);
|
||||
$func = $this->chooseCall((string) $target, $req->getMethod());
|
||||
} catch (Exception404 $e) {
|
||||
return new EmptyResponse(404);
|
||||
} catch (Exception405 $e) {
|
||||
|
@ -112,7 +122,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
}
|
||||
// dispatch
|
||||
try {
|
||||
return $this->$func($req->paths, $data);
|
||||
return $this->$func($target->path, $data);
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
// if there was a REST exception return 400
|
||||
|
@ -124,19 +134,24 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
protected function normalizePath(array $url): string {
|
||||
// any URL components which are database IDs (integers greater than zero) should be replaced with "1", for easier comparison (we don't care about the specific ID)
|
||||
for ($a = 0; $a < sizeof($url); $a++) {
|
||||
if (ValueInfo::id($url[$a])) {
|
||||
$url[$a] = "1";
|
||||
protected function normalizePathIds(string $url): string {
|
||||
// first parse the URL and perform syntactic normalization
|
||||
$target = new Target($url);
|
||||
// any path components which are database IDs (integers greater than zero) should be replaced with "1", for easier comparison (we don't care about the specific ID)
|
||||
for ($a = 0; $a < sizeof($target->path); $a++) {
|
||||
if (ValueInfo::id($target->path[$a])) {
|
||||
$target->path[$a] = "1";
|
||||
}
|
||||
}
|
||||
return implode("/", $url);
|
||||
// discard any fragment ID (there shouldn't be any) and query string (the query is available in the request itself)
|
||||
$target->fragment = "";
|
||||
$target->query = "";
|
||||
return (string) $target;
|
||||
}
|
||||
|
||||
protected function chooseCall(array $url, string $method): string {
|
||||
// normalize the URL path
|
||||
$url = $this->normalizePath($url);
|
||||
protected function chooseCall(string $url, string $method): string {
|
||||
// // normalize the URL path: change any IDs to 1 for easier comparison
|
||||
$url = $this->normalizePathIds($url);
|
||||
// normalize the HTTP method to uppercase
|
||||
$method = strtoupper($method);
|
||||
// we now evaluate the supplied URL against every supported path for the selected scope
|
||||
|
@ -244,9 +259,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
return $article;
|
||||
}
|
||||
|
||||
protected function handleHTTPOptions(array $url): ResponseInterface {
|
||||
// normalize the URL path
|
||||
$url = $this->normalizePath($url);
|
||||
protected function handleHTTPOptions(string $url): ResponseInterface {
|
||||
// normalize the URL path: change any IDs to 1 for easier comparison
|
||||
$url = $this->normalizePathIDs($url);
|
||||
if (isset($this->paths[$url])) {
|
||||
// if the path is supported, respond with the allowed methods and other metadata
|
||||
$allowed = array_keys($this->paths[$url]);
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\REST\NextCloudNews;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Diactoros\Response\JsonResponse as Response;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
|
||||
|
@ -13,24 +15,26 @@ class Versions implements \JKingWeb\Arsse\REST\Handler {
|
|||
public function __construct() {
|
||||
}
|
||||
|
||||
public function dispatch(\JKingWeb\Arsse\REST\Request $req): \Psr\Http\Message\ResponseInterface {
|
||||
if (!preg_match("<^/?$>", $req->path)) {
|
||||
// if the request path is an empty string or just a slash, the client is probably trying a version we don't support
|
||||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
if (!preg_match("<^/?$>", $req->getRequestTarget())) {
|
||||
// if the request path is more than an empty string or a slash, the client is probably trying a version we don't support
|
||||
return new EmptyResponse(404);
|
||||
} elseif ($req->method=="OPTIONS") {
|
||||
// if the request method is OPTIONS, respond accordingly
|
||||
return new EmptyResponse(204, ['Allow' => "HEAD,GET"]);
|
||||
} elseif ($req->method != "GET") {
|
||||
// if a method other than GET was used, this is an error
|
||||
return new EmptyResponse(405, ['Allow' => "HEAD,GET"]);
|
||||
} else {
|
||||
// otherwise return the supported versions
|
||||
$out = [
|
||||
'apiLevels' => [
|
||||
'v1-2',
|
||||
]
|
||||
];
|
||||
return new Response($out);
|
||||
}
|
||||
switch ($req->getMethod()) {
|
||||
case "OPTIONS":
|
||||
// if the request method is OPTIONS, respond accordingly
|
||||
return new EmptyResponse(204, ['Allow' => "HEAD,GET"]);
|
||||
case "GET":
|
||||
// otherwise return the supported versions
|
||||
$out = [
|
||||
'apiLevels' => [
|
||||
'v1-2',
|
||||
]
|
||||
];
|
||||
return new Response($out);
|
||||
default:
|
||||
// if any other method was used, this is an error
|
||||
return new EmptyResponse(405, ['Allow' => "HEAD,GET"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
<?php
|
||||
/** @license MIT
|
||||
* Copyright 2017 J. King, Dustin Wilson et al.
|
||||
* See LICENSE and AUTHORS files for details */
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\REST;
|
||||
|
||||
class Request {
|
||||
public $method = "GET";
|
||||
public $head = false;
|
||||
public $url = "";
|
||||
public $path ="";
|
||||
public $paths = [];
|
||||
public $query = "";
|
||||
public $type ="";
|
||||
public $body = "";
|
||||
|
||||
public function __construct(string $method = null, string $url = null, string $body = null, string $contentType = null) {
|
||||
$method = $method ?? $_SERVER['REQUEST_METHOD'];
|
||||
$url = $url ?? $_SERVER['REQUEST_URI'];
|
||||
$body = $body ?? file_get_contents("php://input");
|
||||
if (is_null($contentType)) {
|
||||
if (isset($_SERVER['HTTP_CONTENT_TYPE'])) {
|
||||
$contentType = $_SERVER['HTTP_CONTENT_TYPE'];
|
||||
} else {
|
||||
$contentType = "";
|
||||
}
|
||||
}
|
||||
$this->method = strtoupper($method);
|
||||
$this->url = $url;
|
||||
$this->body = $body;
|
||||
$this->type = $contentType;
|
||||
if ($this->method=="HEAD") {
|
||||
$this->head = true;
|
||||
$this->method = "GET";
|
||||
}
|
||||
$this->refreshURL();
|
||||
}
|
||||
|
||||
public function refreshURL() {
|
||||
$url = $this->parseURL($this->url);
|
||||
$this->path = $url['path'];
|
||||
$this->paths = $url['paths'];
|
||||
$this->query = $url['query'];
|
||||
}
|
||||
|
||||
protected function parseURL(string $url): array {
|
||||
// split the query string from the path
|
||||
$parts = explode("?", $url);
|
||||
$out = ['path' => $parts[0], 'paths' => [''], 'query' => []];
|
||||
// if there is a query string, parse it
|
||||
if (isset($parts[1])) {
|
||||
// split along & to get key-value pairs
|
||||
$query = explode("&", $parts[1]);
|
||||
for ($a = 0; $a < sizeof($query); $a++) {
|
||||
// split each pair, into no more than two parts
|
||||
$data = explode("=", $query[$a], 2);
|
||||
// decode the key
|
||||
$key = rawurldecode($data[0]);
|
||||
// decode the value if there is one
|
||||
$value = "";
|
||||
if (isset($data[1])) {
|
||||
$value = rawurldecode($data[1]);
|
||||
}
|
||||
// add the pair to the query output, overwriting earlier values for the same key, is present
|
||||
$out['query'][$key] = $value;
|
||||
}
|
||||
}
|
||||
// also include the path as a set of decoded elements
|
||||
// if the path is an empty string or just / nothing needs be done
|
||||
if (!in_array($out['path'], ["/",""])) {
|
||||
$paths = explode("/", $out['path']);
|
||||
// remove the first and last empty elements, if present (they are artefacts of the splitting; others should remain)
|
||||
if (!strlen($paths[0])) {
|
||||
array_shift($paths);
|
||||
}
|
||||
if (!strlen($paths[sizeof($paths)-1])) {
|
||||
array_pop($paths);
|
||||
}
|
||||
// %-decode each path element
|
||||
$paths = array_map(function ($v) {
|
||||
return rawurldecode($v);
|
||||
}, $paths);
|
||||
$out['paths'] = $paths;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,8 @@ use JKingWeb\Arsse\ExceptionType;
|
|||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Db\ResultEmpty;
|
||||
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Diactoros\Response\JsonResponse as Response;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
|
||||
|
@ -89,21 +91,22 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
public function __construct() {
|
||||
}
|
||||
|
||||
public function dispatch(\JKingWeb\Arsse\REST\Request $req): \Psr\Http\Message\ResponseInterface {
|
||||
if (!preg_match("<^(?:/(?:index\.php)?)?$>", $req->path)) {
|
||||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
if (!preg_match("<^(?:/(?:index\.php)?)?$>", $req->getRequestTarget())) {
|
||||
// reject paths other than the index
|
||||
return new EmptyResponse(404);
|
||||
}
|
||||
if ($req->method=="OPTIONS") {
|
||||
if ($req->getMethod()=="OPTIONS") {
|
||||
// respond to OPTIONS rquests; the response is a fib, as we technically accept any type or method
|
||||
return new EmptyResponse(204, [
|
||||
'Allow' => "POST",
|
||||
'Accept' => "application/json, text/json",
|
||||
]);
|
||||
}
|
||||
if ($req->body) {
|
||||
$data = (string) $req->getBody();
|
||||
if ($data) {
|
||||
// only JSON entities are allowed, but Content-Type is ignored, as is request method
|
||||
$data = @json_decode($req->body, true);
|
||||
$data = @json_decode($data, true);
|
||||
if (json_last_error() != \JSON_ERROR_NONE || !is_array($data)) {
|
||||
return new Response(self::FATAL_ERR);
|
||||
}
|
||||
|
|
|
@ -7,17 +7,19 @@ declare(strict_types=1);
|
|||
namespace JKingWeb\Arsse\REST\TinyTinyRSS;
|
||||
|
||||
use JKingWeb\Arsse\Arsse;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Diactoros\Response\EmptyResponse as Response;
|
||||
|
||||
class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
public function dispatch(\JKingWeb\Arsse\REST\Request $req): \Psr\Http\Message\ResponseInterface {
|
||||
if ($req->method != "GET") {
|
||||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
if ($req->getMethod() != "GET") {
|
||||
// only GET requests are allowed
|
||||
return new Response(405, ['Allow' => "GET"]);
|
||||
} elseif (!preg_match("<^(\d+)\.ico$>", $req->url, $match) || !((int) $match[1])) {
|
||||
} elseif (!preg_match("<^(\d+)\.ico$>", $req->getRequestTarget(), $match) || !((int) $match[1])) {
|
||||
return new Response(404);
|
||||
}
|
||||
$url = Arsse::$db->subscriptionFavicon((int) $match[1]);
|
||||
|
|
|
@ -11,13 +11,14 @@ use JKingWeb\Arsse\Conf;
|
|||
use JKingWeb\Arsse\User;
|
||||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\Service;
|
||||
use JKingWeb\Arsse\REST\Request;
|
||||
use JKingWeb\Arsse\Test\Result;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\Context;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Db\Transaction;
|
||||
use JKingWeb\Arsse\REST\NextCloudNews\V1_2;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
use Zend\Diactoros\Response\JsonResponse as Response;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
use Phake;
|
||||
|
@ -300,6 +301,40 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
],
|
||||
];
|
||||
|
||||
protected function req(string $method, string $target, string $data = "", array $headers = []): ResponseInterface {
|
||||
$url = "/index.php/apps/news/api/v1-2".$target;
|
||||
$server = [
|
||||
'REQUEST_METHOD' => $method,
|
||||
'REQUEST_URI' => $url,
|
||||
'PHP_AUTH_USER' => "john.doe@example.com",
|
||||
'PHP_AUTH_PW' => "secret",
|
||||
'REMOTE_USER' => "john.doe@example.com",
|
||||
];
|
||||
if (strlen($data)) {
|
||||
$server['HTTP_CONTENT_TYPE'] = "application/json";
|
||||
}
|
||||
$req = new ServerRequest($server, [], $url, $method, "php://memory");
|
||||
foreach($headers as $key => $value) {
|
||||
if (!is_null($value)) {
|
||||
$req = $req->withHeader($key, $value);
|
||||
} else {
|
||||
$req = $req->withoutHeader($key);
|
||||
}
|
||||
}
|
||||
if (strlen($data)) {
|
||||
$body = $req->getBody();
|
||||
$body->write($data);
|
||||
$req = $req->withBody($body);
|
||||
}
|
||||
$q = $req->getUri()->getQuery();
|
||||
if (strlen($q)) {
|
||||
parse_str($q, $q);
|
||||
$req = $req->withQueryParams($q);
|
||||
}
|
||||
$req = $req->withRequestTarget($target);
|
||||
return $this->h->dispatch($req);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
$this->clearData();
|
||||
Arsse::$conf = new Conf();
|
||||
|
@ -321,7 +356,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function testSendAuthenticationChallenge() {
|
||||
Phake::when(Arsse::$user)->authHTTP->thenReturn(false);
|
||||
$exp = new EmptyResponse(401, ['WWW-Authenticate' => 'Basic realm="'.V1_2::REALM.'"']);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/"));
|
||||
}
|
||||
|
||||
public function testRespondToInvalidPaths() {
|
||||
|
@ -359,22 +394,23 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
foreach ($errs[404] as $req) {
|
||||
$exp = new EmptyResponse(404);
|
||||
list($method, $path) = $req;
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request($method, $path)), "$method call to $path did not return 404.");
|
||||
$this->assertResponse($exp, $this->req($method, $path), "$method call to $path did not return 404.");
|
||||
}
|
||||
foreach ($errs[405] as $allow => $cases) {
|
||||
$exp = new EmptyResponse(405, ['Allow' => $allow]);
|
||||
foreach ($cases as $req) {
|
||||
list($method, $path) = $req;
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request($method, $path)), "$method call to $path did not return 405.");
|
||||
$this->assertResponse($exp, $this->req($method, $path), "$method call to $path did not return 405.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testRespondToInvalidInputTypes() {
|
||||
$exp = new EmptyResponse(415, ['Accept' => "application/json"]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/1", '<data/>', 'application/xml')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1", '<data/>', ['Content-Type' => "application/xml"]));
|
||||
$exp = new EmptyResponse(400);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/1", '<data/>', 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1", '<data/>'));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1", '<data/>', ['Content-Type' => null]));
|
||||
}
|
||||
|
||||
public function testRespondToOptionsRequests() {
|
||||
|
@ -382,19 +418,19 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
'Allow' => "HEAD,GET,POST",
|
||||
'Accept' => "application/json",
|
||||
]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("OPTIONS", "/feeds")));
|
||||
$this->assertResponse($exp, $this->req("OPTIONS", "/feeds"));
|
||||
$exp = new EmptyResponse(204, [
|
||||
'Allow' => "DELETE",
|
||||
'Accept' => "application/json",
|
||||
]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("OPTIONS", "/feeds/2112")));
|
||||
$this->assertResponse($exp, $this->req("OPTIONS", "/feeds/2112"));
|
||||
$exp = new EmptyResponse(204, [
|
||||
'Allow' => "HEAD,GET",
|
||||
'Accept' => "application/json",
|
||||
]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("OPTIONS", "/user")));
|
||||
$this->assertResponse($exp, $this->req("OPTIONS", "/user"));
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("OPTIONS", "/invalid/path")));
|
||||
$this->assertResponse($exp, $this->req("OPTIONS", "/invalid/path"));
|
||||
}
|
||||
|
||||
public function testListFolders() {
|
||||
|
@ -408,9 +444,9 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
];
|
||||
Phake::when(Arsse::$db)->folderList(Arsse::$user->id, null, false)->thenReturn(new Result([]))->thenReturn(new Result($list));
|
||||
$exp = new Response(['folders' => []]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/folders")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/folders"));
|
||||
$exp = new Response(['folders' => $out]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/folders")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/folders"));
|
||||
}
|
||||
|
||||
public function testAddAFolder() {
|
||||
|
@ -438,33 +474,33 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->folderAdd(Arsse::$user->id, ['name' => " "])->thenThrow(new ExceptionInput("whitespace"));
|
||||
// correctly add two folders, using different means
|
||||
$exp = new Response(['folders' => [$out[0]]]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/folders", json_encode($in[0]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("POST", "/folders", json_encode($in[0])));
|
||||
$exp = new Response(['folders' => [$out[1]]]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/folders?name=Hardware")));
|
||||
$this->assertResponse($exp, $this->req("POST", "/folders?name=Hardware"));
|
||||
Phake::verify(Arsse::$db)->folderAdd(Arsse::$user->id, $in[0]);
|
||||
Phake::verify(Arsse::$db)->folderAdd(Arsse::$user->id, $in[1]);
|
||||
Phake::verify(Arsse::$db)->folderPropertiesGet(Arsse::$user->id, 1);
|
||||
Phake::verify(Arsse::$db)->folderPropertiesGet(Arsse::$user->id, 2);
|
||||
// test bad folder names
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/folders")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/folders", '{"name":""}', 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/folders", '{"name":" "}', 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/folders", '{"name":{}}', 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("POST", "/folders"));
|
||||
$this->assertResponse($exp, $this->req("POST", "/folders", '{"name":""}'));
|
||||
$this->assertResponse($exp, $this->req("POST", "/folders", '{"name":" "}'));
|
||||
$this->assertResponse($exp, $this->req("POST", "/folders", '{"name":{}}'));
|
||||
// try adding the same two folders again
|
||||
$exp = new EmptyResponse(409);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/folders?name=Software")));
|
||||
$this->assertResponse($exp, $this->req("POST", "/folders?name=Software"));
|
||||
$exp = new EmptyResponse(409);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/folders", json_encode($in[1]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("POST", "/folders", json_encode($in[1])));
|
||||
}
|
||||
|
||||
public function testRemoveAFolder() {
|
||||
Phake::when(Arsse::$db)->folderRemove(Arsse::$user->id, 1)->thenReturn(true)->thenThrow(new ExceptionInput("subjectMissing"));
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("DELETE", "/folders/1")));
|
||||
$this->assertResponse($exp, $this->req("DELETE", "/folders/1"));
|
||||
// fail on the second invocation because it no longer exists
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("DELETE", "/folders/1")));
|
||||
$this->assertResponse($exp, $this->req("DELETE", "/folders/1"));
|
||||
Phake::verify(Arsse::$db, Phake::times(2))->folderRemove(Arsse::$user->id, 1);
|
||||
}
|
||||
|
||||
|
@ -483,17 +519,17 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->folderPropertiesSet(Arsse::$user->id, 1, $in[4])->thenReturn(true); // this should be stopped by the handler before the request gets to the database
|
||||
Phake::when(Arsse::$db)->folderPropertiesSet(Arsse::$user->id, 3, $this->anything())->thenThrow(new ExceptionInput("subjectMissing")); // folder ID 3 does not exist
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[0]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1", json_encode($in[0])));
|
||||
$exp = new EmptyResponse(409);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/2", json_encode($in[1]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/2", json_encode($in[1])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[2]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1", json_encode($in[2])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[3]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1", json_encode($in[3])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[4]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1", json_encode($in[4])));
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/3", json_encode($in[0]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/3", json_encode($in[0])));
|
||||
}
|
||||
|
||||
public function testRetrieveServerVersion() {
|
||||
|
@ -501,7 +537,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
'version' => V1_2::VERSION,
|
||||
'arsse_version' => Arsse::VERSION,
|
||||
]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/version")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/version"));
|
||||
}
|
||||
|
||||
public function testListSubscriptions() {
|
||||
|
@ -518,9 +554,9 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->articleStarred(Arsse::$user->id)->thenReturn(['total' => 0])->thenReturn(['total' => 5]);
|
||||
Phake::when(Arsse::$db)->editionLatest(Arsse::$user->id)->thenReturn(0)->thenReturn(4758915);
|
||||
$exp = new Response($exp1);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/feeds")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/feeds"));
|
||||
$exp = new Response($exp2);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/feeds")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/feeds"));
|
||||
}
|
||||
|
||||
public function testAddASubscription() {
|
||||
|
@ -553,31 +589,31 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->subscriptionAdd(Arsse::$user->id, "http://example.net/news.atom")->thenThrow(new \JKingWeb\Arsse\Feed\Exception("http://example.net/news.atom", new \PicoFeed\Client\InvalidUrlException()))->thenReturn(47);
|
||||
// add the subscriptions
|
||||
$exp = new Response($out[0]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[0]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("POST", "/feeds", json_encode($in[0])));
|
||||
$exp = new Response($out[1]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[1]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("POST", "/feeds", json_encode($in[1])));
|
||||
// try to add them a second time
|
||||
$exp = new EmptyResponse(409);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[0]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[1]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("POST", "/feeds", json_encode($in[0])));
|
||||
$this->assertResponse($exp, $this->req("POST", "/feeds", json_encode($in[1])));
|
||||
// try to add a bad feed
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[2]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("POST", "/feeds", json_encode($in[2])));
|
||||
// try again (this will succeed), with an invalid folder ID
|
||||
$exp = new Response($out[2]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[3]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("POST", "/feeds", json_encode($in[3])));
|
||||
// try to add no feed
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[4]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("POST", "/feeds", json_encode($in[4])));
|
||||
}
|
||||
|
||||
public function testRemoveASubscription() {
|
||||
Phake::when(Arsse::$db)->subscriptionRemove(Arsse::$user->id, 1)->thenReturn(true)->thenThrow(new ExceptionInput("subjectMissing"));
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("DELETE", "/feeds/1")));
|
||||
$this->assertResponse($exp, $this->req("DELETE", "/feeds/1"));
|
||||
// fail on the second invocation because it no longer exists
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("DELETE", "/feeds/1")));
|
||||
$this->assertResponse($exp, $this->req("DELETE", "/feeds/1"));
|
||||
Phake::verify(Arsse::$db, Phake::times(2))->subscriptionRemove(Arsse::$user->id, 1);
|
||||
}
|
||||
|
||||
|
@ -596,17 +632,17 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->subscriptionPropertiesSet(Arsse::$user->id, 1, ['folder' => -1])->thenThrow(new ExceptionInput("typeViolation")); // folder is invalid
|
||||
Phake::when(Arsse::$db)->subscriptionPropertiesSet(Arsse::$user->id, 42, $this->anything())->thenThrow(new ExceptionInput("subjectMissing")); // subscription does not exist
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[0]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[0])));
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[1]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[1])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[2]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[2])));
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/42/move", json_encode($in[3]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/42/move", json_encode($in[3])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[4]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[4])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[5]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[5])));
|
||||
}
|
||||
|
||||
public function testRenameASubscription() {
|
||||
|
@ -626,17 +662,17 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->subscriptionPropertiesSet(Arsse::$user->id, 1, $this->identicalTo(['title' => false]))->thenThrow(new ExceptionInput("missing"));
|
||||
Phake::when(Arsse::$db)->subscriptionPropertiesSet(Arsse::$user->id, 42, $this->anything())->thenThrow(new ExceptionInput("subjectMissing"));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[0]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[0])));
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[1]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[1])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[2]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[2])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[3]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[3])));
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/42/rename", json_encode($in[4]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/42/rename", json_encode($in[4])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[6]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[6])));
|
||||
}
|
||||
|
||||
public function testListStaleFeeds() {
|
||||
|
@ -652,11 +688,11 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
];
|
||||
Phake::when(Arsse::$db)->feedListStale->thenReturn(array_column($out, "id"));
|
||||
$exp = new Response(['feeds' => $out]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/feeds/all")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/feeds/all"));
|
||||
// retrieving the list when not an admin fails
|
||||
Phake::when(Arsse::$user)->rightsGet->thenReturn(0);
|
||||
$exp = new EmptyResponse(403);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/feeds/all")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/feeds/all"));
|
||||
}
|
||||
|
||||
public function testUpdateAFeed() {
|
||||
|
@ -671,17 +707,17 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->feedUpdate(2112)->thenThrow(new ExceptionInput("subjectMissing"));
|
||||
Phake::when(Arsse::$db)->feedUpdate($this->lessThan(1))->thenThrow(new ExceptionInput("typeViolation"));
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/feeds/update", json_encode($in[0]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("GET", "/feeds/update", json_encode($in[0])));
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/feeds/update", json_encode($in[1]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("GET", "/feeds/update", json_encode($in[1])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/feeds/update", json_encode($in[2]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/feeds/update", json_encode($in[3]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/feeds/update", json_encode($in[4]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("GET", "/feeds/update", json_encode($in[2])));
|
||||
$this->assertResponse($exp, $this->req("GET", "/feeds/update", json_encode($in[3])));
|
||||
$this->assertResponse($exp, $this->req("GET", "/feeds/update", json_encode($in[4])));
|
||||
// updating a feed when not an admin fails
|
||||
Phake::when(Arsse::$user)->rightsGet->thenReturn(0);
|
||||
$exp = new EmptyResponse(403);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/feeds/update", json_encode($in[0]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("GET", "/feeds/update", json_encode($in[0])));
|
||||
}
|
||||
|
||||
public function testListArticles() {
|
||||
|
@ -708,23 +744,23 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->reverse(true)->folder(-1), Database::LIST_TYPICAL)->thenThrow(new ExceptionInput("typeViolation"));
|
||||
$exp = new Response(['items' => $this->articles['rest']]);
|
||||
// check the contents of the response
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/items"))); // first instance of base context
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/items/updated"))); // second instance of base context
|
||||
$this->assertResponse($exp, $this->req("GET", "/items")); // first instance of base context
|
||||
$this->assertResponse($exp, $this->req("GET", "/items/updated")); // second instance of base context
|
||||
// check error conditions
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/items", json_encode($in[0]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/items", json_encode($in[1]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/items", json_encode($in[2]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/items", json_encode($in[3]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("GET", "/items", json_encode($in[0])));
|
||||
$this->assertResponse($exp, $this->req("GET", "/items", json_encode($in[1])));
|
||||
$this->assertResponse($exp, $this->req("GET", "/items", json_encode($in[2])));
|
||||
$this->assertResponse($exp, $this->req("GET", "/items", json_encode($in[3])));
|
||||
// simply run through the remainder of the input for later method verification
|
||||
$this->h->dispatch(new Request("GET", "/items", json_encode($in[4]), 'application/json'));
|
||||
$this->h->dispatch(new Request("GET", "/items", json_encode($in[5]), 'application/json')); // third instance of base context
|
||||
$this->h->dispatch(new Request("GET", "/items", json_encode($in[6]), 'application/json'));
|
||||
$this->h->dispatch(new Request("GET", "/items", json_encode($in[7]), 'application/json'));
|
||||
$this->h->dispatch(new Request("GET", "/items", json_encode($in[8]), 'application/json')); // fourth instance of base context
|
||||
$this->h->dispatch(new Request("GET", "/items", json_encode($in[9]), 'application/json'));
|
||||
$this->h->dispatch(new Request("GET", "/items", json_encode($in[10]), 'application/json'));
|
||||
$this->h->dispatch(new Request("GET", "/items", json_encode($in[11]), 'application/json'));
|
||||
$this->req("GET", "/items", json_encode($in[4]));
|
||||
$this->req("GET", "/items", json_encode($in[5])); // third instance of base context
|
||||
$this->req("GET", "/items", json_encode($in[6]));
|
||||
$this->req("GET", "/items", json_encode($in[7]));
|
||||
$this->req("GET", "/items", json_encode($in[8])); // fourth instance of base context
|
||||
$this->req("GET", "/items", json_encode($in[9]));
|
||||
$this->req("GET", "/items", json_encode($in[10]));
|
||||
$this->req("GET", "/items", json_encode($in[11]));
|
||||
// perform method verifications
|
||||
Phake::verify(Arsse::$db, Phake::times(4))->articleList(Arsse::$user->id, (new Context)->reverse(true), Database::LIST_TYPICAL);
|
||||
Phake::verify(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->reverse(true)->subscription(42), Database::LIST_TYPICAL);
|
||||
|
@ -745,13 +781,13 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->folder(1)->latestEdition(2112))->thenReturn(42);
|
||||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->folder(42)->latestEdition(2112))->thenThrow(new ExceptionInput("idMissing")); // folder doesn't exist
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/1/read", $in, 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/1/read?newestItemId=2112")));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1/read", $in));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1/read?newestItemId=2112"));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/1/read")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/1/read?newestItemId=ook")));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1/read"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/1/read?newestItemId=ook"));
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/folders/42/read", $in, 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/folders/42/read", $in));
|
||||
}
|
||||
|
||||
public function testMarkASubscriptionRead() {
|
||||
|
@ -760,13 +796,13 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->subscription(1)->latestEdition(2112))->thenReturn(42);
|
||||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->subscription(42)->latestEdition(2112))->thenThrow(new ExceptionInput("idMissing")); // subscription doesn't exist
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/read", $in, 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/read?newestItemId=2112")));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/read", $in));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/read?newestItemId=2112"));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/read")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/read?newestItemId=ook")));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/read"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/1/read?newestItemId=ook"));
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/feeds/42/read", $in, 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/feeds/42/read", $in));
|
||||
}
|
||||
|
||||
public function testMarkAllItemsRead() {
|
||||
|
@ -774,11 +810,11 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$in = json_encode(['newestItemId' => 2112]);
|
||||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->latestEdition(2112))->thenReturn(42);
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/read", $in, 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/read?newestItemId=2112")));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/read", $in));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/read?newestItemId=2112"));
|
||||
$exp = new EmptyResponse(422);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/read")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/read?newestItemId=ook")));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/read"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/read?newestItemId=ook"));
|
||||
}
|
||||
|
||||
public function testChangeMarksOfASingleArticle() {
|
||||
|
@ -795,15 +831,15 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $unstar, (new Context)->article(4))->thenReturn(42);
|
||||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $unstar, (new Context)->article(1337))->thenThrow(new ExceptionInput("subjectMissing")); // article doesn't exist doesn't exist
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/1/read")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/2/unread")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/1/3/star")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/4400/4/unstar")));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/1/read"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/2/unread"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/1/3/star"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/4400/4/unstar"));
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/42/read")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/47/unread")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/1/2112/star")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/4400/1337/unstar")));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/42/read"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/47/unread"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/1/2112/star"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/4400/1337/unstar"));
|
||||
Phake::verify(Arsse::$db, Phake::times(8))->articleMark(Arsse::$user->id, $this->anything(), $this->anything());
|
||||
}
|
||||
|
||||
|
@ -826,26 +862,26 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $this->anything(), (new Context)->editions([]))->thenThrow(new ExceptionInput("tooShort")); // data model function requires one valid integer for multiples
|
||||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $this->anything(), (new Context)->articles([]))->thenThrow(new ExceptionInput("tooShort")); // data model function requires one valid integer for multiples
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/read/multiple")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/unread/multiple")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/star/multiple")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/unstar/multiple")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/read/multiple", json_encode(['items' => "ook"]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/unread/multiple", json_encode(['items' => "ook"]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/star/multiple", json_encode(['items' => "ook"]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/unstar/multiple", json_encode(['items' => "ook"]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/read/multiple", json_encode(['items' => []]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/unread/multiple", json_encode(['items' => []]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/read/multiple", json_encode(['items' => $in[0]]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/unread/multiple", json_encode(['items' => $in[0]]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/read/multiple", json_encode(['items' => $in[1]]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/unread/multiple", json_encode(['items' => $in[1]]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/star/multiple", json_encode(['items' => []]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/unstar/multiple", json_encode(['items' => []]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/star/multiple", json_encode(['items' => $inStar[0]]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/unstar/multiple", json_encode(['items' => $inStar[0]]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/star/multiple", json_encode(['items' => $inStar[1]]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "/items/unstar/multiple", json_encode(['items' => $inStar[1]]), 'application/json')));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/read/multiple"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/unread/multiple"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/star/multiple"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/unstar/multiple"));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/read/multiple", json_encode(['items' => "ook"])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/unread/multiple", json_encode(['items' => "ook"])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/star/multiple", json_encode(['items' => "ook"])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/unstar/multiple", json_encode(['items' => "ook"])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/read/multiple", json_encode(['items' => []])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/unread/multiple", json_encode(['items' => []])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/read/multiple", json_encode(['items' => $in[0]])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/unread/multiple", json_encode(['items' => $in[0]])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/read/multiple", json_encode(['items' => $in[1]])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/unread/multiple", json_encode(['items' => $in[1]])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/star/multiple", json_encode(['items' => []])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/unstar/multiple", json_encode(['items' => []])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/star/multiple", json_encode(['items' => $inStar[0]])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/unstar/multiple", json_encode(['items' => $inStar[0]])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/star/multiple", json_encode(['items' => $inStar[1]])));
|
||||
$this->assertResponse($exp, $this->req("PUT", "/items/unstar/multiple", json_encode(['items' => $inStar[1]])));
|
||||
// ensure the data model was queried appropriately for read/unread
|
||||
Phake::verify(Arsse::$db, Phake::atLeast(1))->articleMark(Arsse::$user->id, $read, (new Context)->editions([]));
|
||||
Phake::verify(Arsse::$db, Phake::atLeast(1))->articleMark(Arsse::$user->id, $read, (new Context)->editions($in[0]));
|
||||
|
@ -879,28 +915,28 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$arr2['warnings']['improperlyConfiguredCron'] = true;
|
||||
$arr2['warnings']['incorrectDbCharset'] = true;
|
||||
$exp = new Response($arr1);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/status")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/status"));
|
||||
}
|
||||
|
||||
public function testCleanUpBeforeUpdate() {
|
||||
Phake::when(Arsse::$db)->feedCleanup()->thenReturn(true);
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/cleanup/before-update")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/cleanup/before-update"));
|
||||
Phake::verify(Arsse::$db)->feedCleanup();
|
||||
// performing a cleanup when not an admin fails
|
||||
Phake::when(Arsse::$user)->rightsGet->thenReturn(0);
|
||||
$exp = new EmptyResponse(403);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/cleanup/before-update")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/cleanup/before-update"));
|
||||
}
|
||||
|
||||
public function testCleanUpAfterUpdate() {
|
||||
Phake::when(Arsse::$db)->articleCleanup()->thenReturn(true);
|
||||
$exp = new EmptyResponse(204);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/cleanup/after-update")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/cleanup/after-update"));
|
||||
Phake::verify(Arsse::$db)->articleCleanup();
|
||||
// performing a cleanup when not an admin fails
|
||||
Phake::when(Arsse::$user)->rightsGet->thenReturn(0);
|
||||
$exp = new EmptyResponse(403);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "/cleanup/after-update")));
|
||||
$this->assertResponse($exp, $this->req("GET", "/cleanup/after-update"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ declare(strict_types=1);
|
|||
namespace JKingWeb\Arsse\TestCase\REST\NextCloudNews;
|
||||
|
||||
use JKingWeb\Arsse\REST\NextCloudNews\Versions;
|
||||
use JKingWeb\Arsse\REST\Request;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
use Zend\Diactoros\Response\JsonResponse as Response;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
|
||||
|
@ -17,44 +18,37 @@ class TestVersions extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->clearData();
|
||||
}
|
||||
|
||||
protected function req(string $method, string $target): ResponseInterface {
|
||||
$url = "/index.php/apps/news/api".$target;
|
||||
$server = [
|
||||
'REQUEST_METHOD' => $method,
|
||||
'REQUEST_URI' => $url,
|
||||
];
|
||||
$req = new ServerRequest($server, [], $url, $method, "php://memory");
|
||||
$req = $req->withRequestTarget($target);
|
||||
return (new Versions)->dispatch($req);
|
||||
}
|
||||
|
||||
public function testFetchVersionList() {
|
||||
$exp = new Response(['apiLevels' => ['v1-2']]);
|
||||
$h = new Versions;
|
||||
$req = new Request("GET", "/");
|
||||
$res = $h->dispatch($req);
|
||||
$this->assertResponse($exp, $res);
|
||||
$req = new Request("GET", "");
|
||||
$res = $h->dispatch($req);
|
||||
$this->assertResponse($exp, $res);
|
||||
$req = new Request("GET", "/?id=1827");
|
||||
$res = $h->dispatch($req);
|
||||
$this->assertResponse($exp, $res);
|
||||
$this->assertResponse($exp, $this->req("GET", "/"));
|
||||
$this->assertResponse($exp, $this->req("GET", "/"));
|
||||
$this->assertResponse($exp, $this->req("GET", "/"));
|
||||
}
|
||||
|
||||
public function testRespondToOptionsRequest() {
|
||||
$exp = new EmptyResponse(204, ['Allow' => "HEAD,GET"]);
|
||||
$h = new Versions;
|
||||
$req = new Request("OPTIONS", "/");
|
||||
$res = $h->dispatch($req);
|
||||
$this->assertResponse($exp, $res);
|
||||
$this->assertResponse($exp, $this->req("OPTIONS", "/"));
|
||||
}
|
||||
|
||||
public function testUseIncorrectMethod() {
|
||||
$exp = new EmptyResponse(405, ['Allow' => "HEAD,GET"]);
|
||||
$h = new Versions;
|
||||
$req = new Request("POST", "/");
|
||||
$res = $h->dispatch($req);
|
||||
$this->assertResponse($exp, $res);
|
||||
$this->assertResponse($exp, $this->req("POST", "/"));
|
||||
}
|
||||
|
||||
public function testUseIncorrectPath() {
|
||||
$exp = new EmptyResponse(404);
|
||||
$h = new Versions;
|
||||
$req = new Request("GET", "/ook");
|
||||
$res = $h->dispatch($req);
|
||||
$this->assertResponse($exp, $res);
|
||||
$req = new Request("OPTIONS", "/ook");
|
||||
$res = $h->dispatch($req);
|
||||
$this->assertResponse($exp, $res);
|
||||
$this->assertResponse($exp, $this->req("GET", "/ook"));
|
||||
$this->assertResponse($exp, $this->req("OPTIONS", "/ook"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ use JKingWeb\Arsse\Db\ExceptionInput;
|
|||
use JKingWeb\Arsse\Db\Transaction;
|
||||
use JKingWeb\Arsse\REST\TinyTinyRSS\API;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
use Zend\Diactoros\Response\JsonResponse as Response;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
use Phake;
|
||||
|
@ -124,8 +125,22 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
</section>
|
||||
LONG_STRING;
|
||||
|
||||
protected function req($data): ResponseInterface {
|
||||
return $this->h->dispatch(new Request("POST", "", json_encode($data)));
|
||||
protected function req($data, string $method = "POST", string $target = "", string $strData = null): ResponseInterface {
|
||||
$url = "/tt-rss/api".$target;
|
||||
$server = [
|
||||
'REQUEST_METHOD' => $method,
|
||||
'REQUEST_URI' => $url,
|
||||
'HTTP_CONTENT_TYPE' => "application/x-www-form-urlencoded",
|
||||
];
|
||||
$req = new ServerRequest($server, [], $url, $method, "php://memory");
|
||||
$body = $req->getBody();
|
||||
if (!is_null($strData)) {
|
||||
$body->write($strData);
|
||||
} else {
|
||||
$body->write(json_encode($data));
|
||||
}
|
||||
$req = $req->withBody($body)->withRequestTarget($target);
|
||||
return $this->h->dispatch($req);
|
||||
}
|
||||
|
||||
protected function respGood($content = null, $seq = 0): Response {
|
||||
|
@ -172,11 +187,11 @@ LONG_STRING;
|
|||
|
||||
public function testHandleInvalidPaths() {
|
||||
$exp = $this->respErr("MALFORMED_INPUT", [], null);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "", "")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/", "")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/index.php", "")));
|
||||
$this->assertResponse($exp, $this->req(null, "POST", "", ""));
|
||||
$this->assertResponse($exp, $this->req(null, "POST", "/", ""));
|
||||
$this->assertResponse($exp, $this->req(null, "POST", "/index.php", ""));
|
||||
$exp = new EmptyResponse(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "/bad/path", "")));
|
||||
$this->assertResponse($exp, $this->req(null, "POST", "/bad/path", ""));
|
||||
}
|
||||
|
||||
public function testHandleOptionsRequest() {
|
||||
|
@ -184,13 +199,13 @@ LONG_STRING;
|
|||
'Allow' => "POST",
|
||||
'Accept' => "application/json, text/json",
|
||||
]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("OPTIONS", "")));
|
||||
$this->assertResponse($exp, $this->req(null, "OPTIONS", "", ""));
|
||||
}
|
||||
|
||||
public function testHandleInvalidData() {
|
||||
$exp = $this->respErr("MALFORMED_INPUT", [], null);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "", "This is not valid JSON data")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("POST", "", ""))); // lack of data is also an error
|
||||
$this->assertResponse($exp, $this->req(null, "POST", "", "This is not valid JSON data"));
|
||||
$this->assertResponse($exp, $this->req(null, "POST", "", "")); // lack of data is also an error
|
||||
}
|
||||
|
||||
public function testLogIn() {
|
||||
|
|
|
@ -12,6 +12,8 @@ use JKingWeb\Arsse\User;
|
|||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\REST\TinyTinyRSS\Icon;
|
||||
use JKingWeb\Arsse\REST\Request;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
use Zend\Diactoros\Response\EmptyResponse as Response;
|
||||
use Phake;
|
||||
|
||||
|
@ -32,6 +34,17 @@ class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->clearData();
|
||||
}
|
||||
|
||||
protected function req(string $target, $method = "GET"): ResponseInterface {
|
||||
$url = "/tt-rss/feed-icons/".$target;
|
||||
$server = [
|
||||
'REQUEST_METHOD' => $method,
|
||||
'REQUEST_URI' => $url,
|
||||
];
|
||||
$req = new ServerRequest($server, [], $url, $method, "php://memory");
|
||||
$req = $req->withRequestTarget($target);
|
||||
return $this->h->dispatch($req);
|
||||
}
|
||||
|
||||
public function testRetrieveFavion() {
|
||||
Phake::when(Arsse::$db)->subscriptionFavicon->thenReturn("");
|
||||
Phake::when(Arsse::$db)->subscriptionFavicon(42)->thenReturn("http://example.com/favicon.ico");
|
||||
|
@ -39,19 +52,19 @@ class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Phake::when(Arsse::$db)->subscriptionFavicon(1337)->thenReturn("http://example.org/icon.gif\r\nLocation: http://bad.example.com/");
|
||||
// these requests should succeed
|
||||
$exp = new Response(301, ['Location' => "http://example.com/favicon.ico"]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "42.ico")));
|
||||
$this->assertResponse($exp, $this->req("42.ico"));
|
||||
$exp = new Response(301, ['Location' => "http://example.net/logo.png"]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "2112.ico")));
|
||||
$this->assertResponse($exp, $this->req("2112.ico"));
|
||||
$exp = new Response(301, ['Location' => "http://example.org/icon.gif"]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "1337.ico")));
|
||||
$this->assertResponse($exp, $this->req("1337.ico"));
|
||||
// these requests should fail
|
||||
$exp = new Response(404);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "ook.ico")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "ook")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "47.ico")));
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("GET", "2112.png")));
|
||||
$this->assertResponse($exp, $this->req("ook.ico"));
|
||||
$this->assertResponse($exp, $this->req("ook"));
|
||||
$this->assertResponse($exp, $this->req("47.ico"));
|
||||
$this->assertResponse($exp, $this->req("2112.png"));
|
||||
// only GET is allowed
|
||||
$exp = new Response(405, ['Allow' => "GET"]);
|
||||
$this->assertResponse($exp, $this->h->dispatch(new Request("PUT", "2112.ico")));
|
||||
$this->assertResponse($exp, $this->req("2112.ico", "PUT"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,13 +33,13 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
protected function assertResponse(ResponseInterface $exp, ResponseInterface $act, string $text = null) {
|
||||
$this->assertEquals($exp->getHeaders(), $act->getHeaders(), $text);
|
||||
$this->assertEquals($exp->getStatusCode(), $act->getStatusCode(), $text);
|
||||
$this->assertInstanceOf(get_class($exp), $act);
|
||||
if ($exp instanceof JsonResponse) {
|
||||
$this->assertEquals($exp->getPayload(), $act->getPayload(), $text);
|
||||
$this->assertSame($exp->getPayload(), $act->getPayload(), $text);
|
||||
}
|
||||
$this->assertEquals($exp->getHeaders(), $act->getHeaders(), $text);
|
||||
}
|
||||
|
||||
public function approximateTime($exp, $act) {
|
||||
|
|
Loading…
Reference in a new issue