Add functional tests for Fever API
This commit is contained in:
parent
818c501b07
commit
75808c5369
@ -25,7 +25,9 @@ script:
|
|||||||
- ./vendor/bin/phpunit -c tests/phpunit.unit.sqlite.xml
|
- ./vendor/bin/phpunit -c tests/phpunit.unit.sqlite.xml
|
||||||
- ./vendor/bin/phpunit -c tests/phpunit.unit.postgres.xml
|
- ./vendor/bin/phpunit -c tests/phpunit.unit.postgres.xml
|
||||||
- ./vendor/bin/phpunit -c tests/phpunit.functional.sqlite.xml
|
- ./vendor/bin/phpunit -c tests/phpunit.functional.sqlite.xml
|
||||||
- cp ./tests/ci/config.postgres.php $TRAVIS_BUILD_DIR/config.php && ./vendor/bin/phpunit -c tests/phpunit.functional.postgres.xml
|
- cp ./tests/ci/config.postgres.php $TRAVIS_BUILD_DIR/config.php
|
||||||
|
- ./vendor/bin/phpunit -c tests/phpunit.functional.postgres.xml tests/functional/ApiTest.php
|
||||||
|
- ./vendor/bin/phpunit -c tests/phpunit.functional.postgres.xml tests/functional/FeverApiTest.php
|
||||||
|
|
||||||
after_failure:
|
after_failure:
|
||||||
- cat apache_error.log
|
- cat apache_error.log
|
||||||
|
@ -16,7 +16,7 @@ Version 1.2.0 (unreleased)
|
|||||||
* Add support for Expires and Cache-Control headers (HTTP cache)
|
* Add support for Expires and Cache-Control headers (HTTP cache)
|
||||||
* Update Docker image to Ubuntu 16.04 and PHP 7.0
|
* Update Docker image to Ubuntu 16.04 and PHP 7.0
|
||||||
* Add Docker compose file
|
* Add Docker compose file
|
||||||
* Add functional tests (Json-RPC API)
|
* Add functional tests (Json-RPC API and Fever API)
|
||||||
* Add unit tests
|
* Add unit tests
|
||||||
|
|
||||||
Migration procedure from 1.1.x to 1.2.0:
|
Migration procedure from 1.1.x to 1.2.0:
|
||||||
|
@ -56,6 +56,7 @@ function get_bookmarked_item_ids($user_id)
|
|||||||
->table(Model\Item\TABLE)
|
->table(Model\Item\TABLE)
|
||||||
->eq('user_id', $user_id)
|
->eq('user_id', $user_id)
|
||||||
->eq('bookmark', 1)
|
->eq('bookmark', 1)
|
||||||
|
->asc('id')
|
||||||
->findAllByColumn('id');
|
->findAllByColumn('id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,6 +294,7 @@ function get_item_ids_by_status($user_id, $status)
|
|||||||
->table('items')
|
->table('items')
|
||||||
->eq('user_id', $user_id)
|
->eq('user_id', $user_id)
|
||||||
->eq('status', $status)
|
->eq('status', $status)
|
||||||
|
->asc('id')
|
||||||
->findAllByColumn('id');
|
->findAllByColumn('id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,11 +50,20 @@ route('groups', function () {
|
|||||||
list($user, $authenticated, $response) = auth();
|
list($user, $authenticated, $response) = auth();
|
||||||
|
|
||||||
if ($authenticated) {
|
if ($authenticated) {
|
||||||
$response['groups'] = Model\Group\get_all($user['id']);
|
$response['groups'] = array();
|
||||||
$response['feeds_groups'] = array();
|
$response['feeds_groups'] = array();
|
||||||
$group_map = Model\Group\get_groups_feed_ids($user['id']);
|
|
||||||
|
|
||||||
foreach ($group_map as $group_id => $feed_ids) {
|
$groups = Model\Group\get_all($user['id']);
|
||||||
|
$feed_groups = Model\Group\get_groups_feed_ids($user['id']);
|
||||||
|
|
||||||
|
foreach ($groups as $group) {
|
||||||
|
$response['groups'][] = array(
|
||||||
|
'id' => $group['id'],
|
||||||
|
'title' => $group['title'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($feed_groups as $group_id => $feed_ids) {
|
||||||
$response['feeds_groups'][] = array(
|
$response['feeds_groups'][] = array(
|
||||||
'group_id' => $group_id,
|
'group_id' => $group_id,
|
||||||
'feed_ids' => implode(',', $feed_ids)
|
'feed_ids' => implode(',', $feed_ids)
|
||||||
@ -102,7 +111,6 @@ route('feeds', function () {
|
|||||||
// Call: ?api&favicons
|
// Call: ?api&favicons
|
||||||
route('favicons', function () {
|
route('favicons', function () {
|
||||||
list($user, $authenticated, $response) = auth();
|
list($user, $authenticated, $response) = auth();
|
||||||
|
|
||||||
if ($authenticated) {
|
if ($authenticated) {
|
||||||
$favicons = Model\Favicon\get_favicons_with_data_url($user['id']);
|
$favicons = Model\Favicon\get_favicons_with_data_url($user['id']);
|
||||||
$response['favicons'] = array();
|
$response['favicons'] = array();
|
||||||
@ -110,7 +118,7 @@ route('favicons', function () {
|
|||||||
foreach ($favicons as $favicon) {
|
foreach ($favicons as $favicon) {
|
||||||
$response['favicons'][] = array(
|
$response['favicons'][] = array(
|
||||||
'id' => (int) $favicon['feed_id'],
|
'id' => (int) $favicon['feed_id'],
|
||||||
'data' => $favicon['url'],
|
'data' => $favicon['data_url'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
define('DB_DRIVER', 'postgres');
|
defined('DB_DRIVER') or define('DB_DRIVER', 'postgres');
|
||||||
define('DB_HOSTNAME', 'localhost');
|
defined('DB_HOSTNAME') or define('DB_HOSTNAME', 'localhost');
|
||||||
define('DB_NAME', 'miniflux_functional_test');
|
defined('DB_NAME') or define('DB_NAME', 'miniflux_functional_test');
|
||||||
define('DB_USERNAME', 'postgres');
|
defined('DB_USERNAME') or define('DB_USERNAME', 'postgres');
|
||||||
define('DB_PASSWORD', '');
|
defined('DB_PASSWORD') or define('DB_PASSWORD', '');
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use JsonRPC\Client;
|
|
||||||
|
|
||||||
require_once __DIR__.'/BaseApiTest.php';
|
require_once __DIR__.'/BaseApiTest.php';
|
||||||
|
|
||||||
class ApiTest extends BaseApiTest
|
class ApiTest extends BaseApiTest
|
||||||
@ -192,16 +190,4 @@ class ApiTest extends BaseApiTest
|
|||||||
{
|
{
|
||||||
$this->assertTrue($this->getApiClient()->removeFeed(1));
|
$this->assertTrue($this->getApiClient()->removeFeed(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getApiClient(array $user = array())
|
|
||||||
{
|
|
||||||
if (empty($user)) {
|
|
||||||
$user = $this->adminUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
$apiUserClient = new Client(API_URL);
|
|
||||||
$apiUserClient->authentication($user['username'], $user['api_token']);
|
|
||||||
|
|
||||||
return $apiUserClient;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,41 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use JsonRPC\Client;
|
||||||
|
|
||||||
require_once __DIR__.'/../../app/common.php';
|
require_once __DIR__.'/../../app/common.php';
|
||||||
|
|
||||||
abstract class BaseApiTest extends PHPUnit_Framework_TestCase
|
abstract class BaseApiTest extends PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
protected $adminUser = array();
|
protected $adminUser = array();
|
||||||
|
|
||||||
public function setUp()
|
public static function setUpBeforeClass()
|
||||||
{
|
{
|
||||||
if (DB_DRIVER === 'postgres') {
|
if (DB_DRIVER === 'postgres') {
|
||||||
$pdo = new PDO('pgsql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD);
|
$pdo = new PDO('pgsql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD);
|
||||||
|
$pdo->exec("SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '".DB_NAME."' AND pid <> pg_backend_pid()");
|
||||||
|
$pdo->exec('DROP DATABASE '.DB_NAME);
|
||||||
$pdo->exec('CREATE DATABASE '.DB_NAME.' WITH OWNER '.DB_USERNAME);
|
$pdo->exec('CREATE DATABASE '.DB_NAME.' WITH OWNER '.DB_USERNAME);
|
||||||
|
$pdo = null;
|
||||||
|
} else if (file_exists(DB_FILENAME)) {
|
||||||
|
unlink(DB_FILENAME);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
$db = Miniflux\Database\get_connection();
|
$db = Miniflux\Database\get_connection();
|
||||||
$this->adminUser = $db->table(Miniflux\Model\User\TABLE)->eq('username', 'admin')->findOne();
|
$this->adminUser = $db->table(Miniflux\Model\User\TABLE)->eq('username', 'admin')->findOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getApiClient(array $user = array())
|
||||||
|
{
|
||||||
|
if (empty($user)) {
|
||||||
|
$user = $this->adminUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
$apiUserClient = new Client(API_URL);
|
||||||
|
$apiUserClient->authentication($user['username'], $user['api_token']);
|
||||||
|
|
||||||
|
return $apiUserClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
223
tests/functional/FeverApiTest.php
Normal file
223
tests/functional/FeverApiTest.php
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/BaseApiTest.php';
|
||||||
|
|
||||||
|
class FeverApiTest extends BaseApiTest
|
||||||
|
{
|
||||||
|
public function testGetVersion()
|
||||||
|
{
|
||||||
|
$response = $this->executeFeverApiCall();
|
||||||
|
$this->assertEquals(3, $response['api_version']);
|
||||||
|
$this->assertEquals(1, $response['auth']);
|
||||||
|
$this->assertArrayHasKey('last_refreshed_on_time', $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetLinks()
|
||||||
|
{
|
||||||
|
$response = $this->executeFeverApiCall('links');
|
||||||
|
$this->assertEquals(3, $response['api_version']);
|
||||||
|
$this->assertEquals(1, $response['auth']);
|
||||||
|
$this->assertArrayHasKey('last_refreshed_on_time', $response);
|
||||||
|
$this->assertSame(array(), $response['links']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetEmptyFeeds()
|
||||||
|
{
|
||||||
|
$response = $this->executeFeverApiCall('feeds');
|
||||||
|
$this->assertEquals(3, $response['api_version']);
|
||||||
|
$this->assertEquals(1, $response['auth']);
|
||||||
|
$this->assertArrayHasKey('last_refreshed_on_time', $response);
|
||||||
|
$this->assertSame(array(), $response['feeds']);
|
||||||
|
$this->assertSame(array(), $response['feeds_groups']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetEmptyGroups()
|
||||||
|
{
|
||||||
|
$response = $this->executeFeverApiCall('groups');
|
||||||
|
$this->assertEquals(3, $response['api_version']);
|
||||||
|
$this->assertEquals(1, $response['auth']);
|
||||||
|
$this->assertArrayHasKey('last_refreshed_on_time', $response);
|
||||||
|
$this->assertSame(array(), $response['groups']);
|
||||||
|
$this->assertSame(array(), $response['feeds_groups']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetFeedsAndGroups()
|
||||||
|
{
|
||||||
|
$this->createFeedAndGroups();
|
||||||
|
|
||||||
|
$response = $this->executeFeverApiCall('feeds');
|
||||||
|
|
||||||
|
$this->assertEquals(1, $response['feeds'][0]['id']);
|
||||||
|
$this->assertEquals(1, $response['feeds'][0]['favicon_id']);
|
||||||
|
$this->assertNotEmpty($response['feeds'][0]['title']);
|
||||||
|
$this->assertNotEmpty($response['feeds'][0]['url']);
|
||||||
|
$this->assertNotEmpty($response['feeds'][0]['site_url']);
|
||||||
|
$this->assertNotEmpty($response['feeds'][0]['last_updated_on_time']);
|
||||||
|
$this->assertEquals(0, $response['feeds'][0]['is_spark']);
|
||||||
|
|
||||||
|
$this->assertEquals(array(array('group_id' => 1, 'feed_ids' => '1')), $response['feeds_groups']);
|
||||||
|
|
||||||
|
$response = $this->executeFeverApiCall('groups');
|
||||||
|
|
||||||
|
$this->assertEquals(array(array('id' => 1, 'title' => 'open source software')), $response['groups']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetFavicons()
|
||||||
|
{
|
||||||
|
$response = $this->executeFeverApiCall('favicons');
|
||||||
|
|
||||||
|
$this->assertEquals(1, $response['favicons'][0]['id']);
|
||||||
|
$this->assertNotEmpty($response['favicons'][0]['data']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetItems()
|
||||||
|
{
|
||||||
|
$response = $this->executeFeverApiCall('items');
|
||||||
|
|
||||||
|
$this->assertGreaterThan(2, $response['total_items']);
|
||||||
|
$this->assertEquals(1, $response['items'][0]['id']);
|
||||||
|
$this->assertEquals(1, $response['items'][0]['feed_id']);
|
||||||
|
$this->assertNotEmpty($response['items'][0]['title']);
|
||||||
|
$this->assertNotEmpty($response['items'][0]['author']);
|
||||||
|
$this->assertNotEmpty($response['items'][0]['html']);
|
||||||
|
$this->assertNotEmpty($response['items'][0]['url']);
|
||||||
|
$this->assertEquals(0, $response['items'][0]['is_saved']);
|
||||||
|
$this->assertEquals(0, $response['items'][0]['is_read']);
|
||||||
|
$this->assertGreaterThan(0, $response['items'][0]['created_on_time']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetItemsWithIds()
|
||||||
|
{
|
||||||
|
$response = $this->executeFeverApiCall('items&with_ids=2,3');
|
||||||
|
|
||||||
|
$this->assertGreaterThan(2, $response['total_items']);
|
||||||
|
$this->assertCount(2, $response['items']);
|
||||||
|
$this->assertEquals(2, $response['items'][0]['id']);
|
||||||
|
$this->assertEquals(3, $response['items'][1]['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetItemsWithSinceId()
|
||||||
|
{
|
||||||
|
$response = $this->executeFeverApiCall('items&since_id=1');
|
||||||
|
|
||||||
|
$this->assertGreaterThan(2, $response['total_items']);
|
||||||
|
$this->assertEquals(2, $response['items'][0]['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetUnreadItems()
|
||||||
|
{
|
||||||
|
$response = $this->executeFeverApiCall('unread_item_ids');
|
||||||
|
$this->assertStringStartsWith('1,2,', $response['unread_item_ids']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMarkItemAsRead()
|
||||||
|
{
|
||||||
|
$this->assertNotNull($this->executeFeverApiCall('', array(
|
||||||
|
'mark' => 'item',
|
||||||
|
'as' => 'read',
|
||||||
|
'id' => 1,
|
||||||
|
)));
|
||||||
|
|
||||||
|
$response = $this->executeFeverApiCall('items&with_ids=1');
|
||||||
|
$this->assertEquals(1, $response['items'][0]['id']);
|
||||||
|
$this->assertEquals(1, $response['items'][0]['is_read']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMarkItemAsSaved()
|
||||||
|
{
|
||||||
|
$this->assertNotNull($this->executeFeverApiCall('', array(
|
||||||
|
'mark' => 'item',
|
||||||
|
'as' => 'saved',
|
||||||
|
'id' => 2,
|
||||||
|
)));
|
||||||
|
|
||||||
|
$response = $this->executeFeverApiCall('items&with_ids=2');
|
||||||
|
$this->assertEquals(2, $response['items'][0]['id']);
|
||||||
|
$this->assertEquals(0, $response['items'][0]['is_read']);
|
||||||
|
$this->assertEquals(1, $response['items'][0]['is_saved']);
|
||||||
|
|
||||||
|
$response = $this->executeFeverApiCall('saved_item_ids');
|
||||||
|
$this->assertStringStartsWith('2', $response['saved_item_ids']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMarkItemAsUnSaved()
|
||||||
|
{
|
||||||
|
$this->assertNotNull($this->executeFeverApiCall('', array(
|
||||||
|
'mark' => 'item',
|
||||||
|
'as' => 'unsaved',
|
||||||
|
'id' => 2,
|
||||||
|
)));
|
||||||
|
|
||||||
|
$response = $this->executeFeverApiCall('items&with_ids=2');
|
||||||
|
$this->assertEquals(2, $response['items'][0]['id']);
|
||||||
|
$this->assertEquals(0, $response['items'][0]['is_read']);
|
||||||
|
$this->assertEquals(0, $response['items'][0]['is_saved']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMarkFeedAsRead()
|
||||||
|
{
|
||||||
|
$response = $this->executeFeverApiCall('items');
|
||||||
|
$items = $response['items'];
|
||||||
|
$nbItems = count($items);
|
||||||
|
|
||||||
|
$this->assertNotNull($this->executeFeverApiCall('', array(
|
||||||
|
'mark' => 'feed',
|
||||||
|
'as' => 'read',
|
||||||
|
'id' => 1,
|
||||||
|
'before' => $items[$nbItems - 1]['created_on_time'],
|
||||||
|
)));
|
||||||
|
|
||||||
|
$response = $this->executeFeverApiCall('items&with_ids=' . $items[$nbItems - 2]['id']);
|
||||||
|
$this->assertEquals(0, $response['items'][0]['is_read']);
|
||||||
|
|
||||||
|
$response = $this->executeFeverApiCall('items&with_ids=' . $items[$nbItems - 1]['id']);
|
||||||
|
$this->assertEquals(1, $response['items'][0]['is_read']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMarkGroupAsRead()
|
||||||
|
{
|
||||||
|
$this->assertNotNull($this->executeFeverApiCall('', array(
|
||||||
|
'mark' => 'group',
|
||||||
|
'as' => 'read',
|
||||||
|
'id' => 1,
|
||||||
|
'before' => time(),
|
||||||
|
)));
|
||||||
|
|
||||||
|
$response = $this->executeFeverApiCall('unread_item_ids');
|
||||||
|
$this->assertSame('', $response['unread_item_ids']);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function executeFeverApiCall($endpoint = '', array $data = array())
|
||||||
|
{
|
||||||
|
$url = FEVER_API_URL . '?api&' . $endpoint;
|
||||||
|
$headers = array(
|
||||||
|
'Content-type: application/x-www-form-urlencoded',
|
||||||
|
'Accept: application/json',
|
||||||
|
);
|
||||||
|
|
||||||
|
$payload = array(
|
||||||
|
'api_key' => $this->adminUser['fever_api_key'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$context = stream_context_create(array(
|
||||||
|
'http' => array(
|
||||||
|
'method' => 'POST',
|
||||||
|
'protocol_version' => 1.1,
|
||||||
|
'timeout' => 2,
|
||||||
|
'header' => implode("\r\n", $headers),
|
||||||
|
'content' => http_build_query(array_merge($payload, $data)),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$stream = fopen($url, 'r', false, $context);
|
||||||
|
return json_decode(stream_get_contents($stream), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createFeedAndGroups()
|
||||||
|
{
|
||||||
|
$this->assertNotFalse($this->getApiClient()->createFeed(array(
|
||||||
|
'url' => 'https://miniflux.net/feed',
|
||||||
|
'group_name' => 'open source software',
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
@ -6,5 +6,10 @@
|
|||||||
</testsuites>
|
</testsuites>
|
||||||
<php>
|
<php>
|
||||||
<const name="API_URL" value="http://127.0.0.1/jsonrpc.php" />
|
<const name="API_URL" value="http://127.0.0.1/jsonrpc.php" />
|
||||||
|
<const name="FEVER_API_URL" value="http://127.0.0.1/fever/" />
|
||||||
|
<const name="DB_DRIVER" value="postgres" />
|
||||||
|
<const name="DB_USERNAME" value="postgres" />
|
||||||
|
<const name="DB_PASSWORD" value="" />
|
||||||
|
<const name="DB_NAME" value="miniflux_functional_test" />
|
||||||
</php>
|
</php>
|
||||||
</phpunit>
|
</phpunit>
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
</testsuites>
|
</testsuites>
|
||||||
<php>
|
<php>
|
||||||
<const name="API_URL" value="http://127.0.0.1/jsonrpc.php" />
|
<const name="API_URL" value="http://127.0.0.1/jsonrpc.php" />
|
||||||
|
<const name="FEVER_API_URL" value="http://127.0.0.1/fever/" />
|
||||||
<const name="DB_FILENAME" value="data/db.sqlite" />
|
<const name="DB_FILENAME" value="data/db.sqlite" />
|
||||||
</php>
|
</php>
|
||||||
</phpunit>
|
</phpunit>
|
||||||
|
Loading…
Reference in New Issue
Block a user