Browse Source

Implement NCN API v1-2 feed handling: tests

- Fixes #8
- Fixes #9
- Fixes #10
- Fixes #11
- Fixes #12

- Differentiated between a missing ID which is the subject of an action (e.g. the subscription when moving a subscription) and other missing IDs (e.g. the folder when moving a subscription)
- Enforced same rules for subscription titles as for folder names, save that null is valid for subscriptions
microsub
J. King 7 years ago
parent
commit
88c0f4986c
  1. 1
      lib/AbstractException.php
  2. 38
      lib/Database.php
  3. 24
      lib/REST/NextCloudNews/V1_2.php
  4. 1
      locale/en.php
  5. 188
      tests/REST/NextCloudNews/TestNCNV1_2.php
  6. 14
      tests/lib/Database/SeriesFolder.php
  7. 41
      tests/lib/Database/SeriesSubscription.php

1
lib/AbstractException.php

@ -43,6 +43,7 @@ abstract class AbstractException extends \Exception {
"Db/ExceptionInput.constraintViolation" => 10236,
"Db/ExceptionInput.typeViolation" => 10237,
"Db/ExceptionInput.circularDependence" => 10238,
"Db/ExceptionInput.subjectMissing" => 10239,
"Db/ExceptionTimeout.general" => 10241,
"Conf/Exception.fileMissing" => 10301,
"Conf/Exception.fileUnusable" => 10302,

38
lib/Database.php

@ -344,25 +344,23 @@ class Database {
public function folderRemove(string $user, int $id): bool {
if(!Data::$user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
$changes = $this->db->prepare("DELETE FROM arsse_folders where owner is ? and id is ?", "str", "int")->run($user, $id)->changes();
if(!$changes) throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]);
if(!$changes) throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]);
return true;
}
public function folderPropertiesGet(string $user, int $id): array {
if(!Data::$user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
$props = $this->db->prepare("SELECT id,name,parent from arsse_folders where owner is ? and id is ?", "str", "int")->run($user, $id)->getRow();
if(!$props) throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]);
if(!$props) throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]);
return $props;
}
public function folderPropertiesSet(string $user, int $id, array $data): bool {
if(!Data::$user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
// validate the folder ID and, if specified, the parent to move it to
if(array_key_exists("parent", $data)) {
$f = $this->folderValidateId($user, $id, $data['parent']);
} else {
$f = $this->folderValidateId($user, $id);
}
$parent = null;
if(array_key_exists("parent", $data)) $parent = $data['parent'];
$f = $this->folderValidateId($user, $id, $parent, true);
// if a new name is specified, validate it
if(array_key_exists("name", $data)) {
$this->folderValidateName($data['name']);
@ -381,7 +379,7 @@ class Database {
return (bool) $this->db->prepare("UPDATE arsse_folders set $setClause where owner is ? and id is ?", $setTypes, "str", "int")->run($setValues, $user, $id)->changes();
}
protected function folderValidateId(string $user, int $id = null, int $parent = null): array {
protected function folderValidateId(string $user, int $id = null, int $parent = null, bool $subject = false): array {
if(is_null($id)) {
// if no ID is specified this is a no-op, unless a parent is specified, which is always a circular dependence
if(!is_null($parent)) {
@ -391,7 +389,7 @@ class Database {
}
// check whether the folder exists and is owned by the user
$f = $this->db->prepare("SELECT name,parent from arsse_folders where owner is ? and id is ?", "str", "int")->run($user, $id)->getRow();
if(!$f) throw new Db\ExceptionInput("idMissing", ["action" => $this->caller(), "field" => "folder", 'id' => $parent]);
if(!$f) throw new Db\ExceptionInput($subject ? "subjectMissing" : "idMissing", ["action" => $this->caller(), "field" => "folder", 'id' => $parent]);
// if we're moving a folder to a new parent, check that the parent is valid
if(!is_null($parent)) {
// make sure both that the parent exists, and that the parent is not either the folder itself or one of its children (a circular dependence)
@ -413,7 +411,7 @@ class Database {
protected function folderValidateName($name): bool {
$name = (string) $name;
if($name=="") {
if(!strlen($name)) {
throw new Db\ExceptionInput("missing", ["action" => $this->caller(), "field" => "name"]);
} else if(!strlen(trim($name))) {
throw new Db\ExceptionInput("whitespace", ["action" => $this->caller(), "field" => "name"]);
@ -473,7 +471,7 @@ class Database {
public function subscriptionRemove(string $user, int $id): bool {
if(!Data::$user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
$changes = $this->db->prepare("DELETE from arsse_subscriptions where owner is ? and id is ?", "str", "int")->run($user, $id)->changes();
if(!$changes) throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]);
if(!$changes) throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]);
return true;
}
@ -483,7 +481,7 @@ class Database {
Data::$user->authorizationEnabled(false);
$sub = $this->subscriptionList($user, null, $id)->getRow();
Data::$user->authorizationEnabled(true);
if(!$sub) throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $id]);
if(!$sub) throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $id]);
return $sub;
}
@ -492,18 +490,20 @@ class Database {
$tr = $this->db->begin();
if(!$this->db->prepare("SELECT count(*) from arsse_subscriptions where owner is ? and id is ?", "str", "int")->run($user, $id)->getValue()) {
// if the ID doesn't exist or doesn't belong to the user, throw an exception
throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $id]);
throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $id]);
}
if(array_key_exists("folder", $data)) {
// ensure the target folder exists and belong to the user
$this->folderValidateId($user, $data['folder']);
}
if(array_key_exists("title", $data)) {
// if the title is effectively an empty string, change it to null so that the feed title is used instead
$title = (string) $data['title'];
$title = trim($title);
if($title==="") $title = null;
$data['title'] = $title;
// if the title is null, this signals intended use of the default title; otherwise make sure it's not effectively an empty string
if(!is_null($data['title'])) {
$title = (string) $data['title'];
if(!strlen($title)) throw new Db\ExceptionInput("missing", ["action" => __FUNCTION__, "field" => "title"]);
if(!strlen(trim($title))) throw new Db\ExceptionInput("whitespace", ["action" => __FUNCTION__, "field" => "title"]);
$data['title'] = $title;
}
}
$valid = [
'title' => "str",
@ -558,7 +558,7 @@ class Database {
$tr = $this->db->begin();
// check to make sure the feed exists
$f = $this->db->prepare('SELECT url, username, password, DATEFORMAT("http", modified) AS lastmodified, etag, err_count FROM arsse_feeds where id is ?', "int")->run($feedID)->getRow();
if(!$f) throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $feedID]);
if(!$f) throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $feedID]);
// the Feed object throws an exception when there are problems, but that isn't ideal
// here. When an exception is thrown it should update the database with the
// error instead of failing; if other exceptions are thrown, we should simply roll back

24
lib/REST/NextCloudNews/V1_2.php

@ -159,7 +159,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
} catch(ExceptionInput $e) {
switch($e->getCode()) {
// folder does not exist
case 10235: return new Response(404);
case 10239: return new Response(404);
// folder already exists
case 10236: return new Response(409);
// folder name not acceptable
@ -206,13 +206,12 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
}
$out = ['feeds' => $out];
$out['starredCount'] = Data::$db->articleStarredCount(Data::$user->id);
$newest = Data::$db->editionLatest(Data::$user->id, ['subscription' => $id]);
$newest = Data::$db->editionLatest(Data::$user->id);
if($newest) $out['newestItemId'] = $newest;
return new Response(200, $out);
}
// return list of feeds which should be refreshed
// refresh a feed
protected function feedListStale(array $url, array $data): Response {
// function requires admin rights per spec
if(Data::$user->rightsGet(Data::$user->id)==User::RIGHTS_NONE) return new Response(403);
@ -305,7 +304,15 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
try {
Data::$db->subscriptionPropertiesSet(Data::$user->id, (int) $url[1], $in);
} catch(ExceptionInput $e) {
return new Response(404);
switch($e->getCode()) {
// subscription does not exist
case 10239: return new Response(404);
// name is invalid
case 10231:
case 10232: return new Response(422);
// other errors related to input
default: return new Response(400);
}
}
return new Response(204);
}
@ -326,7 +333,14 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
try {
Data::$db->subscriptionPropertiesSet(Data::$user->id, (int) $url[1], $in);
} catch(ExceptionInput $e) {
return new Response(404);
switch($e->getCode()) {
// subscription does not exist
case 10239: return new Response(404);
// folder does not exist
case 10235: return new Response(422);
// other errors related to input
default: return new Response(400);
}
}
return new Response(204);
}

