*/ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest { protected $h; protected $transaction; protected $token = "Tk2o9YubmZIL2fm2w8Z4KlDEQJz532fNSOcTG0s2_xc="; 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; } /** @dataProvider provideAuthResponses */ public function testAuthenticateAUser($token, bool $auth, bool $success): void { $exp = $success ? new EmptyResponse(404) : new ErrorResponse("401", 401); $user = "john.doe@example.com"; if ($token !== null) { $headers = ['X-Auth-Token' => $token]; } else { $headers = []; } Arsse::$user->id = null; \Phake::when(Arsse::$db)->tokenLookup->thenThrow(new ExceptionInput("subjectMissing")); \Phake::when(Arsse::$db)->tokenLookup("miniflux.login", $this->token)->thenReturn(['user' => $user]); $this->assertMessage($exp, $this->req("GET", "/", "", $headers, $auth)); $this->assertSame($success ? $user : null, Arsse::$user->id); } public function provideAuthResponses(): iterable { return [ [null, false, false], [null, true, true], [$this->token, false, true], [[$this->token, "BOGUS"], false, true], ["", true, true], [["", "BOGUS"], true, true], ["NOT A TOKEN", false, false], ["NOT A TOKEN", true, false], [["BOGUS", $this->token], false, false], [["", $this->token], false, 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], ["/", "OPTIONS", 404], ["/me", "POST", 405, "GET"], ["/me/", "GET", 404], ]; } /** @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", "HEAD, GET, PUT, DELETE", "application/json"], ["/me", "HEAD, GET", "application/json"], ["/users/someone", "HEAD, GET", "application/json"], ["/import", "POST", "application/xml, text/xml, text/x-opml"], ]; } public function testRejectBadlyTypedData(): void { $exp = new ErrorResponse(["invalidInputType", 'field' => "url", 'expected' => "string", 'actual' => "integer"], 400); $this->assertMessage($exp, $this->req("POST", "/discover", ['url' => 2112])); } public function testDiscoverFeeds(): void { $exp = new Response([ ['title' => "Feed", 'type' => "rss", 'url' => "http://localhost:8000/Feed/Discovery/Feed"], ['title' => "Feed", 'type' => "rss", 'url' => "http://localhost:8000/Feed/Discovery/Missing"], ]); $this->assertMessage($exp, $this->req("POST", "/discover", ['url' => "http://localhost:8000/Feed/Discovery/Valid"])); $exp = new Response([]); $this->assertMessage($exp, $this->req("POST", "/discover", ['url' => "http://localhost:8000/Feed/Discovery/Invalid"])); $exp = new ErrorResponse("fetch404", 500); $this->assertMessage($exp, $this->req("POST", "/discover", ['url' => "http://localhost:8000/Feed/Discovery/Missing"])); } }