1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-23 17:12:41 +00:00
Arsse/tests/cases/Database/SeriesSubscription.php

506 lines
22 KiB
PHP
Raw Normal View History

<?php
/** @license MIT
* Copyright 2017 J. King, Dustin Wilson et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
2018-11-23 15:01:17 +00:00
namespace JKingWeb\Arsse\TestCase\Database;
2017-08-29 14:50:31 +00:00
use GuzzleHttp\Exception\ClientException;
use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Test\Database;
use JKingWeb\Arsse\Feed\Exception as FeedException;
trait SeriesSubscription {
2020-01-20 18:52:48 +00:00
public function setUpSeriesSubscription(): void {
2018-11-25 05:03:56 +00:00
$this->data = [
'arsse_users' => [
'columns' => ["id", "password", "num"],
2022-09-15 14:12:04 +00:00
'rows' => [
["jane.doe@example.com", "", 1],
["john.doe@example.com", "", 2],
2020-12-22 21:13:12 +00:00
["jill.doe@example.com", "", 3],
2021-01-16 04:02:33 +00:00
["jack.doe@example.com", "", 4],
2018-11-25 05:03:56 +00:00
],
],
2018-11-25 05:03:56 +00:00
'arsse_folders' => [
'columns' => ["id", "owner", "parent", "name"],
2022-09-15 14:12:04 +00:00
'rows' => [
2018-11-25 05:03:56 +00:00
[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"],
2020-03-01 20:16:50 +00:00
],
],
'arsse_icons' => [
'columns' => ["id", "url", "data"],
2022-09-15 14:12:04 +00:00
'rows' => [
[1,"http://example.com/favicon.ico", "ICON DATA"],
[2,"http://example.net/favicon.ico", null],
],
],
2018-11-25 05:03:56 +00:00
'arsse_feeds' => [
'columns' => ["id", "url", "title", "username", "password", "updated", "next_fetch", "icon"],
2022-09-15 14:12:04 +00:00
'rows' => [
2020-11-09 21:51:30 +00:00
[1,"http://example.com/feed1", "Ook", "", "",strtotime("now"),strtotime("now"),null],
[2,"http://example.com/feed2", "eek", "", "",strtotime("now - 1 hour"),strtotime("now - 1 hour"),1],
[3,"http://example.com/feed3", "Ack", "", "",strtotime("now + 1 hour"),strtotime("now + 1 hour"),2],
[4,"http://example.com/feed4", "Foo", "", "",strtotime("now + 1 hour"),strtotime("now + 1 hour"),null],
2020-11-09 21:51:30 +00:00
],
],
2018-11-25 05:03:56 +00:00
'arsse_subscriptions' => [
'columns' => ["id", "owner", "feed", "title", "folder", "pinned", "order_type", "keep_rule", "block_rule", "scrape"],
2022-09-15 14:12:04 +00:00
'rows' => [
[1,"john.doe@example.com",2,null,null,1,2,null,null,0],
[2,"jane.doe@example.com",2,null,null,0,0,null,null,0],
[3,"john.doe@example.com",3,"Ook",2,0,1,null,null,0],
[4,"jill.doe@example.com",2,null,null,0,0,null,null,0],
[5,"jack.doe@example.com",2,null,null,1,2,"","3|E",0],
[6,"john.doe@example.com",4,"Bar",3,0,0,null,null,0],
2020-03-01 20:16:50 +00:00
],
],
'arsse_tags' => [
'columns' => ["id", "owner", "name"],
2022-09-15 14:12:04 +00:00
'rows' => [
[1,"john.doe@example.com","Interesting"],
[2,"john.doe@example.com","Fascinating"],
[3,"jane.doe@example.com","Boring"],
[4,"john.doe@example.com","Lonely"],
],
],
'arsse_tag_members' => [
'columns' => ["tag", "subscription", "assigned"],
2022-09-15 14:12:04 +00:00
'rows' => [
[1,1,1],
[1,3,0],
[2,1,1],
[2,3,1],
[3,2,1],
],
],
2018-11-25 05:03:56 +00:00
'arsse_articles' => [
'columns' => ["id", "feed", "url_title_hash", "url_content_hash", "title_content_hash", "title"],
2022-09-15 14:12:04 +00:00
'rows' => [
2021-01-16 04:02:33 +00:00
[1,2,"","","","Title 1"],
[2,2,"","","","Title 2"],
[3,2,"","","","Title 3"],
[4,2,"","","","Title 4"],
[5,2,"","","","Title 5"],
[6,3,"","","","Title 6"],
[7,3,"","","","Title 7"],
[8,3,"","","","Title 8"],
],
],
'arsse_editions' => [
'columns' => ["id", "article"],
2022-09-15 14:12:04 +00:00
'rows' => [
2021-01-16 04:02:33 +00:00
[1,1],
[2,2],
[3,3],
[4,4],
[5,5],
[6,6],
[7,7],
[8,8],
],
],
'arsse_categories' => [
'columns' => ["article", "name"],
2022-09-15 14:12:04 +00:00
'rows' => [
2021-01-16 04:02:33 +00:00
[1,"A"],
[2,"B"],
[4,"D"],
[5,"E"],
[6,"F"],
[7,"G"],
[8,"H"],
2020-03-01 20:16:50 +00:00
],
2017-05-17 02:19:40 +00:00
],
2018-11-25 05:03:56 +00:00
'arsse_marks' => [
'columns' => ["article", "subscription", "read", "starred", "hidden"],
2022-09-15 14:12:04 +00:00
'rows' => [
2021-01-16 04:02:33 +00:00
[1,2,1,0,0],
[2,2,1,0,0],
[3,2,1,0,0],
[4,2,1,0,0],
[5,2,1,0,0],
[1,1,1,0,0],
[7,3,1,0,0],
[8,3,0,0,0],
[1,5,1,0,0],
[3,5,1,0,1],
[4,5,0,0,0],
[5,5,0,0,1],
2020-03-01 20:16:50 +00:00
],
2017-05-17 02:19:40 +00:00
],
2018-11-25 05:03:56 +00:00
];
$this->user = "john.doe@example.com";
}
2020-01-20 18:52:48 +00:00
protected function tearDownSeriesSubscription(): void {
2018-11-25 05:03:56 +00:00
unset($this->data, $this->user);
}
2020-01-20 18:52:48 +00:00
public function testAddASubscriptionToAnExistingFeed(): void {
$url = "http://example.com/feed1";
$subID = $this->nextID("arsse_subscriptions");
2021-02-27 20:24:02 +00:00
$db = $this->partialMock(Database::class, static::$drv);
$db->feedUpdate->returns(true);
Arsse::$db = $db->get();
2017-08-29 14:50:31 +00:00
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url));
2021-02-27 20:24:02 +00:00
$db->feedUpdate->never()->called();
$state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password'],
'arsse_subscriptions' => ['id','owner','feed'],
]);
$state['arsse_subscriptions']['rows'][] = [$subID,$this->user,1];
2019-06-21 22:52:27 +00:00
$this->compareExpectations(static::$drv, $state);
}
2020-01-20 18:52:48 +00:00
public function testAddASubscriptionToANewFeed(): void {
$url = "http://example.org/feed1";
$feedID = $this->nextID("arsse_feeds");
$subID = $this->nextID("arsse_subscriptions");
2021-02-27 20:24:02 +00:00
$db = $this->partialMock(Database::class, static::$drv);
$db->feedUpdate->returns(true);
Arsse::$db = $db->get();
2017-10-02 19:42:15 +00:00
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url, "", "", false));
2021-02-27 20:24:02 +00:00
$db->feedUpdate->calledWith($feedID, true, false);
$state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password'],
'arsse_subscriptions' => ['id','owner','feed'],
]);
$state['arsse_feeds']['rows'][] = [$feedID,$url,"",""];
$state['arsse_subscriptions']['rows'][] = [$subID,$this->user,$feedID];
2019-06-21 22:52:27 +00:00
$this->compareExpectations(static::$drv, $state);
}
2020-01-20 18:52:48 +00:00
public function testAddASubscriptionToANewFeedViaDiscovery(): void {
2017-10-02 19:42:15 +00:00
$url = "http://localhost:8000/Feed/Discovery/Valid";
$discovered = "http://localhost:8000/Feed/Discovery/Feed";
$feedID = $this->nextID("arsse_feeds");
$subID = $this->nextID("arsse_subscriptions");
2021-02-27 20:24:02 +00:00
$db = $this->partialMock(Database::class, static::$drv);
$db->feedUpdate->returns(true);
Arsse::$db = $db->get();
2017-10-02 19:42:15 +00:00
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url, "", "", true));
2021-02-27 20:24:02 +00:00
$db->feedUpdate->calledWith($feedID, true, false);
2017-10-02 19:42:15 +00:00
$state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password'],
'arsse_subscriptions' => ['id','owner','feed'],
]);
$state['arsse_feeds']['rows'][] = [$feedID,$discovered,"",""];
$state['arsse_subscriptions']['rows'][] = [$subID,$this->user,$feedID];
2019-06-21 22:52:27 +00:00
$this->compareExpectations(static::$drv, $state);
2017-10-02 19:42:15 +00:00
}
2020-01-20 18:52:48 +00:00
public function testAddASubscriptionToAnInvalidFeed(): void {
$url = "http://example.org/feed1";
$feedID = $this->nextID("arsse_feeds");
2021-02-27 20:24:02 +00:00
$db = $this->partialMock(Database::class, static::$drv);
$db->feedUpdate->throws(new FeedException("", ['url' => $url], $this->mockGuzzleException(ClientException::class, "", 404)));
Arsse::$db = $db->get();
$this->assertException("invalidUrl", "Feed");
try {
2017-10-02 19:42:15 +00:00
Arsse::$db->subscriptionAdd($this->user, $url, "", "", false);
} finally {
2021-02-27 20:24:02 +00:00
$db->feedUpdate->calledWith($feedID, true, false);
$state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password'],
'arsse_subscriptions' => ['id','owner','feed'],
]);
2019-06-21 22:52:27 +00:00
$this->compareExpectations(static::$drv, $state);
}
}
2020-01-20 18:52:48 +00:00
public function testAddADuplicateSubscription(): void {
$url = "http://example.com/feed2";
$this->assertException("constraintViolation", "Db", "ExceptionInput");
Arsse::$db->subscriptionAdd($this->user, $url);
}
2020-01-20 18:52:48 +00:00
public function testAddADuplicateSubscriptionWithEquivalentUrl(): void {
$url = "http://EXAMPLE.COM/feed2";
$this->assertException("constraintViolation", "Db", "ExceptionInput");
Arsse::$db->subscriptionAdd($this->user, $url);
}
2020-01-20 18:52:48 +00:00
public function testAddADuplicateSubscriptionViaRedirection(): void {
2019-08-06 18:17:56 +00:00
$url = "http://localhost:8000/Feed/Parsing/Valid";
Arsse::$db->subscriptionAdd($this->user, $url);
$subID = $this->nextID("arsse_subscriptions");
$url = "http://localhost:8000/Feed/Fetching/RedirectionDuplicate";
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url));
}
2020-01-20 18:52:48 +00:00
public function testRemoveASubscription(): void {
$this->assertTrue(Arsse::$db->subscriptionRemove($this->user, 1));
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']);
2019-06-21 22:52:27 +00:00
$this->compareExpectations(static::$drv, $state);
2017-05-12 03:20:10 +00:00
}
2020-01-20 18:52:48 +00:00
public function testRemoveAMissingSubscription(): void {
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Arsse::$db->subscriptionRemove($this->user, 2112);
2017-05-12 03:20:10 +00:00
}
2020-01-20 18:52:48 +00:00
public function testRemoveAnInvalidSubscription(): void {
2017-09-28 14:16:24 +00:00
$this->assertException("typeViolation", "Db", "ExceptionInput");
Arsse::$db->subscriptionRemove($this->user, -1);
}
2020-01-20 18:52:48 +00:00
public function testRemoveASubscriptionForTheWrongOwner(): void {
$this->user = "jane.doe@example.com";
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Arsse::$db->subscriptionRemove($this->user, 1);
2017-05-12 03:20:10 +00:00
}
2020-01-20 18:52:48 +00:00
public function testListSubscriptions(): void {
$exp = [
[
'url' => "http://example.com/feed2",
'title' => "eek",
'folder' => null,
'top_folder' => null,
'folder_name' => null,
'top_folder_name' => null,
'unread' => 4,
'pinned' => 1,
'order_type' => 2,
'icon_url' => "http://example.com/favicon.ico",
'icon_id' => 1,
],
[
'url' => "http://example.com/feed3",
'title' => "Ook",
'folder' => 2,
'top_folder' => 1,
'folder_name' => "Software",
'top_folder_name' => "Technology",
'unread' => 2,
'pinned' => 0,
'order_type' => 1,
'icon_url' => "http://example.net/favicon.ico",
'icon_id' => null,
],
[
'url' => "http://example.com/feed4",
'title' => "Bar",
'folder' => 3,
'top_folder' => 1,
'folder_name' => "Rocketry",
'top_folder_name' => "Technology",
'unread' => 0,
'pinned' => 0,
'order_type' => 0,
'icon_url' => null,
'icon_id' => null,
],
];
2017-12-08 00:39:32 +00:00
$this->assertResult($exp, Arsse::$db->subscriptionList($this->user));
$this->assertArraySubset($exp[0], Arsse::$db->subscriptionPropertiesGet($this->user, 1));
$this->assertArraySubset($exp[1], Arsse::$db->subscriptionPropertiesGet($this->user, 3));
// test that an absence of marks does not corrupt unread count
$exp = [
[
'url' => "http://example.com/feed2",
'title' => "eek",
'folder' => null,
'top_folder' => null,
'unread' => 5,
'pinned' => 0,
'order_type' => 0,
],
];
$this->assertResult($exp, Arsse::$db->subscriptionList("jill.doe@example.com"));
}
2020-01-20 18:52:48 +00:00
public function testListSubscriptionsInAFolder(): void {
$exp = [
[
'url' => "http://example.com/feed2",
'title' => "eek",
'folder' => null,
'top_folder' => null,
'unread' => 4,
'pinned' => 1,
'order_type' => 2,
],
];
$this->assertResult($exp, Arsse::$db->subscriptionList($this->user, null, false));
}
public function testListSubscriptionsWithRecursion(): void {
$exp = [
[
'url' => "http://example.com/feed3",
'title' => "Ook",
'folder' => 2,
'top_folder' => 1,
'unread' => 2,
'pinned' => 0,
'order_type' => 1,
],
];
$this->assertResult($exp, Arsse::$db->subscriptionList($this->user, 2));
}
2020-01-20 18:52:48 +00:00
public function testListSubscriptionsInAMissingFolder(): void {
$this->assertException("idMissing", "Db", "ExceptionInput");
Arsse::$db->subscriptionList($this->user, 4);
}
2020-01-20 18:52:48 +00:00
public function testCountSubscriptions(): void {
$this->assertSame(3, Arsse::$db->subscriptionCount($this->user));
$this->assertSame(1, Arsse::$db->subscriptionCount($this->user, 2));
}
2020-01-20 18:52:48 +00:00
public function testCountSubscriptionsInAMissingFolder(): void {
$this->assertException("idMissing", "Db", "ExceptionInput");
Arsse::$db->subscriptionCount($this->user, 4);
}
2020-01-20 18:52:48 +00:00
public function testGetThePropertiesOfAMissingSubscription(): void {
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Arsse::$db->subscriptionPropertiesGet($this->user, 2112);
}
2020-01-20 18:52:48 +00:00
public function testGetThePropertiesOfAnInvalidSubscription(): void {
2017-09-28 14:16:24 +00:00
$this->assertException("typeViolation", "Db", "ExceptionInput");
Arsse::$db->subscriptionPropertiesGet($this->user, -1);
}
2020-01-20 18:52:48 +00:00
public function testSetThePropertiesOfASubscription(): void {
2017-08-29 14:50:31 +00:00
Arsse::$db->subscriptionPropertiesSet($this->user, 1, [
2020-03-01 20:16:50 +00:00
'title' => "Ook Ook",
'folder' => 3,
'pinned' => false,
'scrape' => true,
'order_type' => 0,
2021-01-14 17:42:33 +00:00
'keep_rule' => "ook",
'block_rule' => "eek",
]);
$state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password','title'],
'arsse_subscriptions' => ['id','owner','feed','title','folder','pinned','order_type','keep_rule','block_rule','scrape'],
]);
$state['arsse_subscriptions']['rows'][0] = [1,"john.doe@example.com",2,"Ook Ook",3,0,0,"ook","eek",1];
2019-06-21 22:52:27 +00:00
$this->compareExpectations(static::$drv, $state);
2017-08-29 14:50:31 +00:00
Arsse::$db->subscriptionPropertiesSet($this->user, 1, [
2021-01-14 17:42:33 +00:00
'title' => null,
'keep_rule' => null,
'block_rule' => null,
]);
$state['arsse_subscriptions']['rows'][0] = [1,"john.doe@example.com",2,null,3,0,0,null,null,1];
2019-06-21 22:52:27 +00:00
$this->compareExpectations(static::$drv, $state);
// making no changes is a valid result
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['unhinged' => true]);
2019-06-21 22:52:27 +00:00
$this->compareExpectations(static::$drv, $state);
}
2020-01-20 18:52:48 +00:00
public function testMoveASubscriptionToAMissingFolder(): void {
$this->assertException("idMissing", "Db", "ExceptionInput");
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => 4]);
}
2020-01-20 18:52:48 +00:00
public function testMoveASubscriptionToTheRootFolder(): void {
$this->assertTrue(Arsse::$db->subscriptionPropertiesSet($this->user, 3, ['folder' => null]));
}
2021-01-14 17:42:33 +00:00
/** @dataProvider provideInvalidSubscriptionProperties */
public function testSetThePropertiesOfASubscriptionToInvalidValues(array $data, string $exp): void {
$this->assertException($exp, "Db", "ExceptionInput");
Arsse::$db->subscriptionPropertiesSet($this->user, 1, $data);
}
2021-01-14 17:42:33 +00:00
public function provideInvalidSubscriptionProperties(): iterable {
return [
'Empty title' => [['title' => ""], "missing"],
'Whitespace title' => [['title' => " "], "whitespace"],
'Non-string title' => [['title' => []], "typeViolation"],
'Non-string keep rule' => [['keep_rule' => 0], "typeViolation"],
'Invalid keep rule' => [['keep_rule' => "*"], "invalidValue"],
'Non-string block rule' => [['block_rule' => 0], "typeViolation"],
'Invalid block rule' => [['block_rule' => "*"], "invalidValue"],
];
}
2020-01-20 18:52:48 +00:00
public function testRenameASubscriptionToZero(): void {
$this->assertTrue(Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => 0]));
}
2020-01-20 18:52:48 +00:00
public function testSetThePropertiesOfAMissingSubscription(): void {
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Arsse::$db->subscriptionPropertiesSet($this->user, 2112, ['folder' => null]);
}
2020-01-20 18:52:48 +00:00
public function testSetThePropertiesOfAnInvalidSubscription(): void {
2017-09-28 14:16:24 +00:00
$this->assertException("typeViolation", "Db", "ExceptionInput");
Arsse::$db->subscriptionPropertiesSet($this->user, -1, ['folder' => null]);
}
2020-01-20 18:52:48 +00:00
public function testRetrieveTheFaviconOfASubscription(): void {
$exp = "http://example.com/favicon.ico";
2020-11-06 15:27:30 +00:00
$this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 1)['url']);
$this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 2)['url']);
$this->assertSame(null, Arsse::$db->subscriptionIcon(null, 6));
2020-11-06 15:27:30 +00:00
}
public function testRetrieveTheFaviconOfAMissingSubscription(): void {
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Arsse::$db->subscriptionIcon(null, -2112);
}
2020-01-20 18:52:48 +00:00
public function testRetrieveTheFaviconOfASubscriptionWithUser(): void {
$exp = "http://example.com/favicon.ico";
$user = "john.doe@example.com";
2020-11-06 15:27:30 +00:00
$this->assertSame($exp, Arsse::$db->subscriptionIcon($user, 1)['url']);
$this->assertSame(null, Arsse::$db->subscriptionIcon($user, 6));
$user = "jane.doe@example.com";
2020-11-06 15:27:30 +00:00
$this->assertSame($exp, Arsse::$db->subscriptionIcon($user, 2)['url']);
}
public function testRetrieveTheFaviconOfASubscriptionOfTheWrongUser(): void {
$user = "john.doe@example.com";
$this->assertException("subjectMissing", "Db", "ExceptionInput");
2021-01-26 17:03:26 +00:00
Arsse::$db->subscriptionIcon($user, 2);
}
2020-01-20 18:52:48 +00:00
public function testListTheTagsOfASubscription(): void {
$this->assertEquals([1,2], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 1));
$this->assertEquals([2], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 3));
$this->assertEquals(["Fascinating","Interesting"], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 1, true));
$this->assertEquals(["Fascinating"], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 3, true));
}
2020-01-20 18:52:48 +00:00
public function testListTheTagsOfAMissingSubscription(): void {
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Arsse::$db->subscriptionTagsGet($this->user, 101);
}
2020-01-20 18:52:48 +00:00
public function testGetRefreshTimeOfASubscription(): void {
$user = "john.doe@example.com";
$this->assertTime(strtotime("now + 1 hour"), Arsse::$db->subscriptionRefreshed($user));
$this->assertTime(strtotime("now - 1 hour"), Arsse::$db->subscriptionRefreshed($user, 1));
}
2020-01-20 18:52:48 +00:00
public function testGetRefreshTimeOfAMissingSubscription(): void {
$this->assertException("subjectMissing", "Db", "ExceptionInput");
$this->assertTime(strtotime("now - 1 hour"), Arsse::$db->subscriptionRefreshed("john.doe@example.com", 2));
}
2021-01-16 04:02:33 +00:00
public function testSetTheFilterRulesOfASubscriptionCheckingMarks(): void {
Arsse::$db->subscriptionPropertiesSet("jack.doe@example.com", 5, ['keep_rule' => "1|B|3|D", 'block_rule' => "4"]);
$state = $this->primeExpectations($this->data, ['arsse_marks' => ['article', 'subscription', 'hidden']]);
$state['arsse_marks']['rows'][9][2] = 0;
$state['arsse_marks']['rows'][10][2] = 1;
$this->compareExpectations(static::$drv, $state);
}
2017-08-29 14:50:31 +00:00
}