diff --git a/common.php b/common.php
index dc055e9..e07a61b 100644
--- a/common.php
+++ b/common.php
@@ -11,7 +11,7 @@ defined('HTTP_TIMEOUT') or define('HTTP_TIMEOUT', 20);
defined('BASE_URL_DIRECTORY') or define('BASE_URL_DIRECTORY', dirname($_SERVER['PHP_SELF']));
defined('ROOT_DIRECTORY') or define('ROOT_DIRECTORY', __DIR__);
-defined('DATA_DIRECTORY') or define('DATA_DIRECTORY', __DIR__.'/data');
+defined('DATA_DIRECTORY') or define('DATA_DIRECTORY', ROOT_DIRECTORY.DIRECTORY_SEPARATOR.'data');
defined('ENABLE_MULTIPLE_DB') or define('ENABLE_MULTIPLE_DB', true);
defined('DB_FILENAME') or define('DB_FILENAME', 'db.sqlite');
diff --git a/docs/tests.markdown b/docs/tests.markdown
new file mode 100644
index 0000000..ed3f202
--- /dev/null
+++ b/docs/tests.markdown
@@ -0,0 +1,113 @@
+How to run integration tests?
+=============================
+
+[PHPUnit](https://phpunit.de/) and [Selenium server](http://www.seleniumhq.org) is used to run automatic tests on Miniflux.
+
+You can run tests across different browser to be sure that the result is the same everywhere.
+
+Requirements
+------------
+
+- PHP command line
+- PHPUnit (including phpunit-selenium & dbunit) installed
+- Java
+- Selenium server
+
+
+Install the latest version of PHPUnit
+-------------------------------------
+
+Download the PHPUnit PHAR (includes dbunit & phpunit-selenium) and copy the file somewhere in your `$PATH`:
+
+```bash
+wget https://phar.phpunit.de/phpunit.phar
+chmod +x phpunit.phar
+sudo mv phpunit.phar /usr/local/bin/phpunit
+phpunit --version
+PHPUnit 4.4.0 by Sebastian Bergmann.
+```
+
+
+Install the latest version of Selenium Server
+---------------------------------------------
+
+Download the distribution archive of [Selenium Server](http://www.seleniumhq.org/download/) and the platform and browser specific driver. The following browser driver exist:
+
+- Firefox webdriver is default included
+- [Chrome webdriver](https://sites.google.com/a/chromium.org/chromedriver/downloads)
+- [Internet Explorer webdriver](http://www.seleniumhq.org/download/) (windows only, obviously)
+- Safari ([broken at the moment](https://code.google.com/p/selenium/issues/detail?id=4136))
+
+Start the Selenium Server on the machine which has the browser(s) to test against installed by running:
+
+```cmd
+java -jar "C:\selenium\selenium-server-standalone-2.44.0.jar" -Dwebdriver.ie.driver="C:\selenium\IEDriverServer.exe" -Dwebdriver.chrome.driver="C:\selenium\chromedriver.exe"
+```
+
+
+Running integration tests
+-------------------------
+
+PHPUnit creates a new database with the default credentials for the unit tests. You have to run the tests within the Miniflux directory that is accessible via webserver.
+
+You need to setup the Miniflux url and the browser you would like to test against in the configfile `phpunit.xml`. Its highly recommend to test only against one browser per run to speed-up testing. Browser session reusing does not work with selenium server and phpunit-selenium browser sharing feature is limited to cases where only a single browser is used.
+
+The following `phpunit.xml` is used to run phpunit on a linux system with apache2 installed and test against a Internet Explorer on a remote windows with Selenium Server + Internet Explorer webdriver installed:
+
+```xml
+
+
+
+
+
+
+
+
+
+ ./tests/
+
+
+
+
+
+ tests/
+
+
+
+
+```
+
+You can run the tests by executing phpunit within the Miniflux directory:
+
+
+```bash
+/usr/local/bin/phpunit
+
+PHPUnit 4.4.0 by Sebastian Bergmann.
+
+Configuration read from /var/www/miniflux/phpunit.xml
+
+................................................................. 65 / 83 ( 78%)
+..................
+
+Time: 3.74 minutes, Memory: 21.00Mb
+
+OK (83 tests, 485 assertions)
+
+```
+
+In case of unsuccessful tests, you will find screenshots from the failed website in the ./tests/ directory.
+
+
+Limitations
+-----------
+As the webdrivers using javascript to execute the tests within the browsers, it is not possible to disable javascript and tests the non-javascript fall-back functionality.
\ No newline at end of file
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..7a7e353
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+ ./tests/
+
+
+
+
+
+ tests/
+
+
+
+
\ No newline at end of file
diff --git a/tests/integration/datasets/expected_BookmarkReadArticle.xml b/tests/integration/datasets/expected_BookmarkReadArticle.xml
new file mode 100644
index 0000000..fd77c68
--- /dev/null
+++ b/tests/integration/datasets/expected_BookmarkReadArticle.xml
@@ -0,0 +1,178 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_BookmarkUnreadArticle.xml b/tests/integration/datasets/expected_BookmarkUnreadArticle.xml
new file mode 100644
index 0000000..bd62c3d
--- /dev/null
+++ b/tests/integration/datasets/expected_BookmarkUnreadArticle.xml
@@ -0,0 +1,178 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_FirstFeedAllRemoved.xml b/tests/integration/datasets/expected_FirstFeedAllRemoved.xml
new file mode 100644
index 0000000..6aa8d0d
--- /dev/null
+++ b/tests/integration/datasets/expected_FirstFeedAllRemoved.xml
@@ -0,0 +1,155 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+
+ ##TIMESTAMP##92
+ removed
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+
+ ##TIMESTAMP##97
+ removed
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+
+ ##TIMESTAMP##93
+ removed
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+
+ ##TIMESTAMP##94
+ removed
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+
+ ##TIMESTAMP##99
+ removed
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+
+ ##TIMESTAMP##98
+ removed
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+
+ ##TIMESTAMP##95
+ removed
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+
+ ##TIMESTAMP##96
+ removed
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_MarkFeedRead.xml b/tests/integration/datasets/expected_MarkFeedRead.xml
new file mode 100644
index 0000000..0c6c325
--- /dev/null
+++ b/tests/integration/datasets/expected_MarkFeedRead.xml
@@ -0,0 +1,178 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_MarkReadBookmarkedArticle.xml b/tests/integration/datasets/expected_MarkReadBookmarkedArticle.xml
new file mode 100644
index 0000000..1c0a9e2
--- /dev/null
+++ b/tests/integration/datasets/expected_MarkReadBookmarkedArticle.xml
@@ -0,0 +1,178 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_MarkReadNotBookmarkedArticle.xml b/tests/integration/datasets/expected_MarkReadNotBookmarkedArticle.xml
new file mode 100644
index 0000000..1fec888
--- /dev/null
+++ b/tests/integration/datasets/expected_MarkReadNotBookmarkedArticle.xml
@@ -0,0 +1,178 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_MarkUnreadBookmarkedArticle.xml b/tests/integration/datasets/expected_MarkUnreadBookmarkedArticle.xml
new file mode 100644
index 0000000..9de6383
--- /dev/null
+++ b/tests/integration/datasets/expected_MarkUnreadBookmarkedArticle.xml
@@ -0,0 +1,178 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_MarkUnreadNotBookmarkedArticle.xml b/tests/integration/datasets/expected_MarkUnreadNotBookmarkedArticle.xml
new file mode 100644
index 0000000..a4bc051
--- /dev/null
+++ b/tests/integration/datasets/expected_MarkUnreadNotBookmarkedArticle.xml
@@ -0,0 +1,178 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_NoBookmarkedArticles.xml b/tests/integration/datasets/expected_NoBookmarkedArticles.xml
new file mode 100644
index 0000000..523a3d5
--- /dev/null
+++ b/tests/integration/datasets/expected_NoBookmarkedArticles.xml
@@ -0,0 +1,247 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+ 2
+ https://github.com/fguillot/miniflux/commits/master
+ https://github.com/fguillot/miniflux/commits/master.atom
+ Recent Commits to miniflux:master
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 1f4670bf
+ https://github.com/fguillot/miniflux/commit/e1b22f2d3592d653d4c22ce5f137bb1e0ae5dd3f
+ Redirect to the feed page after adding a subscription
+ fguillot
+ <pre>Redirect to the feed page after adding a subscription</pre>
+ ##TIMESTAMP##89
+ unread
+ 2
+ 0
+
+
+ en-US
+
+
+ 2063e830
+ https://github.com/fguillot/miniflux/commit/e732e80deed05ea46667957835b2499bb895ebe9
+ Update the Json-RPC library and improve make-archive.sh
+ fguillot
+ <pre>Update the Json-RPC library and improve make-archive.sh</pre>
+ ##TIMESTAMP##88
+ read
+ 2
+ 0
+
+
+ en-US
+
+
+ 208ee9dd
+ https://github.com/fguillot/miniflux/commit/871f1d1d6410403599c774ad9aa20e55c77162fc
+ Update PicoDb and improve schema migration error handling
+ fguillot
+ <pre>Update PicoDb and improve schema migration error handling</pre>
+ ##TIMESTAMP##87
+ unread
+ 2
+ 0
+
+
+ en-US
+
+
+ 3530d7cd
+ https://github.com/fguillot/miniflux/commit/d7e5cd0ad424859912fc209651494fad5c52cd34
+ New theme: 'Hello' created by Meradoou
+ fguillot
+ <pre>New theme: 'Hello' created by Meradoou</pre>
+ ##TIMESTAMP##86
+ read
+ 2
+ 0
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_NoReadArticles.xml b/tests/integration/datasets/expected_NoReadArticles.xml
new file mode 100644
index 0000000..31d549e
--- /dev/null
+++ b/tests/integration/datasets/expected_NoReadArticles.xml
@@ -0,0 +1,247 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+ 2
+ https://github.com/fguillot/miniflux/commits/master
+ https://github.com/fguillot/miniflux/commits/master.atom
+ Recent Commits to miniflux:master
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 1f4670bf
+ https://github.com/fguillot/miniflux/commit/e1b22f2d3592d653d4c22ce5f137bb1e0ae5dd3f
+ Redirect to the feed page after adding a subscription
+ fguillot
+ <pre>Redirect to the feed page after adding a subscription</pre>
+ ##TIMESTAMP##89
+ unread
+ 2
+ 0
+
+
+ en-US
+
+
+ 2063e830
+ https://github.com/fguillot/miniflux/commit/e732e80deed05ea46667957835b2499bb895ebe9
+ Update the Json-RPC library and improve make-archive.sh
+ fguillot
+ <pre>Update the Json-RPC library and improve make-archive.sh</pre>
+ ##TIMESTAMP##88
+ unread
+ 2
+ 0
+
+
+ en-US
+
+
+ 208ee9dd
+ https://github.com/fguillot/miniflux/commit/871f1d1d6410403599c774ad9aa20e55c77162fc
+ Update PicoDb and improve schema migration error handling
+ fguillot
+ <pre>Update PicoDb and improve schema migration error handling</pre>
+ ##TIMESTAMP##87
+ unread
+ 2
+ 1
+
+
+ en-US
+
+
+ 3530d7cd
+ https://github.com/fguillot/miniflux/commit/d7e5cd0ad424859912fc209651494fad5c52cd34
+ New theme: 'Hello' created by Meradoou
+ fguillot
+ <pre>New theme: 'Hello' created by Meradoou</pre>
+ ##TIMESTAMP##86
+ unread
+ 2
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_NoReadNotBookmarkedArticles.xml b/tests/integration/datasets/expected_NoReadNotBookmarkedArticles.xml
new file mode 100644
index 0000000..db38898
--- /dev/null
+++ b/tests/integration/datasets/expected_NoReadNotBookmarkedArticles.xml
@@ -0,0 +1,243 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+ 2
+ https://github.com/fguillot/miniflux/commits/master
+ https://github.com/fguillot/miniflux/commits/master.atom
+ Recent Commits to miniflux:master
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+
+ ##TIMESTAMP##93
+ removed
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+
+ ##TIMESTAMP##95
+ removed
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 1f4670bf
+ https://github.com/fguillot/miniflux/commit/e1b22f2d3592d653d4c22ce5f137bb1e0ae5dd3f
+ Redirect to the feed page after adding a subscription
+ fguillot
+ <pre>Redirect to the feed page after adding a subscription</pre>
+ ##TIMESTAMP##89
+ unread
+ 2
+ 0
+
+
+ en-US
+
+
+ 2063e830
+ https://github.com/fguillot/miniflux/commit/e732e80deed05ea46667957835b2499bb895ebe9
+ Update the Json-RPC library and improve make-archive.sh
+ fguillot
+
+ ##TIMESTAMP##88
+ removed
+ 2
+ 0
+
+
+ en-US
+
+
+ 208ee9dd
+ https://github.com/fguillot/miniflux/commit/871f1d1d6410403599c774ad9aa20e55c77162fc
+ Update PicoDb and improve schema migration error handling
+ fguillot
+ <pre>Update PicoDb and improve schema migration error handling</pre>
+ ##TIMESTAMP##87
+ unread
+ 2
+ 1
+
+
+ en-US
+
+
+ 3530d7cd
+ https://github.com/fguillot/miniflux/commit/d7e5cd0ad424859912fc209651494fad5c52cd34
+ New theme: 'Hello' created by Meradoou
+ fguillot
+ <pre>New theme: 'Hello' created by Meradoou</pre>
+ ##TIMESTAMP##86
+ read
+ 2
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_RemoveReadBookmarkedArticle.xml b/tests/integration/datasets/expected_RemoveReadBookmarkedArticle.xml
new file mode 100644
index 0000000..d5c94bb
--- /dev/null
+++ b/tests/integration/datasets/expected_RemoveReadBookmarkedArticle.xml
@@ -0,0 +1,176 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+
+ ##TIMESTAMP##96
+ removed
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_RemoveReadNotBookmarkedArticle.xml b/tests/integration/datasets/expected_RemoveReadNotBookmarkedArticle.xml
new file mode 100644
index 0000000..1088ca3
--- /dev/null
+++ b/tests/integration/datasets/expected_RemoveReadNotBookmarkedArticle.xml
@@ -0,0 +1,176 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+
+ ##TIMESTAMP##95
+ removed
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_RemoveUnreadBookmarkedArticle.xml b/tests/integration/datasets/expected_RemoveUnreadBookmarkedArticle.xml
new file mode 100644
index 0000000..aa562d7
--- /dev/null
+++ b/tests/integration/datasets/expected_RemoveUnreadBookmarkedArticle.xml
@@ -0,0 +1,176 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+
+ ##TIMESTAMP##98
+ removed
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_RemoveUnreadNotBookmarkedArticle.xml b/tests/integration/datasets/expected_RemoveUnreadNotBookmarkedArticle.xml
new file mode 100644
index 0000000..bb672d0
--- /dev/null
+++ b/tests/integration/datasets/expected_RemoveUnreadNotBookmarkedArticle.xml
@@ -0,0 +1,169 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+
+ ##TIMESTAMP##99
+ removed
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_UnbookmarkReadArticle.xml b/tests/integration/datasets/expected_UnbookmarkReadArticle.xml
new file mode 100644
index 0000000..dd70f15
--- /dev/null
+++ b/tests/integration/datasets/expected_UnbookmarkReadArticle.xml
@@ -0,0 +1,178 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/expected_UnbookmarkUnreadArticle.xml b/tests/integration/datasets/expected_UnbookmarkUnreadArticle.xml
new file mode 100644
index 0000000..fea57d3
--- /dev/null
+++ b/tests/integration/datasets/expected_UnbookmarkUnreadArticle.xml
@@ -0,0 +1,178 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/fixture_OnlyReadArticles.xml b/tests/integration/datasets/fixture_OnlyReadArticles.xml
new file mode 100644
index 0000000..3e66047
--- /dev/null
+++ b/tests/integration/datasets/fixture_OnlyReadArticles.xml
@@ -0,0 +1,247 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+ 2
+ https://github.com/fguillot/miniflux/commits/master
+ https://github.com/fguillot/miniflux/commits/master.atom
+ Recent Commits to miniflux:master
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 1f4670bf
+ https://github.com/fguillot/miniflux/commit/e1b22f2d3592d653d4c22ce5f137bb1e0ae5dd3f
+ Redirect to the feed page after adding a subscription
+ fguillot
+ <pre>Redirect to the feed page after adding a subscription</pre>
+ ##TIMESTAMP##89
+ read
+ 2
+ 0
+
+
+ en-US
+
+
+ 2063e830
+ https://github.com/fguillot/miniflux/commit/e732e80deed05ea46667957835b2499bb895ebe9
+ Update the Json-RPC library and improve make-archive.sh
+ fguillot
+ <pre>Update the Json-RPC library and improve make-archive.sh</pre>
+ ##TIMESTAMP##88
+ read
+ 2
+ 0
+
+
+ en-US
+
+
+ 208ee9dd
+ https://github.com/fguillot/miniflux/commit/871f1d1d6410403599c774ad9aa20e55c77162fc
+ Update PicoDb and improve schema migration error handling
+ fguillot
+ <pre>Update PicoDb and improve schema migration error handling</pre>
+ ##TIMESTAMP##87
+ read
+ 2
+ 1
+
+
+ en-US
+
+
+ 3530d7cd
+ https://github.com/fguillot/miniflux/commit/d7e5cd0ad424859912fc209651494fad5c52cd34
+ New theme: 'Hello' created by Meradoou
+ fguillot
+ <pre>New theme: 'Hello' created by Meradoou</pre>
+ ##TIMESTAMP##86
+ read
+ 2
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/fixture_feed1.xml b/tests/integration/datasets/fixture_feed1.xml
new file mode 100644
index 0000000..dbe457e
--- /dev/null
+++ b/tests/integration/datasets/fixture_feed1.xml
@@ -0,0 +1,178 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 1
+ http://miniflux.net/
+ http://miniflux.net/feed.xml
+ Recent Miniflux Releases
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 22ca3b4f
+ http://miniflux.net/news.html#2013-03-21
+ Miniflux 1.0.2 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.2.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.2" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##92
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 30d227f3
+ http://miniflux.net/news.html#2013-07-22
+ Miniflux 1.0.10 is released!
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.10.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.10" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##97
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 4b2dbd17
+ http://miniflux.net/news.html#2013-03-26
+ Miniflux 1.0.3 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.3.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.3" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##93
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 51b4239b
+ http://miniflux.net/news.html#2013-04-12
+ Miniflux 1.0.6 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.6.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.6" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##94
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+ 7c6afaa5
+ http://miniflux.net/news.html#2014-01-02
+ Miniflux 1.1.1 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.1.1.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.1.1" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul><p>Major improvements:</p>
+ <ul><li>New theme: Copper (By the contributor Nicolas Dewaele)</li>
+ <li>Display a message next to a feed when there is a parsing error</li>
+ <li>Change default value of autoflush to 15 days if not set to avoid large database</li>
+ <li>Add autoflush value "immediately"</li>
+ <li>Add an option to choose where to be redirected when there is nothing to read</li>
+ <li>Bug fixes</li>
+ </ul>
+ ##TIMESTAMP##99
+ unread
+ 1
+ 0
+
+
+ en-US
+
+
+ 7cb2809d
+ http://miniflux.net/news.html#2013-09-02
+ Miniflux 1.0.11 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.11.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.11" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##98
+ unread
+ 1
+ 1
+
+
+ en-US
+
+
+ 9b20eb66
+ http://miniflux.net/news.html#2013-04-30
+ Miniflux 1.0.7 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.7.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.html#v1.0.7" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##95
+ read
+ 1
+ 0
+
+
+ en-US
+
+
+ 9fa78b54
+ http://miniflux.net/news.html#2013-06-02
+ Miniflux 1.0.8 is released
+
+ <ul><li><a href="http://miniflux.net/miniflux-1.0.8.zip" rel="noreferrer" target="_blank" >Download archive</a></li>
+ <li><a href="http://miniflux.net/changes.htm#v1.0.8" rel="noreferrer" target="_blank" >ChangeLog</a></li>
+ </ul>
+ ##TIMESTAMP##96
+ read
+ 1
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/datasets/fixture_feed2.xml b/tests/integration/datasets/fixture_feed2.xml
new file mode 100644
index 0000000..5ce758e
--- /dev/null
+++ b/tests/integration/datasets/fixture_feed2.xml
@@ -0,0 +1,99 @@
+
+
+
+ id
+ site_url
+ feed_url
+ title
+ last_modified
+ etag
+ last_checked
+ enabled
+ download_content
+ parsing_error
+ rtl
+
+ 2
+ https://github.com/fguillot/miniflux/commits/master
+ https://github.com/fguillot/miniflux/commits/master.atom
+ Recent Commits to miniflux:master
+
+
+
+ 1
+ 0
+ 0
+ 0
+
+
+
+ id
+ url
+ title
+ author
+ content
+ updated
+ status
+ feed_id
+ bookmark
+ enclosure
+ enclosure_type
+ language
+
+ 1f4670bf
+ https://github.com/fguillot/miniflux/commit/e1b22f2d3592d653d4c22ce5f137bb1e0ae5dd3f
+ Redirect to the feed page after adding a subscription
+ fguillot
+ <pre>Redirect to the feed page after adding a subscription</pre>
+ ##TIMESTAMP##89
+ unread
+ 2
+ 0
+
+
+ en-US
+
+
+ 2063e830
+ https://github.com/fguillot/miniflux/commit/e732e80deed05ea46667957835b2499bb895ebe9
+ Update the Json-RPC library and improve make-archive.sh
+ fguillot
+ <pre>Update the Json-RPC library and improve make-archive.sh</pre>
+ ##TIMESTAMP##88
+ read
+ 2
+ 0
+
+
+ en-US
+
+
+ 208ee9dd
+ https://github.com/fguillot/miniflux/commit/871f1d1d6410403599c774ad9aa20e55c77162fc
+ Update PicoDb and improve schema migration error handling
+ fguillot
+ <pre>Update PicoDb and improve schema migration error handling</pre>
+ ##TIMESTAMP##87
+ unread
+ 2
+ 1
+
+
+ en-US
+
+
+ 3530d7cd
+ https://github.com/fguillot/miniflux/commit/d7e5cd0ad424859912fc209651494fad5c52cd34
+ New theme: 'Hello' created by Meradoou
+ fguillot
+ <pre>New theme: 'Hello' created by Meradoou</pre>
+ ##TIMESTAMP##86
+ read
+ 2
+ 1
+
+
+ en-US
+
+
+
diff --git a/tests/integration/keyboardShortcutsTest.php b/tests/integration/keyboardShortcutsTest.php
new file mode 100644
index 0000000..ec44018
--- /dev/null
+++ b/tests/integration/keyboardShortcutsTest.php
@@ -0,0 +1,194 @@
+getURLPageFirstFeed();
+ parent::setUpPage($url);
+
+ $this->basePageHeading = $this->getBasePageHeading();
+ $this->expectedPageUrl = $url;
+ }
+
+ protected function getExpectedPageTitle()
+ {
+ return "($this->expectedCounterPage) $this->basePageHeading";
+ }
+
+ public function testNextItemShortcutA()
+ {
+ $articles = $this->getArticles();
+
+ $this->setArticleAsCurrentArticle($articles[0]);
+ $this->keys($this->getShortcutNextItemA());
+
+ $firstIsNotCurrentArticle = $this->waitForArticleIsNotCurrentArticle($articles[0]);
+ $secondIsCurrentArticle = $this->waitForArticleIsCurrentArticle($articles[1]);
+
+ $this->assertTrue($firstIsNotCurrentArticle, 'The first Article is still the current Article');
+ $this->assertTrue($secondIsCurrentArticle, 'The second Article is not the current Article');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testNextItemShortcutB()
+ {
+ $articles = $this->getArticles();
+
+ $this->setArticleAsCurrentArticle($articles[0]);
+ $this->keys($this->getShortcutNextItemB());
+
+ $firstIsNotCurrentArticle = $this->waitForArticleIsNotCurrentArticle($articles[0]);
+ $secondIsCurrentArticle = $this->waitForArticleIsCurrentArticle($articles[1]);
+
+ $this->assertTrue($firstIsNotCurrentArticle, 'The first Article is still the current Article');
+ $this->assertTrue($secondIsCurrentArticle, 'The second Article is not the current Article');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');;
+ }
+
+ public function testPreviousItemA()
+ {
+ $articles = $this->getArticles();
+
+ $this->setArticleAsCurrentArticle($articles[1]);
+ $this->keys($this->getShortcutPreviousItemA());
+
+ $firstIsCurrentArticle = $this->waitForArticleIsCurrentArticle($articles[0]);
+ $secondIsNotCurrentArticle = $this->waitForArticleIsNotCurrentArticle($articles[1]);
+
+ $this->assertTrue($firstIsCurrentArticle, 'The first Article is not the current Article');
+ $this->assertTrue($secondIsNotCurrentArticle, 'The second Article is still the current Article');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testPreviousItemB()
+ {
+ $articles = $this->getArticles();
+
+ $this->setArticleAsCurrentArticle($articles[1]);
+ $this->keys($this->getShortcutPreviousItemB());
+
+ $firstIsCurrentArticle = $this->waitForArticleIsCurrentArticle($articles[0]);
+ $secondIsNotCurrentArticle = $this->waitForArticleIsNotCurrentArticle($articles[1]);
+
+ $this->assertTrue($firstIsCurrentArticle, 'The first Article is not the current Article');
+ $this->assertTrue($secondIsNotCurrentArticle, 'The second Article is still the current Article');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testNextStopsAtLastArticle()
+ {
+ $articles = $this->getArticles();
+ $lastIndex = count($articles) - 1;
+
+ $this->setArticleAsCurrentArticle($articles[$lastIndex]);
+ $this->keys($this->getShortcutNextItemA());
+
+ $firstIsNotCurrentArticle = $this->waitForArticleIsNotCurrentArticle($articles[0]);
+ $lastIsCurrentArticle = $this->waitForArticleIsCurrentArticle($articles[$lastIndex]);
+
+ $this->assertTrue($firstIsNotCurrentArticle, 'The first Article is still the current Article');
+ $this->assertTrue($lastIsCurrentArticle, 'The last Article is not the current Article');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testPreviousStopsAtFirstArticle()
+ {
+ $articles = $this->getArticles();
+ $lastIndex = count($articles) - 1;
+
+ $this->setArticleAsCurrentArticle($articles[0]);
+ $this->keys($this->getShortcutPreviousItemA());
+
+ $lastIsNotCurrentArticle = $this->waitForArticleIsNotCurrentArticle($articles[$lastIndex]);
+ $firstIsCurrentArticle = $this->waitForArticleIsCurrentArticle($articles[0]);
+
+ $this->assertTrue($lastIsNotCurrentArticle, 'The last Article is still the current Article');
+ $this->assertTrue($firstIsCurrentArticle, 'The first Article is not the current Article');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testShortcutsOnInputFiledAreDisabled()
+ {
+ $url = $this->getURLPagePreferences();
+
+ $this->url($url);
+ $this->byId('form-username')->value($this->getShortcutGoToUnread());
+
+ $this->expectedPageUrl = $url;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+
+ $this->ignorePageTitle = TRUE;
+ }
+
+ public function testGoToBookmarks()
+ {
+ $this->sendKeysAndWaitForPageLoaded('gb');
+
+ $this->expectedCounterPage = '6';
+ $this->expectedPageUrl = $this->getURLPageBookmarks();
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+
+ $this->ignorePageTitle = TRUE;
+ }
+
+ public function testGoToHistory()
+ {
+ $this->sendKeysAndWaitForPageLoaded('gh');
+
+ $this->expectedCounterPage = '6';
+ $this->expectedPageUrl = $this->getURLPageHistory();
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+
+ $this->ignorePageTitle = TRUE;
+ }
+
+ public function testGoToUnread()
+ {
+ $this->sendKeysAndWaitForPageLoaded($this->getShortcutGoToUnread());
+
+ $this->expectedCounterPage = '6';
+ $this->expectedCounterUnread = '6';
+ $this->expectedPageUrl = $this->getURLPageUnread();
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+
+ $this->ignorePageTitle = TRUE;
+ }
+
+ public function testGoToSubscriptions()
+ {
+ $this->sendKeysAndWaitForPageLoaded('gs');
+
+ $this->expectedPageUrl = PHPUNIT_TESTSUITE_EXTENSION_SELENIUM_BASEURL.'?action=feeds';
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+
+ $this->ignorePageTitle = TRUE;
+ }
+
+ public function testGoToPreferences()
+ {
+ $this->sendKeysAndWaitForPageLoaded('gp');
+
+ $this->expectedPageUrl = $this->getURLPagePreferences();
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+
+ $this->ignorePageTitle = TRUE;
+ }
+}
+?>
\ No newline at end of file
diff --git a/tests/integration/minifluxTestCase.php b/tests/integration/minifluxTestCase.php
new file mode 100644
index 0000000..de80179
--- /dev/null
+++ b/tests/integration/minifluxTestCase.php
@@ -0,0 +1,588 @@
+getDatabaseTester('fixture_feed1', TRUE)->onSetUp();
+
+ // Set the base URL for the tests.
+ $this->setBrowserUrl(PHPUNIT_TESTSUITE_EXTENSION_SELENIUM_BASEURL);
+ }
+
+ public function setUpPage($url)
+ {
+ parent::setUpPage();
+
+ // (re)load the requested page
+ $this->url($url);
+
+ // check if login is need and login
+ $elements = $this->elements($this->using('css selector')->value('body#login-page'));
+
+ if (count($elements) === 1) {
+ $this->url('?action=select-db&database='.DB_FILENAME);
+
+ $this->byId('form-username')->click();
+ $this->keys('admin');
+ $this->byId('form-password')->click();
+ $this->keys('admin');
+ $this->byTag('form')->submit();
+
+ $this->url($url);
+ }
+ }
+
+ public static function tearDownAfterClass()
+ {
+ static::$databaseConnection = NULL;
+ static::$databaseTester = NULL;
+ }
+
+ protected function assertPostConditions()
+ {
+ // counter exists on every page
+ $this->assertEquals($this->expectedCounterPage, $this->getCounterPage(), 'page-counter differ from expectation');
+ $this->assertEquals($this->expectedCounterUnread, $this->getCounterUnread(), 'unread counter differ from expectation');
+
+ // url has not been changed (its likely that everything was done via javascript then)
+ $this->assertEquals($this->expectedPageUrl, $this->url(), 'URL has been changed.');
+
+ // some tests switch to a page where no counter exists and the expected
+ // pagetitle doesn't match to definition.
+ if ($this->ignorePageTitle === FALSE) {
+ //remove LEFT-TO-RIGHT MARK char from string as the webdriver does it when using text() on the page
+ $pagetitle = preg_replace('/\x{200E}/u', '', $this->title());
+ $this->assertEquals($this->getExpectedPageTitle(), $pagetitle, 'page title differ from expectation');
+ }
+
+ // assert that the current database matches the expected database
+ $expectedDataSetFiltered = new PHPUnit_Extensions_Database_DataSet_DataSetFilter($this->expectedDataSet);
+ $expectedDataSetFiltered->addIncludeTables(array('items'));
+ $expectedDataSetFiltered->setExcludeColumnsForTable('items', array('updated'));
+
+ // TODO: changes row order, why?
+ //$actualDataSet = $this->getConnection()->createDataSet();
+ $actualDataSet = new PHPUnit_Extensions_Database_DataSet_QueryDataSet($this->getConnection());
+ $actualDataSet->addTable('items', 'SELECT * FROM items');
+ $actualDataSetFiltered = new PHPUnit_Extensions_Database_DataSet_DataSetFilter($actualDataSet);
+ $actualDataSetFiltered->setExcludeColumnsForTable('items', array('updated'));
+
+ PHPUnit_Extensions_Database_TestCase::assertDataSetsEqual($expectedDataSetFiltered, $actualDataSetFiltered, 'Unexpected changes in database');
+ }
+
+ protected function getDataSet($dataSetFile, $appendFeed2 = TRUE)
+ {
+ $compositeDs = new PHPUnit_Extensions_Database_DataSet_CompositeDataSet();
+
+ $ds1 = new PHPUnit_Extensions_Database_DataSet_XmlDataSet(dirname(__FILE__).DIRECTORY_SEPARATOR.'datasets'.DIRECTORY_SEPARATOR.$dataSetFile.'.xml');
+ $compositeDs->addDataSet($ds1);
+
+ if ($appendFeed2) {
+ // feed2 should be normaly untouched
+ $ds2 = new PHPUnit_Extensions_Database_DataSet_XmlDataSet(dirname(__FILE__).DIRECTORY_SEPARATOR.'datasets'.DIRECTORY_SEPARATOR.'fixture_feed2.xml');
+ $compositeDs->addDataSet($ds2);
+ }
+
+ return $compositeDs;
+ }
+
+ protected function getConnection()
+ {
+ if (is_null(static::$databaseConnection)) {
+ // let Miniflux setup the database
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'common.php';
+
+ if (!ENABLE_MULTIPLE_DB) {
+ throw new Exception('Enable multiple databases support to run the tests!');
+ }
+
+ $picoDb = new PicoDb\Database(array(
+ 'driver' => 'sqlite',
+ 'filename' => \Model\Database\get_path(),
+ ));
+
+ $picoDb->schema()->check(Schema\VERSION);
+
+ // make the database world writeable, maybe the current
+ // user != webserver user
+ chmod(\Model\Database\get_path(), 0666);
+
+ // get pdo object
+ $pdo = $picoDb->getConnection();
+
+ // disable fsync! its awefull slow without transactions and I found
+ // no way to use setDataSet function with transactions
+ $pdo->exec("pragma synchronous = off;");
+
+ static::$databaseConnection = new PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection($pdo, 'sqlite');
+ }
+
+ return static::$databaseConnection;
+ }
+
+ protected function getDatabaseTester($dataSetFile, $appendFeed2)
+ {
+ if (is_null(static::$databaseTester)) {
+ $tester = new PHPUnit_Extensions_Database_DefaultTester($this->getConnection());
+
+ // article/feed import on database->onSetUp();
+ $tester->setSetUpOperation(PHPUnit_Extensions_Database_Operation_Factory::CLEAN_INSERT());
+ $dataset = $this->getDataSet($dataSetFile, $appendFeed2);
+ $rdataset = new PHPUnit_Extensions_Database_DataSet_ReplacementDataSet($dataset);
+ $rdataset->addSubStrReplacement('##TIMESTAMP##', substr((string)(time()-100), 0, -2));
+ $tester->setDataSet($rdataset);
+
+ static::$databaseTester = $tester;
+ }
+
+ return static::$databaseTester;
+ }
+
+ private function getCounterUnread()
+ {
+ $value = $this->element($this->using('id')->value('nav-counter'))->text();
+ return $value;
+ }
+
+ private function getCounterPage()
+ {
+ $value = NULL;
+
+ $elements = $this->elements($this->using('id')->value('page-counter'));
+
+ if (count($elements) === 1) {
+ $value = $elements[0]->text();
+ }
+
+ return $value;
+ }
+
+ private function waitForElementVisibility($element, $visible)
+ {
+ // return false in case of timeout
+ try {
+ $value = $this->waitUntil(function() use($element, $visible) {
+ // a "No such Element" or "Stale Element Reference" exception is
+ // valid if an object should disappear
+ try {
+ $displaySize = $element->size();
+
+ if ((($visible === TRUE) && ($element->displayed() && $displaySize['height']>0 && $displaySize['width']>0))
+ || (($visible === FALSE) && ($element->displayed() === FALSE || $displaySize['height']=0 || $displaySize['width']=0))) {
+ return TRUE;
+ }
+ }
+ catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
+
+ $noSuchElement = ($e->getCode() === PHPUnit_Extensions_Selenium2TestCase_WebDriverException::NoSuchElement
+ || $e->getCode() === PHPUnit_Extensions_Selenium2TestCase_WebDriverException::StaleElementReference);
+
+ if (($visible === FALSE) && ($noSuchElement)) {
+ return TRUE;
+ } else {
+ throw $e;
+ }
+ }
+ }, $this->waitTimeout);
+ }
+ catch(PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
+ if ($e->getCode() === PHPUnit_Extensions_Selenium2TestCase_WebDriverException::Timeout) {
+ return FALSE;
+ } else {
+ throw $e;
+ }
+ }
+
+ return $value;
+ }
+
+ private function waitForElementCountByCssSelector($cssSelector, $elementCount)
+ {
+ // return false in case of timeout
+ try {
+ // Workaround for PHP < 5.4
+ $CI = $this;
+
+ $value = $this->waitUntil(function() use($cssSelector, $elementCount, $CI) {
+ $elements = $CI->elements($CI->using('css selector')->value($cssSelector));
+
+ if (count($elements) === $elementCount) {
+ return TRUE;
+ }
+ }, $this->waitTimeout);
+ }
+ catch(PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
+ if ($e->getCode() === PHPUnit_Extensions_Selenium2TestCase_WebDriverException::Timeout) {
+ return FALSE;
+ } else {
+ throw $e;
+ }
+ }
+
+ return $value;
+ }
+
+ private function waitForElementAttributeHasValue($element, $attribute, $attributeValue, $invertMatch = FALSE)
+ {
+ // return false in case of timeout
+ try {
+ $value = $this->waitUntil(function() use($element, $attribute, $attributeValue, $invertMatch) {
+ $attributeHasValue = ($element->attribute($attribute) === $attributeValue);
+
+ if (($attributeHasValue && !$invertMatch) || (!$attributeHasValue && $invertMatch)) {
+ return TRUE;
+ }
+ }, $this->waitTimeout);
+ }
+ catch(PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
+ if ($e->getCode() === PHPUnit_Extensions_Selenium2TestCase_WebDriverException::Timeout) {
+ return FALSE;
+ } else {
+ throw $e;
+ }
+ }
+
+ return $value;
+ }
+
+ private function waitForIconMarkRead($article, $visible)
+ {
+ $icon = $article->elements($article->using('css selector')->value('span.read-icon'));
+
+ $value = $this->waitForElementVisibility($icon[0], $visible);
+ return $value;
+ }
+
+ private function waitForIconBookmark($article, $visible)
+ {
+ $icon = $article->elements($article->using('css selector')->value('span.bookmark-icon'));
+
+ $value = $this->waitForElementVisibility($icon[0], $visible);
+ return $value;
+ }
+
+ public function getBasePageHeading()
+ {
+ /*
+ * WORKAROUND: Its not possible to get an elements text content without
+ * the text of its childs. Thats why we have to differ between
+ * pageheadings with counter and without counter.
+ */
+
+ // text of its childs
+ $pageHeading = $this->byCssSelector('div.page-header > h2:first-child')->text();
+
+ // Some PageHeadings have a counter included
+ $innerHeadingElements = $this->elements($this->using('css selector')->value('div.page-header > h2:first-child *'));
+
+ if (count($innerHeadingElements) > 0)
+ {
+ $innerHeading = $innerHeadingElements[0]->text();
+ $pageHeading = substr($pageHeading, 0, (strlen($innerHeading) * -1));
+ }
+
+ return $pageHeading;
+ }
+
+ public function getURLPageUnread()
+ {
+ return PHPUNIT_TESTSUITE_EXTENSION_SELENIUM_BASEURL.'?action=unread';
+ }
+
+ public function getURLPageBookmarks()
+ {
+ return PHPUNIT_TESTSUITE_EXTENSION_SELENIUM_BASEURL.'?action=bookmarks';
+ }
+
+ public function getURLPageHistory()
+ {
+ return PHPUNIT_TESTSUITE_EXTENSION_SELENIUM_BASEURL.'?action=history';
+ }
+
+ public function getURLPageFirstFeed()
+ {
+ return PHPUNIT_TESTSUITE_EXTENSION_SELENIUM_BASEURL.'?action=feed-items&feed_id=1';
+ }
+
+ public function getURLPagePreferences()
+ {
+ return PHPUNIT_TESTSUITE_EXTENSION_SELENIUM_BASEURL.'?action=config';
+ }
+
+ public function getShortcutNextItemA()
+ {
+ return 'n';
+ }
+
+ public function getShortcutNextItemB()
+ {
+ return 'j';
+ }
+
+ public function getShortcutPreviousItemA()
+ {
+ return 'p';
+ }
+
+ public function getShortcutPreviousItemB()
+ {
+ return 'k';
+ }
+
+ public function getShortcutToogleReadStatus()
+ {
+ return 'm';
+ }
+
+ public function getShortcutToogleBookmarkStatus()
+ {
+ return 'f';
+ }
+
+ public function getShortcutGoToUnread()
+ {
+ return 'gu';
+ }
+
+ public function getArticles()
+ {
+ $cssSelector = 'article';
+
+ $articles = $this->elements($this->using('css selector')->value($cssSelector));
+ return $articles;
+ }
+
+ public function getArticlesUnread()
+ {
+ $cssSelector = 'article[data-item-status="unread"]';
+
+ $articles = $this->elements($this->using('css selector')->value($cssSelector));
+ return $articles;
+ }
+
+ public function getArticlesRead()
+ {
+ $cssSelector = 'article[data-item-status="read"]';
+
+ $articles = $this->elements($this->using('css selector')->value($cssSelector));
+ return $articles;
+ }
+
+ public function getArticlesNotBookmarked()
+ {
+ $cssSelector = 'article[data-item-bookmark="0"]';
+
+ $articles = $this->elements($this->using('css selector')->value($cssSelector));
+ return $articles;
+ }
+
+ public function getArticlesNotFromFeedOne()
+ {
+ $cssSelector = 'article:not(.feed-1)';
+
+ $articles = $this->elements($this->using('css selector')->value($cssSelector));
+ return $articles;
+ }
+
+ public function getArticleUnreadNotBookmarked()
+ {
+ $cssSelector = 'article[data-item-id="7c6afaa5"]';
+
+ $article = $this->element($this->using('css selector')->value($cssSelector));
+ return $article;
+ }
+
+ public function getArticleReadNotBookmarked()
+ {
+ $cssSelector = 'article[data-item-id="9b20eb66"]';
+
+ $article = $this->element($this->using('css selector')->value($cssSelector));
+ return $article;
+ }
+
+ public function getArticleUnreadBookmarked()
+ {
+ $cssSelector = 'article[data-item-id="7cb2809d"]';
+
+ $article = $this->element($this->using('css selector')->value($cssSelector));
+ return $article;
+ }
+
+ public function getArticleReadBookmarked()
+ {
+ $cssSelector = 'article[data-item-id="9fa78b54"]';
+
+ $articles = $this->element($this->using('css selector')->value($cssSelector));
+ return $articles;
+ }
+
+ public function getLinkReadStatusToogle($article)
+ {
+ $link = $article->element($article->using('css selector')->value('a.mark'));
+ return $link;
+ }
+
+ public function getLinkBookmarkStatusToogle($article)
+ {
+ $link = $article->element($article->using('css selector')->value('a.bookmark'));
+ return $link;
+ }
+
+ public function getLinkRemove($article)
+ {
+ $link = $article->element($article->using('css selector')->value('a.delete'));
+ return $link;
+ }
+
+ public function getLinkFeedMarkReadHeader()
+ {
+ $link = $this->element($this->using('css selector')->value('div.page-header a[data-action="mark-feed-read"]'));
+ return $link;
+ }
+
+ public function getLinkFeedMarkReadBottom()
+ {
+ $link = $this->element($this->using('css selector')->value('div#bottom-menu a[data-action="mark-feed-read"]'));
+ return $link;
+ }
+
+ public function getLinkMarkAllReadHeader()
+ {
+ $link = $this->element($this->using('css selector')->value('div.page-header a[data-action="mark-all-read"]'));
+ return $link;
+ }
+
+ public function getLinkMarkAllReadBottom()
+ {
+ $link = $this->element($this->using('css selector')->value('div#bottom-menu a[data-action="mark-all-read"]'));
+ return $link;
+ }
+
+ public function getLinkFlushHistory()
+ {
+ $link = $this->element($this->using('css selector')->value('div.page-header a[href="?action=confirm-flush-history"]'));
+ return $link;
+ }
+
+ public function getLinkDestructive()
+ {
+ $link = $this->element($this->using('css selector')->value('a.btn-red'));
+ return $link;
+ }
+
+ public function waitForArticleIsCurrentArticle($article)
+ {
+ $isCurrent = $this->waitForElementAttributeHasValue($article, 'id', 'current-item');
+ return $isCurrent;
+ }
+
+ public function waitForArticleIsNotCurrentArticle($article)
+ {
+ $isCurrent = $this->waitForElementAttributeHasValue($article, 'id', 'current-item', TRUE);
+ return $isCurrent;
+ }
+
+ public function waitForIconMarkReadVisible($article)
+ {
+ $visible = $this->waitForIconMarkRead($article, TRUE);
+ return $visible;
+ }
+
+ public function waitForIconMarkReadInvisible($article)
+ {
+ $invisible = $this->waitForIconMarkRead($article, FALSE);
+ return $invisible;
+ }
+
+ public function waitForIconBookmarkVisible($article)
+ {
+ $visible = $this->waitForIconBookmark($article, TRUE);
+ return $visible;
+ }
+
+ public function waitForIconBookmarkInvisible($article)
+ {
+ $invisible = $this->waitForIconBookmark($article, FALSE);
+ return $invisible;
+ }
+
+ public function waitForArticleInvisible($article)
+ {
+ $invisible = $this->waitForElementVisibility($article, FALSE);
+ return $invisible;
+ }
+
+ public function waitForArticlesMarkRead()
+ {
+ $cssSelector = 'article[data-item-status="unread"]';
+
+ $read = $this->waitForElementCountByCssSelector($cssSelector, 0);
+ return $read;
+ }
+
+ public function waitForAlert()
+ {
+ $cssSelector = 'p.alert';
+
+ $visible = $this->waitForElementCountByCssSelector($cssSelector, 1);
+ return $visible;
+ }
+
+ public function sendKeysAndWaitForPageLoaded($keys)
+ {
+ $this->keys($keys);
+
+ // Workaround for PHP < 5.4
+ $CI = $this;
+
+ $this->waitUntil(function() use($CI) {
+ $readyState = $CI->execute(array(
+ 'script' => 'return document.readyState;',
+ 'args' => array()
+ ));
+
+ if ($readyState === 'complete') {
+ return TRUE;
+ }
+ }, $this->waitTimeout);
+ }
+
+ public function setArticleAsCurrentArticle($article)
+ {
+ $script = 'document.getElementById("' .$article->attribute('id') .'").id = "current-item";'
+ . 'return true';
+
+ $this->execute(array(
+ 'script' => $script,
+ 'args' => array()
+ ));
+
+ $result = $this->waitForArticleIsCurrentArticle($article);
+ if ($result === FALSE) {
+ throw new Exception('the article could not be set as current article.');
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/tests/integration/pageBookmarksTest.php b/tests/integration/pageBookmarksTest.php
new file mode 100644
index 0000000..96a6948
--- /dev/null
+++ b/tests/integration/pageBookmarksTest.php
@@ -0,0 +1,201 @@
+getURLPageBookmarks();
+ parent::setUpPage($url);
+
+ $this->basePageHeading = $this->getBasePageHeading();
+ $this->expectedPageUrl = $url;
+ }
+
+ public function getExpectedPageTitle()
+ {
+ return "$this->basePageHeading ($this->expectedCounterPage)";
+ }
+
+ public function testItemsFromAllFeeds()
+ {
+ $articles = $this->getArticlesNotFromFeedOne();
+ $this->assertNotEmpty($articles, 'no articles from other feeds found');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testOnlyBookmarkedArticles()
+ {
+ $articles = $this->getArticlesNotBookmarked();
+ $this->assertEmpty($articles, 'found not bookmarked articles.');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testMarkReadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForIconMarkReadVisible($article);
+ $this->assertTrue($visible, 'read icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkReadBookmarkedArticle');
+ }
+
+ public function testMarkReadBookmarkedArticleKeyboard()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleReadStatus());
+
+ $visible = $this->waitForIconMarkReadVisible($article);
+ $this->assertTrue($visible, 'read icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkReadBookmarkedArticle');
+ }
+
+ public function testMarkUnreadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $invisible = $this->waitForIconMarkReadInvisible($article);
+ $this->assertTrue($invisible, 'read icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkUnreadBookmarkedArticle');
+ }
+
+ public function testMarkUnreadBookmarkedArticleKeyboard()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleReadStatus());
+
+ $invisible = $this->waitForIconMarkReadInvisible($article);
+ $this->assertTrue($invisible, 'read icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkUnreadBookmarkedArticle');
+ }
+
+ public function testUnbookmarkReadArticleLink()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkReadArticle');
+
+ }
+
+ public function testUnbookmarkReadArticleKeyboard()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleBookmarkStatus());
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkReadArticle');
+ }
+
+ public function testUnbookmarkUnreadArticleLink()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkUnreadArticle');
+ }
+
+ public function testUnbookmarkUnreadArticleKeyboard()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleBookmarkStatus());
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkUnreadArticle');
+ }
+
+ public function testRemoveReadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_RemoveReadBookmarkedArticle');
+ }
+
+ public function testRemoveUnreadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_RemoveUnreadBookmarkedArticle');
+ }
+
+ public function testRedirectWithZeroArticles()
+ {
+ $articles = $this->getArticles();
+
+ foreach($articles as $article) {
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $this->waitForArticleInvisible($article);
+ }
+
+ $visible = $this->waitForAlert();
+ $this->assertTrue($visible, 'alert box did not appear');
+
+ $this->expectedDataSet = $this->getDataSet('expected_NoBookmarkedArticles', FALSE);
+
+ $this->ignorePageTitle = TRUE;
+ }
+}
+?>
\ No newline at end of file
diff --git a/tests/integration/pageFirstFeedTest.php b/tests/integration/pageFirstFeedTest.php
new file mode 100644
index 0000000..b5f33ab
--- /dev/null
+++ b/tests/integration/pageFirstFeedTest.php
@@ -0,0 +1,356 @@
+getURLPageFirstFeed();
+ parent::setUpPage($url);
+
+ $this->basePageHeading = $this->getBasePageHeading();
+ $this->expectedPageUrl = $url;
+ }
+
+ public function getExpectedPageTitle()
+ {
+ return "($this->expectedCounterPage) $this->basePageHeading";
+ }
+
+ public function testOnlyItemsFromFirstFeed()
+ {
+ $articles = $this->getArticlesNotFromFeedOne();
+ $this->assertEmpty($articles, 'found articles from other feeds on page for first feed.');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testMarkReadNotBookmarkedArticleLink()
+ {
+ $article = $this->getArticleUnreadNotBookmarked();
+
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForIconMarkReadVisible($article);
+ $this->assertTrue($visible, 'read icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkReadNotBookmarkedArticle');
+ }
+
+ public function testMarkReadNotBookmarkedArticleKeyboard()
+ {
+ $article = $this->getArticleUnreadNotBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleReadStatus());
+
+ $visible = $this->waitForIconMarkReadVisible($article);
+ $this->assertTrue($visible, 'read icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkReadNotBookmarkedArticle');
+ }
+
+ public function testMarkReadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForIconMarkReadVisible($article);
+ $this->assertTrue($visible, 'read icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkReadBookmarkedArticle');
+ }
+
+ public function testMarkReadBookmarkedArticleKeyboard()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleReadStatus());
+
+ $visible = $this->waitForIconMarkReadVisible($article);
+ $this->assertTrue($visible, 'read icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkReadBookmarkedArticle');
+ }
+
+ public function testMarkUnreadNotBookmarkedArticleLink()
+ {
+ $article = $this->getArticleReadNotBookmarked();
+
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $invisible = $this->waitForIconMarkReadInvisible($article);
+ $this->assertTrue($invisible, 'read icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkUnreadNotBookmarkedArticle');
+ }
+
+ public function testMarkUnreadNotBookmarkedArticleKeyboard()
+ {
+ $article = $this->getArticleReadNotBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleReadStatus());
+
+ $invisible = $this->waitForIconMarkReadInvisible($article);
+ $this->assertTrue($invisible, 'read icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkUnreadNotBookmarkedArticle');
+ }
+
+ public function testMarkUnreadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $invisible = $this->waitForIconMarkReadInvisible($article);
+ $this->assertTrue($invisible, 'read icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkUnreadBookmarkedArticle');
+ }
+
+ public function testMarkUnreadBookmarkedArticleKeyboard()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleReadStatus());
+
+ $invisible = $this->waitForIconMarkReadInvisible($article);
+ $this->assertTrue($invisible, 'read icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkUnreadBookmarkedArticle');
+ }
+
+ public function testBookmarkReadArticleLink()
+ {
+ $article = $this->getArticleReadNotBookmarked();
+
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForIconBookmarkVisible($article);
+ $this->assertTrue($visible, 'bookmark icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_BookmarkReadArticle');
+ }
+
+ public function testBookmarkReadArticleKeyboard()
+ {
+ $article = $this->getArticleReadNotBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleBookmarkStatus());
+
+ $visible = $this->waitForIconBookmarkVisible($article);
+ $this->assertTrue($visible, 'bookmark icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_BookmarkReadArticle');
+ }
+
+ public function testBookmarkUnreadArticleLink()
+ {
+ $article = $this->getArticleUnreadNotBookmarked();
+
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForIconBookmarkVisible($article);
+ $this->assertTrue($visible, 'bookmark icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_BookmarkUnreadArticle');
+ }
+
+ public function testBookmarkUnreadArticleKeyboard()
+ {
+ $article = $this->getArticleUnreadNotBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleBookmarkStatus());
+
+ $visible = $this->waitForIconBookmarkVisible($article);
+ $this->assertTrue($visible, 'bookmark icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_BookmarkUnreadArticle');
+ }
+
+ public function testUnbookmarkReadArticleLink()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $invisible = $this->waitForIconBookmarkInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkReadArticle');
+ }
+
+ public function testUnbookmarkReadArticleKeyboard()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleBookmarkStatus());
+
+ $invisible = $this->waitForIconBookmarkInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkReadArticle');
+ }
+
+ public function testUnbookmarkUnreadArticleLink()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $invisible = $this->waitForIconBookmarkInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkUnreadArticle');
+ }
+
+ public function testUnbookmarkUnreadArticleKeyboard()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleBookmarkStatus());
+
+ $invisible = $this->waitForIconBookmarkInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkUnreadArticle');
+ }
+
+ public function testRemoveReadNotBookmarkedArticleLink()
+ {
+ $article = $this->getArticleReadNotBookmarked();
+
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_RemoveReadNotBookmarkedArticle');
+ }
+
+ public function testRemoveReadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_RemoveReadBookmarkedArticle');
+ }
+
+ public function testRemoveUnreadNotBookmarkedArticleLink()
+ {
+ $article = $this->getArticleUnreadNotBookmarked();
+
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_RemoveUnreadNotBookmarkedArticle');
+ }
+
+ public function testRemoveUnreadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_RemoveUnreadBookmarkedArticle');
+ }
+
+ public function testMarkFeedReadHeaderLink()
+ {
+ $link = $this->getLinkFeedMarkReadHeader();
+ $link->click();
+
+ $read = $this->waitForArticlesMarkRead();
+ $this->assertTrue($read, 'there are still unread articles');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkFeedRead');
+ }
+
+ public function testMarkFeedReadBottomLink()
+ {
+ $link = $this->getLinkFeedMarkReadBottom();
+ $link->click();
+
+ $read = $this->waitForArticlesMarkRead();
+ $this->assertTrue($read, 'there are still unread articles');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkFeedRead');
+ }
+
+ public function testRedirectWithZeroArticles()
+ {
+ $articles = $this->getArticles();
+ $this->assertGreaterThanOrEqual(1, count($articles), 'no articles found');
+
+ foreach($articles as $article) {
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $this->waitForArticleInvisible($article);
+ }
+
+ $visible = $this->waitForAlert();
+ $this->assertTrue($visible, 'alert box did not appear');
+
+ $this->expectedDataSet = $this->getDataSet('expected_FirstFeedAllRemoved');
+
+ $this->ignorePageTitle = TRUE;
+ }
+}
+?>
\ No newline at end of file
diff --git a/tests/integration/pageHistoryTest.php b/tests/integration/pageHistoryTest.php
new file mode 100644
index 0000000..5268afc
--- /dev/null
+++ b/tests/integration/pageHistoryTest.php
@@ -0,0 +1,215 @@
+getURLPageHistory();
+ parent::setUpPage($url);
+
+ $this->basePageHeading = $this->getBasePageHeading();
+ $this->expectedPageUrl = $url;
+ }
+
+ public function getExpectedPageTitle()
+ {
+ return "$this->basePageHeading ($this->expectedCounterPage)";
+ }
+
+ public function testItemsFromAllFeeds()
+ {
+ $articles = $this->getArticlesNotFromFeedOne();
+ $this->assertNotEmpty($articles, 'no articles from other feeds found');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testOnlyReadArticles()
+ {
+ $articles = $this->getArticlesUnread();
+ $this->assertEmpty($articles, 'found unread articles.');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testMarkUnreadNotBookmarkedArticleLink()
+ {
+ $article = $this->getArticleReadNotBookmarked();
+
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($visible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkUnreadNotBookmarkedArticle');
+ }
+
+ public function testMarkUnreadNotBookmarkedArticleKeyboard()
+ {
+ $article = $this->getArticleReadNotBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleReadStatus());
+
+ $visible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($visible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkUnreadNotBookmarkedArticle');
+ }
+
+ public function testMarkUnreadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($visible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkUnreadBookmarkedArticle');
+ }
+
+ public function testMarkUnreadBookmarkedArticleKeyboard()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleReadStatus());
+
+ $visible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($visible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkUnreadBookmarkedArticle');
+ }
+
+ public function testBookmarkReadArticleLink()
+ {
+ $article = $this->getArticleReadNotBookmarked();
+
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForIconBookmarkVisible($article);
+ $this->assertTrue($visible, 'bookmark icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_BookmarkReadArticle');
+ }
+
+ public function testBookmarkReadArticleKeyboard()
+ {
+ $article = $this->getArticleReadNotBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleBookmarkStatus());
+
+ $visible = $this->waitForIconBookmarkVisible($article);
+ $this->assertTrue($visible, 'bookmark icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_BookmarkReadArticle');
+ }
+
+ public function testUnbookmarkReadArticleLink()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $invisible = $this->waitForIconBookmarkInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkReadArticle');
+ }
+
+ public function testUnbookmarkReadArticleKeyboard()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleBookmarkStatus());
+
+ $invisible = $this->waitForIconBookmarkInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkReadArticle');
+ }
+
+ public function testRemoveReadNotBookmarkedArticleLink()
+ {
+ $article = $this->getArticleReadNotBookmarked();
+
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_RemoveReadNotBookmarkedArticle');
+ }
+
+ public function testRemoveReadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleReadBookmarked();
+
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_RemoveReadBookmarkedArticle');
+ }
+
+ public function testFlushAllKeepsBookmarkedAndUnread()
+ {
+ $link = $this->getLinkFlushHistory();
+ $link->click();
+
+ $destructiveLink = $this->getLinkDestructive();
+ $destructiveLink->click();
+
+ $this->expectedCounterPage = 3;
+ $this->expectedDataSet = $this->getDataSet('expected_NoReadNotBookmarkedArticles', FALSE);
+
+ $this->ignorePageTitle = TRUE;
+ }
+
+ public function testRedirectWithZeroArticles()
+ {
+ $articles = $this->getArticles();
+ $this->assertGreaterThanOrEqual(1, count($articles), 'no articles found');
+
+ foreach($articles as $article) {
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $this->waitForArticleInvisible($article);
+ }
+
+ $visible = $this->waitForAlert();
+ $this->assertTrue($visible, 'alert box did not appear');
+
+ $this->expectedDataSet = $this->getDataSet('expected_NoReadArticles', FALSE);
+
+ $this->ignorePageTitle = TRUE;
+ }
+}
+?>
\ No newline at end of file
diff --git a/tests/integration/pageUnreadTest.php b/tests/integration/pageUnreadTest.php
new file mode 100644
index 0000000..3ef550c
--- /dev/null
+++ b/tests/integration/pageUnreadTest.php
@@ -0,0 +1,246 @@
+getURLPageUnread();
+ parent::setUpPage($url);
+
+ $this->expectedPageUrl = $url;
+ }
+
+ // TODO: Miniflux Title could be localized
+ public function getExpectedPageTitle()
+ {
+ return "Miniflux ($this->expectedCounterPage)";
+ }
+
+ public function testItemsFromAllFeeds()
+ {
+ $articles = $this->getArticlesNotFromFeedOne();
+ $this->assertNotEmpty($articles, 'no articles from other feeds found');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testOnlyUnreadArticles()
+ {
+ $articles = $this->getArticlesRead();
+ $this->assertEmpty($articles, 'found read articles.');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD;
+ $this->expectedDataSet = $this->getDataSet('fixture_feed1');
+ }
+
+ public function testMarkReadNotBookmarkedArticleLink()
+ {
+ $article = $this->getArticleUnreadNotBookmarked();
+
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($visible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkReadNotBookmarkedArticle');
+ }
+
+ public function testMarkReadNotBookmarkedArticleKeyboard()
+ {
+ $article = $this->getArticleUnreadNotBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleReadStatus());
+
+ $visible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($visible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkReadNotBookmarkedArticle');
+ }
+
+ public function testMarkReadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($visible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkReadBookmarkedArticle');
+ }
+
+ public function testMarkReadBookmarkedArticleKeyboard()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleReadStatus());
+
+ $visible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($visible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_MarkReadBookmarkedArticle');
+ }
+
+ public function testBookmarkUnreadArticleLink()
+ {
+ $article = $this->getArticleUnreadNotBookmarked();
+
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $visible = $this->waitForIconBookmarkVisible($article);
+ $this->assertTrue($visible, 'bookmark icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD;
+ $this->expectedDataSet = $this->getDataSet('expected_BookmarkUnreadArticle');
+ }
+
+ public function testBookmarkUnreadArticleKeyboard()
+ {
+ $article = $this->getArticleUnreadNotBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleBookmarkStatus());
+
+ $visible = $this->waitForIconBookmarkVisible($article);
+ $this->assertTrue($visible, 'bookmark icon is not visible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD;
+ $this->expectedDataSet = $this->getDataSet('expected_BookmarkUnreadArticle');
+ }
+
+ public function testUnbookmarkUnreadArticleLink()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $link = $this->getLinkBookmarkStatusToogle($article);
+ $link->click();
+
+ $invisible = $this->waitForIconBookmarkInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkUnreadArticle');
+ }
+
+ public function testUnbookmarkUnreadArticleKeyboard()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $this->setArticleAsCurrentArticle($article);
+ $this->keys($this->getShortcutToogleBookmarkStatus());
+
+ $invisible = $this->waitForIconBookmarkInvisible($article);
+ $this->assertTrue($invisible, 'bookmark icon is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD;
+ $this->expectedDataSet = $this->getDataSet('expected_UnbookmarkUnreadArticle');
+ }
+
+ public function testRemoveUnreadNotBookmarkedArticleLink()
+ {
+ $article = $this->getArticleUnreadNotBookmarked();
+
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_RemoveUnreadNotBookmarkedArticle');
+ }
+
+ public function testRemoveUnreadBookmarkedArticleLink()
+ {
+ $article = $this->getArticleUnreadBookmarked();
+
+ $link = $this->getLinkRemove($article);
+ $link->click();
+
+ $invisible = $this->waitForArticleInvisible($article);
+ $this->assertTrue($invisible, 'article is is not invisible');
+
+ $this->expectedCounterPage = static::DEFAULT_COUNTER_PAGE - 1;
+ $this->expectedCounterUnread = static::DEFAULT_COUNTER_UNREAD - 1;
+ $this->expectedDataSet = $this->getDataSet('expected_RemoveUnreadBookmarkedArticle');
+ }
+
+ public function testMarkAllReadHeaderLink()
+ {
+ $link = $this->getLinkMarkAllReadHeader();
+ $link->click();
+
+ $read = $this->waitForArticlesMarkRead();
+ $this->assertTrue($read, 'there are still unread articles');
+
+ $this->expectedCounterUnread = '';
+ $this->expectedPageUrl = PHPUNIT_TESTSUITE_EXTENSION_SELENIUM_BASEURL.'?action=feeds¬hing_to_read=1';
+ $this->expectedDataSet = $this->getDataSet('fixture_OnlyReadArticles', FALSE);
+
+ $this->ignorePageTitle = TRUE;
+ }
+
+ public function testMarkAllReadBottomLink()
+ {
+ $link = $this->getLinkMarkAllReadBottom();
+ $link->click();
+
+ $read = $this->waitForArticlesMarkRead();
+ $this->assertTrue($read, 'there are still unread articles');
+
+ $this->expectedCounterUnread = '';
+ $this->expectedPageUrl = PHPUNIT_TESTSUITE_EXTENSION_SELENIUM_BASEURL.'?action=feeds¬hing_to_read=1';
+ $this->expectedDataSet = $this->getDataSet('fixture_OnlyReadArticles', FALSE);
+
+ $this->ignorePageTitle = TRUE;
+ }
+
+ public function testRedirectWithZeroArticles()
+ {
+ $articles = $this->getArticles();
+ $this->assertGreaterThanOrEqual(1, count($articles), 'no articles found');
+
+ foreach($articles as $article) {
+ $link = $this->getLinkReadStatusToogle($article);
+ $link->click();
+
+ $this->waitForArticleInvisible($article);
+ }
+
+ $visible = $this->waitForAlert();
+ $this->assertTrue($visible, 'alert box did not appear');
+
+ $this->expectedCounterUnread = '';
+ $this->expectedPageUrl = PHPUNIT_TESTSUITE_EXTENSION_SELENIUM_BASEURL.'?action=feeds¬hing_to_read=1';
+ $this->expectedDataSet = $this->getDataSet('fixture_OnlyReadArticles', FALSE);
+
+ $this->ignorePageTitle = TRUE;
+ }
+}
+?>
\ No newline at end of file