Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/roundcube/roundcubemail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2019-12-29 14:00:15 +0300
committerAleksander Machniak <alec@alec.pl>2019-12-29 14:00:15 +0300
commit0b9ff6426ee6ad27aff038a582aefd4b023bdbca (patch)
tree09f99352a6f2c0bcf302c848d7ab3117f2d26f1e /tests
parent47d9ed6d0c6bd8cb3ba551555ba8995a244cfcd0 (diff)
Rewrite Selenium tests with use of laravel/dusk
Diffstat (limited to 'tests')
-rw-r--r--tests/Browser/Addressbook/Addressbook.php24
-rw-r--r--tests/Browser/Addressbook/Import.php34
-rw-r--r--tests/Browser/DuskTestCase.php190
-rw-r--r--tests/Browser/Login.php36
-rw-r--r--tests/Browser/Logout.php25
-rw-r--r--tests/Browser/Mail/CheckRecent.php15
-rw-r--r--tests/Browser/Mail/Compose.php28
-rw-r--r--tests/Browser/Mail/Getunread.php37
-rw-r--r--tests/Browser/Mail/List.php35
-rw-r--r--tests/Browser/Mail/Mail.php26
-rw-r--r--tests/Browser/README.md60
-rw-r--r--tests/Browser/Settings/About.php19
-rw-r--r--tests/Browser/Settings/Folders.php23
-rw-r--r--tests/Browser/Settings/Identities.php22
-rw-r--r--tests/Browser/Settings/Settings.php20
-rw-r--r--tests/Browser/bootstrap.php174
-rw-r--r--tests/Browser/data/mail/list_00.eml (renamed from tests/Selenium/data/mail/list_00.eml)0
-rw-r--r--tests/Browser/data/mysql.sql (renamed from tests/Selenium/data/mysql.sql)0
-rw-r--r--tests/Browser/install.php67
-rw-r--r--tests/Browser/phpunit.xml (renamed from tests/Selenium/phpunit.xml)22
-rw-r--r--tests/Selenium/Addressbook/Addressbook.php21
-rw-r--r--tests/Selenium/Addressbook/Import.php29
-rw-r--r--tests/Selenium/Login.php28
-rw-r--r--tests/Selenium/Logout.php20
-rw-r--r--tests/Selenium/Mail/CheckRecent.php14
-rw-r--r--tests/Selenium/Mail/Compose.php25
-rw-r--r--tests/Selenium/Mail/Getunread.php37
-rw-r--r--tests/Selenium/Mail/List.php50
-rw-r--r--tests/Selenium/Mail/Mail.php23
-rw-r--r--tests/Selenium/README.md49
-rw-r--r--tests/Selenium/Settings/About.php15
-rw-r--r--tests/Selenium/Settings/Folders.php20
-rw-r--r--tests/Selenium/Settings/Identities.php19
-rw-r--r--tests/Selenium/Settings/Settings.php17
-rw-r--r--tests/Selenium/bootstrap.php348
-rw-r--r--tests/Selenium/index.html8
36 files changed, 845 insertions, 735 deletions
diff --git a/tests/Browser/Addressbook/Addressbook.php b/tests/Browser/Addressbook/Addressbook.php
new file mode 100644
index 000000000..a73a542c0
--- /dev/null
+++ b/tests/Browser/Addressbook/Addressbook.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Tests\Browser\Addressbook;
+
+class Addressbook extends \Tests\Browser\DuskTestCase
+{
+ public function testAddressbook()
+ {
+ $this->browse(function ($browser) {
+ $this->go('addressbook');
+
+ // check task
+ $this->assertEnvEquals('task', 'addressbook');
+
+ $objects = $this->getObjects();
+
+ // these objects should be there always
+ $this->assertContains('qsearchbox', $objects);
+ $this->assertContains('folderlist', $objects);
+ $this->assertContains('contactslist', $objects);
+ $this->assertContains('countdisplay', $objects);
+ });
+ }
+}
diff --git a/tests/Browser/Addressbook/Import.php b/tests/Browser/Addressbook/Import.php
new file mode 100644
index 000000000..4b136ccbf
--- /dev/null
+++ b/tests/Browser/Addressbook/Import.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Tests\Browser\Addressbook;
+
+class Import extends \Tests\Browser\DuskTestCase
+{
+ public function testImport()
+ {
+ $this->browse(function ($browser) {
+ $this->go('addressbook', 'import');
+
+ // check task and action
+ $this->assertEnvEquals('task', 'addressbook');
+ $this->assertEnvEquals('action', 'import');
+
+ $objects = $this->getObjects();
+
+ // these objects should be there always
+ $this->assertContains('importform', $objects);
+ });
+ }
+
+ public function testImport2()
+ {
+ $this->browse(function ($browser) {
+ $this->go('addressbook', 'import');
+
+ $objects = $this->getObjects();
+
+ // these objects should be there always
+ $this->assertContains('importform', $objects);
+ });
+ }
+}
diff --git a/tests/Browser/DuskTestCase.php b/tests/Browser/DuskTestCase.php
new file mode 100644
index 000000000..0381a0b9c
--- /dev/null
+++ b/tests/Browser/DuskTestCase.php
@@ -0,0 +1,190 @@
+<?php
+
+namespace Tests\Browser;
+
+use PHPUnit\Framework\TestCase;
+use Facebook\WebDriver\Chrome\ChromeOptions;
+use Facebook\WebDriver\Remote\RemoteWebDriver;
+use Facebook\WebDriver\Remote\DesiredCapabilities;
+use Laravel\Dusk\Browser;
+use Laravel\Dusk\Chrome\SupportsChrome;
+use Laravel\Dusk\Concerns\ProvidesBrowser;
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Process\Process;
+
+abstract class DuskTestCase extends TestCase
+{
+ use ProvidesBrowser,
+ SupportsChrome;
+
+ protected $app;
+ protected static $phpProcess;
+
+
+ /**
+ * Prepare for Dusk test execution.
+ *
+ * @beforeClass
+ * @return void
+ */
+ public static function prepare()
+ {
+ static::startWebServer();
+ static::startChromeDriver();
+ }
+
+ /**
+ * Create the RemoteWebDriver instance.
+ *
+ * @return \Facebook\WebDriver\Remote\RemoteWebDriver
+ */
+ protected function driver()
+ {
+ $options = (new ChromeOptions())->addArguments([
+ '--disable-gpu',
+ '--headless',
+ '--window-size=1280,720',
+ ]);
+
+ return RemoteWebDriver::create(
+ 'http://localhost:9515',
+ DesiredCapabilities::chrome()->setCapability(
+ ChromeOptions::CAPABILITY,
+ $options
+ )
+ );
+ }
+
+ /**
+ * Set up the test run
+ *
+ * @return void
+ */
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->app = \rcmail::get_instance();
+
+ Browser::$baseUrl = 'http://localhost:8000';
+ Browser::$storeScreenshotsAt = __DIR__ . '/screenshots';
+ Browser::$storeConsoleLogAt = __DIR__ . '/console';
+
+ // Purge screenshots from the last test run
+ $pattern = sprintf('failure-%s_%s-*',
+ str_replace("\\", '_', get_class($this)),
+ $this->getName(false)
+ );
+
+ try {
+ $files = Finder::create()->files()->in(__DIR__ . '/screenshots')->name($pattern);
+ foreach ($files as $file) {
+ @unlink($file->getRealPath());
+ }
+ }
+ catch (\Symfony\Component\Finder\Exception\DirectoryNotFoundException $e) {
+ // ignore missing screenshots directory
+ }
+ }
+
+ /**
+ * Assert specified rcmail.env value
+ */
+ protected function assertEnvEquals($key, $expected)
+ {
+ $this->assertEquals($expected, $this->getEnv($key));
+ }
+
+ /**
+ * Get content of rcmail.env entry
+ */
+ protected function getEnv($key)
+ {
+ $this->browse(function (Browser $browser) use ($key, &$result) {
+ $result = $browser->script("return rcmail.env['$key']");
+ $result = $result[0];
+ });
+
+ return $result;
+ }
+
+ /**
+ * Get HTML IDs of defined buttons for specified Roundcube action
+ */
+ protected function getButtons($action)
+ {
+ $this->browse(function (Browser $browser) use ($action, &$buttons) {
+ $buttons = $browser->script("return rcmail.buttons['$action']");
+ $buttons = $buttons[0];
+ });
+
+ if (is_array($buttons)) {
+ foreach ($buttons as $idx => $button) {
+ $buttons[$idx] = $button['id'];
+ }
+ }
+
+ return (array) $buttons;
+ }
+
+ /**
+ * Return names of defined gui_objects
+ */
+ protected function getObjects()
+ {
+ $this->browse(function (Browser $browser) use (&$objects) {
+ $objects = $browser->script("var i, r = []; for (i in rcmail.gui_objects) r.push(i); return r");
+ $objects = $objects[0];
+ });
+
+ return (array) $objects;
+ }
+
+ /**
+ * Log in the test user
+ */
+ protected function doLogin()
+ {
+ $this->browse(function (Browser $browser) {
+ $browser->type('_user', TESTS_USER);
+ $browser->type('_pass', TESTS_PASS);
+ $browser->click('button[type="submit"]');
+
+ // wait after successful login
+ //$browser->waitForReload();
+ $browser->waitUntil('!rcmail.busy');
+ });
+ }
+
+ /**
+ * Visit specified task/action with logon if needed
+ */
+ protected function go($task = 'mail', $action = null, $login = true)
+ {
+ $this->browse(function (Browser $browser) use ($task, $action, $login) {
+ $browser->visit("/?_task=$task&_action=$action");
+
+ // check if we have a valid session
+ if ($login && $this->getEnv('task') == 'login') {
+ $this->doLogin();
+ }
+ });
+ }
+
+ /**
+ * Starts PHP server.
+ */
+ protected static function startWebServer()
+ {
+ $path = realpath(__DIR__ . '/../../public_html');
+ $cmd = ['php', '-S', 'localhost:8000'];
+
+ static::$phpProcess = new Process($cmd, null, []);
+ static::$phpProcess->setWorkingDirectory($path);
+ static::$phpProcess->start();
+
+ static::afterClass(function () {
+ static::$phpProcess->stop();
+ });
+ }
+}
diff --git a/tests/Browser/Login.php b/tests/Browser/Login.php
new file mode 100644
index 000000000..dcc20ad3c
--- /dev/null
+++ b/tests/Browser/Login.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Tests\Browser;
+
+class Login extends DuskTestCase
+{
+ protected function setUp()
+ {
+ parent::setUp();
+
+ \bootstrap::init_db();
+ \bootstrap::init_imap();
+ }
+
+ public function testLogin()
+ {
+ // first test, we're already on the login page
+ $this->browse(function ($browser) {
+ $browser->visit('/');
+
+ $browser->assertTitleContains($this->app->config->get('product_name'));
+
+ // task should be set to 'login'
+ $this->assertEnvEquals('task', 'login');
+
+ $browser->assertVisible('#rcmloginuser');
+ $browser->assertVisible('#rcmloginpwd');
+
+ // test valid login
+ $this->go('mail');
+
+ // task should be set to 'mail' now
+ $this->assertEnvEquals('task', 'mail');
+ });
+ }
+}
diff --git a/tests/Browser/Logout.php b/tests/Browser/Logout.php
new file mode 100644
index 000000000..4e563e264
--- /dev/null
+++ b/tests/Browser/Logout.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Tests\Browser;
+
+class Logout extends DuskTestCase
+{
+ public function testLogout()
+ {
+ $this->browse(function ($browser) {
+ $this->go('settings');
+
+ // wait for the menu and then click the Logout button
+ $browser->waitFor('#taskmenu');
+ $browser->click('#taskmenu a.logout');
+
+ // task should be set to 'login'
+ $this->assertEnvEquals('task', 'login');
+
+ // form should exist
+ $browser->assertVisible('input[name="_user"]');
+ $browser->assertVisible('input[name="_pass"]');
+ $browser->assertMissing('#taskmenu');
+ });
+ }
+}
diff --git a/tests/Browser/Mail/CheckRecent.php b/tests/Browser/Mail/CheckRecent.php
new file mode 100644
index 000000000..4af02034e
--- /dev/null
+++ b/tests/Browser/Mail/CheckRecent.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Tests\Browser\Mail;
+
+class CheckRecent extends \Tests\Browser\DuskTestCase
+{
+ public function testCheckRecent()
+ {
+ $this->browse(function ($browser) {
+ $this->go('mail');
+
+ // TODO
+ });
+ }
+}
diff --git a/tests/Browser/Mail/Compose.php b/tests/Browser/Mail/Compose.php
new file mode 100644
index 000000000..5d9d988e7
--- /dev/null
+++ b/tests/Browser/Mail/Compose.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Tests\Browser\Mail;
+
+class Compose extends \Tests\Browser\DuskTestCase
+{
+ public function testCompose()
+ {
+ $this->browse(function ($browser) {
+ $this->go('mail', 'compose');
+
+ // check task and action
+ $this->assertEnvEquals('task', 'mail');
+ $this->assertEnvEquals('action', 'compose');
+
+ $objects = $this->getObjects();
+
+ // these objects should be there always
+ $this->assertContains('qsearchbox', $objects);
+ $this->assertContains('addressbookslist', $objects);
+ $this->assertContains('contactslist', $objects);
+ $this->assertContains('messageform', $objects);
+ $this->assertContains('attachmentlist', $objects);
+ $this->assertContains('filedrop', $objects);
+ $this->assertContains('uploadform', $objects);
+ });
+ }
+}
diff --git a/tests/Browser/Mail/Getunread.php b/tests/Browser/Mail/Getunread.php
new file mode 100644
index 000000000..e6300680c
--- /dev/null
+++ b/tests/Browser/Mail/Getunread.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Tests\Browser\Mail;
+
+class Getunread extends \Tests\Browser\DuskTestCase
+{
+ protected $msgcount = 0;
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ \bootstrap::init_imap();
+ \bootstrap::purge_mailbox('INBOX');
+
+ // import email messages
+ foreach (glob(TESTS_DIR . 'data/mail/list_*.eml') as $f) {
+ \bootstrap::import_message($f, 'INBOX');
+ $this->msgcount++;
+ }
+ }
+
+ public function testGetunread()
+ {
+ $this->browse(function ($browser) {
+ $this->go('mail');
+
+ // Folders list state
+ $browser->waitFor('.folderlist li.inbox.unread');
+
+ $this->assertEquals(strval($this->msgcount), $browser->text('.folderlist li.inbox span.unreadcount'));
+
+ // Messages list state
+ $this->assertCount($this->msgcount, $browser->elements('#messagelist tr.unread'));
+ });
+ }
+}
diff --git a/tests/Browser/Mail/List.php b/tests/Browser/Mail/List.php
new file mode 100644
index 000000000..134f0bc3f
--- /dev/null
+++ b/tests/Browser/Mail/List.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Tests\Browser\Mail;
+
+class MailList extends \Tests\Browser\DuskTestCase
+{
+ protected function setUp()
+ {
+ parent::setUp();
+
+ \bootstrap::init_imap();
+ \bootstrap::purge_mailbox('INBOX');
+
+ // import email messages
+ foreach (glob(TESTS_DIR . 'data/mail/list_00.eml') as $f) {
+ \bootstrap::import_message($f, 'INBOX');
+ }
+ }
+
+ public function testList()
+ {
+ $this->browse(function ($browser) {
+ $this->go('mail');
+
+ $this->assertCount(1, $browser->elements('#messagelist tbody tr'));
+
+ // check message list
+ $browser->assertVisible('#messagelist tbody tr:first-child.unread');
+
+ $this->assertEquals('Lines', $browser->text('#messagelist tbody tr:first-child span.subject'));
+
+ //$browser->assertVisible('#messagelist tbody tr:first-child span.msgicon.unread');
+ });
+ }
+}
diff --git a/tests/Browser/Mail/Mail.php b/tests/Browser/Mail/Mail.php
new file mode 100644
index 000000000..1e767c2b8
--- /dev/null
+++ b/tests/Browser/Mail/Mail.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Tests\Browser\Mail;
+
+class Mail extends \Tests\Browser\DuskTestCase
+{
+ public function testMail()
+ {
+ $this->browse(function ($browser) {
+ $this->go('mail');
+
+ // check task
+ $this->assertEnvEquals('task', 'mail');
+
+ $objects = $this->getObjects();
+
+ // these objects should be there always
+ $this->assertContains('qsearchbox', $objects);
+ $this->assertContains('mailboxlist', $objects);
+ $this->assertContains('messagelist', $objects);
+ $this->assertContains('quotadisplay', $objects);
+ $this->assertContains('search_filter', $objects);
+ $this->assertContains('countdisplay', $objects);
+ });
+ }
+}
diff --git a/tests/Browser/README.md b/tests/Browser/README.md
new file mode 100644
index 000000000..56f5d10ca
--- /dev/null
+++ b/tests/Browser/README.md
@@ -0,0 +1,60 @@
+In-Browser Tests
+================
+
+The idea of these testing suite is to make it as simple as possible to execute
+the tests. So, you don't have to run any additional services, nor download
+and install anything manually.
+
+The tests are using [Laravel Dusk][laravel-dusk] and Chrome WebDriver.
+PHP server is used to serve Roundcube instance on tests run.
+
+
+INSTALLATION
+------------
+
+Installation:
+
+1. Add `"laravel/dusk": "~5.7.0"` to your composer.json file and run `composer update`.
+2. Install Chrome WebDriver for the version of Chrome/Chromium in your system. Yes,
+ you have to have Chrome/Chromium installed.
+```
+php tests/Browser/install.php [version]`
+```
+3. Configure the test account and Roundcube instance.
+
+Create a config file named `config-test.inc.php` in the Roundcube config dir.
+That file should provide specific `db_dsnw` and
+`default_host` values for testing purposes as well as the credentials of a
+valid IMAP user account used for running the tests with.
+
+Add these config options used by the Browser tests:
+
+```php
+ // Unit tests settings
+ $config['tests_username'] = 'roundcube.test@example.org';
+ $config['tests_password'] = '<test-account-password>';
+```
+
+WARNING
+-------
+Please note that the configured IMAP account as well as the Roundcube database
+configred in `db_dsnw` will be wiped and filled with test data in every test
+run. Under no circumstances you should use credentials of a production database
+or email account!
+
+Please, keep the file as simple as possible, i.e. containing only database
+and imap/smtp settings needed for the test user authentication. We would
+want to test default configuration. Especially only Elastic skin is supported.
+
+
+EXECUTING THE TESTS
+-------------------
+
+To run the test suite call `phpunit` from the tests/Browser directory:
+
+```
+ cd <roundcube-dir>/tests/Browser
+ phpunit # or ../../vendor/bin/phpunit
+```
+
+[laravel-dusk]: https://github.com/laravel/dusk
diff --git a/tests/Browser/Settings/About.php b/tests/Browser/Settings/About.php
new file mode 100644
index 000000000..f687a9d1e
--- /dev/null
+++ b/tests/Browser/Settings/About.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Tests\Browser\Settings;
+
+class About extends \Tests\Browser\DuskTestCase
+{
+ public function testAbout()
+ {
+ $this->browse(function ($browser) {
+ $this->go('settings', 'about');
+
+ // check task and action
+ $this->assertEnvEquals('task', 'settings');
+ $this->assertEnvEquals('action', 'about');
+
+ $browser->assertVisible('#pluginlist');
+ });
+ }
+}
diff --git a/tests/Browser/Settings/Folders.php b/tests/Browser/Settings/Folders.php
new file mode 100644
index 000000000..82c0b7d2e
--- /dev/null
+++ b/tests/Browser/Settings/Folders.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Tests\Browser\Settings;
+
+class Folders extends \Tests\Browser\DuskTestCase
+{
+ public function testFolders()
+ {
+ $this->browse(function ($browser) {
+ $this->go('settings', 'folders');
+
+ // task should be set to 'settings' and action to 'folders'
+ $this->assertEnvEquals('task', 'settings');
+ $this->assertEnvEquals('action', 'folders');
+
+ $objects = $this->getObjects();
+
+ // these objects should be there always
+ $this->assertContains('quotadisplay', $objects);
+ $this->assertContains('subscriptionlist', $objects);
+ });
+ }
+}
diff --git a/tests/Browser/Settings/Identities.php b/tests/Browser/Settings/Identities.php
new file mode 100644
index 000000000..d885f9edb
--- /dev/null
+++ b/tests/Browser/Settings/Identities.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Tests\Browser\Settings;
+
+class Identities extends \Tests\Browser\DuskTestCase
+{
+ public function testIdentities()
+ {
+ $this->browse(function ($browser) {
+ $this->go('settings', 'identities');
+
+ // check task and action
+ $this->assertEnvEquals('task', 'settings');
+ $this->assertEnvEquals('action', 'identities');
+
+ $objects = $this->getObjects();
+
+ // these objects should be there always
+ $this->assertContains('identitieslist', $objects);
+ });
+ }
+}
diff --git a/tests/Browser/Settings/Settings.php b/tests/Browser/Settings/Settings.php
new file mode 100644
index 000000000..cfef01ceb
--- /dev/null
+++ b/tests/Browser/Settings/Settings.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Tests\Browser\Settings;
+
+class Settings extends \Tests\Browser\DuskTestCase
+{
+ public function testSettings()
+ {
+ $this->browse(function ($browser) {
+ $this->go('settings');
+
+ // task should be set to 'settings'
+ $this->assertEnvEquals('task', 'settings');
+
+ $objects = $this->getObjects();
+
+ $this->assertContains('sectionslist', $objects);
+ });
+ }
+}
diff --git a/tests/Browser/bootstrap.php b/tests/Browser/bootstrap.php
new file mode 100644
index 000000000..f8803c420
--- /dev/null
+++ b/tests/Browser/bootstrap.php
@@ -0,0 +1,174 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | This file is part of the Roundcube Webmail client |
+ | |
+ | Copyright (C) The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Environment initialization script for functional tests |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ | Author: Aleksander Machniak <alec@alec.pl> |
+ +-----------------------------------------------------------------------+
+*/
+
+if (php_sapi_name() != 'cli')
+ die("Not in shell mode (php-cli)");
+
+if (!defined('INSTALL_PATH')) define('INSTALL_PATH', realpath(__DIR__ . '/../../') . '/' );
+
+require_once(INSTALL_PATH . 'program/include/iniset.php');
+
+$rcmail = rcmail::get_instance(0, 'test');
+
+define('TESTS_DIR', realpath(__DIR__) . '/');
+define('TESTS_USER', $rcmail->config->get('tests_username'));
+define('TESTS_PASS', $rcmail->config->get('tests_password'));
+
+require_once(__DIR__ . '/DuskTestCase.php');
+
+
+/**
+ * Utilities for test environment setup
+ */
+class bootstrap
+{
+ static $imap_ready = null;
+
+ /**
+ * Wipe and re-initialize database
+ */
+ public static function init_db()
+ {
+ $rcmail = rcmail::get_instance();
+ $dsn = rcube_db::parse_dsn($rcmail->config->get('db_dsnw'));
+
+ if ($dsn['phptype'] == 'mysql' || $dsn['phptype'] == 'mysqli') {
+ // drop all existing tables first
+ $db = $rcmail->get_dbh();
+ $db->query("SET FOREIGN_KEY_CHECKS=0");
+ $sql_res = $db->query("SHOW TABLES");
+ while ($sql_arr = $db->fetch_array($sql_res)) {
+ $table = reset($sql_arr);
+ $db->query("DROP TABLE $table");
+ }
+
+ // init database with schema
+ system(sprintf('cat %s %s | mysql -h %s -u %s --password=%s %s',
+ realpath(INSTALL_PATH . '/SQL/mysql.initial.sql'),
+ realpath(TESTS_DIR . 'data/mysql.sql'),
+ escapeshellarg($dsn['hostspec']),
+ escapeshellarg($dsn['username']),
+ escapeshellarg($dsn['password']),
+ escapeshellarg($dsn['database'])
+ ));
+ }
+ else if ($dsn['phptype'] == 'sqlite') {
+ // delete database file -- will be re-initialized on first access
+ system(sprintf('rm -f %s', escapeshellarg($dsn['database'])));
+ }
+ }
+
+ /**
+ * Wipe the configured IMAP account and fill with test data
+ */
+ public static function init_imap()
+ {
+ if (!TESTS_USER) {
+ return false;
+ }
+ else if (self::$imap_ready !== null) {
+ return self::$imap_ready;
+ }
+
+ self::connect_imap(TESTS_USER, TESTS_PASS);
+ self::purge_mailbox('INBOX');
+ self::ensure_mailbox('Archive', true);
+
+ return self::$imap_ready;
+ }
+
+ /**
+ * Authenticate to IMAP with the given credentials
+ */
+ public static function connect_imap($username, $password, $host = null)
+ {
+ $rcmail = rcmail::get_instance();
+ $imap = $rcmail->get_storage();
+
+ if ($imap->is_connected()) {
+ $imap->close();
+ self::$imap_ready = false;
+ }
+
+ $imap_host = $host ?: $rcmail->config->get('default_host');
+ $a_host = parse_url($imap_host);
+ if ($a_host['host']) {
+ $imap_host = $a_host['host'];
+ $imap_ssl = isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'));
+ $imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143);
+ }
+ else {
+ $imap_port = 143;
+ $imap_ssl = false;
+ }
+
+ if (!$imap->connect($imap_host, $username, $password, $imap_port, $imap_ssl)) {
+ die("IMAP error: unable to authenticate with user " . TESTS_USER);
+ }
+
+ self::$imap_ready = true;
+ }
+
+ /**
+ * Import the given file into IMAP
+ */
+ public static function import_message($filename, $mailbox = 'INBOX')
+ {
+ if (!self::init_imap()) {
+ die(__METHOD__ . ': IMAP connection unavailable');
+ }
+
+ $imap = rcmail::get_instance()->get_storage();
+ $imap->save_message($mailbox, file_get_contents($filename));
+ }
+
+ /**
+ * Delete all messages from the given mailbox
+ */
+ public static function purge_mailbox($mailbox)
+ {
+ if (!self::init_imap()) {
+ die(__METHOD__ . ': IMAP connection unavailable');
+ }
+
+ $imap = rcmail::get_instance()->get_storage();
+ $imap->delete_message('*', $mailbox);
+ }
+
+ /**
+ * Make sure the given mailbox exists in IMAP
+ */
+ public static function ensure_mailbox($mailbox, $empty = false)
+ {
+ if (!self::init_imap()) {
+ die(__METHOD__ . ': IMAP connection unavailable');
+ }
+
+ $imap = rcmail::get_instance()->get_storage();
+
+ $folders = $imap->list_folders();
+ if (!in_array($mailbox, $folders)) {
+ $imap->create_folder($mailbox, true);
+ }
+ else if ($empty) {
+ $imap->delete_message('*', $mailbox);
+ }
+ }
+}
diff --git a/tests/Selenium/data/mail/list_00.eml b/tests/Browser/data/mail/list_00.eml
index e5977d4fc..e5977d4fc 100644
--- a/tests/Selenium/data/mail/list_00.eml
+++ b/tests/Browser/data/mail/list_00.eml
diff --git a/tests/Selenium/data/mysql.sql b/tests/Browser/data/mysql.sql
index fe6741a02..fe6741a02 100644
--- a/tests/Selenium/data/mysql.sql
+++ b/tests/Browser/data/mysql.sql
diff --git a/tests/Browser/install.php b/tests/Browser/install.php
new file mode 100644
index 000000000..4fba9022d
--- /dev/null
+++ b/tests/Browser/install.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | This file is part of the Roundcube Webmail client |
+ | |
+ | Copyright (C) The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Chrome WebDriver download tool |
+ +-----------------------------------------------------------------------+
+ | Author: Aleksander Machniak <alec@alec.pl> |
+ +-----------------------------------------------------------------------+
+*/
+
+if (php_sapi_name() != 'cli')
+ die("Not in shell mode (php-cli)");
+
+if (!defined('INSTALL_PATH')) define('INSTALL_PATH', realpath(__DIR__ . '/../../') . '/' );
+
+require_once(INSTALL_PATH . 'program/include/iniset.php');
+
+class Installer extends Laravel\Dusk\Console\ChromeDriverCommand
+{
+ /**
+ * Execute the console command.
+ *
+ * @param string $version
+ *
+ * @return void
+ */
+ public function install($version = null)
+ {
+ $version = trim($this->getUrl(sprintf($this->versionUrl, $version ?: $this->latestVersion())));
+ $currentOS = Laravel\Dusk\OperatingSystem::id();
+
+ foreach ($this->slugs as $os => $slug) {
+ if ($os === $currentOS) {
+ $archive = $this->download($version, $slug);
+ $binary = $this->extract($archive);
+
+ $this->rename($binary, $os);
+ }
+ }
+
+ echo "ChromeDriver binary successfully installed for version $version.\n";
+ }
+
+ /**
+ * Get the contents of a URL
+ *
+ * @param string $url URL
+ *
+ * @return string|bool
+ */
+ protected function getUrl(string $url)
+ {
+ return file_get_contents($url);
+ }
+}
+
+$installer = new Installer;
+$installer->install($argv[1]);
diff --git a/tests/Selenium/phpunit.xml b/tests/Browser/phpunit.xml
index fe0c7016c..eb6ea316c 100644
--- a/tests/Selenium/phpunit.xml
+++ b/tests/Browser/phpunit.xml
@@ -2,28 +2,26 @@
bootstrap="bootstrap.php"
colors="true">
<testsuites>
- <testsuite name="Mail">
- <file>Login.php</file><!-- Login.php test must be first -->
- <file>Mail/Mail.php</file>
- <file>Mail/CheckRecent.php</file>
- <file>Mail/Compose.php</file>
- <file>Mail/Getunread.php</file>
- <file>Mail/List.php</file>
- <file>Logout.php</file><!-- Logout.php test must be last -->
+ <testsuite name="Logon">
+ <file>Login.php</file>
+ <file>Logout.php</file>
</testsuite>
<testsuite name="Addressbook">
- <file>Login.php</file>
<file>Addressbook/Addressbook.php</file>
<file>Addressbook/Import.php</file>
- <file>Logout.php</file>
</testsuite>
<testsuite name="Settings">
- <file>Login.php</file>
<file>Settings/About.php</file>
<file>Settings/Folders.php</file>
<file>Settings/Identities.php</file>
<file>Settings/Settings.php</file>
- <file>Logout.php</file>
+ </testsuite>
+ <testsuite name="Mail">
+ <file>Mail/Mail.php</file>
+ <file>Mail/CheckRecent.php</file>
+ <file>Mail/Compose.php</file>
+ <file>Mail/Getunread.php</file>
+ <file>Mail/List.php</file>
</testsuite>
</testsuites>
</phpunit>
diff --git a/tests/Selenium/Addressbook/Addressbook.php b/tests/Selenium/Addressbook/Addressbook.php
deleted file mode 100644
index 9a22b6e13..000000000
--- a/tests/Selenium/Addressbook/Addressbook.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-class Selenium_Addressbook_Addressbook extends Selenium_Test
-{
- public function testAddressbook()
- {
- $this->go('addressbook');
-
- // check task
- $env = $this->get_env();
- $this->assertEquals('addressbook', $env['task']);
-
- $objects = $this->get_objects();
-
- // these objects should be there always
- $this->assertContains('qsearchbox', $objects);
- $this->assertContains('folderlist', $objects);
- $this->assertContains('contactslist', $objects);
- $this->assertContains('countdisplay', $objects);
- }
-}
diff --git a/tests/Selenium/Addressbook/Import.php b/tests/Selenium/Addressbook/Import.php
deleted file mode 100644
index 13d81740f..000000000
--- a/tests/Selenium/Addressbook/Import.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-class Selenium_Addressbook_Import extends Selenium_Test
-{
- public function testImport()
- {
- $this->go('addressbook', 'import');
-
- // check task and action
- $env = $this->get_env();
- $this->assertEquals('addressbook', $env['task']);
- $this->assertEquals('import', $env['action']);
-
- $objects = $this->get_objects();
-
- // these objects should be there always
- $this->assertContains('importform', $objects);
- }
-
- public function testImport2()
- {
- $this->go('addressbook', 'import');
-
- $objects = $this->get_objects();
-
- // these objects should be there always
- $this->assertContains('importform', $objects);
- }
-}
diff --git a/tests/Selenium/Login.php b/tests/Selenium/Login.php
deleted file mode 100644
index 6910b43e6..000000000
--- a/tests/Selenium/Login.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-
-class Selenium_Login extends Selenium_Test
-{
- protected function setUp()
- {
- bootstrap::init_db();
- bootstrap::init_imap();
- parent::setUp();
- }
-
- public function testLogin()
- {
- // first test, we're already on the login page
- $this->url(TESTS_URL);
-
- // task should be set to 'login'
- $env = $this->get_env();
- $this->assertEquals('login', $env['task']);
-
- // test valid login
- $this->login();
-
- // task should be set to 'mail' now
- $env = $this->get_env();
- $this->assertEquals('mail', $env['task']);
- }
-}
diff --git a/tests/Selenium/Logout.php b/tests/Selenium/Logout.php
deleted file mode 100644
index 95eeda57c..000000000
--- a/tests/Selenium/Logout.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-class Selenium_Logout extends Selenium_Test
-{
- public function testLogout()
- {
- $this->go('mail');
-
- $this->click_button('logout');
-
- sleep(TESTS_SLEEP);
-
- // task should be set to 'login'
- $env = $this->get_env();
- $this->assertEquals('login', $env['task']);
-
- // form should exist
- $user_input = $this->byCssSelector('form input[name="_user"]');
- }
-}
diff --git a/tests/Selenium/Mail/CheckRecent.php b/tests/Selenium/Mail/CheckRecent.php
deleted file mode 100644
index 865421c2d..000000000
--- a/tests/Selenium/Mail/CheckRecent.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-class Selenium_Mail_CheckRecent extends Selenium_Test
-{
- public function testCheckRecent()
- {
- $this->go('mail');
-
- $res = $this->ajaxResponse('check-recent', "rcmail.command('checkmail')");
-
- $this->assertEquals('check-recent', $res['action']);
- $this->assertRegExp('/this\.set_unread_count/', $res['exec']);
- }
-}
diff --git a/tests/Selenium/Mail/Compose.php b/tests/Selenium/Mail/Compose.php
deleted file mode 100644
index e707ef17d..000000000
--- a/tests/Selenium/Mail/Compose.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-class Selenium_Mail_Compose extends Selenium_Test
-{
- public function testCompose()
- {
- $this->go('mail', 'compose');
-
- // check task and action
- $env = $this->get_env();
- $this->assertEquals('mail', $env['task']);
- $this->assertEquals('compose', $env['action']);
-
- $objects = $this->get_objects();
-
- // these objects should be there always
- $this->assertContains('qsearchbox', $objects);
- $this->assertContains('addressbookslist', $objects);
- $this->assertContains('contactslist', $objects);
- $this->assertContains('messageform', $objects);
- $this->assertContains('attachmentlist', $objects);
- $this->assertContains('filedrop', $objects);
- $this->assertContains('uploadform', $objects);
- }
-}
diff --git a/tests/Selenium/Mail/Getunread.php b/tests/Selenium/Mail/Getunread.php
deleted file mode 100644
index c18ddc0dd..000000000
--- a/tests/Selenium/Mail/Getunread.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-class Selenium_Mail_Getunread extends Selenium_Test
-{
- protected $msgcount = 0;
-
- protected function setUp()
- {
- parent::setUp();
-
- bootstrap::init_imap();
- bootstrap::purge_mailbox('INBOX');
-
- // import email messages
- foreach (glob(TESTS_DIR . 'Selenium/data/mail/list_*.eml') as $f) {
- bootstrap::import_message($f, 'INBOX');
- $this->msgcount++;
- }
- }
-
- public function testGetunread()
- {
- $this->go('mail');
-
- $res = $this->ajaxResponse('getunread', "rcmail.http_request('getunread')");
- $this->assertEquals('getunread', $res['action']);
-
- $env = $this->get_env();
- $this->assertEquals($env['unread_counts']['INBOX'], $this->msgcount);
-
- $li = $this->byCssSelector('.folderlist li.inbox');
- $this->assertHasClass('unread', $li);
-
- $badge = $this->byCssSelector('.folderlist li.inbox span.unreadcount');
- $this->assertEquals(strval($this->msgcount), $this->getText($badge));
- }
-}
diff --git a/tests/Selenium/Mail/List.php b/tests/Selenium/Mail/List.php
deleted file mode 100644
index dc2857777..000000000
--- a/tests/Selenium/Mail/List.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-class Selenium_Mail_List extends Selenium_Test
-{
- protected function setUp()
- {
- parent::setUp();
-
- bootstrap::init_imap();
- bootstrap::purge_mailbox('INBOX');
-
- // import email messages
- foreach (glob(TESTS_DIR . 'Selenium/data/mail/list_00.eml') as $f) {
- bootstrap::import_message($f, 'INBOX');
- }
- }
-
- public function testList()
- {
- $this->go('mail');
-
- $res = $this->ajaxResponse('list', "rcmail.command('list')");
-
- $this->assertEquals('list', $res['action']);
- $this->assertRegExp('/this\.set_pagetitle/', $res['exec']);
- $this->assertRegExp('/this\.set_unread_count/', $res['exec']);
- $this->assertRegExp('/this\.set_rowcount/', $res['exec']);
- $this->assertRegExp('/this\.set_message_coltypes/', $res['exec']);
-
- $this->assertContains('current_page', $res['env']);
- $this->assertContains('exists', $res['env']);
- $this->assertContains('pagecount', $res['env']);
- $this->assertContains('pagesize', $res['env']);
- $this->assertContains('messagecount', $res['env']);
- $this->assertContains('mailbox', $res['env']);
-
- $this->assertEquals($res['env']['mailbox'], 'INBOX');
- $this->assertEquals($res['env']['messagecount'], 1);
-
- // check message list
- $row = $this->byCssSelector('.messagelist tbody tr:first-child');
- $this->assertHasClass('unread', $row);
-
- $subject = $this->byCssSelector('.messagelist tbody tr:first-child td.subject');
- $this->assertEquals('Lines', $this->getText($subject));
-
- $icon = $this->byCssSelector('.messagelist tbody tr:first-child td.status span');
- $this->assertHasClass('unread', $icon);
- }
-}
diff --git a/tests/Selenium/Mail/Mail.php b/tests/Selenium/Mail/Mail.php
deleted file mode 100644
index 98413787b..000000000
--- a/tests/Selenium/Mail/Mail.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-
-class Selenium_Mail_Mail extends Selenium_Test
-{
- public function testMail()
- {
- $this->go('mail');
-
- // check task
- $env = $this->get_env();
- $this->assertEquals('mail', $env['task']);
-
- $objects = $this->get_objects();
-
- // these objects should be there always
- $this->assertContains('qsearchbox', $objects);
- $this->assertContains('mailboxlist', $objects);
- $this->assertContains('messagelist', $objects);
- $this->assertContains('quotadisplay', $objects);
- $this->assertContains('search_filter', $objects);
- $this->assertContains('countdisplay', $objects);
- }
-}
diff --git a/tests/Selenium/README.md b/tests/Selenium/README.md
deleted file mode 100644
index 5610fae71..000000000
--- a/tests/Selenium/README.md
+++ /dev/null
@@ -1,49 +0,0 @@
-Running Selenium Tests
-======================
-
-In order to run the Selenium-based web tests, some configuration for the
-Roundcube test instance need to be created. Along with the default config for a
-given Roundcube instance, you should provide a config specifically for running
-tests. To do so, create a config file named `config-test.inc.php` in the
-regular Roundcube config dir. That should provide specific `db_dsnw` and
-`default_host` values for testing purposes as well as the credentials of a
-valid IMAP user account used for running the tests with.
-
-Add these config options used by the Selenium tests:
-
-```php
- // Unit tests settings
- $config['tests_username'] = 'roundcube.test@example.org';
- $config['tests_password'] = '<test-account-password>';
- $config['tests_url'] = 'http://localhost/roundcube/index-test.php';
-```
-
-The `tests_url` should point to Roundcube's index-test.php file accessible by
-the Selenium web browser.
-
-WARNING
--------
-Please note that the configured IMAP account as well as the Roundcube database
-configred in `db_dsnw` will be wiped and filled with test data in every test
-run. Under no circumstances you should use credentials of a production database
-or email account!
-
-
-Run the tests
--------------
-
-First you need to start a Selenium server. We recommend to use the
-[Selenium Standalone Server][selenium-server] but the tests will also run on a
-Selenium Grid. The tests are based in [PHPUnit_Selenium][phpunit] which can be
-installed through [PEAR][pear-phpunit].
-
-To start the test suite call `phpunit` from the Selenium directory:
-
-```
- cd <roundcube-dir>/tests/Selenium
- phpunit
-```
-
-[phpunit]: http://phpunit.de/manual/4.0/en/selenium.html
-[pear-phpunit]: http://pear.phpunit.de/
-[selenium-server]: http://docs.seleniumhq.org/download/
diff --git a/tests/Selenium/Settings/About.php b/tests/Selenium/Settings/About.php
deleted file mode 100644
index 4cd49431a..000000000
--- a/tests/Selenium/Settings/About.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-class Selenium_Settings_About extends Selenium_Test
-{
- public function testAbout()
- {
- $this->url(TESTS_URL . '?_task=settings&_action=about');
- sleep(TESTS_SLEEP);
-
- // check task and action
- $env = $this->get_env();
- $this->assertEquals('settings', $env['task']);
- $this->assertEquals('about', $env['action']);
- }
-}
diff --git a/tests/Selenium/Settings/Folders.php b/tests/Selenium/Settings/Folders.php
deleted file mode 100644
index fa64e45d6..000000000
--- a/tests/Selenium/Settings/Folders.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-class Selenium_Settings_Folders extends Selenium_Test
-{
- public function testFolders()
- {
- $this->go('settings', 'folders');
-
- // task should be set to 'settings' and action to 'folders'
- $env = $this->get_env();
- $this->assertEquals('settings', $env['task']);
- $this->assertEquals('folders', $env['action']);
-
- $objects = $this->get_objects();
-
- // these objects should be there always
- $this->assertContains('quotadisplay', $objects);
- $this->assertContains('subscriptionlist', $objects);
- }
-}
diff --git a/tests/Selenium/Settings/Identities.php b/tests/Selenium/Settings/Identities.php
deleted file mode 100644
index 869018b09..000000000
--- a/tests/Selenium/Settings/Identities.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-class Selenium_Settings_Identities extends Selenium_Test
-{
- public function testIdentities()
- {
- $this->go('settings', 'identities');
-
- // check task and action
- $env = $this->get_env();
- $this->assertEquals('settings', $env['task']);
- $this->assertEquals('identities', $env['action']);
-
- $objects = $this->get_objects();
-
- // these objects should be there always
- $this->assertContains('identitieslist', $objects);
- }
-}
diff --git a/tests/Selenium/Settings/Settings.php b/tests/Selenium/Settings/Settings.php
deleted file mode 100644
index 08d8339f1..000000000
--- a/tests/Selenium/Settings/Settings.php
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-
-class Selenium_Settings_Settings extends Selenium_Test
-{
- public function testSettings()
- {
- $this->go('settings');
-
- // task should be set to 'settings'
- $env = $this->get_env();
- $this->assertEquals('settings', $env['task']);
-
- $objects = $this->get_objects();
-
- $this->assertContains('sectionslist', $objects);
- }
-}
diff --git a/tests/Selenium/bootstrap.php b/tests/Selenium/bootstrap.php
deleted file mode 100644
index 47e53757f..000000000
--- a/tests/Selenium/bootstrap.php
+++ /dev/null
@@ -1,348 +0,0 @@
-<?php
-
-/*
- +-----------------------------------------------------------------------+
- | This file is part of the Roundcube Webmail client |
- | |
- | Copyright (C) The Roundcube Dev Team |
- | |
- | Licensed under the GNU General Public License version 3 or |
- | any later version with exceptions for skins & plugins. |
- | See the README file for a full license statement. |
- | |
- | PURPOSE: |
- | Environment initialization script for unit tests |
- +-----------------------------------------------------------------------+
- | Author: Thomas Bruederli <roundcube@gmail.com> |
- | Author: Aleksander Machniak <alec@alec.pl> |
- +-----------------------------------------------------------------------+
-*/
-
-if (php_sapi_name() != 'cli')
- die("Not in shell mode (php-cli)");
-
-if (!defined('INSTALL_PATH')) define('INSTALL_PATH', realpath(__DIR__ . '/../../') . '/' );
-
-define('TESTS_DIR', realpath(__DIR__ . '/../') . '/');
-
-if (@is_dir(TESTS_DIR . 'config')) {
- define('RCUBE_CONFIG_DIR', TESTS_DIR . 'config');
-}
-
-require_once(INSTALL_PATH . 'program/include/iniset.php');
-
-// Extend include path so some plugin test won't fail
-$include_path = ini_get('include_path') . PATH_SEPARATOR . TESTS_DIR . '..';
-if (set_include_path($include_path) === false) {
- die("Fatal error: ini_set/set_include_path does not work.");
-}
-
-$rcmail = rcmail::get_instance(0, 'test');
-
-define('TESTS_URL', $rcmail->config->get('tests_url'));
-define('TESTS_BROWSER', $rcmail->config->get('tests_browser', 'firefox'));
-define('TESTS_USER', $rcmail->config->get('tests_username'));
-define('TESTS_PASS', $rcmail->config->get('tests_password'));
-define('TESTS_SLEEP', $rcmail->config->get('tests_sleep', 5));
-
-PHPUnit_Extensions_Selenium2TestCase::shareSession(true);
-
-
-/**
- * satisfy PHPUnit
- */
-class bootstrap
-{
- static $imap_ready = null;
-
- /**
- * Wipe and re-initialize (mysql) database
- */
- public static function init_db()
- {
- $rcmail = rcmail::get_instance();
- $dsn = rcube_db::parse_dsn($rcmail->config->get('db_dsnw'));
-
- if ($dsn['phptype'] == 'mysql' || $dsn['phptype'] == 'mysqli') {
- // drop all existing tables first
- $db = $rcmail->get_dbh();
- $db->query("SET FOREIGN_KEY_CHECKS=0");
- $sql_res = $db->query("SHOW TABLES");
- while ($sql_arr = $db->fetch_array($sql_res)) {
- $table = reset($sql_arr);
- $db->query("DROP TABLE $table");
- }
-
- // init database with schema
- system(sprintf('cat %s %s | mysql -h %s -u %s --password=%s %s',
- realpath(INSTALL_PATH . '/SQL/mysql.initial.sql'),
- realpath(TESTS_DIR . 'Selenium/data/mysql.sql'),
- escapeshellarg($dsn['hostspec']),
- escapeshellarg($dsn['username']),
- escapeshellarg($dsn['password']),
- escapeshellarg($dsn['database'])
- ));
- }
- else if ($dsn['phptype'] == 'sqlite') {
- // delete database file -- will be re-initialized on first access
- system(sprintf('rm -f %s', escapeshellarg($dsn['database'])));
- }
- }
-
- /**
- * Wipe the configured IMAP account and fill with test data
- */
- public static function init_imap()
- {
- if (!TESTS_USER) {
- return false;
- }
- else if (self::$imap_ready !== null) {
- return self::$imap_ready;
- }
-
- self::connect_imap(TESTS_USER, TESTS_PASS);
- self::purge_mailbox('INBOX');
- self::ensure_mailbox('Archive', true);
-
- return self::$imap_ready;
- }
-
- /**
- * Authenticate to IMAP with the given credentials
- */
- public static function connect_imap($username, $password, $host = null)
- {
- $rcmail = rcmail::get_instance();
- $imap = $rcmail->get_storage();
-
- if ($imap->is_connected()) {
- $imap->close();
- self::$imap_ready = false;
- }
-
- $imap_host = $host ?: $rcmail->config->get('default_host');
- $a_host = parse_url($imap_host);
- if ($a_host['host']) {
- $imap_host = $a_host['host'];
- $imap_ssl = isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'));
- $imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143);
- }
- else {
- $imap_port = 143;
- $imap_ssl = false;
- }
-
- if (!$imap->connect($imap_host, $username, $password, $imap_port, $imap_ssl)) {
- die("IMAP error: unable to authenticate with user " . TESTS_USER);
- }
-
- self::$imap_ready = true;
- }
-
- /**
- * Import the given file into IMAP
- */
- public static function import_message($filename, $mailbox = 'INBOX')
- {
- if (!self::init_imap()) {
- die(__METHOD__ . ': IMAP connection unavailable');
- }
-
- $imap = rcmail::get_instance()->get_storage();
- $imap->save_message($mailbox, file_get_contents($filename));
- }
-
- /**
- * Delete all messages from the given mailbox
- */
- public static function purge_mailbox($mailbox)
- {
- if (!self::init_imap()) {
- die(__METHOD__ . ': IMAP connection unavailable');
- }
-
- $imap = rcmail::get_instance()->get_storage();
- $imap->delete_message('*', $mailbox);
- }
-
- /**
- * Make sure the given mailbox exists in IMAP
- */
- public static function ensure_mailbox($mailbox, $empty = false)
- {
- if (!self::init_imap()) {
- die(__METHOD__ . ': IMAP connection unavailable');
- }
-
- $imap = rcmail::get_instance()->get_storage();
-
- $folders = $imap->list_folders();
- if (!in_array($mailbox, $folders)) {
- $imap->create_folder($mailbox, true);
- }
- else if ($empty) {
- $imap->delete_message('*', $mailbox);
- }
- }
-}
-
-// @TODO: make sure mailbox has some content (always the same) or is empty
-// @TODO: plugins: enable all?
-
-/**
- * Base class for all tests in this directory
- */
-class Selenium_Test extends PHPUnit_Extensions_Selenium2TestCase
-{
- protected $login_data = null;
-
- protected function setUp()
- {
- $this->setBrowser(TESTS_BROWSER);
- $this->login_data = array(TESTS_USER, TESTS_PASS);
-
- // Set root to our index.html, for better performance
- // See https://github.com/sebastianbergmann/phpunit-selenium/issues/217
- $baseurl = preg_replace('!/index(-.+)?\.php^!', '', TESTS_URL);
- $this->setBrowserUrl($baseurl . '/tests/Selenium');
- }
-
- protected function login($username = null, $password = null)
- {
- if (!empty($username)) {
- $this->login_data = array($username, $password);
- }
-
- $this->go('mail', null, true);
- }
-
- protected function do_login()
- {
- $user_input = $this->byCssSelector('form input[name="_user"]');
- $pass_input = $this->byCssSelector('form input[name="_pass"]');
- $submit = $this->byCssSelector('form input[type="submit"]');
-
- $user_input->value($this->login_data[0]);
- $pass_input->value($this->login_data[1]);
-
- // submit login form
- $submit->click();
-
- // wait after successful login
- sleep(TESTS_SLEEP);
- }
-
- protected function go($task = 'mail', $action = null, $login = true)
- {
- $this->url(TESTS_URL . '?_task=' . $task);
-
- // wait for interface load (initial ajax requests, etc.)
- sleep(TESTS_SLEEP);
-
- // check if we have a valid session
- $env = $this->get_env();
- if ($login && $env['task'] == 'login') {
- $this->do_login();
- }
-
- if ($action) {
- $this->click_button($action);
- sleep(TESTS_SLEEP);
- }
- }
-
- protected function get_env()
- {
- return $this->execute(array(
- 'script' => 'return window.rcmail ? rcmail.env : {};',
- 'args' => array(),
- ));
- }
-
- protected function get_buttons($action)
- {
- $buttons = $this->execute(array(
- 'script' => "return rcmail.buttons['$action'];",
- 'args' => array(),
- ));
-
- if (is_array($buttons)) {
- foreach ($buttons as $idx => $button) {
- $buttons[$idx] = $button['id'];
- }
- }
-
- return (array) $buttons;
- }
-
- protected function get_objects()
- {
- return $this->execute(array(
- 'script' => "var i,r = []; for (i in rcmail.gui_objects) r.push(i); return r;",
- 'args' => array(),
- ));
- }
-
- protected function click_button($action)
- {
- $buttons = $this->get_buttons($action);
- $id = array_shift($buttons);
-
- // this doesn't work for me
- $this->byId($id)->click();
- }
-
- protected function ajaxResponse($action, $script = '', $button = false)
- {
- if (!$script && !$button) {
- $script = "rcmail.command('$action')";
- }
-
- $script =
- "if (!window.test_ajax_response) {
- window.test_ajax_response_object = {};
- function test_ajax_response(response)
- {
- if (response.response && response.response.action) {
- window.test_ajax_response_object[response.response.action] = response.response;
- }
- }
- rcmail.addEventListener('responsebefore', test_ajax_response);
- }
- window.test_ajax_response_object['$action'] = null;
- $script;
- ";
-
- // run request
- $this->execute(array(
- 'script' => $script,
- 'args' => array(),
- ));
-
- if ($button) {
- $this->click_button($action);
- }
-
- // wait
- sleep(TESTS_SLEEP);
-
- // get response
- $response = $this->execute(array(
- 'script' => "return window.test_ajax_response_object ? test_ajax_response_object['$action'] : {};",
- 'args' => array(),
- ));
-
- return $response;
- }
-
- protected function getText($element)
- {
- return $element->text() ?: $element->attribute('textContent');
- }
-
- protected function assertHasClass($classname, $element)
- {
- $this->assertContains($classname, $element->attribute('class'));
- }
-}
diff --git a/tests/Selenium/index.html b/tests/Selenium/index.html
deleted file mode 100644
index 7aa65f829..000000000
--- a/tests/Selenium/index.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<head>
- <title>Roundcube Webmail Tests</title>
-</head>
-<body>
-Testing...
-</body>
-</html>