mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 21:22:40 +00:00
Tests for Miniflux feed listing
This commit is contained in:
parent
2cf4bf0d4d
commit
14d2d19ae1
4 changed files with 121 additions and 34 deletions
|
@ -34,6 +34,7 @@ Miniflux version 2.0.27 is emulated, though not all features are implemented
|
||||||
- The "All" category is treated specially (see below for details)
|
- The "All" category is treated specially (see below for details)
|
||||||
- Category names consisting only of whitespace are rejected along with the empty string
|
- Category names consisting only of whitespace are rejected along with the empty string
|
||||||
- Filtering rules may not function identically (see below for details)
|
- Filtering rules may not function identically (see below for details)
|
||||||
|
- The `checked_at` field of feeds indicates when the feed was last updated rather than when it was last checked
|
||||||
|
|
||||||
# Behaviour of filtering (block and keep) rules
|
# Behaviour of filtering (block and keep) rules
|
||||||
|
|
||||||
|
|
|
@ -777,8 +777,9 @@ class Database {
|
||||||
* - "edited": The date and time at which the newsfeed was last modified by its authors
|
* - "edited": The date and time at which the newsfeed was last modified by its authors
|
||||||
* - "modified": The date and time at which the subscription properties were last changed by the user
|
* - "modified": The date and time at which the subscription properties were last changed by the user
|
||||||
* - "next_fetch": The date and time and which the feed will next be fetched
|
* - "next_fetch": The date and time and which the feed will next be fetched
|
||||||
* - "unread": The number of unread articles associated with the subscription
|
|
||||||
* - "etag": The ETag header-field in the last fetch response
|
* - "etag": The ETag header-field in the last fetch response
|
||||||
|
* - "scrape": Whether the user wants scrape full-article content
|
||||||
|
* - "unread": The number of unread articles associated with the subscription
|
||||||
*
|
*
|
||||||
* @param string $user The user whose subscriptions are to be listed
|
* @param string $user The user whose subscriptions are to be listed
|
||||||
* @param integer|null $folder The identifier of the folder under which to list subscriptions; by default the root folder is used
|
* @param integer|null $folder The identifier of the folder under which to list subscriptions; by default the root folder is used
|
||||||
|
|
|
@ -591,50 +591,59 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
return new EmptyResponse(204);
|
return new EmptyResponse(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getFeeds(): ResponseInterface {
|
protected function mapFolders(): array {
|
||||||
$meta = Arsse::$user->propertiesGet(Arsse::$user->id, false);
|
$meta = Arsse::$user->propertiesGet(Arsse::$user->id, false);
|
||||||
$tr = Arsse::$db->begin();
|
|
||||||
$out = [];
|
|
||||||
// compile the list of folders; the feed list includes folder names
|
|
||||||
$folders = [0 => ['id' => 1, 'title' => $meta['root_folder_name'] ?? Arsse::$lang->msg("API.Miniflux.DefaultCategoryName"), 'user_id' => $meta['num']]];
|
$folders = [0 => ['id' => 1, 'title' => $meta['root_folder_name'] ?? Arsse::$lang->msg("API.Miniflux.DefaultCategoryName"), 'user_id' => $meta['num']]];
|
||||||
foreach(Arsse::$db->folderList(Arsse::$user->id, null, false) as $r) {
|
foreach (Arsse::$db->folderList(Arsse::$user->id, null, false) as $r) {
|
||||||
$folders[(int) $r['id']] = [
|
$folders[(int) $r['id']] = [
|
||||||
'id' => ((int) $r['id']) + 1,
|
'id' => ((int) $r['id']) + 1,
|
||||||
'title' => $r['name'],
|
'title' => $r['name'],
|
||||||
'user_id' => $meta['num'],
|
'user_id' => $meta['num'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
return $folders;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function transformFeed(array $sub, array $folders): array {
|
||||||
|
$url = new Uri($sub['url']);
|
||||||
|
return [
|
||||||
|
'id' => (int) $sub['id'],
|
||||||
|
'user_id' => $folders[0]['user_id'],
|
||||||
|
'feed_url' => (string) $url->withUserInfo(""),
|
||||||
|
'site_url' => (string) $sub['source'],
|
||||||
|
'title' => (string) $sub['title'],
|
||||||
|
'checked_at' => Date::transform($sub['updated'], "iso8601m", "sql"),
|
||||||
|
'next_check_at' => Date::transform($sub['next_fetch'], "iso8601m", "sql") ?? "0001-01-01T00:00:00.000000Z",
|
||||||
|
'etag_header' => (string) $sub['etag'],
|
||||||
|
'last_modified_header' => (string) Date::transform($sub['edited'], "http", "sql"),
|
||||||
|
'parsing_error_message' => (string) $sub['err_msg'],
|
||||||
|
'parsing_error_count' => (int) $sub['err_count'],
|
||||||
|
'scraper_rules' => "",
|
||||||
|
'rewrite_rules' => "",
|
||||||
|
'crawler' => (bool) $sub['scrape'],
|
||||||
|
'blocklist_rules' => (string) $sub['block_rule'],
|
||||||
|
'keeplist_rules' => (string) $sub['keep_rule'],
|
||||||
|
'user_agent' => "",
|
||||||
|
'username' => rawurldecode(explode(":", $url->getUserInfo(), 2)[0] ?? ""),
|
||||||
|
'password' => rawurldecode(explode(":", $url->getUserInfo(), 2)[1] ?? ""),
|
||||||
|
'disabled' => false,
|
||||||
|
'ignore_http_cache' => false,
|
||||||
|
'fetch_via_proxy' => false,
|
||||||
|
'category' => $folders[(int) $sub['top_folder']],
|
||||||
|
'icon' => $sub['icon_id'] ? ['feed_id' => (int) $sub['id'], 'icon_id' => (int) $sub['icon_id']] : null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getFeeds(): ResponseInterface {
|
||||||
|
$tr = Arsse::$db->begin();
|
||||||
|
// compile the list of folders; the feed list includes folder names
|
||||||
|
$folders = $this->mapFolders();
|
||||||
// next compile the list of feeds
|
// next compile the list of feeds
|
||||||
|
$out = [];
|
||||||
foreach (Arsse::$db->subscriptionList(Arsse::$user->id) as $r) {
|
foreach (Arsse::$db->subscriptionList(Arsse::$user->id) as $r) {
|
||||||
$url = new Uri($r['url']);
|
$out[] = $this->transformFeed($r, $folders);
|
||||||
$out = [
|
|
||||||
'id' => (int) $r['id'],
|
|
||||||
'user_id' => $meta['num'],
|
|
||||||
'feed_url' => $url->withUserInfo(""),
|
|
||||||
'site_url' => $r['source'],
|
|
||||||
'title' => $r['title'],
|
|
||||||
'checked_at' => Date::transform($r['updated'], "iso8601", "sql"),
|
|
||||||
'next_check_at' => Date::transform($r['next_fetch'], "iso8601", "sql") ?? "0001-01-01T00:00:00Z",
|
|
||||||
'etag_header' => $r['etag'] ?? "",
|
|
||||||
'last_modified_header' => (string) Date::transform($r['edited'], "http", "sql"),
|
|
||||||
'parsing_error_message' => (string) $r['err_msg'],
|
|
||||||
'parsing_error_count' => (int) $r['err_count'],
|
|
||||||
'scraper_rules' => "",
|
|
||||||
'rewrite_rules' => "",
|
|
||||||
'crawler' => (bool) $r['scrape'],
|
|
||||||
'blocklist_rules' => (string) $r['block_rule'],
|
|
||||||
'keeplist_rules' => (string) $r['keep_rule'],
|
|
||||||
'user_agent' => "",
|
|
||||||
'username' => explode(":", $url->getUserInfo(), 2)[0] ?? "",
|
|
||||||
'password' => explode(":", $url->getUserInfo(), 2)[1] ?? "",
|
|
||||||
'disabled' => false,
|
|
||||||
'ignore_http_cache' => false,
|
|
||||||
'fetch_via_proxy' => false,
|
|
||||||
'category' => $folders[$r['top_folder']],
|
|
||||||
'icon' => $r['icon_id'] ? ['feed_id' => (int) $r['id'], 'icon_id' => (int) $r['icon_id']] : null,
|
|
||||||
];
|
|
||||||
return new Response($out);
|
|
||||||
}
|
}
|
||||||
|
return new Response($out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function tokenGenerate(string $user, string $label): string {
|
public static function tokenGenerate(string $user, string $label): string {
|
||||||
|
|
|
@ -525,4 +525,80 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
\Phake::verify(Arsse::$db)->articleMark("john.doe@example.com", ['read' => true], (new Context)->folder(2111))
|
\Phake::verify(Arsse::$db)->articleMark("john.doe@example.com", ['read' => true], (new Context)->folder(2111))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testListReeds(): void {
|
||||||
|
\Phake::when(Arsse::$db)->folderList->thenReturn(new Result([
|
||||||
|
['id' => 5, 'name' => "Cat Ook"],
|
||||||
|
]));
|
||||||
|
\Phake::when(Arsse::$db)->subscriptionList->thenReturn(new Result([
|
||||||
|
['id' => 1, 'feed' => 12, 'url' => "http://example.com/ook", 'title' => "Ook", 'source' => "http://example.com/", 'icon_id' => 47, 'icon_url' => "http://example.com/icon", 'folder' => 2112, 'top_folder' => 5, 'pinned' => 0, 'err_count' => 1, 'err_msg' => "Oopsie", 'order_type' => 0, 'keep_rule' => "this|that", 'block_rule' => "both", 'added' => "2020-12-21 21:12:00", 'updated' => "2021-01-05 13:51:32", 'edited' => "2021-01-01 00:00:00", 'modified' => "2020-11-30 04:08:52", 'next_fetch' => "2021-01-20 00:00:00", 'etag' => "OOKEEK", 'scrape' => 0, 'unread' => 42],
|
||||||
|
['id' => 55, 'feed' => 12, 'url' => "http://j%20k:super%20secret@example.com/eek", 'title' => "Eek", 'source' => "http://example.com/", 'icon_id' => null, 'icon_url' => null, 'folder' => null, 'top_folder' => null, 'pinned' => 0, 'err_count' => 0, 'err_msg' => null, 'order_type' => 0, 'keep_rule' => null, 'block_rule' => null, 'added' => "2020-12-21 21:12:00", 'updated' => "2021-01-05 13:51:32", 'edited' => null, 'modified' => "2020-11-30 04:08:52", 'next_fetch' => null, 'etag' => null, 'scrape' => 1, 'unread' => 0],
|
||||||
|
]));
|
||||||
|
$exp = new Response([
|
||||||
|
[
|
||||||
|
'id' => 1,
|
||||||
|
'user_id' => 42,
|
||||||
|
'feed_url' => "http://example.com/ook",
|
||||||
|
'site_url' => "http://example.com/",
|
||||||
|
'title' => "Ook",
|
||||||
|
'checked_at' => "2021-01-05T13:51:32.000000Z",
|
||||||
|
'next_check_at' => "2021-01-20T00:00:00.000000Z",
|
||||||
|
'etag_header' => "OOKEEK",
|
||||||
|
'last_modified_header' => "Fri, 01 Jan 2021 00:00:00 GMT",
|
||||||
|
'parsing_error_message' => "Oopsie",
|
||||||
|
'parsing_error_count' => 1,
|
||||||
|
'scraper_rules' => "",
|
||||||
|
'rewrite_rules' => "",
|
||||||
|
'crawler' => false,
|
||||||
|
'blocklist_rules' => "both",
|
||||||
|
'keeplist_rules' => "this|that",
|
||||||
|
'user_agent' => "",
|
||||||
|
'username' => "",
|
||||||
|
'password' => "",
|
||||||
|
'disabled' => false,
|
||||||
|
'ignore_http_cache' => false,
|
||||||
|
'fetch_via_proxy' => false,
|
||||||
|
'category' => [
|
||||||
|
'id' => 6,
|
||||||
|
'title' => "Cat Ook",
|
||||||
|
'user_id' => 42
|
||||||
|
],
|
||||||
|
'icon' => [
|
||||||
|
'feed_id' => 1,
|
||||||
|
'icon_id' => 47
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'id' => 55,
|
||||||
|
'user_id' => 42,
|
||||||
|
'feed_url' => "http://example.com/eek",
|
||||||
|
'site_url' => "http://example.com/",
|
||||||
|
'title' => "Eek",
|
||||||
|
'checked_at' => "2021-01-05T13:51:32.000000Z",
|
||||||
|
'next_check_at' => "0001-01-01T00:00:00.000000Z",
|
||||||
|
'etag_header' => "",
|
||||||
|
'last_modified_header' => "",
|
||||||
|
'parsing_error_message' => "",
|
||||||
|
'parsing_error_count' => 0,
|
||||||
|
'scraper_rules' => "",
|
||||||
|
'rewrite_rules' => "",
|
||||||
|
'crawler' => true,
|
||||||
|
'blocklist_rules' => "",
|
||||||
|
'keeplist_rules' => "",
|
||||||
|
'user_agent' => "",
|
||||||
|
'username' => "j k",
|
||||||
|
'password' => "super secret",
|
||||||
|
'disabled' => false,
|
||||||
|
'ignore_http_cache' => false,
|
||||||
|
'fetch_via_proxy' => false,
|
||||||
|
'category' => [
|
||||||
|
'id' => 1,
|
||||||
|
'title' => "All",
|
||||||
|
'user_id' => 42
|
||||||
|
],
|
||||||
|
'icon' => null,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->assertMessage($exp, $this->req("GET", "/feeds"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue