Page MenuHomePhorge

No OneTemporary

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

Mime Type
text/x-diff
Expires
Mon, Aug 25, 7:30 PM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
257763
Default Alt Text
(43 KB)

Event Timeline