diff --git a/.ci/compose.yaml b/.ci/compose.yaml index 507072487d1..d5acd36cdda 100644 --- a/.ci/compose.yaml +++ b/.ci/compose.yaml @@ -1,6 +1,10 @@ services: mailhost: image: docker.io/greenmail/standalone + environment: + GREENMAIL_OPTS: '-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -Dgreenmail.preload.dir=/emails' + volumes: + - "../tests/MessageRendering/data/greenmail:/emails" browserhost: image: docker.io/selenium/standalone-chromium ports: @@ -40,6 +44,17 @@ services: command: - .ci/run_tests.sh + test_message_rendering: + depends_on: + - mailhost + image: ghcr.io/roundcube/roundcubemail-testrunner:php8.3 + environment: + RC_CONFIG_IMAP_HOST: 'tls://mailhost:3143' + volumes: + - '..:/app' + command: + - .ci/run_test_message_rendering.sh + codespell: image: ghcr.io/roundcube/roundcubemail-testrunner:php8.3 volumes: diff --git a/.ci/run_test_message_rendering.sh b/.ci/run_test_message_rendering.sh new file mode 100755 index 00000000000..a452683c30d --- /dev/null +++ b/.ci/run_test_message_rendering.sh @@ -0,0 +1,11 @@ +#!/bin/bash -ex + +if ! test -f config/config-test.inc.php; then + cp -v .ci/config-test.inc.php config/config-test.inc.php +fi + +# Install dependencies, prefer highest. +composer update --prefer-dist --no-interaction --no-progress + +# Execute tests. +vendor/bin/phpunit -c ./tests/MessageRendering/phpunit.xml --fail-on-warning --fail-on-risky diff --git a/.github/workflows/message_rendering.yml b/.github/workflows/message_rendering.yml new file mode 100644 index 00000000000..e72ed73c996 --- /dev/null +++ b/.github/workflows/message_rendering.yml @@ -0,0 +1,37 @@ +name: Message Rendering + +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + message_rendering: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')" + + strategy: + fail-fast: false + + name: Linux / PHP 8.3 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + # Run via docker compose because we can't run greenmail in a server here + # (it requires the testing emails to be present when starting but + # services are started before the repo is cloned). And instead of + # re-building what our compose-file contains we can just use it. + - name: Run tests via docker compose + run: docker compose -f .ci/compose.yaml run test_message_rendering + + - name: Upload artifacts + uses: actions/upload-artifact@master + if: failure() + with: + name: Logs + path: logs/errors.log + diff --git a/.gitignore b/.gitignore index c88cfb29614..9b3ed0104be 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,6 @@ skins/elastic/styles/_variables.less .vscode .DS_Store .idea + +# Ignore files used for local overriding. +/tests/MessageRendering/.env diff --git a/program/actions/mail/show.php b/program/actions/mail/show.php index 4b831754838..bf586ad22aa 100644 --- a/program/actions/mail/show.php +++ b/program/actions/mail/show.php @@ -172,7 +172,7 @@ public function run($args = []) } } - exit; + $rcmail->output->sendExit(); } /** diff --git a/tests/MessageRendering/.gitignore b/tests/MessageRendering/.gitignore new file mode 100644 index 00000000000..0a6870c64a0 --- /dev/null +++ b/tests/MessageRendering/.gitignore @@ -0,0 +1,11 @@ +src/maildir/subscriptions +src/maildir/dovecot-uidvalidity +src/maildir/dovecot.*.log +src/maildir/dovecot.*.cache +src/maildir/dovecot.list.index +src/maildir/dovecot-uid* +src/maildir/.Drafts +src/maildir/.Junk +src/maildir/.Sent +src/maildir/.Trash +.phpunit.result.cache diff --git a/tests/MessageRendering/BasicMessagesTest.php b/tests/MessageRendering/BasicMessagesTest.php new file mode 100644 index 00000000000..9ef43ea2099 --- /dev/null +++ b/tests/MessageRendering/BasicMessagesTest.php @@ -0,0 +1,69 @@ +runAndGetHtmlOutputDomxpath('99839b8ec12482419372f1edafa9de75@woodcrest.local'); + $this->assertSame('Lines', $this->getScrubbedSubject($domxpath)); + + $this->assertStringStartsWith('Plain text message body.', $this->getBody($domxpath)); + + $attchElems = $domxpath->query('//span[@class="attachment-name"]'); + $this->assertCount(2, $attchElems, 'Attachments'); + $this->assertStringStartsWith('lines.txt', $attchElems[0]->textContent); + $this->assertStringStartsWith('lines_lf.txt', $attchElems[1]->textContent); + } + + /** + * Test that one inline image is not shown as attachment. + */ + public function testList01() + { + $domxpath = $this->runAndGetHtmlOutputDomxpath('3ef8a0120cd7dc2fd776468c8515e29a@domain.tld'); + + $this->assertSame('Test HTML with local and remote image', $this->getScrubbedSubject($domxpath)); + + $this->assertSame("Attached image: \nRemote image:", $this->getBody($domxpath)); + + $attchNames = $domxpath->query('//span[@class="attachment-name"]'); + $this->assertCount(0, $attchNames, 'Attachments'); + } + + /** + * Test that text parts are shown and also listed as attachments, and that + * filenames are properly listed. + */ + public function testFilename() + { + $domxpath = $this->runAndGetHtmlOutputDomxpath('de75@tester.local'); + + $this->assertSame('Attachment filename encoding', $this->getScrubbedSubject($domxpath)); + + $msgParts = $domxpath->query('//div[@class="message-part"]'); + $this->assertCount(3, $msgParts, 'Message text parts'); + + $this->assertSame("foo\nbar\ngna", $msgParts[0]->textContent); + $this->assertSame('潦੯慢ੲ湧', $msgParts[1]->textContent); + $this->assertSame("foo\nbar\ngna", $msgParts[2]->textContent); + + $attchNames = $domxpath->query('//span[@class="attachment-name"]'); + $this->assertCount(6, $attchNames, 'Attachments'); + + $this->assertSame('A011.txt', $attchNames[0]->textContent); + $this->assertSame('A012.txt', $attchNames[1]->textContent); + $this->assertSame('A014.txt', $attchNames[2]->textContent); + $this->assertSame('żółć.png', $attchNames[3]->textContent); + $this->assertSame('żółć.png', $attchNames[4]->textContent); + $this->assertSame('very very very very long very very very very long ćććććć very very very long name.txt', $attchNames[5]->textContent); + } +} diff --git a/tests/MessageRendering/MessageRenderingTestCase.php b/tests/MessageRendering/MessageRenderingTestCase.php new file mode 100644 index 00000000000..293c7d8da11 --- /dev/null +++ b/tests/MessageRendering/MessageRenderingTestCase.php @@ -0,0 +1,95 @@ +query('//div[@id="messagebody"]'); + $this->assertCount(1, $bodyElem, 'Message body'); + return trim($bodyElem[0]->textContent); + } + + /** + * Get the subject from the document, stripped by the prefix "Subject: ", + * the suffix "Open in new window", and trimmed from surrounding whitespace. + */ + protected function getScrubbedSubject(\DOMXPath $domxpath): string + { + $subjectElem = $domxpath->query('//h2[@class="subject"][1]'); + $subject = preg_replace('/^\s*Subject:\s*(.*)\s*Open in new window$/', '$1', trim($subjectElem[0]->textContent)); + return trim($subject); + } + + /** + * Execute run() to render the message with the given $msgId. + * + * This is useful to check how rcmail_action_mail_show() renders messages. + * It requires a running dovecot to fetch the messages from. Messages need + * to be placed as individual files in + * `tests/src/emails/test@example/Mail/cur/`. + */ + protected function runAndGetHtmlOutputDomxpath(string $msgId): \DOMXPath + { + $imap_host = getenv('RC_CONFIG_IMAP_HOST') ?: 'tls://localhost:143'; + $rcmail = \rcmail::get_instance(); + // We need to overwrite the storage object, else storage_init() just + // returns the cached one (which might be a StorageMock instance). + $mockStorage = $rcmail->storage = null; + $rcmail->storage_init(); + // Login our test user so we can fetch messages from the imap server. + $rcmail->login('test-message-rendering@localhost', 'pass', $imap_host); + $storage = $rcmail->get_storage(); + $storage->set_options(['all_headers' => true]); + // We need to set the folder, else no message can be fetched. + $storage->set_folder('INBOX'); + $output = $this->initOutput(\rcmail_action::MODE_HTTP, 'mail', 'preview'); + // TODO: Why do we need to set the skin manually? + $output->set_skin('elastic'); + + $action = new \rcmail_action_mail_show(); + $this->assertTrue($action->checks()); + + $messagesList = $storage->list_messages(); + + // Find the UID of the wanted message. + $messageUid = null; + foreach ($messagesList as $messageHeaders) { + if ($messageHeaders->get('message-id') === "<{$msgId}>") { + $messageUid = $messageHeaders->uid; + break; + } + } + if ($messageUid === null) { + throw new \Exception("No message found in messages list with Message-Id '{$msgId}'"); + } + + // Prepare and trigger the rendering. + $_GET = ['_uid' => $messageUid]; + $html = ''; + try { + $action->run(); + } catch (ExitException $e) { + $html = $output->getOutput(); + } + + // Reset the storage to the mocked one most other tests expect. + $rcmail->storage = $mockStorage; + + // disabled_html_ns=true is a workaround for the performance issue + // https://github.com/Masterminds/html5-php/issues/181 + $html5 = new HTML5(['disable_html_ns' => true]); + return new \DOMXPath($html5->loadHTML($html)); + } +} diff --git a/tests/MessageRendering/SingleImageNoTextTest.php b/tests/MessageRendering/SingleImageNoTextTest.php new file mode 100644 index 00000000000..3e70377e68a --- /dev/null +++ b/tests/MessageRendering/SingleImageNoTextTest.php @@ -0,0 +1,29 @@ +markTestSkipped('TBD: test for fixing GH issue 9443'); + // This next comment line prevents phpstan from reporting this as + // unreachable code (technically it is right, but that's on purpose + // here...). + // @phpstan-ignore-next-line + $domxpath = $this->runAndGetHtmlOutputDomxpath('XXXXXXXXXXXXX@mx01.lytzenitmail.dk'); + + $this->assertSame('Not OK', $this->getScrubbedSubject($domxpath)); + + $attchNames = $domxpath->query('//span[@class="attachment-name"]'); + $this->assertCount(1, $attchNames, 'Attachments'); + $this->assertStringStartsWith('Resized_20240427_200026(1).jpeg', $attchNames[0]->textContent); + } +} diff --git a/tests/MessageRendering/bootstrap.php b/tests/MessageRendering/bootstrap.php new file mode 100644 index 00000000000..1a4cdcc9fe4 --- /dev/null +++ b/tests/MessageRendering/bootstrap.php @@ -0,0 +1,44 @@ + | + | Author: Aleksander Machniak | + +-----------------------------------------------------------------------+ +*/ + +error_reporting(\E_ALL); + +if (\PHP_SAPI != 'cli') { + exit('Not in shell mode (php-cli)'); +} + +if (!defined('INSTALL_PATH')) { + define('INSTALL_PATH', realpath(__DIR__ . '/../../') . '/'); +} + +define('ROUNDCUBE_TEST_MODE', true); +define('ROUNDCUBE_TEST_SESSION', microtime(true)); +define('TESTS_DIR', __DIR__ . '/'); + +if (@is_dir(TESTS_DIR . 'config')) { + define('RCUBE_CONFIG_DIR', TESTS_DIR . 'config'); +} + +// Some tests depend on the way phpunit is executed +$_SERVER['SCRIPT_NAME'] = 'vendor/bin/phpunit'; + +require_once INSTALL_PATH . 'program/include/iniset.php'; + +rcmail::get_instance(0, 'test')->config->set('devel_mode', false); diff --git a/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/attachment-gh9443.eml b/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/attachment-gh9443.eml new file mode 100644 index 00000000000..89301f406ff --- /dev/null +++ b/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/attachment-gh9443.eml @@ -0,0 +1,34 @@ +Message-Id: +Date:Mon, 06 May 2024 15:24:47 +0200 +From: <+45XXXXXXXX@telenor.dk> +To: XXXXXX@jubii.dk +Subject: Not OK +Mime-Version:1.0 +Content-Type:multipart/mixed;boundary="--------------------------------------------=_NextPart_0_24856" + +this is a multi-part message in MIME format. + +----------------------------------------------=_NextPart_0_24856 +Content-Type:image/jpeg; name="Resized_20240427_200026(1).jpeg" +Content-Transfer-Encoding:base64 +Content-Location:Resized_20240427_200026(1).jpeg +Content-ID: + +iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAADMElEQVR4nOzVwQnAIBQFQYXff81R +UkQCOyDj1YOPnbXWPmeTRef+/3O/OyBjzh3CD95BfqICMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0C +MK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMO0TAAD//2An +hf4QtqobAAAAAElFTkSuQmCC + +----------------------------------------------=_NextPart_0_24856-- diff --git a/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/filename.eml b/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/filename.eml new file mode 100644 index 00000000000..b0887421d3b --- /dev/null +++ b/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/filename.eml @@ -0,0 +1,46 @@ +From: "Thomas B." +To: Tom Tester +Subject: Attachment filename encoding +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary=1234; +Date: Fri, 23 May 2014 19:44:50 +0200 +Message-ID: + +--1234 +Content-Transfer-Encoding: base64 +Content-Type: text/plain; name=A011.txt + +Zm9vDQpiYXINCmduYQ== +--1234 +Content-Transfer-Encoding: base64 +Content-Type: text/plain; charset=UTF-16LE; name=A012.txt + +Zm9vCmJhcgpnbmE= +--1234 +Content-Transfer-Encoding: base64 +Content-Type: text/plain; name=A013.txt +Content-Disposition: attachment; filename=A014.txt + +Zm9vDQpiYXINCmduYQ== +--1234 +Content-Transfer-Encoding: base64 +Content-Type: image/png; charset=UTF-16LE; + name="=?UTF-8?Q?=C5=BC=C3=B3=C5=82=C4=87=2Epng?=" + +Zm9vCmJhcgpnbmE= +--1234 +Content-Transfer-Encoding: base64 +Content-Type: image/png; charset=UTF-16LE; name=A016.txt +Content-Disposition: attachment; + filename*=UTF-8''%C5%BC%C3%B3%C5%82%C4%87.png + +Zm9vCmJhcgpnbmE= +--1234 +Content-Transfer-Encoding: base64 +Content-Type: text/plain; charset=iso-8859-1; + name="=?UTF-8?Q?very_very_very_very_long_very_very_very_very_long_=C4=87?= + =?UTF-8?Q?=C4=87=C4=87=C4=87=C4=87=C4=87_very_very_very_long_name=2Etxt?= + =?UTF-8?Q??=" + +Zm9vCmJhcgpnbmE= +--1234-- diff --git a/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/list_00.eml b/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/list_00.eml new file mode 100644 index 00000000000..3c0d10cc746 --- /dev/null +++ b/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/list_00.eml @@ -0,0 +1,46 @@ +Return-Path: +X-Original-To: tb@tester.local +From: "Thomas B." +To: Tom Tester +Subject: Lines +Cc: test1@domain.tld, test2@domain.tld, test3@domain.tld, test4@domain.tld, + test5@domain.tld, test6@domain.tld, test7@domain.tld, test8@domain.tld, + test9@domain.tld, test10@domain.tld, test11@domain.tld, test12@domain.tld +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="=_8853bfb47b7da1852ac882e69cc724f3" +Date: Fri, 23 May 2014 19:44:50 +0200 +Reply-To: hello@roundcube.net +Mail-Reply-To: hello@roundcube.net +Message-ID: <99839b8ec12482419372f1edafa9de75@woodcrest.local> +X-Sender: thomas@roundcube.net + +--=_8853bfb47b7da1852ac882e69cc724f3 +Content-Transfer-Encoding: 7bit +Content-Type: text/plain; charset=UTF-8; + format=flowed + +Plain text message body. + +-- +Developer of Free Software +Sent with Roundcube Webmail - roundcube.net +--=_8853bfb47b7da1852ac882e69cc724f3 +Content-Transfer-Encoding: base64 +Content-Type: text/plain; + name=lines.txt +Content-Disposition: attachment; + filename=lines.txt; + size=13 + +Zm9vDQpiYXINCmduYQ== +--=_8853bfb47b7da1852ac882e69cc724f3 +Content-Transfer-Encoding: base64 +Content-Type: text/plain; + name=lines_lf.txt +Content-Disposition: attachment; + filename=lines_lf.txt; + size=11 + +Zm9vCmJhcgpnbmE= +--=_8853bfb47b7da1852ac882e69cc724f3-- diff --git a/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/list_01.eml b/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/list_01.eml new file mode 100644 index 00000000000..b39a875785f --- /dev/null +++ b/tests/MessageRendering/data/greenmail/test-message-rendering@localhost/INBOX/list_01.eml @@ -0,0 +1,89 @@ +MIME-Version: 1.0 +Content-Type: multipart/alternative; + boundary="=_08f545e592541b77db5fd93e3267655b" +Date: Sat, 11 Jan 2020 19:31:21 +0100 +From: test-from@domain.tld +To: test-to@domain.tld +Subject: Test HTML with local and remote image +Message-ID: <3ef8a0120cd7dc2fd776468c8515e29a@domain.tld> + +--=_08f545e592541b77db5fd93e3267655b +Content-Transfer-Encoding: 7bit +Content-Type: text/plain; charset=US-ASCII; + format=flowed + +Attached image: + +Remote image: +--=_08f545e592541b77db5fd93e3267655b +Content-Type: multipart/related; + boundary="=_48ae8051b8f2cc74607d3ed75f3568af" + +--=_48ae8051b8f2cc74607d3ed75f3568af +Content-Transfer-Encoding: quoted-printable +Content-Type: text/html; charset=UTF-8 + + +

