J. King
4 years ago
13 changed files with 328 additions and 33 deletions
@ -0,0 +1,19 @@ |
|||
<?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\Miniflux; |
|||
|
|||
use JKingWeb\Arsse\Arsse; |
|||
|
|||
class ErrorResponse extends \Laminas\Diactoros\Response\JsonResponse { |
|||
public function __construct($data, int $status = 400, array $headers = [], int $encodingOptions = self::DEFAULT_JSON_FLAGS) { |
|||
assert(isset(Arsse::$lang) && Arsse::$lang instanceof \JKingWeb\Arsse\Lang, new \Exception("Language database must be initialized before use")); |
|||
$data = (array) $data; |
|||
$msg = array_shift($data); |
|||
$data = ["error_message" => Arsse::$lang->msg("API.Miniflux.Error.".$msg, $data)]; |
|||
parent::__construct($data, $status, $headers, $encodingOptions); |
|||
} |
|||
} |
@ -0,0 +1,37 @@ |
|||
<?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\Miniflux; |
|||
|
|||
use Psr\Http\Message\ServerRequestInterface; |
|||
use Psr\Http\Message\ResponseInterface; |
|||
use Laminas\Diactoros\Response\EmptyResponse; |
|||
use Laminas\Diactoros\Response\TextResponse; |
|||
|
|||
class Status extends \JKingWeb\Arsse\REST\AbstractHandler { |
|||
public function __construct() { |
|||
} |
|||
|
|||
public function dispatch(ServerRequestInterface $req): ResponseInterface { |
|||
$target = parse_url($req->getRequestTarget())['path'] ?? ""; |
|||
if (!in_array($target, ["/version", "/healthcheck"])) { |
|||
return new EmptyResponse(404); |
|||
} |
|||
$method = $req->getMethod(); |
|||
if ($method === "OPTIONS") { |
|||
return new EmptyResponse(204, ['Allow' => "HEAD, GET"]); |
|||
} elseif ($method !== "GET") { |
|||
return new EmptyResponse(405, ['Allow' => "HEAD, GET"]); |
|||
} |
|||
$out = ""; |
|||
if ($target === "/version") { |
|||
$out = V1::VERSION; |
|||
} elseif ($target === "/healthcheck") { |
|||
$out = "OK"; |
|||
} |
|||
return new TextResponse($out); |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
<?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\TestCase\REST\Miniflux; |
|||
|
|||
use JKingWeb\Arsse\REST\Miniflux\ErrorResponse; |
|||
|
|||
/** @covers \JKingWeb\Arsse\REST\Miniflux\ErrorResponse */ |
|||
class TestErrorResponse extends \JKingWeb\Arsse\Test\AbstractTest { |
|||
public function testCreateConstantResponse(): void { |
|||
$act = new ErrorResponse("401", 401); |
|||
$this->assertSame('{"error_message":"Access Unauthorized"}', (string) $act->getBody()); |
|||
} |
|||
|
|||
public function testCreateVariableResponse(): void { |
|||
$act = new ErrorResponse(["invalidBodyJSON", "Doh!"], 401); |
|||
$this->assertSame('{"error_message":"Invalid JSON payload: Doh!"}', (string) $act->getBody()); |
|||
} |
|||
} |
@ -0,0 +1,34 @@ |
|||
<?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\TestCase\REST\Miniflux; |
|||
|
|||
use JKingWeb\Arsse\REST\Miniflux\Status; |
|||
use JKingWeb\Arsse\REST\Miniflux\V1; |
|||
use Psr\Http\Message\ResponseInterface; |
|||
use Laminas\Diactoros\Response\EmptyResponse; |
|||
use Laminas\Diactoros\Response\TextResponse; |
|||
|
|||
/** @covers \JKingWeb\Arsse\REST\Miniflux\Status */ |
|||
class TestStatus extends \JKingWeb\Arsse\Test\AbstractTest { |
|||
/** @dataProvider provideRequests */ |
|||
public function testAnswerStatusRequests(string $url, string $method, ResponseInterface $exp): void { |
|||
$act = (new Status)->dispatch($this->serverRequest($method, $url, "")); |
|||
$this->assertMessage($exp, $act); |
|||
} |
|||
|
|||
public function provideRequests(): iterable { |
|||
return [ |
|||
["/version", "GET", new TextResponse(V1::VERSION)], |
|||
["/version", "POST", new EmptyResponse(405, ['Allow' => "HEAD, GET"])], |
|||
["/version", "OPTIONS", new EmptyResponse(204, ['Allow' => "HEAD, GET"])], |
|||
["/healthcheck", "GET", new TextResponse("OK")], |
|||
["/healthcheck", "POST", new EmptyResponse(405, ['Allow' => "HEAD, GET"])], |
|||
["/healthcheck", "OPTIONS", new EmptyResponse(204, ['Allow' => "HEAD, GET"])], |
|||
["/version/", "GET", new EmptyResponse(404)], |
|||
]; |
|||
} |
|||
} |
@ -0,0 +1,118 @@ |
|||
<?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\TestCase\REST\NextcloudNews; |
|||
|
|||
use JKingWeb\Arsse\Arsse; |
|||
use JKingWeb\Arsse\User; |
|||
use JKingWeb\Arsse\Database; |
|||
use JKingWeb\Arsse\Db\Transaction; |
|||
use JKingWeb\Arsse\REST\Miniflux\V1; |
|||
use Psr\Http\Message\ResponseInterface; |
|||
|
|||
/** @covers \JKingWeb\Arsse\REST\Miniflux\V1<extended> */ |
|||
class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest { |
|||
protected $h; |
|||
protected $transaction; |
|||
|
|||
protected function req(string $method, string $target, $data = "", array $headers = [], bool $authenticated = true, bool $body = true): ResponseInterface { |
|||
$prefix = "/v1"; |
|||
$url = $prefix.$target; |
|||
if ($body) { |
|||
$params = []; |
|||
} else { |
|||
$params = $data; |
|||
$data = []; |
|||
} |
|||
$req = $this->serverRequest($method, $url, $prefix, $headers, [], $data, "application/json", $params, $authenticated ? "john.doe@example.com" : ""); |
|||
return $this->h->dispatch($req); |
|||
} |
|||
|
|||
public function setUp(): void { |
|||
self::clearData(); |
|||
self::setConf(); |
|||
// create a mock user manager |
|||
Arsse::$user = \Phake::mock(User::class); |
|||
Arsse::$user->id = "john.doe@example.com"; |
|||
// create a mock database interface |
|||
Arsse::$db = \Phake::mock(Database::class); |
|||
$this->transaction = \Phake::mock(Transaction::class); |
|||
\Phake::when(Arsse::$db)->begin->thenReturn($this->transaction); |
|||
//initialize a handler |
|||
$this->h = new V1(); |
|||
} |
|||
|
|||
public function tearDown(): void { |
|||
self::clearData(); |
|||
} |
|||
|
|||
protected function v($value) { |
|||
return $value; |
|||
} |
|||
|
|||
public function testSendAuthenticationChallenge(): void { |
|||
$exp = new EmptyResponse(401); |
|||
$this->assertMessage($exp, $this->req("GET", "/", "", [], false)); |
|||
} |
|||
|
|||
/** @dataProvider provideInvalidPaths */ |
|||
public function testRespondToInvalidPaths($path, $method, $code, $allow = null): void { |
|||
$exp = new EmptyResponse($code, $allow ? ['Allow' => $allow] : []); |
|||
$this->assertMessage($exp, $this->req($method, $path)); |
|||
} |
|||
|
|||
public function provideInvalidPaths(): array { |
|||
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"], |
|||
]; |
|||
} |
|||
|
|||
public function testRespondToInvalidInputTypes(): void { |
|||
$exp = new EmptyResponse(415, ['Accept' => "application/json"]); |
|||
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>', ['Content-Type' => "application/xml"])); |
|||
$exp = new EmptyResponse(400); |
|||
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>')); |
|||
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>', ['Content-Type' => null])); |
|||
} |
|||
|
|||
/** @dataProvider provideOptionsRequests */ |
|||
public function testRespondToOptionsRequests(string $url, string $allow, string $accept): void { |
|||
$exp = new EmptyResponse(204, [ |
|||
'Allow' => $allow, |
|||
'Accept' => $accept, |
|||
]); |
|||
$this->assertMessage($exp, $this->req("OPTIONS", $url)); |
|||
} |
|||
|
|||
public function provideOptionsRequests(): array { |
|||
return [ |
|||
["/feeds", "HEAD,GET,POST", "application/json"], |
|||
["/feeds/2112", "DELETE", "application/json"], |
|||
["/user", "HEAD,GET", "application/json"], |
|||
]; |
|||
} |
|||
} |
Loading…
Reference in new issue