summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Framework/Mime.php62
-rw-r--r--tests/Framework/StringReplacer.php24
-rw-r--r--tests/Framework/Utils.php65
-rw-r--r--tests/Framework/VCard.php14
-rw-r--r--tests/Framework/Washtml.php45
-rw-r--r--tests/MailFunc.php8
-rw-r--r--tests/Selenium/Addressbook/Addressbook.php21
-rw-r--r--tests/Selenium/Addressbook/Import.php29
-rw-r--r--tests/Selenium/Login.php21
-rw-r--r--tests/Selenium/Logout.php20
-rw-r--r--tests/Selenium/Mail/CheckRecent.php14
-rw-r--r--tests/Selenium/Mail/Compose.php25
-rw-r--r--tests/Selenium/Mail/Getunread.php13
-rw-r--r--tests/Selenium/Mail/List.php25
-rw-r--r--tests/Selenium/Mail/Mail.php23
-rw-r--r--tests/Selenium/Settings/About.php14
-rw-r--r--tests/Selenium/Settings/Folders.php20
-rw-r--r--tests/Selenium/Settings/Identities.php19
-rw-r--r--tests/Selenium/Settings/Settings.php17
-rw-r--r--tests/Selenium/bootstrap.php185
-rw-r--r--tests/Selenium/index.html8
-rw-r--r--tests/Selenium/phpunit.xml21
-rw-r--r--tests/src/Csv2vcard/tb_plain.csv2
-rw-r--r--tests/src/Csv2vcard/tb_plain.vcf2
-rw-r--r--tests/src/format-flowed-unfolded.txt2
-rw-r--r--tests/src/format-flowed.txt6
26 files changed, 683 insertions, 22 deletions
diff --git a/tests/Framework/Mime.php b/tests/Framework/Mime.php
index 1f9a8c58f..4db1856be 100644
--- a/tests/Framework/Mime.php
+++ b/tests/Framework/Mime.php
@@ -39,6 +39,8 @@ class Framework_Mime extends PHPUnit_Framework_TestCase
19 => 'Test <"test test"@domain.tld>',
20 => '<"test test"@domain.tld>',
21 => '"test test"@domain.tld',
+ // invalid (#1489092)
+ 22 => '"John Doe @ SomeBusinessName" <MAILER-DAEMON>',
);
$results = array(
@@ -64,6 +66,8 @@ class Framework_Mime extends PHPUnit_Framework_TestCase
19 => array(1, 'Test', '"test test"@domain.tld'),
20 => array(1, '', '"test test"@domain.tld'),
21 => array(1, '', '"test test"@domain.tld'),
+ // invalid (#1489092)
+ 22 => array(1, 'John Doe @ SomeBusinessName', 'MAILER-DAEMON'),
);
foreach ($headers as $idx => $header) {
@@ -142,4 +146,62 @@ class Framework_Mime extends PHPUnit_Framework_TestCase
$this->assertEquals($unfolded, rcube_mime::unfold_flowed($flowed), "Test correct unfolding of quoted lines");
}
+
+ /**
+ * Test wordwrap()
+ */
+ function test_wordwrap()
+ {
+ $samples = array(
+ array(
+ array("aaaa aaaa\n aaaa"),
+ "aaaa aaaa\n aaaa",
+ ),
+ array(
+ array("123456789 123456789 123456789 123", 29),
+ "123456789 123456789 123456789\n123",
+ ),
+ array(
+ array("123456789 3456789 123456789", 29),
+ "123456789 3456789 123456789",
+ ),
+ array(
+ array("123456789 123456789 123456789 123", 29),
+ "123456789 123456789 123456789\n 123",
+ ),
+ array(
+ array("abc", 1, "\n", true),
+ "a\nb\nc",
+ ),
+ array(
+ array("ąść", 1, "\n", true, 'UTF-8'),
+ "ą\nś\nć",
+ ),
+ array(
+ array(">abc\n>def", 2, "\n", true),
+ ">abc\n>def",
+ ),
+ array(
+ array("abc def", 3, "-"),
+ "abc-def",
+ ),
+ array(
+ array("----------------------------------------------------------------------------------------\nabc def123456789012345", 76),
+ "----------------------------------------------------------------------------------------\nabc def123456789012345",
+ ),
+ array(
+ array("-------\nabc def", 5),
+ "-------\nabc\ndef",
+ ),
+ array(
+ array("http://xx.xxx.xx.xxx:8080/addressbooks/roundcubexxxxx%40xxxxxxxxxxxxxxxxxxxxxxx.xx.xx/testing/", 70),
+ "http://xx.xxx.xx.xxx:8080/addressbooks/roundcubexxxxx%40xxxxxxxxxxxxxxxxxxxxxxx.xx.xx/testing/",
+ ),
+ );
+
+ foreach ($samples as $sample) {
+ $this->assertEquals($sample[1], call_user_func_array(array('rcube_mime', 'wordwrap'), $sample[0]), "Test text wrapping");
+ }
+ }
+
}
diff --git a/tests/Framework/StringReplacer.php b/tests/Framework/StringReplacer.php
index e630ebac0..dc7638734 100644
--- a/tests/Framework/StringReplacer.php
+++ b/tests/Framework/StringReplacer.php
@@ -24,19 +24,21 @@ class Framework_StringReplacer extends PHPUnit_Framework_TestCase
function data_replace()
{
return array(
- array('http://domain.tld/path*path2', '<a href="http://domain.tld/path*path2" target="_blank">http://domain.tld/path*path2</a>'),
- array("Click this link:\nhttps://mail.xn--brderli-o2a.ch/rc/ EOF", "Click this link:\n<a href=\"https://mail.xn--brderli-o2a.ch/rc/\" target=\"_blank\">https://mail.xn--brderli-o2a.ch/rc/</a> EOF"),
- array('Start http://localhost/?foo End', 'Start <a href="http://localhost/?foo" target="_blank">http://localhost/?foo</a> End'),
- array('www.domain.tld', '<a href="http://www.domain.tld" target="_blank">www.domain.tld</a>'),
- array('WWW.DOMAIN.TLD', '<a href="http://WWW.DOMAIN.TLD" target="_blank">WWW.DOMAIN.TLD</a>'),
- array('[http://link.com]', '[<a href="http://link.com" target="_blank">http://link.com</a>]'),
- array('http://link.com?a[]=1', '<a href="http://link.com?a[]=1" target="_blank">http://link.com?a[]=1</a>'),
- array('http://link.com?a[]', '<a href="http://link.com?a[]" target="_blank">http://link.com?a[]</a>'),
- array('(http://link.com)', '(<a href="http://link.com" target="_blank">http://link.com</a>)'),
- array('http://link.com?a(b)c', '<a href="http://link.com?a(b)c" target="_blank">http://link.com?a(b)c</a>'),
- array('http://link.com?(link)', '<a href="http://link.com?(link)" target="_blank">http://link.com?(link)</a>'),
+ array('http://domain.tld/path*path2', '<a href="http://domain.tld/path*path2">http://domain.tld/path*path2</a>'),
+ array("Click this link:\nhttps://mail.xn--brderli-o2a.ch/rc/ EOF", "Click this link:\n<a href=\"https://mail.xn--brderli-o2a.ch/rc/\">https://mail.xn--brderli-o2a.ch/rc/</a> EOF"),
+ array('Start http://localhost/?foo End', 'Start <a href="http://localhost/?foo">http://localhost/?foo</a> End'),
+ array('www.domain.tld', '<a href="http://www.domain.tld">www.domain.tld</a>'),
+ array('WWW.DOMAIN.TLD', '<a href="http://WWW.DOMAIN.TLD">WWW.DOMAIN.TLD</a>'),
+ array('[http://link.com]', '[<a href="http://link.com">http://link.com</a>]'),
+ array('http://link.com?a[]=1', '<a href="http://link.com?a[]=1">http://link.com?a[]=1</a>'),
+ array('http://link.com?a[]', '<a href="http://link.com?a[]">http://link.com?a[]</a>'),
+ array('(http://link.com)', '(<a href="http://link.com">http://link.com</a>)'),
+ array('http://link.com?a(b)c', '<a href="http://link.com?a(b)c">http://link.com?a(b)c</a>'),
+ array('http://link.com?(link)', '<a href="http://link.com?(link)">http://link.com?(link)</a>'),
array('http://<test>', 'http://<test>'),
array('http://', 'http://'),
+ array('1@1.com www.domain.tld', '<a href="mailto:1@1.com">1@1.com</a> <a href="http://www.domain.tld">www.domain.tld</a>'),
+ array(' www.domain.tld ', ' <a href="http://www.domain.tld">www.domain.tld</a> '),
);
}
diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php
index 7c1e92ac8..abfb7cb65 100644
--- a/tests/Framework/Utils.php
+++ b/tests/Framework/Utils.php
@@ -195,6 +195,23 @@ class Framework_Utils extends PHPUnit_Framework_TestCase
}
/**
+ * Check rcube_utils::explode_quoted_string()
+ */
+ function test_explode_quoted_string()
+ {
+ $data = array(
+ '"a,b"' => array('"a,b"'),
+ '"a,b","c,d"' => array('"a,b"','"c,d"'),
+ '"a,\\"b",d' => array('"a,\\"b"', 'd'),
+ );
+
+ foreach ($data as $text => $res) {
+ $result = rcube_utils::explode_quoted_string(',', $text);
+ $this->assertSame($res, $result);
+ }
+ }
+
+ /**
* Check rcube_utils::explode_quoted_string() compat. with explode()
*/
function test_explode_quoted_string_compat()
@@ -229,4 +246,52 @@ class Framework_Utils extends PHPUnit_Framework_TestCase
}
}
+ /**
+ * rcube:utils::file2class()
+ */
+ function test_file2class()
+ {
+ $test = array(
+ array('', '', 'unknown'),
+ array('text', 'text', 'text'),
+ array('image/png', 'image.png', 'image png'),
+ );
+
+ foreach ($test as $v) {
+ $result = rcube_utils::file2class($v[0], $v[1]);
+ $this->assertSame($v[2], $result);
+ }
+ }
+
+ /**
+ * rcube:utils::strtotime()
+ */
+ function test_strtotime()
+ {
+ $test = array(
+ '1' => 1,
+ '' => 0,
+ );
+
+ foreach ($test as $datetime => $ts) {
+ $result = rcube_utils::strtotime($datetime);
+ $this->assertSame($ts, $result);
+ }
+ }
+
+ /**
+ * rcube:utils::normalize _string()
+ */
+ function test_normalize_string()
+ {
+ $test = array(
+ '' => '',
+ 'abc def' => 'abc def',
+ );
+
+ foreach ($test as $input => $output) {
+ $result = rcube_utils::normalize_string($input);
+ $this->assertSame($output, $result);
+ }
+ }
}
diff --git a/tests/Framework/VCard.php b/tests/Framework/VCard.php
index 15aa5d816..3353b5b13 100644
--- a/tests/Framework/VCard.php
+++ b/tests/Framework/VCard.php
@@ -65,6 +65,20 @@ class Framework_VCard extends PHPUnit_Framework_TestCase
$this->assertEquals("prefix", $vcard['prefix'], "Decode backslash character");
}
+ /**
+ * Backslash parsing test (#1489085)
+ */
+ function test_parse_five()
+ {
+ $vcard = "BEGIN:VCARD\nVERSION:3.0\nN:last\\\\\\a;fir\\nst\nURL:http\\://domain.tld\nEND:VCARD";
+ $vcard = new rcube_vcard($vcard, null);
+ $vcard = $vcard->get_assoc();
+
+ $this->assertEquals("last\\a", $vcard['surname'], "Decode dummy backslash character");
+ $this->assertEquals("fir\nst", $vcard['firstname'], "Decode backslash character");
+ $this->assertEquals("http://domain.tld", $vcard['website:other'][0], "Decode dummy backslash character");
+ }
+
function test_import()
{
$input = file_get_contents($this->_srcpath('apple.vcf'));
diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php
index 088ac4a8c..cb7234314 100644
--- a/tests/Framework/Washtml.php
+++ b/tests/Framework/Washtml.php
@@ -18,11 +18,54 @@ class Framework_Washtml extends PHPUnit_Framework_TestCase
.'<a href="vbscript:alert(document.cookie)">Internet Explorer</a></p>';
$washer = new rcube_washtml;
-
$washed = $washer->wash($html);
$this->assertNotRegExp('/data:text/', $washed, "Remove data:text/html links");
$this->assertNotRegExp('/vbscript:/', $washed, "Remove vbscript: links");
}
+ /**
+ * Test fixing of invalid href (#1488940)
+ */
+ function test_href()
+ {
+ $html = "<p><a href=\"\nhttp://test.com\n\">Firefox</a>";
+
+ $washer = new rcube_washtml;
+ $washed = $washer->wash($html);
+
+ $this->assertRegExp('|href="http://test.com">|', $washed, "Link href with newlines (#1488940)");
+ }
+
+ /**
+ * Test handling HTML comments
+ */
+ function test_comments()
+ {
+ $washer = new rcube_washtml;
+
+ $html = "<!--[if gte mso 10]><p>p1</p><!--><p>p2</p>";
+ $washed = $washer->wash($html);
+
+ $this->assertEquals('<!-- node type 8 --><!-- html ignored --><!-- body ignored --><p>p2</p>', $washed, "HTML conditional comments (#1489004)");
+
+ $html = "<!--TestCommentInvalid><p>test</p>";
+ $washed = $washer->wash($html);
+
+ $this->assertEquals('<!-- html ignored --><!-- body ignored --><p>test</p>', $washed, "HTML invalid comments (#1487759)");
+ }
+
+ /**
+ * Test fixing of invalid self-closing elements (#1489137)
+ */
+ function test_self_closing()
+ {
+ $html = "<textarea>test";
+
+ $washer = new rcube_washtml;
+ $washed = $washer->wash($html);
+
+ $this->assertRegExp('|<textarea>test</textarea>|', $washed, "Self-closing textarea (#1489137)");
+ }
+
}
diff --git a/tests/MailFunc.php b/tests/MailFunc.php
index 38c0bac30..319075abd 100644
--- a/tests/MailFunc.php
+++ b/tests/MailFunc.php
@@ -54,7 +54,7 @@ class MailFunc extends PHPUnit_Framework_TestCase
$this->assertNotRegExp('/<form [^>]+>/', $html, "No form tags allowed");
$this->assertRegExp('/Subscription form/', $html, "Include <form> contents");
$this->assertRegExp('/<!-- link ignored -->/', $html, "No external links allowed");
- $this->assertRegExp('/<a[^>]+ target="_blank">/', $html, "Set target to _blank");
+ $this->assertRegExp('/<a[^>]+ target="_blank"/', $html, "Set target to _blank");
$this->assertTrue($GLOBALS['REMOTE_OBJECTS'], "Remote object detected");
// render HTML in safe mode
@@ -133,8 +133,8 @@ class MailFunc extends PHPUnit_Framework_TestCase
$html = rcmail_print_body($part, array('safe' => true));
$this->assertRegExp('/<a href="mailto:nobody@roundcube.net" onclick="return rcmail.command\(\'compose\',\'nobody@roundcube.net\',this\)">nobody@roundcube.net<\/a>/', $html, "Mailto links with onclick");
- $this->assertRegExp('#<a href="http://www.apple.com/legal/privacy" target="_blank">http://www.apple.com/legal/privacy</a>#', $html, "Links with target=_blank");
- $this->assertRegExp('#\\[<a href="http://example.com/\\?tx\\[a\\]=5" target="_blank">http://example.com/\\?tx\\[a\\]=5</a>\\]#', $html, "Links with square brackets");
+ $this->assertRegExp('#<a rel="noreferrer" target="_blank" href="http://www.apple.com/legal/privacy">http://www.apple.com/legal/privacy</a>#', $html, "Links with target=_blank");
+ $this->assertRegExp('#\\[<a rel="noreferrer" target="_blank" href="http://example.com/\\?tx\\[a\\]=5">http://example.com/\\?tx\\[a\\]=5</a>\\]#', $html, "Links with square brackets");
}
/**
@@ -148,7 +148,7 @@ class MailFunc extends PHPUnit_Framework_TestCase
$html = rcmail_html4inline(rcmail_print_body($part, array('safe' => false)), 'foo');
$mailto = '<a href="mailto:me@me.com?subject=this is the subject&amp;body=this is the body"'
- .' onclick="return rcmail.command(\'compose\',\'me@me.com?subject=this is the subject&amp;body=this is the body\',this)">e-mail</a>';
+ .' onclick="return rcmail.command(\'compose\',\'me@me.com?subject=this is the subject&amp;body=this is the body\',this)" rel="noreferrer">e-mail</a>';
$this->assertRegExp('|'.preg_quote($mailto, '|').'|', $html, "Extended mailto links");
}
diff --git a/tests/Selenium/Addressbook/Addressbook.php b/tests/Selenium/Addressbook/Addressbook.php
new file mode 100644
index 000000000..9a22b6e13
--- /dev/null
+++ b/tests/Selenium/Addressbook/Addressbook.php
@@ -0,0 +1,21 @@
+<?php
+
+class Selenium_Addressbook_Addressbook extends Selenium_Test
+{
+ public function testAddressbook()
+ {
+ $this->go('addressbook');
+
+ // check task
+ $env = $this->get_env();
+ $this->assertEquals('addressbook', $env['task']);
+
+ $objects = $this->get_objects();
+
+ // these objects should be there always
+ $this->assertContains('qsearchbox', $objects);
+ $this->assertContains('folderlist', $objects);
+ $this->assertContains('contactslist', $objects);
+ $this->assertContains('countdisplay', $objects);
+ }
+}
diff --git a/tests/Selenium/Addressbook/Import.php b/tests/Selenium/Addressbook/Import.php
new file mode 100644
index 000000000..13d81740f
--- /dev/null
+++ b/tests/Selenium/Addressbook/Import.php
@@ -0,0 +1,29 @@
+<?php
+
+class Selenium_Addressbook_Import extends Selenium_Test
+{
+ public function testImport()
+ {
+ $this->go('addressbook', 'import');
+
+ // check task and action
+ $env = $this->get_env();
+ $this->assertEquals('addressbook', $env['task']);
+ $this->assertEquals('import', $env['action']);
+
+ $objects = $this->get_objects();
+
+ // these objects should be there always
+ $this->assertContains('importform', $objects);
+ }
+
+ public function testImport2()
+ {
+ $this->go('addressbook', 'import');
+
+ $objects = $this->get_objects();
+
+ // these objects should be there always
+ $this->assertContains('importform', $objects);
+ }
+}
diff --git a/tests/Selenium/Login.php b/tests/Selenium/Login.php
new file mode 100644
index 000000000..a3f0ab6b4
--- /dev/null
+++ b/tests/Selenium/Login.php
@@ -0,0 +1,21 @@
+<?php
+
+class Selenium_Login extends Selenium_Test
+{
+ public function testLogin()
+ {
+ // first test, we're already on the login page
+ $this->url(TESTS_URL);
+
+ // task should be set to 'login'
+ $env = $this->get_env();
+ $this->assertEquals('login', $env['task']);
+
+ // test valid login
+ $this->login();
+
+ // task should be set to 'mail' now
+ $env = $this->get_env();
+ $this->assertEquals('mail', $env['task']);
+ }
+}
diff --git a/tests/Selenium/Logout.php b/tests/Selenium/Logout.php
new file mode 100644
index 000000000..95eeda57c
--- /dev/null
+++ b/tests/Selenium/Logout.php
@@ -0,0 +1,20 @@
+<?php
+
+class Selenium_Logout extends Selenium_Test
+{
+ public function testLogout()
+ {
+ $this->go('mail');
+
+ $this->click_button('logout');
+
+ sleep(TESTS_SLEEP);
+
+ // task should be set to 'login'
+ $env = $this->get_env();
+ $this->assertEquals('login', $env['task']);
+
+ // form should exist
+ $user_input = $this->byCssSelector('form input[name="_user"]');
+ }
+}
diff --git a/tests/Selenium/Mail/CheckRecent.php b/tests/Selenium/Mail/CheckRecent.php
new file mode 100644
index 000000000..865421c2d
--- /dev/null
+++ b/tests/Selenium/Mail/CheckRecent.php
@@ -0,0 +1,14 @@
+<?php
+
+class Selenium_Mail_CheckRecent extends Selenium_Test
+{
+ public function testCheckRecent()
+ {
+ $this->go('mail');
+
+ $res = $this->ajaxResponse('check-recent', "rcmail.command('checkmail')");
+
+ $this->assertEquals('check-recent', $res['action']);
+ $this->assertRegExp('/this\.set_unread_count/', $res['exec']);
+ }
+}
diff --git a/tests/Selenium/Mail/Compose.php b/tests/Selenium/Mail/Compose.php
new file mode 100644
index 000000000..e707ef17d
--- /dev/null
+++ b/tests/Selenium/Mail/Compose.php
@@ -0,0 +1,25 @@
+<?php
+
+class Selenium_Mail_Compose extends Selenium_Test
+{
+ public function testCompose()
+ {
+ $this->go('mail', 'compose');
+
+ // check task and action
+ $env = $this->get_env();
+ $this->assertEquals('mail', $env['task']);
+ $this->assertEquals('compose', $env['action']);
+
+ $objects = $this->get_objects();
+
+ // these objects should be there always
+ $this->assertContains('qsearchbox', $objects);
+ $this->assertContains('addressbookslist', $objects);
+ $this->assertContains('contactslist', $objects);
+ $this->assertContains('messageform', $objects);
+ $this->assertContains('attachmentlist', $objects);
+ $this->assertContains('filedrop', $objects);
+ $this->assertContains('uploadform', $objects);
+ }
+}
diff --git a/tests/Selenium/Mail/Getunread.php b/tests/Selenium/Mail/Getunread.php
new file mode 100644
index 000000000..d6362f2f4
--- /dev/null
+++ b/tests/Selenium/Mail/Getunread.php
@@ -0,0 +1,13 @@
+<?php
+
+class Selenium_Mail_Getunread extends Selenium_Test
+{
+ public function testGetunread()
+ {
+ $this->go('mail');
+
+ $res = $this->ajaxResponse('getunread', "rcmail.http_request('getunread')");
+
+ $this->assertEquals('getunread', $res['action']);
+ }
+}
diff --git a/tests/Selenium/Mail/List.php b/tests/Selenium/Mail/List.php
new file mode 100644
index 000000000..7574c1801
--- /dev/null
+++ b/tests/Selenium/Mail/List.php
@@ -0,0 +1,25 @@
+<?php
+
+class Selenium_Mail_List extends Selenium_Test
+{
+ public function testCheckRecent()
+ {
+ $this->go('mail');
+
+ $res = $this->ajaxResponse('list', "rcmail.command('list')");
+
+ $this->assertEquals('list', $res['action']);
+ $this->assertRegExp('/this\.set_pagetitle/', $res['exec']);
+ $this->assertRegExp('/this\.set_unread_count/', $res['exec']);
+ $this->assertRegExp('/this\.set_rowcount/', $res['exec']);
+ $this->assertRegExp('/this\.set_message_coltypes/', $res['exec']);
+// $this->assertRegExp('/this\.add_message_row/', $res['exec']);
+
+ $this->assertContains('current_page', $res['env']);
+ $this->assertContains('exists', $res['env']);
+ $this->assertContains('pagecount', $res['env']);
+ $this->assertContains('pagesize', $res['env']);
+ $this->assertContains('messagecount', $res['env']);
+ $this->assertContains('mailbox', $res['env']);
+ }
+}
diff --git a/tests/Selenium/Mail/Mail.php b/tests/Selenium/Mail/Mail.php
new file mode 100644
index 000000000..98413787b
--- /dev/null
+++ b/tests/Selenium/Mail/Mail.php
@@ -0,0 +1,23 @@
+<?php
+
+class Selenium_Mail_Mail extends Selenium_Test
+{
+ public function testMail()
+ {
+ $this->go('mail');
+
+ // check task
+ $env = $this->get_env();
+ $this->assertEquals('mail', $env['task']);
+
+ $objects = $this->get_objects();
+
+ // these objects should be there always
+ $this->assertContains('qsearchbox', $objects);
+ $this->assertContains('mailboxlist', $objects);
+ $this->assertContains('messagelist', $objects);
+ $this->assertContains('quotadisplay', $objects);
+ $this->assertContains('search_filter', $objects);
+ $this->assertContains('countdisplay', $objects);
+ }
+}
diff --git a/tests/Selenium/Settings/About.php b/tests/Selenium/Settings/About.php
new file mode 100644
index 000000000..9a6c31d4b
--- /dev/null
+++ b/tests/Selenium/Settings/About.php
@@ -0,0 +1,14 @@
+<?php
+
+class Selenium_Settings_About extends Selenium_Test
+{
+ public function testAbout()
+ {
+ $this->url(TESTS_URL . '/?_task=settings&_action=about');
+
+ // check task and action
+ $env = $this->get_env();
+ $this->assertEquals('settings', $env['task']);
+ $this->assertEquals('about', $env['action']);
+ }
+}
diff --git a/tests/Selenium/Settings/Folders.php b/tests/Selenium/Settings/Folders.php
new file mode 100644
index 000000000..fa64e45d6
--- /dev/null
+++ b/tests/Selenium/Settings/Folders.php
@@ -0,0 +1,20 @@
+<?php
+
+class Selenium_Settings_Folders extends Selenium_Test
+{
+ public function testFolders()
+ {
+ $this->go('settings', 'folders');
+
+ // task should be set to 'settings' and action to 'folders'
+ $env = $this->get_env();
+ $this->assertEquals('settings', $env['task']);
+ $this->assertEquals('folders', $env['action']);
+
+ $objects = $this->get_objects();
+
+ // these objects should be there always
+ $this->assertContains('quotadisplay', $objects);
+ $this->assertContains('subscriptionlist', $objects);
+ }
+}
diff --git a/tests/Selenium/Settings/Identities.php b/tests/Selenium/Settings/Identities.php
new file mode 100644
index 000000000..869018b09
--- /dev/null
+++ b/tests/Selenium/Settings/Identities.php
@@ -0,0 +1,19 @@
+<?php
+
+class Selenium_Settings_Identities extends Selenium_Test
+{
+ public function testIdentities()
+ {
+ $this->go('settings', 'identities');
+
+ // check task and action
+ $env = $this->get_env();
+ $this->assertEquals('settings', $env['task']);
+ $this->assertEquals('identities', $env['action']);
+
+ $objects = $this->get_objects();
+
+ // these objects should be there always
+ $this->assertContains('identitieslist', $objects);
+ }
+}
diff --git a/tests/Selenium/Settings/Settings.php b/tests/Selenium/Settings/Settings.php
new file mode 100644
index 000000000..08d8339f1
--- /dev/null
+++ b/tests/Selenium/Settings/Settings.php
@@ -0,0 +1,17 @@
+<?php
+
+class Selenium_Settings_Settings extends Selenium_Test
+{
+ public function testSettings()
+ {
+ $this->go('settings');
+
+ // task should be set to 'settings'
+ $env = $this->get_env();
+ $this->assertEquals('settings', $env['task']);
+
+ $objects = $this->get_objects();
+
+ $this->assertContains('sectionslist', $objects);
+ }
+}
diff --git a/tests/Selenium/bootstrap.php b/tests/Selenium/bootstrap.php
new file mode 100644
index 000000000..6611e8feb
--- /dev/null
+++ b/tests/Selenium/bootstrap.php
@@ -0,0 +1,185 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | tests/Selenium/bootstrap.php |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2009-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Environment initialization script for unit tests |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ | Author: Aleksander Machniak <alec@alec.pl> |
+ +-----------------------------------------------------------------------+
+*/
+
+if (php_sapi_name() != 'cli')
+ die("Not in shell mode (php-cli)");
+
+if (!defined('INSTALL_PATH')) define('INSTALL_PATH', realpath(dirname(__FILE__) . '/../../') . '/' );
+
+define('TESTS_DIR', dirname(__FILE__) . '/');
+
+if (@is_dir(TESTS_DIR . 'config')) {
+ define('RCMAIL_CONFIG_DIR', TESTS_DIR . 'config');
+}
+
+require_once(INSTALL_PATH . 'program/include/iniset.php');
+
+// Extend include path so some plugin test won't fail
+$include_path = ini_get('include_path') . PATH_SEPARATOR . TESTS_DIR . '..';
+if (set_include_path($include_path) === false) {
+ die("Fatal error: ini_set/set_include_path does not work.");
+}
+
+$rcmail = rcube::get_instance();
+
+define('TESTS_URL', $rcmail->config->get('tests_url'));
+define('TESTS_BROWSER', $rcmail->config->get('tests_browser', 'firefox'));
+define('TESTS_USER', $rcmail->config->get('tests_username'));
+define('TESTS_PASS', $rcmail->config->get('tests_password'));
+define('TESTS_SLEEP', $rcmail->config->get('tests_sleep', 5));
+
+PHPUnit_Extensions_Selenium2TestCase::shareSession(true);
+
+// @TODO: remove user record from DB before running tests
+// @TODO: make sure mailbox has some content (always the same) or is empty
+// @TODO: plugins: enable all?
+
+/**
+ * Base class for all tests in this directory
+ */
+class Selenium_Test extends PHPUnit_Extensions_Selenium2TestCase
+{
+ protected function setUp()
+ {
+// $this->rc = rcube::get_instance();
+ $this->setBrowser(TESTS_BROWSER);
+
+ // Set root to our index.html, for better performance
+ // See https://github.com/sebastianbergmann/phpunit-selenium/issues/217
+ $this->setBrowserUrl(TESTS_URL . '/tests/Selenium');
+ }
+
+ protected function login()
+ {
+ $this->go('mail');
+
+ $user_input = $this->byCssSelector('form input[name="_user"]');
+ $pass_input = $this->byCssSelector('form input[name="_pass"]');
+ $submit = $this->byCssSelector('form input[type="submit"]');
+
+ $user_input->value(TESTS_USER);
+ $pass_input->value(TESTS_PASS);
+
+ // submit login form
+ $submit->click();
+
+ // wait after successful login
+ sleep(TESTS_SLEEP);
+ }
+
+ protected function go($task = 'mail', $action = null)
+ {
+ $this->url(TESTS_URL . '/?_task=' . $task);
+
+ // wait for interface load (initial ajax requests, etc.)
+ sleep(TESTS_SLEEP);
+
+ if ($action) {
+ $this->click_button($action);
+
+ sleep(TESTS_SLEEP);
+ }
+ }
+
+ protected function get_env()
+ {
+ return $this->execute(array(
+ 'script' => 'return rcmail.env;',
+ 'args' => array(),
+ ));
+ }
+
+ protected function get_buttons($action)
+ {
+ $buttons = $this->execute(array(
+ 'script' => "return rcmail.buttons['$action'];",
+ 'args' => array(),
+ ));
+
+ if (is_array($buttons)) {
+ foreach ($buttons as $idx => $button) {
+ $buttons[$idx] = $button['id'];
+ }
+ }
+
+ return (array) $buttons;
+ }
+
+ protected function get_objects()
+ {
+ return $this->execute(array(
+ 'script' => "var i,r = []; for (i in rcmail.gui_objects) r.push(i); return r;",
+ 'args' => array(),
+ ));
+ }
+
+ protected function click_button($action)
+ {
+ $buttons = $this->get_buttons($action);
+ $id = array_shift($buttons);
+
+ // this doesn't work for me
+ $this->byId($id)->click();
+ }
+
+ protected function ajaxResponse($action, $script = '', $button = false)
+ {
+ if (!$script && !$button) {
+ $script = "rcmail.command('$action')";
+ }
+
+ $script =
+ "if (!window.test_ajax_response) {
+ window.test_ajax_response_object = {};
+ function test_ajax_response(response)
+ {
+ if (response.response && response.response.action) {
+ window.test_ajax_response_object[response.response.action] = response.response;
+ }
+ }
+ rcmail.addEventListener('responsebefore', test_ajax_response);
+ }
+ window.test_ajax_response_object['$action'] = null;
+ $script;
+ ";
+
+ // run request
+ $this->execute(array(
+ 'script' => $script,
+ 'args' => array(),
+ ));
+
+ if ($button) {
+ $this->click_button($action);
+ }
+
+ // wait
+ sleep(TESTS_SLEEP);
+
+ // get response
+ $response = $this->execute(array(
+ 'script' => "return window.test_ajax_response_object['$action'];",
+ 'args' => array(),
+ ));
+
+ return $response;
+ }
+}
diff --git a/tests/Selenium/index.html b/tests/Selenium/index.html
new file mode 100644
index 000000000..7aa65f829
--- /dev/null
+++ b/tests/Selenium/index.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+ <title>Roundcube Webmail Tests</title>
+</head>
+<body>
+Testing...
+</body>
+</html>
diff --git a/tests/Selenium/phpunit.xml b/tests/Selenium/phpunit.xml
new file mode 100644
index 000000000..b5835cf74
--- /dev/null
+++ b/tests/Selenium/phpunit.xml
@@ -0,0 +1,21 @@
+<phpunit backupGlobals="false"
+ bootstrap="bootstrap.php"
+ colors="true">
+ <testsuites>
+ <testsuite name="All Tests">
+ <file>Login.php</file><!-- Login.php test must be first -->
+ <file>Addressbook/Addressbook.php</file>
+ <file>Addressbook/Import.php</file>
+ <file>Mail/Mail.php</file>
+ <file>Mail/CheckRecent.php</file>
+ <file>Mail/Compose.php</file>
+ <file>Mail/Getunread.php</file>
+ <file>Mail/List.php</file>
+ <file>Settings/About.php</file>
+ <file>Settings/Folders.php</file>
+ <file>Settings/Identities.php</file>
+ <file>Settings/Settings.php</file>
+ <file>Logout.php</file><!-- Logout.php test must be last -->
+ </testsuite>
+ </testsuites>
+</phpunit>
diff --git a/tests/src/Csv2vcard/tb_plain.csv b/tests/src/Csv2vcard/tb_plain.csv
index 94ea766c0..4c4af14ca 100644
--- a/tests/src/Csv2vcard/tb_plain.csv
+++ b/tests/src/Csv2vcard/tb_plain.csv
@@ -1,2 +1,2 @@
First Name,Last Name,Display Name,Nickname,Primary Email,Secondary Email,Screen Name,Work Phone,Home Phone,Fax Number,Pager Number,Mobile Number,Home Address,Home Address 2,Home City,Home State,Home ZipCode,Home Country,Work Address,Work Address 2,Work City,Work State,Work ZipCode,Work Country,Job Title,Department,Organization,Web Page 1,Web Page 2,Birth Year,Birth Month,Birth Day,Custom 1,Custom 2,Custom 3,Custom 4,Notes,
-Firstname,Lastname,Displayname,Nick,test@domain.tld,next@domain.tld,,phone work,phone home,fax,pager,mobile,Priv address,,City,region,xx-xxx,USA,Addr work,,city,region,33-333,Poland,title,department,Organization,http://page.com,http://webpage.tld,1970,11,15,,,,,,
+Firstname,Lastname,Displayname,Nick,test@domain.tld,next@domain.tld,,phone work,phone home,fax,pager,mobile,Priv address,,City,region,xx-xxx,USA,Addr work,,Wcity,Wstate,33-333,Poland,title,department,Organization,http://page.com,http://webpage.tld,1970,11,15,,,,,,
diff --git a/tests/src/Csv2vcard/tb_plain.vcf b/tests/src/Csv2vcard/tb_plain.vcf
index b001c3924..2aa91adf8 100644
--- a/tests/src/Csv2vcard/tb_plain.vcf
+++ b/tests/src/Csv2vcard/tb_plain.vcf
@@ -16,5 +16,5 @@ URL;TYPE=homepage:http://page.com
URL;TYPE=other:http://webpage.tld
BDAY;VALUE=date:1970-11-15
ADR;TYPE=home:;;Priv address;City;region;xx-xxx;USA
-ADR;TYPE=work:;;Addr work;;;33-333;Poland
+ADR;TYPE=work:;;Addr work;Wcity;Wstate;33-333;Poland
END:VCARD
diff --git a/tests/src/format-flowed-unfolded.txt b/tests/src/format-flowed-unfolded.txt
index 14e526be4..0af9b7130 100644
--- a/tests/src/format-flowed-unfolded.txt
+++ b/tests/src/format-flowed-unfolded.txt
@@ -5,7 +5,7 @@ X
On XX.YY.YYYY Y:YY, Somebody wrote:
> This part is a reply wihtout any flowing lines. rcube_mime::unfold_flowed()
-> has to be careful with empty quoted lines because they might end with a
+>> has to be careful with empty quoted lines because they might end with a
> space but still shouldn't be considered as flowed!
>
> The above empty line should persist after unfolding.
diff --git a/tests/src/format-flowed.txt b/tests/src/format-flowed.txt
index a390ffd11..da36064e0 100644
--- a/tests/src/format-flowed.txt
+++ b/tests/src/format-flowed.txt
@@ -1,13 +1,13 @@
I'm replying on this with a very long line which is then wrapped and
space-stuffed because the draft is saved as format=flowed.
- From what's specified in RFC 2646 some lines need to be space-stuffed to
-avoid muning during transport.
+ From what's specified in RFC 2646 some lines need to be space-stuffed to avoid
+muning during transport.
X
On XX.YY.YYYY Y:YY, Somebody wrote:
> This part is a reply wihtout any flowing lines. rcube_mime::unfold_flowed()
-> has to be careful with empty quoted lines because they might end with a
+>> has to be careful with empty quoted lines because they might end with a
> space but still shouldn't be considered as flowed!
>
> The above empty line should persist after unfolding.