Attached image: 3D""

+

Remote image:

+


+ + + +--=_48ae8051b8f2cc74607d3ed75f3568af +Content-Transfer-Encoding: base64 +Content-ID: <15787674815e1a1479c8db2452476888@alec.pl> +Content-Type: image/x-icon; + name=favicon.ico +Content-Disposition: inline; + filename=favicon.ico; + size=2294 + +AAABAAIAEBAAAAEAIABoBAAAJgAAABAQAAABACAAaAQAAI4EAAAoAAAAEAAAACAAAAABACAAAAAA +AAAEAADDDgAAww4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRPQABUT0ADT0xAQW9hP8DkrDjA +/8E3Qf++NwP/vjcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVE9AAFRPQABUT0AiVE9AilNOQOhp +XD//6rE4//+/N+j/vjeK/743Iv++NwD/vjcAAAAAAAAAAABUT0AAVE9AAFRPQBJUT0BrVE9A11RP +QP5TTkD/aVw//+qxOP//vzf//743/v++N9f/vjdr/743Ev++NwD/vjcAVE9ACFRPQExUT0C/VE9A ++1RPQP9UT0D/U05A/2hcPv/qsDj//783//++N///vjf//743+/++N7//vjdM/743CFRPQKxUT0Dx +VE9A/1RPQP9UT0D/VE9A/1FNPv9sYUb/7LRA//++Nf//vjf//743//++N///vjf//7438f++N6xU +T0D/VE9A/1RPQP9UT0D/U04//1VRQv91cmf/uriz/+vZs//4yWb//r45//++Nf//vjf//743//++ +N///vjf/VE9A/1RPQP9UT0D/U04//2hkWP+cmpT/0NDP/+bn5//l5uj/5+Pb/+/Vn//7xVX//742 +//++N///vjf//743/1RPQP9UT0D/V1JD/4mGfv++vbv/0NDQ/+Hh4f/l5eX/5eXl/+Xl5v/l5uf/ +6ODQ//PPhP/+vzv//743//++N/9UT0D/Uk0+/29rYP/FxcT/zc3N/9PT0//k5OT/5eXl/+Xl5f/l +5eX/5eXl/+Xl5//n49z/+cdf//++Nf//vjf/VE9Ay1JNPvqJh37/zc3N/8zMzP/X19f/5eXl/+Xl +5f/l5eX/5eXl/+Xl5f/l5eX/5eXn//PPhf//vTT6/743y1RPQBZRSzxum5mT4M3Nzf/MzMz/2NjY +/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5//v1Z/g/70ybv++NxZUT0AA////AMbGxXTMzMz/ +zMzM/9bW1v/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5uPdddb9/wD/vjcAAAAAAMzMzADM +zMw2zMzM7MzMzP/T09P/5OTk/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl7OXl5Tfl5eUAAAAAAAAA +AADMzMwAzMzMBczMzJXMzMz/zs7O/+Dg4P/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5Zbk5OQF5OTk +AAAAAAAAAAAAzMzMAMzMzADMzMwYzMzMp8zMzPvW1tb/5OTk/+Xl5f/l5eX/5eXl++Xl5anl5eUZ +5eXlAOHh4QAAAAAAAAAAAAAAAADMzMwAzMzMAMzMzBLMzMx1zc3N1Nzc3Prl5eX65eXl1uXl5Xfl +5eUT5eXlAOLi4gAAAAAAAAAAAPgfAADwDwAAwAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAwAMAAMADAADAAwAA4AcAAPAPAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAADDDgAAww4A +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRPQABUT0ADT0xAQW9hP8DkrDjA/8E3Qf++NwP/vjcA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVE9AAFRPQABUT0AiVE9AilNOQOhpXD//6rE4//+/N+j/ +vjeK/743Iv++NwD/vjcAAAAAAAAAAABUT0AAVE9AAFRPQBJUT0BrVE9A11RPQP5TTkD/aVw//+qx +OP//vzf//743/v++N9f/vjdr/743Ev++NwD/vjcAVE9ACFRPQExUT0C/VE9A+1RPQP9UT0D/U05A +/2hcPv/qsDj//783//++N///vjf//743+/++N7//vjdM/743CFRPQKxUT0DxVE9A/1RPQP9UT0D/ +VE9A/1FNPv9sYUb/7LRA//++Nf//vjf//743//++N///vjf//7438f++N6xUT0D/VE9A/1RPQP9U +T0D/U04//1VRQv91cmf/uriz/+vZs//4yWb//r45//++Nf//vjf//743//++N///vjf/VE9A/1RP +QP9UT0D/U04//2hkWP+cmpT/0NDP/+bn5//l5uj/5+Pb/+/Vn//7xVX//742//++N///vjf//743 +/1RPQP9UT0D/V1JD/4mGfv++vbv/0NDQ/+Hh4f/l5eX/5eXl/+Xl5v/l5uf/6ODQ//PPhP/+vzv/ +/743//++N/9UT0D/Uk0+/29rYP/FxcT/zc3N/9PT0//k5OT/5eXl/+Xl5f/l5eX/5eXl/+Xl5//n +49z/+cdf//++Nf//vjf/VE9Ay1JNPvqJh37/zc3N/8zMzP/X19f/5eXl/+Xl5f/l5eX/5eXl/+Xl +5f/l5eX/5eXn//PPhf//vTT6/743y1RPQBZRSzxum5mT4M3Nzf/MzMz/2NjY/+Xl5f/l5eX/5eXl +/+Xl5f/l5eX/5eXl/+Xl5//v1Z/g/70ybv++NxZUT0AA////AMbGxXTMzMz/zMzM/9bW1v/l5eX/ +5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5uPdddb9/wD/vjcAAAAAAMzMzADMzMw2zMzM7MzMzP/T +09P/5OTk/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl7OXl5Tfl5eUAAAAAAAAAAADMzMwAzMzMBczM +zJXMzMz/zs7O/+Dg4P/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5Zbk5OQF5OTkAAAAAAAAAAAAzMzM +AMzMzADMzMwYzMzMp8zMzPvW1tb/5OTk/+Xl5f/l5eX/5eXl++Xl5anl5eUZ5eXlAOHh4QAAAAAA +AAAAAAAAAADMzMwAzMzMAMzMzBLMzMx1zc3N1Nzc3Prl5eX65eXl1uXl5Xfl5eUT5eXlAOLi4gAA +AAAAAAAAAPgfAADwDwAAwAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAMAAMAD +AADAAwAA4AcAAPAPAAA= +--=_48ae8051b8f2cc74607d3ed75f3568af-- + +--=_08f545e592541b77db5fd93e3267655b-- diff --git a/tests/MessageRendering/phpunit.xml b/tests/MessageRendering/phpunit.xml new file mode 100644 index 00000000000..aad043ff017 --- /dev/null +++ b/tests/MessageRendering/phpunit.xml @@ -0,0 +1,14 @@ + + + + + + + + . + + + diff --git a/tests/MessageRendering/run-tests.sh b/tests/MessageRendering/run-tests.sh new file mode 100755 index 00000000000..c83c7416e6d --- /dev/null +++ b/tests/MessageRendering/run-tests.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +testsdir=$(realpath $(dirname $0)) +cont_name="roundcubetest-dovecot" + +ROUNDCUBE_TEST_IMAP_SERVER_IMAGE="docker.io/dovecot/dovecot:latest" + +test -f "$testsdir/.env" && source "$testsdir/.env" + +docker run -it --rm -d --name "$cont_name" \ + -p 143:143 \ + -v "$testsdir/data/maildir:/srv/mail/test" \ + -v "$testsdir/dovecot-maildir.conf:/etc/dovecot/conf.d/dovecot-maildir.conf" \ + "$ROUNDCUBE_TEST_IMAP_SERVER_IMAGE" >/dev/null || exit 1 + +"$testsdir/../../vendor/bin/phpunit" -c "$testsdir/phpunit.xml" --fail-on-warning --fail-on-risky + +docker stop "$cont_name" >/dev/null diff --git a/tests/OutputHtmlMock.php b/tests/OutputHtmlMock.php index 7b680a09351..2a09eb64df1 100644 --- a/tests/OutputHtmlMock.php +++ b/tests/OutputHtmlMock.php @@ -85,7 +85,7 @@ public function sendExit($body = '', $headers = []) $this->header($header); } - $this->output = $body; + $this->output .= $body; throw new ExitException('Output sent', self::E_EXIT); } diff --git a/tests/phpunit.xml b/tests/phpunit.xml index fc7cacc90f6..035816f7cae 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -22,6 +22,7 @@ . Browser + MessageRendering ../plugins/acl/tests