Page MenuHomePhorge

No OneTemporary

Size
15 KB
Referenced Files
None
Subscribers
None
diff --git a/tests/Browser/Components/HtmlEditor.php b/tests/Browser/Components/HtmlEditor.php
new file mode 100644
index 000000000..40d71a393
--- /dev/null
+++ b/tests/Browser/Components/HtmlEditor.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace Tests\Browser\Components;
+
+use App;
+use Tests\Browser\Browser;
+use Laravel\Dusk\Component;
+
+class HtmlEditor extends Component
+{
+ const MODE_PLAIN = 'plain';
+ const MODE_HTML = 'html';
+
+ public $id;
+
+ /**
+ * Class constructor
+ */
+ public function __construct($id)
+ {
+ $this->id = trim($id);
+ }
+
+ /**
+ * Get the root selector for the component.
+ *
+ * @return string
+ */
+ public function selector()
+ {
+ return '#' . $this->id;
+ }
+
+ /**
+ * Assert that the browser page contains the component.
+ *
+ * @param Browser $browser
+ *
+ * @return void
+ */
+ public function assert($browser)
+ {
+ $browser->waitFor($this->selector() . '.html-editor');
+ }
+
+ /**
+ * Get the element shortcuts for the component.
+ *
+ * @return array
+ */
+ public function elements()
+ {
+ return [
+ '@plain-toolbar' => '.editor-toolbar',
+ '@plain-body' => 'textarea',
+ '@html-editor' => '.mce-tinymce',
+ '@html-toolbar' => '.mce-tinymce .mce-toolbar',
+ '@html-body' => 'iframe',
+ ];
+ }
+
+ /**
+ * Assert editor mode
+ */
+ public function assertMode($browser, $mode)
+ {
+ if ($mode == self::MODE_PLAIN) {
+ $browser->assertVisible('@plain-toolbar')
+ ->assertMissing('@html-body');
+ }
+ else {
+ $browser->assertMissing('@plain-toolbar')
+ ->assertVisible('@html-body');
+ }
+ }
+
+ /**
+ * Switch editor mode
+ */
+ public function switchMode($browser, $mode, $accept_warning = false)
+ {
+ if ($mode == self::MODE_HTML) {
+ $browser->click('@plain-toolbar a.mce-i-html');
+ if ($accept_warning) {
+ $browser->waitForDialog()->acceptDialog();
+ }
+ $browser->waitFor('@html-body');
+ }
+ else {
+ $browser->click('@html-toolbar .mce-i-plaintext');
+ if ($accept_warning) {
+ $browser->waitForDialog()->acceptDialog();
+ }
+ $browser->waitFor('@plain-body');
+ }
+ }
+}
diff --git a/tests/Browser/Mail/ComposeTest.php b/tests/Browser/Mail/ComposeTest.php
index b9b8812c6..a61025837 100644
--- a/tests/Browser/Mail/ComposeTest.php
+++ b/tests/Browser/Mail/ComposeTest.php
@@ -1,68 +1,101 @@
<?php
namespace Tests\Browser\Mail;
+use Facebook\Webdriver\WebDriverKeys;
use Tests\Browser\Components\App;
+use Tests\Browser\Components\HtmlEditor;
class ComposeTest extends \Tests\Browser\TestCase
{
public function testCompose()
{
$this->browse(function ($browser) {
$browser->go('mail');
$browser->clickTaskMenuItem('compose');
// check task and action
$browser->with(new App(), function ($browser) {
$browser->assertEnv('task', 'mail');
$browser->assertEnv('action', 'compose');
// these objects should be there always
$browser->assertObjects([
'qsearchbox',
'addressbookslist',
'contactslist',
'messageform',
'attachmentlist',
'filedrop',
'uploadform'
]);
});
// Toolbar menu
$browser->assertToolbarMenu(
['save.draft', 'responses', 'spellcheck'], // active items
['signature'], // inactive items
);
if ($browser->isPhone()) {
$browser->assertToolbarMenu(['options'], []);
}
else {
$browser->assertToolbarMenu(['attach'], []);
$browser->assertMissing('#toolbar-menu a.options');
}
// Task menu
$browser->assertTaskMenu('compose');
// Header inputs
$browser->assertVisible('#_from');
$browser->assertVisible('#compose-subject');
$browser->assertInputValue('#compose-subject', '');
// Mail body input
$browser->assertVisible('#composebodycontainer.html-editor');
$browser->assertVisible('#composebodycontainer > textarea');
if ($browser->isPhone()) {
$browser->clickToolbarMenuItem('options');
}
// Compose options
$browser->assertSeeIn('#layout-sidebar .header', 'Options and attachments');
$browser->assertVisible('#compose-attachments');
});
}
+
+ /**
+ * depends @testCompose
+ */
+ function testPlainEditor()
+ {
+ // Test for #7230: Shift+PageUp text selection
+ // and copy-pasting with keyboard
+ $this->browse(function ($browser) {
+ $browser->with(new HtmlEditor('composebodycontainer'), function ($browser) {
+ $browser->assertMode(HtmlEditor::MODE_PLAIN)
+ ->type('@plain-body', "line1\nline2\n")
+ ->keys('@plain-body', [WebDriverKeys::SHIFT, WebDriverKeys::PAGE_UP])
+ ->keys('@plain-body', [WebDriverKeys::CONTROL, 'c'])
+ ->keys('@plain-body', [WebDriverKeys::CONTROL, 'x'])
+ ->keys('@plain-body', [WebDriverKeys::CONTROL, 'v'])
+ ->keys('@plain-body', [WebDriverKeys::CONTROL, 'v'])
+ ->assertValue('@plain-body', "line1\nline2\nline1\nline2\n");
+ });
+ });
+
+ // Test switching to HTML and back
+ $this->browse(function ($browser) {
+ $browser->with(new HtmlEditor('composebodycontainer'), function ($browser) {
+ $browser->switchMode(HtmlEditor::MODE_HTML, true)
+ ->switchMode(HtmlEditor::MODE_PLAIN)
+ ->assertValue('@plain-body', "line1\nline2\nline1\nline2")
+ ->switchMode(HtmlEditor::MODE_HTML, false);
+ });
+ });
+ }
}
diff --git a/tests/Browser/bootstrap.php b/tests/Browser/bootstrap.php
index 23442da68..01244d2d5 100644
--- a/tests/Browser/bootstrap.php
+++ b/tests/Browser/bootstrap.php
@@ -1,258 +1,259 @@
<?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__ . '/Browser.php');
require_once(__DIR__ . '/TestCase.php');
require_once(__DIR__ . '/Components/App.php');
require_once(__DIR__ . '/Components/Dialog.php');
+require_once(__DIR__ . '/Components/HtmlEditor.php');
require_once(__DIR__ . '/Components/Popupmenu.php');
require_once(__DIR__ . '/Components/Taskmenu.php');
require_once(__DIR__ . '/Components/Toolbarmenu.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'));
$db = $rcmail->get_dbh();
if ($dsn['phptype'] == 'mysql' || $dsn['phptype'] == 'mysqli') {
// drop all existing tables first
$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/data.sql'),
escapeshellarg($dsn['hostspec']),
escapeshellarg($dsn['username']),
escapeshellarg($dsn['password']),
escapeshellarg($dsn['database'])
));
}
else if ($dsn['phptype'] == 'sqlite') {
$db->closeConnection();
// delete database file
system(sprintf('rm -f %s', escapeshellarg($dsn['database'])));
// load sample test data
// Note: exec_script() does not really work with these queries
$sql = file_get_contents(TESTS_DIR . 'data/data.sql');
$sql = preg_split('/;\n/', $sql, -1, PREG_SPLIT_NO_EMPTY);
foreach ($sql as $query) {
$result = $db->query($query);
if ($db->is_error($result)) {
rcube::raise_error($db->is_error(), false, true);
}
}
}
}
/**
* 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);
return self::$imap_ready;
}
/**
* Authenticate to IMAP with the given credentials
*/
public static function connect_imap($username, $password)
{
$rcmail = rcmail::get_instance();
$imap = $rcmail->get_storage();
if ($imap->is_connected()) {
$imap->close();
self::$imap_ready = false;
}
$imap_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)) {
rcube::raise_error("IMAP error: unable to authenticate with user " . TESTS_USER, false, true);
}
if (in_array('archive', (array) $rcmail->config->get('plugins'))) {
// Register special folder type for the Archive plugin.
// As we're in cli mode the plugin can't do it by its own
rcube_storage::$folder_types[] = 'archive';
}
self::$imap_ready = true;
}
/**
* Import the given file into IMAP
*/
public static function import_message($filename, $mailbox = 'INBOX')
{
if (!self::init_imap()) {
rcube::raise_error(__METHOD__ . ': IMAP connection unavailable', false, true);
}
$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()) {
rcube::raise_error(__METHOD__ . ': IMAP connection unavailable', false, true);
}
$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()) {
rcube::raise_error(__METHOD__ . ': IMAP connection unavailable', false, true);
}
$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);
}
}
/**
* Make sure only special folders exist in IMAP
*/
public static function reset_mailboxes()
{
if (!self::init_imap()) {
rcube::raise_error(__METHOD__ . ': IMAP connection unavailable', false, true);
}
$rcmail = rcmail::get_instance();
$imap = $rcmail->get_storage();
$got_defaults = $rcmail->config->get('create_default_folders');
$vendor = $imap->get_vendor();
// Note: We do not expect IMAP server auto-creating any folders
foreach ($imap->list_folders() as $folder) {
if ($folder != 'INBOX' && (!$got_defaults || !$imap->is_special_folder($folder))) {
// GreenMail throws errors when unsubscribing a deleted folder
if ($vendor == 'greenmail') {
$imap->conn->deleteFolder($folder);
}
else {
$imap->delete_folder($folder);
}
}
}
}
/**
* Check IMAP capabilities
*/
public static function get_storage()
{
if (!self::init_imap()) {
rcube::raise_error(__METHOD__ . ': IMAP connection unavailable', false, true);
}
return rcmail::get_instance()->get_storage();
}
/**
* Return user preferences directly from database
*/
public static function get_prefs()
{
$rcmail = rcmail::get_instance();
// Create a separate connection to the DB, otherwise
// we hit some strange and hard to investigate locking issues
$db = rcube_db::factory($rcmail->config->get('db_dsnw'), $rcmail->config->get('db_dsnr'), false);
$db->set_debug((bool)$rcmail->config->get('sql_debug'));
$query = $db->query("SELECT preferences FROM users WHERE username = ?", TESTS_USER);
$record = $db->fetch_assoc($query);
return unserialize($record['preferences']);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, May 22, 5:24 AM (21 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
783241
Default Alt Text
(15 KB)

Event Timeline