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 () {
2017-06-18 16:24:19 +00:00
$this -> data = [
'arsse_users' => [
'columns' => [
'id' => 'str' ,
'password' => 'str' ,
'name' => 'str' ,
'rights' => 'int' ,
],
'rows' => [
[ " admin@example.net " , '$2y$10$PbcG2ZR3Z8TuPzM7aHTF8.v61dtCjzjK78gdZJcp4UePE8T9jEgBW' , " Hard Lip Herbert " , UserDriver :: RIGHTS_GLOBAL_ADMIN ], // password is hash of "secret"
[ " jane.doe@example.com " , " " , " Jane Doe " , UserDriver :: RIGHTS_NONE ],
[ " john.doe@example.com " , " " , " John Doe " , UserDriver :: RIGHTS_NONE ],
],
],
'arsse_folders' => [
'columns' => [
'id' => " int " ,
'owner' => " str " ,
'parent' => " int " ,
'name' => " str " ,
],
'rows' => [
[ 1 , " john.doe@example.com " , null , " Technology " ],
[ 2 , " john.doe@example.com " , 1 , " Software " ],
[ 3 , " john.doe@example.com " , 1 , " Rocketry " ],
[ 4 , " jane.doe@example.com " , null , " Politics " ],
[ 5 , " john.doe@example.com " , null , " Politics " ],
[ 6 , " john.doe@example.com " , 2 , " Politics " ],
]
],
2017-05-11 02:01:00 +00:00
'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
];
$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
}