1
locale/en.php

@ -66,6 +66,7 @@ return [
'Exception.JKingWeb/Arsse/Db/ExceptionInput.whitespace' => 'Required field "{field}" of action "{action}" may not contain only whitespace',
'Exception.JKingWeb/Arsse/Db/ExceptionInput.tooLong' => 'Required field "{field}" of action "{action}" has a maximum length of {max}',
'Exception.JKingWeb/Arsse/Db/ExceptionInput.tooShort' => 'Required field "{field}" of action "{action}" has a minimum length of {min}',
'Exception.JKingWeb/Arsse/Db/ExceptionInput.subjectMissing' => 'Referenced ID ({id}) in field "{field}" does not exist',
'Exception.JKingWeb/Arsse/Db/ExceptionInput.idMissing' => 'Referenced ID ({id}) in field "{field}" does not exist',
'Exception.JKingWeb/Arsse/Db/ExceptionInput.circularDependence' => 'Referenced ID ({id}) in field "{field}" creates a circular dependence',
'Exception.JKingWeb/Arsse/Db/ExceptionInput.constraintViolation' => '{0}',

188
tests/REST/NextCloudNews/TestNCNV1_2.php

@ -11,6 +11,68 @@ class TestNCNV1_2 extends \PHPUnit\Framework\TestCase {
use Test\Tools;
protected $h;
protected $feeds = [ // expected sample output of a feed list from the database, and the resultant expected transformation by the REST handler
'db' => [
[
'id' => 2112,
'url' => 'http://example.com/news.atom',
'favicon' => 'http://example.com/favicon.png',
'source' => 'http://example.com/',
'folder' => NULL,
'pinned' => 0,
'err_count' => 0,
'err_msg' => '',
'order_type' => 0,
'added' => 1495287354,
'title' => 'First example feed',
'unread' => 50048,
],
[
'id' => 42,
'url' => 'http://example.org/news.atom',
'favicon' => 'http://example.org/favicon.png',
'source' => 'http://example.org/',
'folder' => 8,
'pinned' => 1,
'err_count' => 0,
'err_msg' => '',
'order_type' => 2,
'added' => 1495287354,
'title' => 'Second example feed',
'unread' => 23,
],
],
'rest' => [
[
'id' => 2112,
'url' => 'http://example.com/news.atom',
'faviconLink' => 'http://example.com/favicon.png',
'link' => 'http://example.com/',
'folderId' => 0,
'pinned' => false,
'updateErrorCount' => 0,
'lastUpdateError' => '',
'ordering' => 0,
'added' => 1495287354,
'title' => 'First example feed',
'unreadCount' => 50048,
],
[
'id' => 42,
'url' => 'http://example.org/news.atom',
'faviconLink' => 'http://example.org/favicon.png',
'link' => 'http://example.org/',
'folderId' => 8,
'pinned' => true,
'updateErrorCount' => 0,
'lastUpdateError' => '',
'ordering' => 2,
'added' => 1495287354,
'title' => 'Second example feed',
'unreadCount' => 23,
],
],
];
function setUp() {
$this->clearData();
@ -78,7 +140,9 @@ class TestNCNV1_2 extends \PHPUnit\Framework\TestCase {
['id' => 1, 'name' => "Software", 'parent' => null],
['id' => 12, 'name' => "Hardware", 'parent' => null],
];
Phake::when(Data::$db)->folderList(Data::$user->id, null, false)->thenReturn(new Result($list));
Phake::when(Data::$db)->folderList(Data::$user->id, null, false)->thenReturn(new Result([]))->thenReturn(new Result($list));
$exp = new Response(200, ['folders' => []]);
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/folders")));
$exp = new Response(200, ['folders' => $list]);
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/folders")));
}
@ -123,7 +187,7 @@ class TestNCNV1_2 extends \PHPUnit\Framework\TestCase {
}
function testRemoveAFolder() {
Phake::when(Data::$db)->folderRemove(Data::$user->id, 1)->thenReturn(true)->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("idMissing"));
Phake::when(Data::$db)->folderRemove(Data::$user->id, 1)->thenReturn(true)->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing"));
$exp = new Response(204);
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/folders/1")));
// fail on the second invocation because it no longer exists
@ -145,7 +209,7 @@ class TestNCNV1_2 extends \PHPUnit\Framework\TestCase {
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[2])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("missing"));
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[3])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("whitespace"));
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[4])->thenReturn(true); // this should be stopped by the handler before the request gets to the database
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 3, $this->anything())->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("idMissing")); // folder ID 3 does not exist
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 3, $this->anything())->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing")); // folder ID 3 does not exist
$exp = new Response(204);
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[0]), 'application/json')));
$exp = new Response(409);
@ -164,4 +228,122 @@ class TestNCNV1_2 extends \PHPUnit\Framework\TestCase {
$exp = new Response(200, ['version' => \JKingWeb\Arsse\VERSION]);
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/version")));
}
function testListSubscriptions() {
$exp1 = [
'feeds' => [],
'starredCount' => 0,
];
$exp2 = [
'feeds' => $this->feeds['rest'],
'starredCount' => 5,
'newestItemId' => 4758915,
];
Phake::when(Data::$db)->subscriptionList(Data::$user->id)->thenReturn(new Result([]))->thenReturn(new Result($this->feeds['db']));
Phake::when(Data::$db)->articleStarredCount(Data::$user->id)->thenReturn(0)->thenReturn(5);
Phake::when(Data::$db)->editionLatest(Data::$user->id)->thenReturn(0)->thenReturn(4758915);
$exp = new Response(200, $exp1);
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds")));
$exp = new Response(200, $exp2);
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds")));
// make sure the correct date format is actually requested
Phake::verify(Data::$db, Phake::atLeast(1))->dateFormatDefault("unix");
}
function testAddASubscription() {
$in = [
['url' => "http://example.com/news.atom", 'folderId' => 3],
['url' => "http://example.org/news.atom", 'folderId' => 8],
['url' => "http://example.net/news.atom", 'folderId' => 0],
];
$out = [
['feeds' => [$this->feeds['rest'][0]]],
['feeds' => [$this->feeds['rest'][1]], 'newestItemId' => 4758915],
[],
];
// set up the necessary mocks
Phake::when(Data::$db)->subscriptionAdd(Data::$user->id, "http://example.com/news.atom")->thenReturn(2112)->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("constraintViolation")); // error on the second call
Phake::when(Data::$db)->subscriptionAdd(Data::$user->id, "http://example.org/news.atom")->thenReturn( 42 )->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("constraintViolation")); // error on the second call
Phake::when(Data::$db)->subscriptionPropertiesGet(Data::$user->id, 2112)->thenReturn($this->feeds['db'][0]);
Phake::when(Data::$db)->subscriptionPropertiesGet(Data::$user->id, 42)->thenReturn($this->feeds['db'][1]);
Phake::when(Data::$db)->editionLatest(Data::$user->id, ['subscription' => 2112])->thenReturn(0);
Phake::when(Data::$db)->editionLatest(Data::$user->id, ['subscription' => 42])->thenReturn(4758915);
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 2112, ['folder' => 3])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("idMissing")); // folder ID 3 does not exist
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 42, ['folder' => 8])->thenReturn(true);
// set up a mock for a bad feed
Phake::when(Data::$db)->subscriptionAdd(Data::$user->id, "http://example.net/news.atom")->thenThrow(new \JKingWeb\Arsse\Feed\Exception("http://example.net/news.atom", new \PicoFeed\Client\InvalidUrlException()));
// add the subscriptions
$exp = new Response(200, $out[0]);
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[0]), 'application/json')));
$exp = new Response(200, $out[1]);
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[1]), 'application/json')));
// try to add them a second time
$exp = new Response(409);
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[0]), 'application/json')));
$exp = new Response(409);
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[1]), 'application/json')));
// try to add a bad feed
$exp = new Response(422);
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[2]), 'application/json')));
// make sure the correct date format is actually requested
Phake::verify(Data::$db, Phake::atLeast(1))->dateFormatDefault("unix");
}
function testRemoveASubscription() {
Phake::when(Data::$db)->subscriptionRemove(Data::$user->id, 1)->thenReturn(true)->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing"));
$exp = new Response(204);
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/feeds/1")));
// fail on the second invocation because it no longer exists
$exp = new Response(404);
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/feeds/1")));
Phake::verify(Data::$db, Phake::times(2))->subscriptionRemove(Data::$user->id, 1);
}
function testMoveASubscription() {
$in = [
['folderId' => 0],
['folderId' => 42],
['folderId' => 2112],
['folderId' => 42],
];
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 1, ['folder' => 42])->thenReturn(true);
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 1, ['folder' => null])->thenReturn(true);
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 1, ['folder' => 2112])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("idMissing")); // folder does not exist
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 42, $this->anything())->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing")); // subscription does not exist
$exp = new Response(204);
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[0]), 'application/json')));
$exp = new Response(204);
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[1]), 'application/json')));
$exp = new Response(422);
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[2]), 'application/json')));
$exp = new Response(404);
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/42/move", json_encode($in[3]), 'application/json')));
}
function testRenameASubscription() {
$in = [
['feedTitle' => null],
['feedTitle' => "Ook"],
['feedTitle' => " "],
['feedTitle' => ""],
['feedTitle' => false],
['feedTitle' => "Feed does not exist"],
];
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 1, $this->identicalTo(['title' => null]))->thenReturn(true);
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 1, $this->identicalTo(['title' => "Ook"]))->thenReturn(true);
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 1, $this->identicalTo(['title' => " "]))->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("whitespace"));
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 1, $this->identicalTo(['title' => ""]))->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("missing"));
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 1, $this->identicalTo(['title' => false]))->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("missing"));
Phake::when(Data::$db)->subscriptionPropertiesSet(Data::$user->id, 42, $this->anything())->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing"));
$exp = new Response(204);
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[0]), 'application/json')));
$exp = new Response(204);
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[1]), 'application/json')));
$exp = new Response(422);
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[2]), 'application/json')));
$exp = new Response(422);
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[3]), 'application/json')));
$exp = new Response(404);
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/42/rename", json_encode($in[4]), 'application/json')));
}
}

