Page MenuHomePhorge

No OneTemporary

Size
52 KB
Referenced Files
None
Subscribers
None
diff --git a/tests/Browser/Contacts/Contacts.php b/tests/Browser/Contacts/Contacts.php
index 76aef1750..b706074da 100644
--- a/tests/Browser/Contacts/Contacts.php
+++ b/tests/Browser/Contacts/Contacts.php
@@ -1,71 +1,83 @@
<?php
namespace Tests\Browser\Contacts;
class Contacts extends \Tests\Browser\DuskTestCase
{
protected function setUp()
{
parent::setUp();
\bootstrap::init_db();
}
/**
* Contacts UI Basics
*/
- public function testAddressbook()
+ public function testContactsUI()
{
$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);
+ if (!$this->isDesktop()) {
+ $browser->assertMissing('#directorylist');
+ $browser->click('a.back-sidebar-button');
+ }
+
$browser->assertSeeIn('#layout-sidebar .header', 'Groups');
// Groups/Addressbooks list
$browser->assertVisible('#directorylist');
$browser->assertSeeIn('#directorylist li:first-child', 'Personal Addresses');
$browser->assertMissing('#directorylist .treetoggle.expanded');
// Contacts list
- $browser->assertVisible('#contacts-table');
+ if (!$this->isDesktop()) {
+ $browser->assertMissing('#contacts-table');
+ $browser->click('#directorylist li:first-child');
+ $browser->waitFor('#contacts-table');
+ }
+ else {
+ $browser->assertVisible('#contacts-table');
+ }
// Contacts list menu
- $browser->assertVisible('#toolbar-list-menu a.select:not(.disabled)');
+ if ($this->isPhone()) {
+ $this->assertToolbarMenu(['select'], []);
+ }
+ else if ($this->isTablet()) {
+ $browser->click('.toolbar-list-button');
+ $browser->assertVisible('#toolbar-list-menu a.select:not(.disabled)');
+ $browser->click();
+ }
+ else {
+ $browser->assertVisible('#toolbar-list-menu a.select:not(.disabled)');
+ }
// Toolbar menu
- $browser->with('#toolbar-menu', function($browser) {
- $browser->assertVisible('a.create:not(.disabled)');
- $browser->assertVisible('a.print.disabled');
- $browser->assertVisible('a.delete.disabled');
- $browser->assertVisible('a.search:not(.disabled)');
- $browser->assertVisible('a.import:not(.disabled)');
- $browser->assertVisible('a.export:not(.disabled)');
- $browser->assertVisible('a.more.disabled');
- });
+ $this->assertToolbarMenu(
+ ['create', 'search', 'import', 'export'], // active items
+ ['print', 'delete', 'more'], // inactive items
+ );
// Contact frame
- $browser->assertVisible('#contact-frame');
+ if (!$this->isPhone()) {
+ $browser->assertVisible('#contact-frame');
+ }
// Task menu
- $browser->with('#taskmenu', function($browser) {
- $browser->assertVisible('a.compose:not(.disabled):not(.selected)');
- $browser->assertVisible('a.mail:not(.disabled):not(.selected)');
- $browser->assertVisible('a.contacts.selected');
- $browser->assertVisible('a.settings:not(.disabled):not(.selected)');
- $browser->assertVisible('a.about:not(.disabled):not(.selected)');
- $browser->assertVisible('a.logout:not(.disabled):not(.selected)');
- });
+ $this->assertTaskMenu('contacts');
});
}
}
diff --git a/tests/Browser/Contacts/Import.php b/tests/Browser/Contacts/Import.php
index d7530a1fb..50514f23b 100644
--- a/tests/Browser/Contacts/Import.php
+++ b/tests/Browser/Contacts/Import.php
@@ -1,103 +1,103 @@
<?php
namespace Tests\Browser\Contacts;
class Import extends \Tests\Browser\DuskTestCase
{
/**
* Test basic elements of contacts import UI
*/
public function testImportUI()
{
$this->browse(function ($browser) {
$this->go('addressbook');
- $browser->click('#toolbar-menu a.import');
+ $this->clickToolbarMenuItem('import');
$browser->assertSeeIn('.ui-dialog-title', 'Import contacts');
$browser->assertVisible('.ui-dialog button.mainaction.import');
$browser->assertVisible('.ui-dialog button.cancel');
$browser->withinFrame('.ui-dialog iframe', function ($browser) {
// 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);
$browser->assertSee('You can upload');
$browser->assertVisible('#rcmImportForm');
$browser->assertVisible('#rcmImportForm select');
$browser->assertVisible('#rcmImportForm .custom-switch');
// FIXME: selecting the file input directly does not work
$browser->assertVisible('#rcmImportForm .custom-file');
$browser->assertSelected('#rcmImportForm select', 0);
});
// Close the dialog
$browser->click('.ui-dialog button.cancel');
$browser->assertMissing('.ui-dialog');
});
}
/**
* Import contacts from a vCard file
*
* @depends testImportUI
*/
public function testImportProcess()
{
$this->browse(function ($browser) {
// Open the dialog again
- $browser->click('#toolbar-menu a.import');
+ $this->clickToolbarMenuItem('import');
$browser->assertSeeIn('.ui-dialog-title', 'Import contacts');
// Submit the form with no file attached
$browser->click('.ui-dialog button.mainaction');
$browser->waitForText('Attention');
$browser->assertSee('Please select a file');
$browser->driver->getKeyboard()->sendKeys(\Facebook\WebDriver\WebDriverKeys::ESCAPE);
$this->assertCount(1, $browser->elements('.ui-dialog'));
$browser->withinFrame('.ui-dialog iframe', function ($browser) {
$browser->attach('.custom-file input', TESTS_DIR . 'data/contacts.vcf');
});
$browser->click('.ui-dialog button.mainaction');
$browser->withinFrame('.ui-dialog iframe', function ($browser) {
$browser->waitForText('Successfully imported 2 contacts:');
});
// Close the dialog
$browser->click('.ui-dialog button.cancel');
// Expected existing contacts + imported
$browser->waitFor('#contacts-table tr');
$this->assertCount(4, $browser->elements('#contacts-table tbody tr'));
$browser->assertSeeIn('#rcmcountdisplay', '1 – 4 of 4');
});
}
/**
* Test imported contact
*
* @depends testImportProcess
*/
public function testImportResult()
{
$this->browse(function ($browser) {
// Open the dialog again
$browser->click('#contacts-table tr:last-child');
$browser->withinFrame('#contact-frame', function ($browser) {
$browser->waitFor('a.email'); // wait for iframe to load
$browser->assertSeeIn('.names', 'Sylvester Stalone');
$browser->assertSeeIn('a.email', 's.stalone@rambo.tv');
});
});
}
}
diff --git a/tests/Browser/DuskTestCase.php b/tests/Browser/DuskTestCase.php
index 67f7b936b..bb37242bc 100644
--- a/tests/Browser/DuskTestCase.php
+++ b/tests/Browser/DuskTestCase.php
@@ -1,263 +1,420 @@
<?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([
+ '--lang=en_US',
'--disable-gpu',
'--headless',
- '--window-size=1280,720',
]);
+ if (getenv('TESTS_MODE') == 'phone') {
+ // Fake User-Agent string for mobile mode
+ $ua = 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Mobile Safari/537.36';
+ $options->setExperimentalOption('mobileEmulation', ['userAgent' => $ua]);
+ $options->addArguments(['--window-size=375,667']);
+ }
+ else if (getenv('TESTS_MODE') == 'tablet') {
+ // Fake User-Agent string for mobile mode
+ $ua = 'Mozilla/5.0 (Linux; Android 6.0.1; vivo 1603 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36';
+ $options->setExperimentalOption('mobileEmulation', ['userAgent' => $ua]);
+ $options->addArguments(['--window-size=1024,768']);
+ }
+ else {
+ $options->addArguments(['--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';
// This folder must exist in case Browser will try to write logs to it
if (!is_dir(Browser::$storeConsoleLogAt)) {
mkdir(Browser::$storeConsoleLogAt, 0777, true);
}
// 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(Browser::$storeScreenshotsAt)->name($pattern);
foreach ($files as $file) {
@unlink($file->getRealPath());
}
}
catch (\Symfony\Component\Finder\Exception\DirectoryNotFoundException $e) {
// ignore missing screenshots directory
}
// Purge console logs from the last test run
$pattern = sprintf('%s_%s-*',
str_replace("\\", '_', get_class($this)),
$this->getName(false)
);
try {
$files = Finder::create()->files()->in(Browser::$storeConsoleLogAt)->name($pattern);
foreach ($files as $file) {
@unlink($file->getRealPath());
}
}
catch (\Symfony\Component\Finder\Exception\DirectoryNotFoundException $e) {
// ignore missing screenshots directory
}
}
+ /**
+ * Check if in Phone mode
+ */
+ public static function isPhone()
+ {
+ return getenv('TESTS_MODE') == 'phone';
+ }
+
+ /**
+ * Check if in Tablet mode
+ */
+ public static function isTablet()
+ {
+ return getenv('TESTS_MODE') == 'tablet';
+ }
+
+ /**
+ * Check if in Desktop mode
+ */
+ public static function isDesktop()
+ {
+ return !self::isPhone() && !self::isTablet();
+ }
+
/**
* Assert specified rcmail.env value
*/
protected function assertEnvEquals($key, $expected)
{
$this->assertEquals($expected, $this->getEnv($key));
}
/**
* Assert specified checkbox state
*/
protected function assertCheckboxState($selector, $state)
{
$this->browse(function (Browser $browser) use ($selector, $state) {
if ($state) {
$browser->assertChecked($selector);
}
else {
$browser->assertNotChecked($selector);
}
});
}
+ /**
+ * Assert Task menu state
+ */
+ protected function assertTaskMenu($selected)
+ {
+ $this->browse(function (Browser $browser) use ($selected) {
+ // On phone the menu is invisible, open it
+ if ($this->isPhone()) {
+ $browser->click('.task-menu-button');
+ }
+
+ $browser->with('#taskmenu', function(Browser $browser) use ($selected) {
+ $options = ['compose', 'mail', 'contacts', 'settings', 'about', 'logout'];
+ foreach ($options as $option) {
+ $browser->assertVisible("a.{$option}:not(.disabled)" . ($selected == $option ? ".selected" : ":not(.selected)"));
+ }
+ });
+
+ // hide the menu back
+ if ($this->isPhone()) {
+ $browser->click('.popover a.button.cancel');
+ $browser->waitUntilMissing('#taskmenu');
+ }
+ });
+ }
+
+ /**
+ * Assert toolbar menu state
+ */
+ protected function assertToolbarMenu($active, $disabled)
+ {
+ $this->browse(function (Browser $browser) use ($active, $disabled) {
+ // On phone the menu is invisible, open it
+ if ($this->isPhone()) {
+ $browser->click('.toolbar-menu-button');
+ }
+
+ $browser->with('#toolbar-menu', function(Browser $browser) use ($active, $disabled) {
+ foreach ($active as $option) {
+ // Print action is disabled on phones
+ if ($option == 'print' && $this->isPhone()) {
+ $browser->assertMissing("a.print");
+ }
+ else {
+ $browser->assertVisible("a.{$option}:not(.disabled)");
+ }
+ }
+ foreach ($disabled as $option) {
+ if ($option == 'print' && $this->isPhone()) {
+ $browser->assertMissing("a.print");
+ }
+ else {
+ $browser->assertVisible("a.{$option}.disabled");
+ }
+ }
+ });
+
+ $this->closeToolbarMenu();
+ });
+ }
+
+ /**
+ * Close toolbar menu (on phones)
+ */
+ protected function closeToolbarMenu()
+ {
+ // hide the menu back
+ if ($this->isPhone()) {
+ $this->browse(function (Browser $browser) {
+ $browser->script("window.UI.menu_hide('toolbar-menu')");
+ $browser->waitUntilMissing('#toolbar-menu');
+ // FIXME: For some reason sometimes .popover-overlay does not close,
+ // we have to remove it manually
+ $browser->script(
+ "Array.from(document.getElementsByClassName('popover-overlay')).forEach(function(elem) { elem.parentNode.removeChild(elem); })"
+ );
+ });
+ }
+ }
+
+ /**
+ * Select taskmenu item
+ */
+ protected function clickTaskMenuItem($name)
+ {
+ $this->browse(function (Browser $browser) use ($name) {
+ if ($this->isPhone()) {
+ $browser->click('.task-menu-button');
+ }
+
+ $browser->click("#taskmenu a.{$name}");
+
+ if ($this->isPhone()) {
+ $browser->waitUntilMissing('#taskmenu');
+ }
+ });
+ }
+
+ /**
+ * Select toolbar menu item
+ */
+ protected function clickToolbarMenuItem($name)
+ {
+ $this->browse(function (Browser $browser) use ($name) {
+ if ($this->isPhone()) {
+ $browser->click('.toolbar-menu-button');
+ }
+
+ $browser->click("#toolbar-menu a.{$name}");
+
+ if ($this->isPhone()) {
+ $this->closeToolbarMenu();
+// $browser->waitUntilMissing('#toolbar-menu');
+ }
+ });
+ }
+
/**
* 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();
}
});
}
/**
* Change state of the Elastic's pretty checkbox
*/
protected function setCheckboxState($selector, $state)
{
// Because you can't operate on the original checkbox directly
$this->browse(function (Browser $browser) use ($selector, $state) {
$browser->ensurejQueryIsAvailable();
if ($state) {
$run = "if (!element.prev().is(':checked')) element.click()";
}
else {
$run = "if (element.prev().is(':checked')) element.click()";
}
$browser->script(
"var element = jQuery('$selector')[0] || jQuery('input[name=$selector]')[0];"
."element = jQuery(element).next('.custom-control-label'); $run;"
);
});
}
/**
* Wait for UI (notice/confirmation/loading/error/warning) message
* and assert it's text
*/
protected function waitForMessage($type, $text)
{
$selector = '#messagestack > div.' . $type;
$this->browse(function ($browser) use ($selector, $text) {
$browser->waitFor($selector)->assertSeeIn($selector, $text);
});
}
/**
* Starts PHP server.
*/
protected static function startWebServer()
{
$path = realpath(__DIR__ . '/../../public_html');
$cmd = ['php', '-S', 'localhost:8000'];
$env = [];
static::$phpProcess = new Process($cmd, null, $env);
static::$phpProcess->setWorkingDirectory($path);
static::$phpProcess->start();
static::afterClass(function () {
static::$phpProcess->stop();
});
}
}
diff --git a/tests/Browser/Logout.php b/tests/Browser/Logout.php
index 4e563e264..c601ca887 100644
--- a/tests/Browser/Logout.php
+++ b/tests/Browser/Logout.php
@@ -1,25 +1,24 @@
<?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');
+ // click the Logout button in taskmenu
+ $this->clickTaskMenuItem('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/Compose.php b/tests/Browser/Mail/Compose.php
index b5a82c3c3..8b536aa9e 100644
--- a/tests/Browser/Mail/Compose.php
+++ b/tests/Browser/Mail/Compose.php
@@ -1,60 +1,64 @@
<?php
namespace Tests\Browser\Mail;
class Compose extends \Tests\Browser\DuskTestCase
{
public function testCompose()
{
$this->browse(function ($browser) {
$this->go('mail');
- $browser->click('#taskmenu a.compose');
+ $this->clickTaskMenuItem('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);
// Toolbar menu
- $browser->with('#toolbar-menu', function($browser) {
- $browser->assertVisible('a.save.draft:not(.disabled)');
- $browser->assertVisible('a.attach:not(.disabled)');
- $browser->assertVisible('a.signature.disabled');
- $browser->assertVisible('a.responses:not(.disabled)');
- $browser->assertVisible('a.spellcheck:not(.disabled)');
- });
+ $this->assertToolbarMenu(
+ ['save.draft', 'responses', 'spellcheck'], // active items
+ ['signature'], // inactive items
+ );
+
+ if ($this->isPhone()) {
+ $this->assertToolbarMenu(['options'], []);
+ }
+ else {
+ $this->assertToolbarMenu(['attach'], []);
+ $browser->assertMissing('#toolbar-menu a.options');
+ }
// Task menu
- $browser->with('#taskmenu', function($browser) {
- $browser->assertVisible('a.compose:not(.disabled).selected');
- $browser->assertVisible('a.mail:not(.disabled):not(.selected)');
- $browser->assertVisible('a.contacts:not(.disabled):not(.selected)');
- $browser->assertVisible('a.settings:not(.disabled):not(.selected)');
- $browser->assertVisible('a.about:not(.disabled):not(.selected)');
- $browser->assertVisible('a.logout:not(.disabled):not(.selected)');
- });
+ $this->assertTaskMenu('compose');
// Header inputs
- $browser->assertSeeIn('#layout-sidebar .header', 'Options and attachments');
- $browser->assertVisible('#compose-attachments');
$browser->assertVisible('#_from');
$browser->assertVisible('#compose-subject');
$browser->assertInputValue('#compose-subject', '');
// Mail body input
$browser->assertVisible('#composebodycontainer.html-editor');
$browser->assertVisible('#composebodycontainer > textarea');
+
+ if ($this->isPhone()) {
+ $this->clickToolbarMenuItem('options');
+ }
+
+ // Compose options
+ $browser->assertSeeIn('#layout-sidebar .header', 'Options and attachments');
+ $browser->assertVisible('#compose-attachments');
});
}
}
diff --git a/tests/Browser/Mail/Getunread.php b/tests/Browser/Mail/Getunread.php
index e6300680c..2fa714bc8 100644
--- a/tests/Browser/Mail/Getunread.php
+++ b/tests/Browser/Mail/Getunread.php
@@ -1,37 +1,43 @@
<?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');
+ $browser->waitFor('#messagelist tbody tr');
+
+ // Messages list state
+ $this->assertCount($this->msgcount, $browser->elements('#messagelist tbody tr.unread'));
+
+ if (!$this->isDesktop()) {
+ $browser->click('.back-sidebar-button');
+ }
+
// Folders list state
- $browser->waitFor('.folderlist li.inbox.unread');
+ $browser->assertVisible('.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
index 333a4a5a0..183eb342f 100644
--- a/tests/Browser/Mail/List.php
+++ b/tests/Browser/Mail/List.php
@@ -1,77 +1,129 @@
<?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'));
// Note: This element icon has width=0, use assertPresent() not assertVisible()
$browser->assertPresent('#messagelist tbody tr:first-child span.msgicon.unread');
// List toolbar menu
- $browser->assertVisible('#toolbar-list-menu a.select:not(.disabled)');
- $browser->assertVisible('#toolbar-list-menu a.options:not(.disabled)');
- $browser->assertVisible('a.toolbar-button.refresh:not(.disabled)');
+ $browser->assertVisible('#layout-list .header a.toolbar-button.refresh:not(.disabled)');
- $imap = \bootstrap::get_storage();
- if ($imap->get_threading()) {
- $browser->assertVisible('#toolbar-list-menu a.threads:not(.disabled)');
+ if ($this->isDesktop()) {
+ $browser->with('#toolbar-list-menu', function ($browser) {
+ $browser->assertVisible('a.select:not(.disabled)');
+ $browser->assertVisible('a.options:not(.disabled)');
+
+ $imap = \bootstrap::get_storage();
+ if ($imap->get_threading()) {
+ $browser->assertVisible('a.threads:not(.disabled)');
+ }
+ else {
+ $browser->assertMissing('a.threads');
+ }
+ });
}
- else {
- $browser->assertMissing('#toolbar-list-menu a.threads');
+ else if ($this->isTablet()) {
+ $browser->click('.toolbar-list-button');
+
+ $browser->with('#toolbar-list-menu', function ($browser) {
+ $browser->assertVisible('a.select:not(.disabled)');
+ $browser->assertVisible('a.options:not(.disabled)');
+
+ $imap = \bootstrap::get_storage();
+ if ($imap->get_threading()) {
+ $browser->assertVisible('a.threads:not(.disabled)');
+ }
+ else {
+ $browser->assertMissing('a.threads');
+ }
+ });
+
+ $browser->click(); // hide the popup menu
+ }
+ else { // phone
+ // On phones list options are in the toolbar menu
+ $browser->click('.toolbar-menu-button');
+
+ $browser->with('#toolbar-menu', function ($browser) {
+ $browser->assertVisible('a.select:not(.disabled)');
+ $browser->assertVisible('a.options:not(.disabled)');
+
+ $imap = \bootstrap::get_storage();
+ if ($imap->get_threading()) {
+ $browser->assertVisible('a.threads:not(.disabled)');
+ }
+ else {
+ $browser->assertMissing('a.threads');
+ }
+ });
+
+ $this->closeToolbarMenu();
}
});
}
/**
* @depends testList
*/
public function testListSelection()
{
$this->browse(function ($browser) {
- $browser->click('#toolbar-list-menu a.select');
- $browser->assertFocused('#toolbar-list-menu a.select');
+ if ($this->isPhone()) {
+ $browser->click('.toolbar-menu-button');
+ $browser->click('#toolbar-menu a.select');
+ }
+ else if ($this->isTablet()) {
+ $browser->click('.toolbar-list-button');
+ $browser->click('#toolbar-list-menu a.select');
+ }
+ else {
+ $browser->click('#toolbar-list-menu a.select');
+ $browser->assertFocused('#toolbar-list-menu a.select');
+ }
// Popup menu content
$browser->with('#listselect-menu', function($browser) {
$browser->assertVisible('a.selection:not(.disabled)');
$browser->assertVisible('a.select.all:not(.disabled)');
$browser->assertVisible('a.select.page:not(.disabled)');
$browser->assertVisible('a.select.unread:not(.disabled)');
$browser->assertVisible('a.select.flagged:not(.disabled)');
$browser->assertVisible('a.select.invert:not(.disabled)');
$browser->assertVisible('a.select.none:not(.disabled)');
});
- // Close the menu by clicking the page body
+ // Close the menu(s) by clicking the page body
$browser->click();
$browser->waitUntilMissing('#listselect-menu');
// TODO: Test selection actions
});
}
}
diff --git a/tests/Browser/Mail/Mail.php b/tests/Browser/Mail/Mail.php
index 894a72134..64cff0f96 100644
--- a/tests/Browser/Mail/Mail.php
+++ b/tests/Browser/Mail/Mail.php
@@ -1,55 +1,53 @@
<?php
namespace Tests\Browser\Mail;
class Mail extends \Tests\Browser\DuskTestCase
{
public function testMailUI()
{
$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);
+ if (!$this->isDesktop()) {
+ $browser->click('.back-sidebar-button');
+ }
+
$browser->assertSeeIn('#layout-sidebar .header', TESTS_USER);
// Folders list
$browser->assertVisible('#mailboxlist li.mailbox.inbox.selected');
+ if (!$this->isDesktop()) {
+ $browser->click('.back-list-button');
+ }
+
// Mail preview frame
- $browser->assertVisible('#messagecontframe');
+ if (!$this->isPhone()) {
+ $browser->assertVisible('#messagecontframe');
+ }
// Toolbar menu
- $browser->with('#toolbar-menu', function($browser) {
- $browser->assertMissing('a.compose'); // this is always hidden button
- $browser->assertVisible('a.reply.disabled');
- $browser->assertVisible('a.reply-all.disabled');
- $browser->assertVisible('a.forward.disabled');
- $browser->assertVisible('a.delete.disabled');
- $browser->assertVisible('a.markmessage.disabled');
- $browser->assertVisible('a.more:not(.disabled)');
- });
+ $this->assertToolbarMenu(
+ ['more'], // active items
+ ['reply', 'reply-all', 'forward', 'delete', 'markmessage'], // inactive items
+ );
// Task menu
- $browser->with('#taskmenu', function($browser) {
- $browser->assertVisible('a.compose:not(.disabled):not(.selected)');
- $browser->assertVisible('a.mail.selected');
- $browser->assertVisible('a.contacts:not(.disabled):not(.selected)');
- $browser->assertVisible('a.settings:not(.disabled):not(.selected)');
- $browser->assertVisible('a.about:not(.disabled):not(.selected)');
- $browser->assertVisible('a.logout:not(.disabled):not(.selected)');
- });
+ $this->assertTaskMenu('mail');
});
}
}
diff --git a/tests/Browser/Settings/About.php b/tests/Browser/Settings/About.php
index 73c7df56a..5d065653d 100644
--- a/tests/Browser/Settings/About.php
+++ b/tests/Browser/Settings/About.php
@@ -1,27 +1,27 @@
<?php
namespace Tests\Browser\Settings;
class About extends \Tests\Browser\DuskTestCase
{
public function testAbout()
{
$this->browse(function ($browser) {
$this->go('settings');
- $browser->click('#taskmenu a.about');
+ $this->clickTaskMenuItem('about');
$browser->assertSeeIn('.ui-dialog-title', 'About');
$browser->assertVisible('.ui-dialog #aboutframe');
$browser->withinFrame('#aboutframe', function ($browser) {
// check task and action
$this->assertEnvEquals('task', 'settings');
$this->assertEnvEquals('action', 'about');
$browser->assertSee($this->app->config->get('product_name'));
$browser->assertVisible('#pluginlist');
});
});
}
}
diff --git a/tests/Browser/Settings/Folders.php b/tests/Browser/Settings/Folders.php
index 549922460..ca3ccff1a 100644
--- a/tests/Browser/Settings/Folders.php
+++ b/tests/Browser/Settings/Folders.php
@@ -1,33 +1,33 @@
<?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);
- $browser->assertVisible('#settings-menu li.folders.selected');
+ if ($this->isDesktop()) {
+ $browser->assertVisible('#settings-menu li.folders.selected');
+ }
// Folders list
$browser->assertVisible('#subscription-table li.mailbox.inbox');
// Toolbar menu
- $browser->assertVisible('#toolbar-menu a.create:not(.disabled)');
- $browser->assertVisible('#toolbar-menu a.delete.disabled');
- $browser->assertVisible('#toolbar-menu a.purge.disabled');
+ $this->assertToolbarMenu(['create'], ['delete', 'purge']);
});
}
}
diff --git a/tests/Browser/Settings/Identities.php b/tests/Browser/Settings/Identities.php
index f3e3fd701..62c95e80c 100644
--- a/tests/Browser/Settings/Identities.php
+++ b/tests/Browser/Settings/Identities.php
@@ -1,32 +1,33 @@
<?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);
- $browser->assertVisible('#settings-menu li.identities.selected');
+ if ($this->isDesktop()) {
+ $browser->assertVisible('#settings-menu li.identities.selected');
+ }
// Identities list
$browser->assertVisible('#identities-table tr:first-child.focused');
$browser->assertSeeIn('#identities-table tr:first-child td.mail', TESTS_USER);
// Toolbar menu
- $browser->assertVisible('#toolbar-menu a.create:not(.disabled)');
- $browser->assertVisible('#toolbar-menu a.delete.disabled');
+ $this->assertToolbarMenu(['create'], ['delete']);
});
}
}
diff --git a/tests/Browser/Settings/Preferences.php b/tests/Browser/Settings/Preferences.php
index 2143eae6c..bb9a1fc48 100644
--- a/tests/Browser/Settings/Preferences.php
+++ b/tests/Browser/Settings/Preferences.php
@@ -1,30 +1,37 @@
<?php
namespace Tests\Browser\Settings;
class Preferences extends \Tests\Browser\DuskTestCase
{
public function testPreferences()
{
$this->browse(function ($browser) {
$this->go('settings');
$objects = $this->getObjects();
$this->assertContains('sectionslist', $objects);
$browser->assertVisible('#settings-menu li.preferences.selected');
+ // On phone/tablet #sections-table is initially hidden
+ if ($this->isPhone() || $this->isTablet()) {
+ $browser->assertMissing('#sections-table');
+ $browser->click('#settings-menu li.preferences');
+ $browser->waitFor('#sections-table');
+ }
+
// Preferences actions
$browser->with('#sections-table', function($browser) {
$browser->assertSeeIn('tr.general', 'User Interface');
$browser->assertSeeIn('tr.mailbox', 'Mailbox View');
$browser->assertSeeIn('tr.mailview', 'Displaying Messages');
$browser->assertSeeIn('tr.compose', 'Composing Messages');
$browser->assertSeeIn('tr.addressbook', 'Contacts');
$browser->assertSeeIn('tr.folders', 'Special Folders');
$browser->assertSeeIn('tr.server', 'Server Settings');
});
});
}
}
diff --git a/tests/Browser/Settings/Preferences/General.php b/tests/Browser/Settings/Preferences/General.php
index 34a140a3b..24b4f77b9 100644
--- a/tests/Browser/Settings/Preferences/General.php
+++ b/tests/Browser/Settings/Preferences/General.php
@@ -1,144 +1,163 @@
<?php
namespace Tests\Browser\Settings\Preferences;
class General extends \Tests\Browser\DuskTestCase
{
protected function tearDown()
{
parent::tearDown();
// Reset user preferences back to defaults
$db = $this->app->get_dbh();
$db->query("UPDATE users SET preferences = '' WHERE username = ?", TESTS_USER);
}
public function testGeneral()
{
$this->browse(function ($browser) {
$this->go('settings');
- $browser->click('#sections-table tr.general');
+ if ($this->isPhone() || $this->isTablet()) {
+ $browser->click('#settings-menu li.preferences');
+ $browser->waitFor('#sections-table');
+ }
$browser->assertVisible('#sections-table tr.general.focused');
+ $browser->click('#sections-table tr.general');
+
+ if ($this->isPhone()) {
+ $browser->waitFor('#layout-content .footer a.button.submit:not(.disabled)');
+ $browser->assertVisible('#layout-content .footer a.button.prev.disabled');
+ $browser->assertVisible('#layout-content .footer a.button.next:not(.disabled)');
+ }
+
$browser->withinFrame('#preferences-frame', function ($browser) {
- $browser->waitFor('.formbuttons button.submit');
+ if (!$this->isPhone()) {
+ $browser->waitFor('.formbuttons button.submit');
+ }
// check task and action
$this->assertEnvEquals('task', 'settings');
$this->assertEnvEquals('action', 'edit-prefs');
// Main Options fieldset
$browser->with('form.propform fieldset.main', function ($browser) {
$browser->assertSeeIn('legend', 'Main Options');
$browser->assertSeeIn('label[for=rcmfd_lang]', 'Language');
$browser->assertVisible('select[name=_language]');
$browser->assertSelected('select[name=_language]', 'en_US');
$browser->assertSeeIn('label[for=rcmfd_timezone]', 'Time zone');
$browser->assertVisible('select[name=_timezone]');
// we don't know what timezone has been autodetected
// $browser->assertSelected('select[name=_timezone]', 'auto');
$browser->assertSeeIn('label[for=rcmfd_time_format]', 'Time format');
$browser->assertVisible('select[name=_time_format]');
$browser->assertSelected('select[name=_time_format]', $this->app->config->get('time_format'));
$browser->assertSeeIn('label[for=rcmfd_date_format]', 'Date format');
$browser->assertVisible('select[name=_date_format]');
$browser->assertSelected('select[name=_date_format]', $this->app->config->get('date_format'));
$browser->assertSeeIn('label[for=rcmfd_prettydate]', 'Pretty dates');
$this->assertCheckboxState('_pretty_date', $this->app->config->get('prettydate'));
$browser->assertSeeIn('label[for=rcmfd_displaynext]', 'Display next');
$this->assertCheckboxState('_display_next', $this->app->config->get('display_next'));
$browser->assertSeeIn('label[for=rcmfd_refresh_interval]', 'Refresh');
$browser->assertVisible('select[name=_refresh_interval]');
$browser->assertSelected('select[name=_refresh_interval]', $this->app->config->get('refresh_interval')/60);
});
// Interface Skin fieldset
$browser->with('form.propform fieldset.skin', function ($browser) {
$browser->assertSeeIn('legend', 'Interface skin');
// TODO
});
// Browser Options fieldset
$browser->with('form.propform fieldset.browser', function ($browser) {
$browser->assertSeeIn('legend', 'Browser Options');
$browser->assertSeeIn('label[for=rcmfd_standard_windows]', 'Handle popups');
$this->assertCheckboxState('_standard_windows', $this->app->config->get('standard_windows'));
});
});
});
}
/**
* Test (all) User Interface preferences change
*
* @depends testGeneral
*/
public function testPreferencesChange()
{
// Values we're changing to
// TODO: Skin or language change causes page reload, we should test this separately
$this->settings = [
'timezone' => 'Pacific/Midway',
'time_format' => 'h:i A',
'date_format' => 'd-m-Y',
'refresh_interval' => 60,
'pretty_date' => !boolval($this->app->config->get('prettydate')),
'display_next' => !boolval($this->app->config->get('display_next')),
'standard_windows' => !boolval($this->app->config->get('standard_windows')),
];
$this->browse(function ($browser) {
// Update preferences
$browser->withinFrame('#preferences-frame', function ($browser) {
$browser->select('_timezone', $this->settings['timezone']);
$browser->select('_time_format', $this->settings['time_format']);
$browser->select('_date_format', $this->settings['date_format']);
$browser->select('_refresh_interval', $this->settings['refresh_interval']);
$this->setCheckboxState('_pretty_date', $this->settings['pretty_date']);
$this->setCheckboxState('_display_next', $this->settings['display_next']);
$this->setCheckboxState('_standard_windows', $this->settings['standard_windows']);
// Submit form
- $browser->click('.formbuttons button.submit');
+ if (!$this->isPhone()) {
+ $browser->click('.formbuttons button.submit');
+ }
});
+ if ($this->isPhone()) {
+ $browser->click('#layout-content .footer a.submit');
+ }
+
$this->waitForMessage('confirmation', 'Successfully saved');
// Verify if every option has been updated
$browser->withinFrame('#preferences-frame', function ($browser) {
$browser->assertSelected('_timezone', $this->settings['timezone']);
$browser->assertSelected('_time_format', $this->settings['time_format']);
$browser->assertSelected('_date_format', $this->settings['date_format']);
$browser->assertSelected('_refresh_interval', $this->settings['refresh_interval']);
$this->assertCheckboxState('_pretty_date', $this->settings['pretty_date']);
$this->assertCheckboxState('_display_next', $this->settings['display_next']);
$this->assertCheckboxState('_standard_windows', $this->settings['standard_windows']);
// Assert the options have been saved in database properly
$prefs = \bootstrap::get_prefs();
$options = array_diff(array_keys($this->settings), ['refresh_interval', 'pretty_date']);
foreach ($options as $option) {
$this->assertEquals($this->settings[$option], $prefs[$option]);
}
$this->assertEquals($this->settings['pretty_date'], $prefs['prettydate']);
$this->assertEquals($this->settings['refresh_interval'], $prefs['refresh_interval']/60);
});
});
}
}
diff --git a/tests/Browser/Settings/Responses.php b/tests/Browser/Settings/Responses.php
index 9de267aef..5c3a09501 100644
--- a/tests/Browser/Settings/Responses.php
+++ b/tests/Browser/Settings/Responses.php
@@ -1,32 +1,33 @@
<?php
namespace Tests\Browser\Settings;
class Responses extends \Tests\Browser\DuskTestCase
{
public function testIdentities()
{
$this->browse(function ($browser) {
$this->go('settings', 'responses');
// check task and action
$this->assertEnvEquals('task', 'settings');
$this->assertEnvEquals('action', 'responses');
$objects = $this->getObjects();
// these objects should be there always
$this->assertContains('responseslist', $objects);
- $browser->assertVisible('#settings-menu li.responses.selected');
+ if ($this->isDesktop()) {
+ $browser->assertVisible('#settings-menu li.responses.selected');
+ }
// Responses list
$browser->assertPresent('#responses-table');
$browser->assertMissing('#responses-table tr');
// Toolbar menu
- $browser->assertVisible('#toolbar-menu a.create:not(.disabled)');
- $browser->assertVisible('#toolbar-menu a.delete.disabled');
+ $this->assertToolbarMenu(['create'], ['delete']);
});
}
}
diff --git a/tests/Browser/Settings/Settings.php b/tests/Browser/Settings/Settings.php
index d19d4e7e7..a5fd9d889 100644
--- a/tests/Browser/Settings/Settings.php
+++ b/tests/Browser/Settings/Settings.php
@@ -1,36 +1,29 @@
<?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');
$browser->assertSeeIn('#layout-sidebar .header', 'Settings');
// Sidebar menu
$browser->with('#settings-menu', function($browser) {
$browser->assertSeeIn('li.preferences', 'Preferences');
$browser->assertSeeIn('li.folders', 'Folders');
$browser->assertSeeIn('li.identities', 'Identities');
$browser->assertSeeIn('li.responses', 'Responses');
});
// Task menu
- $browser->with('#taskmenu', function($browser) {
- $browser->assertVisible('a.compose:not(.disabled):not(.selected)');
- $browser->assertVisible('a.mail:not(.disabled):not(.selected)');
- $browser->assertVisible('a.contacts:not(.disabled):not(.selected)');
- $browser->assertVisible('a.settings:not(.disabled).selected');
- $browser->assertVisible('a.about:not(.disabled):not(.selected)');
- $browser->assertVisible('a.logout:not(.disabled):not(.selected)');
- });
+ $this->assertTaskMenu('settings');
});
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jul 8, 7:10 PM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1051839
Default Alt Text
(52 KB)

Event Timeline