2017-05-11 02:01:00 +00:00
|
|
|
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace JKingWeb\Arsse\Test\Database;
|
|
|
|
use JKingWeb\Arsse\Data;
|
|
|
|
use JKingWeb\Arsse\Test\Database;
|
|
|
|
use JKingWeb\Arsse\User\Driver as UserDriver;
|
|
|
|
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
|
|
|
use Phake;
|
|
|
|
|
|
|
|
trait SeriesSubscription {
|
|
|
|
function setUpSeries() {
|
|
|
|
$data = [
|
|
|
|
'arsse_feeds' => [
|
|
|
|
'columns' => [
|
2017-05-19 03:03:33 +00:00
|
|
|
'id' => "int",
|
|
|
|
'url' => "str",
|
|
|
|
'title' => "str",
|
|
|
|
'username' => "str",
|
|
|
|
'password' => "str",
|
|
|
|
'next_fetch' => "datetime",
|
2017-05-11 02:01:00 +00:00
|
|
|
],
|
|
|
|
'rows' => [
|
2017-05-19 03:03:33 +00:00
|
|
|
[1,"http://example.com/feed1", "Ook", "", "",strtotime("now")],
|
|
|
|
[2,"http://example.com/feed2", "Eek", "", "",strtotime("now - 1 hour")],
|
|
|
|
[3,"http://example.com/feed3", "Ack", "", "",strtotime("now + 1 hour")],
|
2017-05-11 02:01:00 +00:00
|
|
|
]
|
|
|
|
],
|
|
|
|
'arsse_subscriptions' => [
|
|
|
|
'columns' => [
|
2017-05-18 17:21:17 +00:00
|
|
|
'id' => "int",
|
|
|
|
'owner' => "str",
|
|
|
|
'feed' => "int",
|
|
|
|
'title' => "str",
|
|
|
|
'folder' => "int",
|
|
|
|
'pinned' => "bool",
|
|
|
|
'order_type' => "int",
|
2017-05-11 02:01:00 +00:00
|
|
|
],
|
|
|
|
'rows' => [
|
2017-05-18 17:21:17 +00:00
|
|
|
[1,"john.doe@example.com",2,null,null,1,2],
|
|
|
|
[2,"jane.doe@example.com",2,null,null,0,0],
|
|
|
|
[3,"john.doe@example.com",3,"Ook",2,0,1],
|
2017-05-11 02:01:00 +00:00
|
|
|
]
|
2017-05-15 03:03:48 +00:00
|
|
|
],
|
2017-05-17 02:19:40 +00:00
|
|
|
'arsse_articles' => [
|
|
|
|
'columns' => [
|
2017-05-18 17:21:17 +00:00
|
|
|
'id' => "int",
|
|
|
|
'feed' => "int",
|
|
|
|
'url_title_hash' => "str",
|
|
|
|
'url_content_hash' => "str",
|
2017-05-17 02:19:40 +00:00
|
|
|
'title_content_hash' => "str",
|
|
|
|
],
|
|
|
|
'rows' => [
|
|
|
|
[1,2,"","",""],
|
|
|
|
[2,2,"","",""],
|
|
|
|
[3,2,"","",""],
|
|
|
|
[4,2,"","",""],
|
|
|
|
[5,2,"","",""],
|
|
|
|
[6,3,"","",""],
|
|
|
|
[7,3,"","",""],
|
|
|
|
[8,3,"","",""],
|
|
|
|
]
|
|
|
|
],
|
|
|
|
'arsse_marks' => [
|
|
|
|
'columns' => [
|
|
|
|
'id' => "int",
|
|
|
|
'article' => "int",
|
|
|
|
'owner' => "str",
|
|
|
|
'read' => "bool",
|
|
|
|
'starred' => "bool",
|
|
|
|
],
|
|
|
|
'rows' => [
|
2017-05-18 17:21:17 +00:00
|
|
|
[1,1,"jane.doe@example.com",1,0],
|
|
|
|
[2,2,"jane.doe@example.com",1,0],
|
|
|
|
[3,3,"jane.doe@example.com",1,0],
|
|
|
|
[4,4,"jane.doe@example.com",1,0],
|
|
|
|
[5,5,"jane.doe@example.com",1,0],
|
|
|
|
[6,6,"jane.doe@example.com",1,0],
|
|
|
|
[7,7,"jane.doe@example.com",1,0],
|
|
|
|
[8,8,"jane.doe@example.com",1,0],
|
|
|
|
[9, 1,"john.doe@example.com",1,0],
|
|
|
|
[10,7,"john.doe@example.com",1,0],
|
|
|
|
[11,8,"john.doe@example.com",0,0],
|
2017-05-17 02:19:40 +00:00
|
|
|
]
|
|
|
|
],
|
2017-05-11 02:01:00 +00:00
|
|
|
];
|
2017-05-11 22:00:35 +00:00
|
|
|
// merge tables
|
2017-05-11 02:01:00 +00:00
|
|
|
$this->data = array_merge($this->data, $data);
|
|
|
|
$this->primeDatabase($this->data);
|
|
|
|
// initialize a partial mock of the Database object to later manipulate the feedUpdate method
|
|
|
|
Data::$db = Phake::PartialMock(Database::class, $this->drv);
|
2017-05-18 17:21:17 +00:00
|
|
|
$this->user = "john.doe@example.com";
|
2017-05-11 02:01:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function testAddASubscriptionToAnExistingFeed() {
|
|
|
|
$url = "http://example.com/feed1";
|
|
|
|
$subID = $this->nextID("arsse_subscriptions");
|
|
|
|
Phake::when(Data::$db)->feedUpdate->thenReturn(true);
|
2017-05-18 17:21:17 +00:00
|
|
|
$this->assertSame($subID,Data::$db->subscriptionAdd($this->user, $url));
|
|
|
|
Phake::verify(Data::$user)->authorize($this->user, "subscriptionAdd");
|
2017-05-11 02:01:00 +00:00
|
|
|
Phake::verify(Data::$db, Phake::times(0))->feedUpdate(1, true);
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
|
|
|
'arsse_feeds' => ['id','url','username','password'],
|
|
|
|
'arsse_subscriptions' => ['id','owner','feed'],
|
|
|
|
]);
|
2017-05-18 17:21:17 +00:00
|
|
|
$state['arsse_subscriptions']['rows'][] = [$subID,$this->user,1];
|
2017-05-11 02:01:00 +00:00
|
|
|
$this->compareExpectations($state);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testAddASubscriptionToANewFeed() {
|
|
|
|
$url = "http://example.org/feed1";
|
|
|
|
$feedID = $this->nextID("arsse_feeds");
|
|
|
|
$subID = $this->nextID("arsse_subscriptions");
|
|
|
|
Phake::when(Data::$db)->feedUpdate->thenReturn(true);
|
2017-05-18 17:21:17 +00:00
|
|
|
$this->assertSame($subID,Data::$db->subscriptionAdd($this->user, $url));
|
|
|
|
Phake::verify(Data::$user)->authorize($this->user, "subscriptionAdd");
|
2017-05-11 02:01:00 +00:00
|
|
|
Phake::verify(Data::$db)->feedUpdate($feedID, true);
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
|
|
|
'arsse_feeds' => ['id','url','username','password'],
|
|
|
|
'arsse_subscriptions' => ['id','owner','feed'],
|
|
|
|
]);
|
|
|
|
$state['arsse_feeds']['rows'][] = [$feedID,$url,"",""];
|
2017-05-18 17:21:17 +00:00
|
|
|
$state['arsse_subscriptions']['rows'][] = [$subID,$this->user,$feedID];
|
2017-05-11 02:01:00 +00:00
|
|
|
$this->compareExpectations($state);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testAddASubscriptionToAnInvalidFeed() {
|
|
|
|
$url = "http://example.org/feed1";
|
|
|
|
$feedID = $this->nextID("arsse_feeds");
|
|
|
|
Phake::when(Data::$db)->feedUpdate->thenThrow(new FeedException($url, new \PicoFeed\Client\InvalidUrlException()));
|
|
|
|
try {
|
2017-05-18 17:21:17 +00:00
|
|
|
Data::$db->subscriptionAdd($this->user, $url);
|
2017-05-11 02:01:00 +00:00
|
|
|
} catch(FeedException $e) {
|
2017-05-18 17:21:17 +00:00
|
|
|
Phake::verify(Data::$user)->authorize($this->user, "subscriptionAdd");
|
2017-05-11 02:01:00 +00:00
|
|
|
Phake::verify(Data::$db)->feedUpdate($feedID, true);
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
|
|
|
'arsse_feeds' => ['id','url','username','password'],
|
|
|
|
'arsse_subscriptions' => ['id','owner','feed'],
|
|
|
|
]);
|
|
|
|
$this->compareExpectations($state);
|
|
|
|
$this->assertException("invalidUrl", "Feed");
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
}
|
2017-05-11 22:00:35 +00:00
|
|
|
|
|
|
|
function testAddADuplicateSubscription() {
|
|
|
|
$url = "http://example.com/feed2";
|
|
|
|
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
2017-05-18 17:21:17 +00:00
|
|
|
Data::$db->subscriptionAdd($this->user, $url);
|
2017-05-11 22:00:35 +00:00
|
|
|
}
|
|
|
|
|
2017-05-12 03:20:10 +00:00
|
|
|
function testAddASubscriptionWithoutAuthority() {
|
2017-05-11 22:00:35 +00:00
|
|
|
$url = "http://example.com/feed1";
|
|
|
|
Phake::when(Data::$user)->authorize->thenReturn(false);
|
|
|
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
2017-05-18 17:21:17 +00:00
|
|
|
Data::$db->subscriptionAdd($this->user, $url);
|
2017-05-11 22:00:35 +00:00
|
|
|
}
|
2017-05-12 03:20:10 +00:00
|
|
|
|
|
|
|
function testRemoveASubscription() {
|
2017-05-18 17:21:17 +00:00
|
|
|
$this->assertTrue(Data::$db->subscriptionRemove($this->user, 1));
|
|
|
|
Phake::verify(Data::$user)->authorize($this->user, "subscriptionRemove");
|
2017-05-12 03:20:10 +00:00
|
|
|
$state = $this->primeExpectations($this->data, [
|
|
|
|
'arsse_feeds' => ['id','url','username','password'],
|
|
|
|
'arsse_subscriptions' => ['id','owner','feed'],
|
|
|
|
]);
|
|
|
|
array_shift($state['arsse_subscriptions']['rows']);
|
|
|
|
$this->compareExpectations($state);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testRemoveAMissingSubscription() {
|
2017-05-21 14:10:36 +00:00
|
|
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
2017-05-18 17:21:17 +00:00
|
|
|
Data::$db->subscriptionRemove($this->user, 2112);
|
2017-05-12 03:20:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function testRemoveASubscriptionForTheWrongOwner() {
|
2017-05-18 17:21:17 +00:00
|
|
|
$this->user = "jane.doe@example.com";
|
2017-05-21 14:10:36 +00:00
|
|
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
2017-05-18 17:21:17 +00:00
|
|
|
Data::$db->subscriptionRemove($this->user, 1);
|
2017-05-12 03:20:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function testRemoveASubscriptionWithoutAuthority() {
|
|
|
|
Phake::when(Data::$user)->authorize->thenReturn(false);
|
|
|
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
2017-05-18 17:21:17 +00:00
|
|
|
Data::$db->subscriptionRemove($this->user, 1);
|
2017-05-12 03:20:10 +00:00
|
|
|
}
|
2017-05-15 03:03:48 +00:00
|
|
|
|
|
|
|
function testListSubscriptions() {
|
|
|
|
$exp = [
|
|
|
|
[
|
2017-05-18 17:21:17 +00:00
|
|
|
'url' => "http://example.com/feed2",
|
|
|
|
'title' => "Eek",
|
|
|
|
'folder' => null,
|
2017-06-01 22:12:08 +00:00
|
|
|
'top_folder' => null,
|
2017-05-18 17:21:17 +00:00
|
|
|
'unread' => 4,
|
|
|
|
'pinned' => 1,
|
|
|
|
'order_type' => 2,
|
2017-05-15 03:03:48 +00:00
|
|
|
],
|
|
|
|
[
|
2017-05-18 17:21:17 +00:00
|
|
|
'url' => "http://example.com/feed3",
|
|
|
|
'title' => "Ook",
|
|
|
|
'folder' => 2,
|
2017-06-01 22:12:08 +00:00
|
|
|
'top_folder' => 1,
|
2017-05-18 17:21:17 +00:00
|
|
|
'unread' => 2,
|
|
|
|
'pinned' => 0,
|
|
|
|
'order_type' => 1,
|
2017-05-15 03:03:48 +00:00
|
|
|
],
|
|
|
|
];
|
2017-05-18 17:21:17 +00:00
|
|
|
$this->assertResult($exp, Data::$db->subscriptionList($this->user));
|
|
|
|
Phake::verify(Data::$user)->authorize($this->user, "subscriptionList");
|
|
|
|
$this->assertArraySubset($exp[0], Data::$db->subscriptionPropertiesGet($this->user, 1));
|
|
|
|
Phake::verify(Data::$user)->authorize($this->user, "subscriptionPropertiesGet");
|
|
|
|
$this->assertArraySubset($exp[1], Data::$db->subscriptionPropertiesGet($this->user, 3));
|
2017-05-15 03:03:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function testListSubscriptionsInAFolder() {
|
|
|
|
$exp = [
|
|
|
|
[
|
2017-05-18 17:21:17 +00:00
|
|
|
'url' => "http://example.com/feed3",
|
|
|
|
'title' => "Ook",
|
|
|
|
'folder' => 2,
|
2017-06-01 22:12:08 +00:00
|
|
|
'top_folder' => 1,
|
2017-05-18 17:21:17 +00:00
|
|
|
'unread' => 2,
|
|
|
|
'pinned' => 0,
|
|
|
|
'order_type' => 1,
|
2017-05-15 03:03:48 +00:00
|
|
|
],
|
|
|
|
];
|
2017-05-18 17:21:17 +00:00
|
|
|
$this->assertResult($exp, Data::$db->subscriptionList($this->user, 2));
|
|
|
|
}
|
|
|
|
|
|
|
|
function testListSubscriptionsWithDifferentDateFormats() {
|
|
|
|
Data::$db->dateFormatDefault("iso8601");
|
|
|
|
$d1 = Data::$db->subscriptionList($this->user, 2)->getRow()['added'];
|
|
|
|
Data::$db->dateFormatDefault("http");
|
|
|
|
$d2 = Data::$db->subscriptionList($this->user, 2)->getRow()['added'];
|
|
|
|
$this->assertNotEquals($d1, $d2);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testListSubscriptionsInAMissingFolder() {
|
|
|
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
|
|
|
Data::$db->subscriptionList($this->user, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testListSubscriptionsWithoutAuthority() {
|
|
|
|
Phake::when(Data::$user)->authorize->thenReturn(false);
|
|
|
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
|
|
|
Data::$db->subscriptionList($this->user);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testSetThePropertiesOfASubscription() {
|
|
|
|
Data::$db->subscriptionPropertiesSet($this->user, 1,[
|
|
|
|
'title' => "Ook Ook",
|
|
|
|
'folder' => 3,
|
|
|
|
'pinned' => false,
|
|
|
|
'order_type' => 0,
|
|
|
|
]);
|
|
|
|
Phake::verify(Data::$user)->authorize($this->user, "subscriptionPropertiesSet");
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
|
|
|
'arsse_feeds' => ['id','url','username','password','title'],
|
|
|
|
'arsse_subscriptions' => ['id','owner','feed','title','folder','pinned','order_type'],
|
|
|
|
]);
|
|
|
|
$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,[
|
2017-05-21 14:10:36 +00:00
|
|
|
'title' => null,
|
2017-05-18 17:21:17 +00:00
|
|
|
]);
|
|
|
|
$state['arsse_subscriptions']['rows'][0] = [1,"john.doe@example.com",2,null,3,0,0];
|
|
|
|
$this->compareExpectations($state);
|
|
|
|
}
|
|
|
|
|
2017-05-21 14:10:36 +00:00
|
|
|
function testMoveASubscriptionToAMissingFolder() {
|
2017-05-18 17:21:17 +00:00
|
|
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
2017-05-21 14:10:36 +00:00
|
|
|
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]));
|
2017-05-18 17:21:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function testSetThePropertiesOfAMissingSubscription() {
|
2017-05-21 14:10:36 +00:00
|
|
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
|
|
|
Data::$db->subscriptionPropertiesSet($this->user, 2112, ['folder' => null]);
|
2017-05-18 17:21:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function testSetThePropertiesOfASubscriptionWithoutAuthority() {
|
|
|
|
Phake::when(Data::$user)->authorize->thenReturn(false);
|
|
|
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
2017-05-21 14:10:36 +00:00
|
|
|
Data::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => null]);
|
2017-05-15 03:03:48 +00:00
|
|
|
}
|
2017-05-11 02:01:00 +00:00
|
|
|
}
|