14
tests/lib/Database/SeriesFolder.php

@ -139,12 +139,12 @@ trait SeriesFolder {
}
function testRemoveAMissingFolder() {
$this->assertException("idMissing", "Db", "ExceptionInput");
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Data::$db->folderRemove("john.doe@example.com", 2112);
}
function testRemoveAFolderOfTheWrongOwner() {
$this->assertException("idMissing", "Db", "ExceptionInput");
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Data::$db->folderRemove("john.doe@example.com", 4); // folder ID 4 belongs to Jane
}
@ -165,12 +165,12 @@ trait SeriesFolder {
}
function testGetThePropertiesOfAMissingFolder() {
$this->assertException("idMissing", "Db", "ExceptionInput");
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Data::$db->folderPropertiesGet("john.doe@example.com", 2112);
}
function testGetThePropertiesOfAFolderOfTheWrongOwner() {
$this->assertException("idMissing", "Db", "ExceptionInput");
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Data::$db->folderPropertiesGet("john.doe@example.com", 4); // folder ID 4 belongs to Jane
}
@ -217,12 +217,12 @@ trait SeriesFolder {
}
function testSetThePropertiesOfAMissingFolder() {
$this->assertException("idMissing", "Db", "ExceptionInput");
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Data::$db->folderPropertiesSet("john.doe@example.com", 2112, ['parent' => null]);
}
function testSetThePropertiesOfAFolderOfTheWrongOwner() {
$this->assertException("idMissing", "Db", "ExceptionInput");
function testSetThePropertiesOfAFolderForTheWrongOwner() {
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Data::$db->folderPropertiesSet("john.doe@example.com", 4, ['parent' => null]); // folder ID 4 belongs to Jane
}

41
tests/lib/Database/SeriesSubscription.php

@ -167,13 +167,13 @@ trait SeriesSubscription {
}
function testRemoveAMissingSubscription() {
$this->assertException("idMissing", "Db", "ExceptionInput");
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Data::$db->subscriptionRemove($this->user, 2112);
}
function testRemoveASubscriptionForTheWrongOwner() {
$this->user = "jane.doe@example.com";
$this->assertException("idMissing", "Db", "ExceptionInput");
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Data::$db->subscriptionRemove($this->user, 1);
}
@ -257,31 +257,44 @@ trait SeriesSubscription {
$state['arsse_subscriptions']['rows'][0] = [1,"john.doe@example.com",2,"Ook Ook",3,0,0];
$this->compareExpectations($state);
Data::$db->subscriptionPropertiesSet($this->user, 1,[
'title' => " ",
'title' => null,
]);
$state['arsse_subscriptions']['rows'][0] = [1,"john.doe@example.com",2,null,3,0,0];
$this->compareExpectations($state);
}
function testMoveSubscriptionToAMissingFolder() {
function testMoveASubscriptionToAMissingFolder() {
$this->assertException("idMissing", "Db", "ExceptionInput");
Data::$db->subscriptionPropertiesSet($this->user, 1,[
'folder' => 4,
]);
Data::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => 4]);
}
function testRenameASubscriptionToABlankTitle() {
$this->assertException("missing", "Db", "ExceptionInput");
Data::$db->subscriptionPropertiesSet($this->user, 1, ['title' => ""]);
}
function testRenameASubscriptionToAWhitespaceTitle() {
$this->assertException("whitespace", "Db", "ExceptionInput");
Data::$db->subscriptionPropertiesSet($this->user, 1, ['title' => " "]);
}
function testRenameASubscriptionToFalse() {
$this->assertException("missing", "Db", "ExceptionInput");
Data::$db->subscriptionPropertiesSet($this->user, 1, ['title' => false]);
}
function testRenameASubscriptionToZero() {
$this->assertTrue(Data::$db->subscriptionPropertiesSet($this->user, 1, ['title' => 0]));
}
function testSetThePropertiesOfAMissingSubscription() {
$this->assertException("idMissing", "Db", "ExceptionInput");
Data::$db->subscriptionPropertiesSet($this->user, 2112,[
'folder' => null,
]);
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Data::$db->subscriptionPropertiesSet($this->user, 2112, ['folder' => null]);
}
function testSetThePropertiesOfASubscriptionWithoutAuthority() {
Phake::when(Data::$user)->authorize->thenReturn(false);
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
Data::$db->subscriptionPropertiesSet($this->user, 1,[
'folder' => null,
]);
Data::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => null]);
}
}
Loading…
Cancel
Save