Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F1842050
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
43 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/tests/Browser/Components/Dialog.php b/tests/Browser/Components/Dialog.php
new file mode 100644
index 000000000..7645a6314
--- /dev/null
+++ b/tests/Browser/Components/Dialog.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace Tests\Browser\Components;
+
+use Tests\Browser\Browser;
+use Laravel\Dusk\Component;
+
+class Dialog extends Component
+{
+ public $num;
+
+ /**
+ * Class constructor
+ */
+ public function __construct($num = 1)
+ {
+ $this->num = $num ?: 1;
+ }
+
+ /**
+ * Get the root selector for the component.
+ *
+ * @return string
+ */
+ public function selector()
+ {
+ // work with the specified dialog (in case there's more than one)
+ $suffix = $this->num > 1 ? str_repeat(' + div + .ui-dialog', $this->num - 1) : '';
+ return '.ui-dialog' . $suffix;
+ }
+
+ /**
+ * Assert that the browser page contains the component.
+ *
+ * @param Browser $browser
+ *
+ * @return void
+ */
+ public function assert($browser)
+ {
+ $browser->waitFor($this->selector());
+ }
+
+ /**
+ * Get the element shortcuts for the component.
+ *
+ * @return array
+ */
+ public function elements()
+ {
+ return [
+ '@title' => '.ui-dialog-titlebar',
+ '@content' => '.ui-dialog-content',
+ '@footer' => '.ui-dialog-buttonset',
+ ];
+ }
+
+ /**
+ * Assert dialog title
+ */
+ public function assertDialogTitle($browser, $title)
+ {
+ $browser->assertSeeIn('@title', $title);
+ }
+
+ /**
+ * Assert dialog content (for simple text dialogs)
+ */
+ public function assertDialogContent($browser, $text)
+ {
+ $browser->assertSeeIn('@content', $text);
+ }
+
+ /**
+ * Assert dialog button
+ */
+ public function assertButton($browser, $name, $label)
+ {
+ $selector = "@footer button.{$name}";
+ $browser->assertVisible($selector, $title)
+ ->assertSeeIn($selector, $label);
+ }
+
+ /**
+ * Click dialog button
+ */
+ public function clickButton($browser, $name, $expect_close = true)
+ {
+ $browser->click('@footer button.' . $name);
+
+ if ($expect_close) {
+ $browser->waitUntilMissing($this->selector());
+ }
+ }
+
+ /**
+ * Close dialog
+ */
+ public function closeDialog($browser)
+ {
+ $browser->click('@footer button.cancel, @footer button.close')
+ ->waitUntilMissing($this->selector());
+ }
+
+ /**
+ * Close dialog with ESC key
+ */
+ public function pressESC($browser)
+ {
+ $browser->driver->getKeyboard()->sendKeys(\Facebook\WebDriver\WebDriverKeys::ESCAPE);
+ $browser->waitUntilMissing($this->selector());
+ }
+
+ /**
+ * Execute code within dialog's iframe
+ */
+ public function withinDialogFrame($browser, $callback)
+ {
+ $browser->withinFrame('@content iframe', function ($browser) use ($callback) {
+ $browser->withinBody(function ($browser) use ($callback) {
+ $callback($browser);
+ });
+ });
+ }
+}
diff --git a/tests/Browser/Contacts/GroupsTest.php b/tests/Browser/Contacts/GroupsTest.php
index 4d7dc7a7d..f4db05571 100644
--- a/tests/Browser/Contacts/GroupsTest.php
+++ b/tests/Browser/Contacts/GroupsTest.php
@@ -1,184 +1,182 @@
<?php
namespace Tests\Browser\Contacts;
+use Tests\Browser\Components\Dialog;
use Tests\Browser\Components\Popupmenu;
class GroupsTest extends \Tests\Browser\TestCase
{
public static function setUpBeforeClass()
{
\bootstrap::init_db();
}
/**
* Contact groups UI basics
*/
public function testGroups()
{
$this->browse(function ($browser) {
$browser->go('addressbook');
if (!$browser->isDesktop()) {
$browser->assertMissing('#directorylist');
$browser->click('a.back-sidebar-button');
}
// Groups/Addressbooks list
$browser->assertVisible('#directorylist');
$browser->assertSeeIn('#directorylist li:first-child', 'Personal Addresses');
$browser->assertSeeIn('#layout-sidebar .header', 'Groups');
$browser->click('#layout-sidebar .header .sidebar-menu');
$browser->with(new Popupmenu('groupoptions-menu'), function ($browser) {
// Note: These are button class names, not action names
$active = ['create'];
$disabled = ['group.rename', 'group.delete', 'search', 'search.delete'];
$browser->assertMenuState($active, $disabled);
$browser->closeMenu();
});
});
}
/**
* Contact group creation
*/
public function testGroupCreate()
{
$this->browse(function ($browser) {
$browser->go('addressbook');
if (!$browser->isDesktop()) {
$browser->click('a.back-sidebar-button');
}
$browser->click('#layout-sidebar .header .sidebar-menu');
$browser->with(new Popupmenu('groupoptions-menu'), function ($browser) {
$browser->clickMenuItem('create');
});
- $browser->waitFor('.ui-dialog');
- $browser->with('.ui-dialog', function ($browser) {
- $browser
- ->assertSeeIn('.ui-dialog-titlebar', 'Create new group')
- ->assertFocused('input.form-control')
- ->type('input.form-control', 'New Group')
- ->click('button.mainaction');
+ $browser->with(new Dialog(), function ($browser) {
+ $browser->assertDialogTitle('Create new group')
+ ->assertButton('save.mainaction', 'Save')
+ ->assertButton('cancel', 'Cancel')
+ ->assertFocused('@content input.form-control')
+ ->type('@content input.form-control', 'New Group')
+ ->clickButton('save');
});
- $browser->waitUntilMissing('.ui-dialog');
-
$browser->with('#directorylist', function ($browser) {
$browser->waitFor('li:first-child ul.groups')
->assertVisible('.treetoggle.expanded')
->assertElementsCount('ul.groups > li.contactgroup', 1)
->assertSeeIn('ul.groups > li.contactgroup', 'New Group');
// Test expand toggle
$browser->click('.treetoggle.expanded')
->assertMissing('ul.groups')
->click('.treetoggle.collapsed')
->assertSeeIn('ul.groups > li.contactgroup', 'New Group');
});
});
}
/**
* Contact group rename
*
* @depends testGroupCreate
*/
public function testGroupRename()
{
$this->browse(function ($browser) {
$browser->go('addressbook');
if (!$browser->isDesktop()) {
$browser->click('a.back-sidebar-button');
}
$browser->click('#directorylist ul.groups > li:first-child');
if (!$browser->isDesktop()) {
$browser->click('a.back-sidebar-button');
}
$browser->click('#layout-sidebar .header .sidebar-menu');
$browser->with(new Popupmenu('groupoptions-menu'), function ($browser) {
$browser->clickMenuItem('group.rename');
});
- $browser->waitFor('.ui-dialog');
- $browser->with('.ui-dialog', function ($browser) {
- $browser->assertSeeIn('.ui-dialog-titlebar', 'Rename group')
- ->assertFocused('input.form-control')
- ->assertValue('input.form-control', 'New Group')
- ->type('input.form-control', 'Renamed')
- ->click('button.mainaction');
+ $browser->with(new Dialog(), function ($browser) {
+ $browser
+ ->assertDialogTitle('Rename group')
+ ->assertButton('save.mainaction', 'Save')
+ ->assertButton('cancel', 'Cancel')
+ ->assertFocused('@content input.form-control')
+ ->assertValue('@content input.form-control', 'New Group')
+ ->type('@content input.form-control', 'Renamed')
+ ->clickButton('save');
});
- $browser->waitUntilMissing('.ui-dialog');
-
$browser->with('#directorylist', function ($browser) {
$browser->waitFor('li:first-child ul.groups')
->assertVisible('.treetoggle.expanded')
->assertElementsCount('ul.groups > li.contactgroup', 1)
->assertSeeIn('ul.groups > li.contactgroup', 'Renamed');
// Test if expand toggle is still working
$browser->click('.treetoggle.expanded')
->assertMissing('ul.groups')
->click('.treetoggle.collapsed')
->assertSeeIn('ul.groups > li.contactgroup', 'Renamed');
});
});
}
/**
* Contact group deletion
*
* @depends testGroupRename
*/
public function testGroupDelete()
{
$this->browse(function ($browser) {
$browser->go('addressbook');
if (!$browser->isDesktop()) {
$browser->click('a.back-sidebar-button');
}
$browser->click('#directorylist ul.groups > li:first-child');
if (!$browser->isDesktop()) {
$browser->click('a.back-sidebar-button');
}
$browser->click('#layout-sidebar .header .sidebar-menu');
$browser->with(new Popupmenu('groupoptions-menu'), function ($browser) {
$browser->clickMenuItem('group.delete');
});
- $browser->waitFor('.ui-dialog');
- $browser->with('.ui-dialog', function ($browser) {
- $browser->assertSeeIn('.ui-dialog-titlebar', 'Are you sure...')
- ->assertSeeIn('.ui-dialog-content', 'Do you really want to delete selected group?')
- ->assertFocused('button.mainaction.delete')
- ->click('button.mainaction.delete');
+ $browser->with(new Dialog(), function ($browser) {
+ $browser
+ ->assertDialogTitle('Are you sure...')
+ ->assertDialogContent('Do you really want to delete selected group?')
+ ->assertButton('delete.mainaction', 'Delete')
+ ->assertButton('cancel', 'Cancel')
+ ->clickButton('delete');
});
- $browser->waitUntilMissing('.ui-dialog');
-
$browser->with('#directorylist', function ($browser) {
$browser->assertMissing('.treetoggle.expanded')
->assertMissing('ul.groups');
});
});
}
}
diff --git a/tests/Browser/Contacts/ImportTest.php b/tests/Browser/Contacts/ImportTest.php
index 48a2e0b24..2d1994497 100644
--- a/tests/Browser/Contacts/ImportTest.php
+++ b/tests/Browser/Contacts/ImportTest.php
@@ -1,109 +1,116 @@
<?php
namespace Tests\Browser\Contacts;
use Tests\Browser\Components\App;
+use Tests\Browser\Components\Dialog;
class ImportTest extends \Tests\Browser\TestCase
{
public static function setUpBeforeClass()
{
\bootstrap::init_db();
}
/**
* Test basic elements of contacts import UI
*/
public function testImportUI()
{
$this->browse(function ($browser) {
$browser->go('addressbook');
$browser->clickToolbarMenuItem('import');
- $browser->assertSeeIn('.ui-dialog-title', 'Import contacts');
- $browser->assertVisible('.ui-dialog button.mainaction.import');
- $browser->assertVisible('.ui-dialog button.cancel');
+ $browser->with(new Dialog(), function ($browser) {
+ $browser->assertDialogTitle('Import contacts')
+ ->assertButton('mainaction.import', 'Import')
+ ->assertButton('cancel', 'Cancel');
+ });
$browser->withinFrame('.ui-dialog iframe', function ($browser) {
// check task and action
$browser->with(new App(), function ($browser) {
$browser->assertEnv('task', 'addressbook');
$browser->assertEnv('action', 'import');
// these objects should be there always
$browser->assertObjects(['importform']);
});
$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');
+ $browser->with(new Dialog(), function ($browser) {
+ $browser->clickButton('cancel');
+ });
});
}
/**
* Import contacts from a vCard file
*
* @depends testImportUI
*/
public function testImportProcess()
{
$this->browse(function ($browser) {
// Open the dialog again
$browser->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);
- $browser->assertElementsCount('.ui-dialog', 1);
-
- $browser->withinFrame('.ui-dialog iframe', function ($browser) {
- $browser->attach('.custom-file input', TESTS_DIR . 'data/contacts.vcf');
+ $browser->with(new Dialog(), function ($browser) {
+ $browser->assertDialogTitle('Import contacts')
+ ->clickButton('import');
});
- $browser->click('.ui-dialog button.mainaction');
-
- $browser->withinFrame('.ui-dialog iframe', function ($browser) {
- $browser->waitForText('Successfully imported 2 contacts:');
+ // Submit the form with no file attached
+ $browser->with(new Dialog(2), function ($browser) {
+ $browser->assertDialogTitle('Attention')
+ ->assertDialogContent('Please select a file')
+ ->assertButton('save.mainaction', 'OK')
+ ->pressESC();
});
- // Close the dialog
- $browser->click('.ui-dialog button.cancel');
+ $browser->with(new Dialog(), function ($browser) {
+ $browser->withinDialogFrame(function ($browser) {
+ $browser->attach('.custom-file input', TESTS_DIR . 'data/contacts.vcf');
+ })
+ ->clickButton('import')
+ ->withinDialogFrame(function ($browser) {
+ $browser->waitForText('Successfully imported 2 contacts:');
+ })
+ ->closeDialog();
+ });
// Expected existing contacts + imported
$browser->waitFor('#contacts-table tr')
->assertElementsCount('#contacts-table tbody tr', 4)
->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/Mail/PreviewTest.php b/tests/Browser/Mail/PreviewTest.php
index aa33f46da..6b6bbc021 100644
--- a/tests/Browser/Mail/PreviewTest.php
+++ b/tests/Browser/Mail/PreviewTest.php
@@ -1,176 +1,175 @@
<?php
namespace Tests\Browser\Mail;
use Tests\Browser\Components\App;
+use Tests\Browser\Components\Dialog;
use Tests\Browser\Components\Popupmenu;
class PreviewTest extends \Tests\Browser\TestCase
{
public static function setUpBeforeClass()
{
\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');
}
}
/**
* Test opening an email in preview frame
*/
public function testPreview()
{
$this->browse(function ($browser) {
$browser->go('mail');
$browser->waitFor('#messagelist tbody tr:first-child')
->click('#messagelist tbody tr:first-child')
->waitForMessage('loading', 'Loading...')
->waitFor('#messagecontframe')
->waitUntilMissing('#messagestack');
// On phone check frame controls
if ($browser->isPhone()) {
$browser->with('#layout-content .footer', function ($browser) {
$browser->assertVisible('a.button.prev.disabled')
->assertVisible('a.button.next:not(.disabled)')
->assertVisible('a.button.reply:not(.disabled)')
->assertSeeIn('a.button.prev', 'Previous')
->assertSeeIn('a.button.reply', 'Reply')
->assertSeeIn('a.button.next', 'Next');
});
}
$browser->withinFrame('#messagecontframe', function ($browser) {
$browser->waitFor('img.contactphoto');
// Privacy warning
$browser->assertVisible('#remote-objects-message.alert-warning')
->assertSeeIn('#remote-objects-message', 'To protect your privacy remote resources have been blocked.');
// Images
$this->assertRegExp('/action=get/', $browser->attribute('p#v1attached > img', 'src'));
$this->assertRegExp('/blocked/', $browser->attribute('p#v1remote > img', 'src'));
// Attachments list
$browser->with('#attachment-list', function ($browser) {
$browser->assertVisible('li.image.ico')
->assertSeeIn('li .attachment-name', 'favicon.ico')
->assertSeeIn('li .attachment-size', '(~2 KB)')
->click('a.dropdown');
});
if (!$browser->isPhone()) {
$browser->waitFor('#attachmentmenu')
->with('#attachmentmenu', function ($browser) {
$browser->assertVisible('a.extwin.disabled')
->assertVisible('a.download:not(.disabled)')
->click('a.download');
});
}
});
if ($browser->isPhone()) {
$browser->waitFor('#attachmentmenu-clone')
->with('#attachmentmenu-clone', function ($browser) {
$browser->assertVisible('a.extwin.disabled')
->assertVisible('a.download:not(.disabled)')
->click('a.download');
});
}
$ico = $browser->readDownloadedFile('favicon.ico');
$this->assertTrue(strlen($ico) == 2294);
$this->assertSame("\0\0\1\0", substr($ico, 0, 4));
$browser->removeDownloadedFile('favicon.ico');
// On phone check Back button
if ($browser->isPhone()) {
$browser->click('#layout-content .header a.back-list-button')
->assertVisible('#messagelist');
}
});
}
/**
* Test "X more..." link on mail preview with many recipients,
* and some more
*/
public function testPreviewMorelink()
{
$this->browse(function ($browser) {
$browser->go('mail');
$browser->waitFor('#messagelist tbody tr:last-child')
->click('#messagelist tbody tr:last-child')
->waitForMessage('loading', 'Loading...')
->waitFor('#messagecontframe')
->waitUntilMissing('#messagestack');
$browser->withinFrame('#messagecontframe', function ($browser) {
$browser->waitFor('img.contactphoto');
$browser->assertSeeIn('.subject', 'Lines')
->assertSeeIn('.message-part div.pre', 'Plain text message body.')
->assertVisible('.message-part div.pre .sig');
$browser->assertMissing('.headers-table')
->click('a.envelope')
->waitFor('.headers-table')
->assertVisible('.header.cc')
->assertSeeIn('.header.cc', 'test10@domain.tld')
->assertDontSeeIn('.header.cc', 'test11@domain.tld')
->assertSeeIn('.header.cc a.morelink', '2 more...')
->click('.header.cc a.morelink');
});
- $browser->waitFor('.ui-dialog')
- ->with('.ui-dialog', function ($browser) {
- $browser->assertSeeIn('.ui-dialog-titlebar', 'Cc')
- ->assertSeeIn('.ui-dialog-content', 'test1@domain.tld')
- ->assertSeeIn('.ui-dialog-content', 'test12@domain.tld')
- ->assertElementsCount('span.adr', 12)
- ->click('.ui-dialog-buttonset button.cancel');
- });
-
- $browser->waitUntilMissing('.ui-dialog');
+ $browser->with(new Dialog(), function ($browser) {
+ $browser->assertDialogTitle('Cc')
+ ->assertDialogContent('test1@domain.tld')
+ ->assertDialogContent('test12@domain.tld')
+ ->assertElementsCount('@content span.adr', 12)
+ ->assertButton('cancel', 'Close')
+ ->clickButton('cancel');
+ });
// Attachments list
$browser->withinFrame('#messagecontframe', function ($browser) {
$browser->with('#attachment-list', function ($browser) {
$browser->assertElementsCount('li', 2)
->assertVisible('li.text.plain')
->assertSeeIn('li:first-child .attachment-name', 'lines.txt')
->assertSeeIn('li:first-child .attachment-size', '(~13 B)')
->assertSeeIn('li:last-child .attachment-name', 'lines_lf.txt')
->assertSeeIn('li:last-child .attachment-size', '(~11 B)')
->click('li:first-child a.dropdown');
});
if (!$browser->isPhone()) {
$browser->waitFor('#attachmentmenu')
->with('#attachmentmenu', function ($browser) {
$browser->assertVisible('a.extwin:not(.disabled)')
->assertVisible('a.download:not(.disabled)');
});
}
});
if ($browser->isPhone()) {
$browser->waitFor('#attachmentmenu-clone')
->with('#attachmentmenu-clone', function ($browser) {
$browser->assertVisible('a.extwin:not(.disabled)')
->assertVisible('a.download:not(.disabled)');
})
->click('.popover a.cancel')
->waitUntilMissing('.popover')
->click('#layout-content .header a.back-list-button')
->assertVisible('#messagelist');
}
});
}
}
diff --git a/tests/Browser/Settings/AboutTest.php b/tests/Browser/Settings/AboutTest.php
index c2b9932af..00c3eb561 100644
--- a/tests/Browser/Settings/AboutTest.php
+++ b/tests/Browser/Settings/AboutTest.php
@@ -1,31 +1,43 @@
<?php
namespace Tests\Browser\Settings;
use Tests\Browser\Components\App;
+use Tests\Browser\Components\Dialog;
class AboutTest extends \Tests\Browser\TestCase
{
public function testAbout()
{
$this->browse(function ($browser) {
$browser->go('settings');
$browser->clickTaskMenuItem('about');
- $browser->assertSeeIn('.ui-dialog-title', 'About');
- $browser->assertVisible('.ui-dialog #aboutframe');
+ $browser->with(new Dialog(), function ($browser) {
+ $browser->assertDialogTitle('About')
+ ->assertButton('cancel', 'Close')
+ ->assertVisible('@content #aboutframe');
+
+ if ($url = \rcmail::get_instance()->config->get('support_url')) {
+ $browser->assertButton('mainaction.help', 'Get support');
+ }
+ });
$browser->withinFrame('#aboutframe', function ($browser) {
// check task and action
$browser->with(new App(), function ($browser) {
$browser->assertEnv('task', 'settings');
$browser->assertEnv('action', 'about');
});
$browser->assertSee($this->app->config->get('product_name'));
$browser->assertVisible('#pluginlist');
});
+
+ $browser->with(new Dialog(), function ($browser) {
+ $browser->closeDialog();
+ });
});
}
}
diff --git a/tests/Browser/Settings/ResponsesTest.php b/tests/Browser/Settings/ResponsesTest.php
index ef006f59d..0a13dd8dd 100644
--- a/tests/Browser/Settings/ResponsesTest.php
+++ b/tests/Browser/Settings/ResponsesTest.php
@@ -1,196 +1,197 @@
<?php
namespace Tests\Browser\Settings;
use Tests\Browser\Components\App;
+use Tests\Browser\Components\Dialog;
use Tests\Browser\Components\Popupmenu;
class ResponsesTest extends \Tests\Browser\TestCase
{
public static function setUpBeforeClass()
{
\bootstrap::init_db();
}
public function testResponses()
{
$this->browse(function ($browser) {
$browser->go('settings', 'responses');
$browser->with(new App(), function ($browser) {
// check task and action
$browser->assertEnv('task', 'settings');
$browser->assertEnv('action', 'responses');
// these objects should be there always
$browser->assertObjects(['responseslist']);
});
if ($browser->isDesktop()) {
$browser->assertVisible('#settings-menu li.responses.selected');
}
// Responses list
$browser->assertPresent('#responses-table')
->assertMissing('#responses-table tr');
// Toolbar menu
$browser->assertToolbarMenu(['create'], ['delete']);
});
}
/**
* Test response creation
*/
public function testResponseCreate()
{
$this->browse(function ($browser) {
$browser->go('settings', 'responses');
if ($browser->isPhone()) {
$browser->assertVisible('.floating-action-buttons a.create:not(.disabled)')
->click('.floating-action-buttons a.create')
->waitFor('#preferences-frame');
}
else {
$browser->clickToolbarMenuItem('create');
}
$browser->withinFrame('#preferences-frame', function($browser) {
$browser->waitFor('form')
->with('form', function ($browser) {
$browser->assertVisible('input[name=_name]')
->assertValue('input[name=_name]', '')
->assertSeeIn('label[for=ffname]', 'Name')
->assertVisible('textarea[name=_text]')
->assertValue('textarea[name=_text]', '')
->assertSeeIn('label[for=fftext]', 'Response Text');
})
->type('_name', 'Test')
->type('_text', 'Response Body');
if (!$browser->isPhone()) {
$browser->click('.formbuttons button.submit');
}
});
if ($browser->isPhone()) {
$browser->assertVisible('#layout-content .header a.back-list-button')
->assertVisible('#layout-content .footer .buttons a.button.submit')
->click('#layout-content .footer .buttons a.button.submit');
}
$browser->waitForMessage('confirmation', 'Successfully saved.')
->closeMessage('confirmation')
->waitFor('#preferences-frame');
$browser->withinFrame('#preferences-frame', function($browser) {
$browser->waitFor('form')
->with('form', function ($browser) {
$browser->assertVisible('input[name=_name]')
->assertValue('input[name=_name]', 'Test')
->assertValue('textarea[name=_text]', 'Response Body');
});
});
if ($browser->isPhone()) {
$browser->click('#layout-content .header a.back-list-button')
->waitFor('#responses-table');
}
// Responses list
$browser->with('#responses-table', function ($browser) {
$browser->assertElementsCount('tbody tr', 1)
->assertSeeIn('tbody tr:nth-child(1)', 'Test');
});
if ($browser->isPhone()) {
$browser->click('#responses-table tbody tr:first-child')
->waitFor('#preferences-frame');
}
// Toolbar menu (Delete button is active now)
$browser->assertToolbarMenu(['create', 'delete']);
});
}
/**
* Test response deletion
*
* @depends testResponseCreate
*/
public function testResponseDelete()
{
$this->browse(function ($browser) {
$browser->clickToolbarMenuItem('delete');
- $browser->waitFor('.ui-dialog')
- ->with('.ui-dialog', function ($browser) {
- $browser->assertSeeIn('.ui-dialog-title', 'Are you sure...')
- ->assertSeeIn('.ui-dialog-content', 'Do you really want to delete this response text?')
- ->click('.ui-dialog-buttonpane button.mainaction.delete');
- });
+ $browser->with(new Dialog(), function ($browser) {
+ $browser->assertDialogTitle('Are you sure...')
+ ->assertDialogContent('Do you really want to delete this response text?')
+ ->assertButton('mainaction.delete', 'Delete')
+ ->assertButton('cancel', 'Cancel')
+ ->clickButton('mainaction.delete');
+ });
$browser->waitForMessage('confirmation', 'Successfully deleted.')
- ->assertMissing('.ui-dialog')
->closeMessage('confirmation');
// Preview frame should reset to the watermark page
$browser->withinFrame('#preferences-frame', function($browser) {
$browser->waitUntilMissing('> div');
});
$browser->waitFor('#layout-list')
->assertElementsCount('#responses-table tbody tr', 0);
// Toolbar menu (Delete button is inactive again)
$browser->assertToolbarMenu(['create'], ['delete']);
});
}
/**
* Test responses in mail composer
*
* @depends testResponseDelete
*/
public function testResponsesInComposer()
{
// Quickly create a set of responses
$responses = array(
array('name' => 'Test 1', 'text' => 'Response 1', 'format' => 'text', 'key' => substr(md5('Test 1'), 0, 16)),
array('name' => 'Test 2', 'text' => 'Response 2', 'format' => 'text', 'key' => substr(md5('Test 2'), 0, 16)),
);
(new \rcube_user(1))->save_prefs(array('compose_responses' => $responses));
$this->browse(function ($browser) {
if ($browser->isPhone()) {
$browser->click('a.back-sidebar-button');
}
// Goto Compose and test the responses menu
$browser->clickTaskMenuItem('compose')
->waitFor('#compose-content')
->clickToolbarMenuItem('responses')
->with(new Popupmenu('responses-menu'), function ($browser) {
$browser->assertMenuState(['create.responses', 'edit.responses'])
->with('#responseslist', function ($browser) {
$browser->assertElementsCount('li', 2)
->assertSeeIn('li:nth-child(1) a.insertresponse', 'Test 1')
->assertSeeIn('li:nth-child(2) a.insertresponse', 'Test 2');
})
->closeMenu();
});
// Insert a response to the message body
$browser->type('#composebody', 'Body and ')
->clickToolbarMenuItem('responses')
->waitFor('#responseslist')
->click('#responseslist li:nth-child(1) a.insertresponse')
->waitUntilMissing('#responses-menu')
->assertValue('#composebody', 'Body and Response 1');
// TODO: Test HTML mode, test response creation
});
}
}
diff --git a/tests/Browser/bootstrap.php b/tests/Browser/bootstrap.php
index a7b0ccdb5..80e89452a 100644
--- a/tests/Browser/bootstrap.php
+++ b/tests/Browser/bootstrap.php
@@ -1,247 +1,248 @@
<?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/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);
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)
{
$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);
}
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()
{
$db = rcmail::get_instance()->get_dbh();
$query = $db->query("SELECT preferences FROM users WHERE username = ?", TESTS_USER);
$record = $db->fetch_assoc($query);
return unserialize($record['preferences']);
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Aug 25, 7:30 PM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
257763
Default Alt Text
(43 KB)
Attached To
Mode
R3 roundcubemail
Attached
Detach File
Event Timeline
Log In to Comment