From 0bc15ff75943f2250b4358a429206dbadf207209 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 9 Dec 2020 23:29:35 +0100 Subject: [PATCH 1/4] [PhpUnitBridge] Lint files with PHP 5.5 --- .github/workflows/phpunit-bridge.yml | 28 +++++++++++++++++++ .../Bridge/PhpUnit/ClassExistsMock.php | 12 ++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/phpunit-bridge.yml diff --git a/.github/workflows/phpunit-bridge.yml b/.github/workflows/phpunit-bridge.yml new file mode 100644 index 0000000000..bdda65de1b --- /dev/null +++ b/.github/workflows/phpunit-bridge.yml @@ -0,0 +1,28 @@ +name: PhpUnitBridge + +on: + push: + paths: + - 'src/Symfony/Bridge/PhpUnit/**' + pull_request: + paths: + - 'src/Symfony/Bridge/PhpUnit/**' + +jobs: + + lint: + name: Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + coverage: "none" + php-version: "5.5" + + - name: Lint + run: find ./src/Symfony/Bridge/PhpUnit -name '*.php' | grep -v -e /Tests/ -e ForV6 -e ForV7 -e ForV8 -e ForV9 -e ConstraintLogicTrait | parallel -j 4 php -l {} diff --git a/src/Symfony/Bridge/PhpUnit/ClassExistsMock.php b/src/Symfony/Bridge/PhpUnit/ClassExistsMock.php index e8ca4ac940..d61d7887be 100644 --- a/src/Symfony/Bridge/PhpUnit/ClassExistsMock.php +++ b/src/Symfony/Bridge/PhpUnit/ClassExistsMock.php @@ -30,17 +30,23 @@ class ClassExistsMock public static function class_exists($name, $autoload = true) { - return (bool) (self::$classes[ltrim($name, '\\')] ?? \class_exists($name, $autoload)); + $name = ltrim($name, '\\'); + + return isset(self::$classes[$name]) ? (bool) self::$classes[$name] : \class_exists($name, $autoload); } public static function interface_exists($name, $autoload = true) { - return (bool) (self::$classes[ltrim($name, '\\')] ?? \interface_exists($name, $autoload)); + $name = ltrim($name, '\\'); + + return isset(self::$classes[$name]) ? (bool) self::$classes[$name] : \interface_exists($name, $autoload); } public static function trait_exists($name, $autoload = true) { - return (bool) (self::$classes[ltrim($name, '\\')] ?? \trait_exists($name, $autoload)); + $name = ltrim($name, '\\'); + + return isset(self::$classes[$name]) ? (bool) self::$classes[$name] : \trait_exists($name, $autoload); } public static function register($class) From 55ed00cd3ca28bd4b6785abff54081587e52aecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Mon, 14 Dec 2020 16:50:10 +0100 Subject: [PATCH 2/4] Stop using deprecated trait --- .../Tests/DeprecationErrorHandler/DeprecationTest.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php index 5c2f282640..f36c689099 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php @@ -15,12 +15,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Deprecation; use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV5; -use Symfony\Bridge\PhpUnit\SetUpTearDownTrait; class DeprecationTest extends TestCase { - use SetUpTearDownTrait; - private static $vendorDir; private static $prefixDirsPsr4; @@ -261,7 +258,7 @@ class DeprecationTest extends TestCase rmdir($dir); } - private static function doSetupBeforeClass() + public static function setupBeforeClass(): void { foreach (get_declared_classes() as $class) { if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { @@ -281,7 +278,7 @@ class DeprecationTest extends TestCase } } - private static function doTearDownAfterClass() + public static function tearDownAfterClass(): void { foreach (self::$prefixDirsPsr4 as [$prop, $loader, $prefixDirsPsr4]) { $prop->setValue($loader, $prefixDirsPsr4); From a40d1375f93095576d937438f833072e3980b884 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Fri, 11 Dec 2020 14:04:59 +0100 Subject: [PATCH 3/4] [Mailer] [Amazon] Ensure "ext-simplexml" is loaded if SesApiTransport is used --- .../Mailer/Bridge/Amazon/Transport/SesTransportFactory.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesTransportFactory.php index 5977d2f376..7e1f130788 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesTransportFactory.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesTransportFactory.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Mailer\Bridge\Amazon\Transport; +use Symfony\Component\Mailer\Exception\LogicException; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; use Symfony\Component\Mailer\Transport\AbstractTransportFactory; use Symfony\Component\Mailer\Transport\Dsn; @@ -31,6 +32,10 @@ final class SesTransportFactory extends AbstractTransportFactory $port = $dsn->getPort(); if ('ses+api' === $scheme) { + if (!\extension_loaded('simplexml')) { + throw new LogicException(sprintf('Cannot use "%s". Make sure you have "ext-simplexml" installed and enabled.', SesApiTransport::class)); + } + return (new SesApiTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); } From 856e19168760c3717e01cb3cb6a17f42f3d94c1c Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Fri, 11 Dec 2020 11:45:26 +0100 Subject: [PATCH 4/4] [Notifier] Rework/streamline bridges (5.1) --- .../Bridge/Firebase/FirebaseOptions.php | 3 - .../Firebase/FirebaseTransportFactory.php | 11 ++- .../Tests/FirebaseTransportFactoryTest.php | 61 ++++++++++++ .../Firebase/Tests/FirebaseTransportTest.php | 54 +++++++++++ .../Notifier/Bridge/Firebase/composer.json | 2 +- .../Notifier/Bridge/Firebase/phpunit.xml.dist | 31 +++++++ .../FreeMobile/FreeMobileTransportFactory.php | 11 ++- .../Tests/FreeMobileTransportFactoryTest.php | 35 ++++--- .../Tests/FreeMobileTransportTest.php | 13 +-- .../Mattermost/MattermostTransportFactory.php | 17 +++- .../Tests/MattermostTransportFactoryTest.php | 92 +++++++++++++++++++ .../Tests/MattermostTransportTest.php | 53 +++++++++++ .../Notifier/Bridge/Mattermost/composer.json | 2 +- .../Bridge/Mattermost/phpunit.xml.dist | 31 +++++++ .../Nexmo/Tests/NexmoTransportFactoryTest.php | 14 +-- .../Tests/OvhCloudTransportFactoryTest.php | 17 ++-- .../Bridge/RocketChat/RocketChatTransport.php | 2 +- .../RocketChat/RocketChatTransportFactory.php | 11 ++- .../Tests/RocketChatTransportFactoryTest.php | 73 +++++++++++++++ .../Tests/RocketChatTransportTest.php | 53 +++++++++++ .../Notifier/Bridge/RocketChat/composer.json | 2 +- .../Bridge/RocketChat/phpunit.xml.dist | 31 +++++++ .../Sinch/Tests/SinchTransportFactoryTest.php | 14 +-- .../Bridge/Slack/SlackTransportFactory.php | 14 +-- .../Slack/Tests/SlackTransportFactoryTest.php | 41 ++++++++- .../Bridge/Slack/Tests/SlackTransportTest.php | 53 ++++++----- .../Telegram/TelegramTransportFactory.php | 11 ++- .../Tests/TelegramTransportFactoryTest.php | 30 ++++-- .../Telegram/Tests/TelegramTransportTest.php | 4 +- .../Tests/TwilioTransportFactoryTest.php | 35 ++++--- .../Bridge/Twilio/TwilioTransportFactory.php | 11 ++- 31 files changed, 687 insertions(+), 145 deletions(-) create mode 100644 src/Symfony/Component/Notifier/Bridge/Firebase/Tests/FirebaseTransportFactoryTest.php create mode 100644 src/Symfony/Component/Notifier/Bridge/Firebase/Tests/FirebaseTransportTest.php create mode 100644 src/Symfony/Component/Notifier/Bridge/Firebase/phpunit.xml.dist create mode 100644 src/Symfony/Component/Notifier/Bridge/Mattermost/Tests/MattermostTransportFactoryTest.php create mode 100644 src/Symfony/Component/Notifier/Bridge/Mattermost/Tests/MattermostTransportTest.php create mode 100644 src/Symfony/Component/Notifier/Bridge/Mattermost/phpunit.xml.dist create mode 100644 src/Symfony/Component/Notifier/Bridge/RocketChat/Tests/RocketChatTransportFactoryTest.php create mode 100644 src/Symfony/Component/Notifier/Bridge/RocketChat/Tests/RocketChatTransportTest.php create mode 100644 src/Symfony/Component/Notifier/Bridge/RocketChat/phpunit.xml.dist diff --git a/src/Symfony/Component/Notifier/Bridge/Firebase/FirebaseOptions.php b/src/Symfony/Component/Notifier/Bridge/Firebase/FirebaseOptions.php index 0d098fe286..2072a4cb6a 100644 --- a/src/Symfony/Component/Notifier/Bridge/Firebase/FirebaseOptions.php +++ b/src/Symfony/Component/Notifier/Bridge/Firebase/FirebaseOptions.php @@ -22,12 +22,9 @@ use Symfony\Component\Notifier\Message\MessageOptionsInterface; */ abstract class FirebaseOptions implements MessageOptionsInterface { - /** @var string the recipient */ private $to; /** - * @var array - * * @see https://firebase.google.com/docs/cloud-messaging/xmpp-server-ref.html#notification-payload-support */ protected $options; diff --git a/src/Symfony/Component/Notifier/Bridge/Firebase/FirebaseTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/Firebase/FirebaseTransportFactory.php index e4e55612d2..69f3ee30f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/Firebase/FirebaseTransportFactory.php +++ b/src/Symfony/Component/Notifier/Bridge/Firebase/FirebaseTransportFactory.php @@ -26,15 +26,16 @@ final class FirebaseTransportFactory extends AbstractTransportFactory public function create(Dsn $dsn): TransportInterface { $scheme = $dsn->getScheme(); + + if ('firebase' !== $scheme) { + throw new UnsupportedSchemeException($dsn, 'firebase', $this->getSupportedSchemes()); + } + $token = sprintf('%s:%s', $this->getUser($dsn), $this->getPassword($dsn)); $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); $port = $dsn->getPort(); - if ('firebase' === $scheme) { - return (new FirebaseTransport($token, $this->client, $this->dispatcher))->setHost($host)->setPort($port); - } - - throw new UnsupportedSchemeException($dsn, 'firebase', $this->getSupportedSchemes()); + return (new FirebaseTransport($token, $this->client, $this->dispatcher))->setHost($host)->setPort($port); } protected function getSupportedSchemes(): array diff --git a/src/Symfony/Component/Notifier/Bridge/Firebase/Tests/FirebaseTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/Firebase/Tests/FirebaseTransportFactoryTest.php new file mode 100644 index 0000000000..80a1153a1b --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Firebase/Tests/FirebaseTransportFactoryTest.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Firebase\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Bridge\Firebase\FirebaseTransportFactory; +use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; +use Symfony\Component\Notifier\Transport\Dsn; + +/** + * @author Oskar Stark + */ +final class FirebaseTransportFactoryTest extends TestCase +{ + public function testCreateWithDsn() + { + $factory = $this->createFactory(); + + $transport = $factory->create(Dsn::fromString('firebase://username:password@default')); + $transport->setHost('host.test'); + + $this->assertSame('firebase://host.test', (string) $transport); + } + + public function testSupportsReturnsTrueWithSupportedScheme() + { + $factory = $this->createFactory(); + + $this->assertTrue($factory->supports(Dsn::fromString('firebase://username:password@default'))); + } + + public function testSupportsReturnsFalseWithUnsupportedScheme() + { + $factory = $this->createFactory(); + + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://username:password@default'))); + } + + public function testUnsupportedSchemeThrowsUnsupportedSchemeException() + { + $factory = $this->createFactory(); + + $this->expectException(UnsupportedSchemeException::class); + + $factory->create(Dsn::fromString('somethingElse://username:password@default')); + } + + private function createFactory(): FirebaseTransportFactory + { + return new FirebaseTransportFactory(); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Firebase/Tests/FirebaseTransportTest.php b/src/Symfony/Component/Notifier/Bridge/Firebase/Tests/FirebaseTransportTest.php new file mode 100644 index 0000000000..8f377cdd88 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Firebase/Tests/FirebaseTransportTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Firebase\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Bridge\Firebase\FirebaseTransport; +use Symfony\Component\Notifier\Exception\LogicException; +use Symfony\Component\Notifier\Message\ChatMessage; +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * @author Oskar Stark + */ +final class FirebaseTransportTest extends TestCase +{ + public function testToStringContainsProperties() + { + $transport = $this->createTransport(); + + $this->assertSame('firebase://host.test', (string) $transport); + } + + public function testSupportsMessageInterface() + { + $transport = $this->createTransport(); + + $this->assertTrue($transport->supports(new ChatMessage('testChatMessage'))); + $this->assertFalse($transport->supports($this->createMock(MessageInterface::class))); + } + + public function testSendNonSmsMessageThrowsException() + { + $transport = $this->createTransport(); + + $this->expectException(LogicException::class); + + $transport->send($this->createMock(MessageInterface::class)); + } + + private function createTransport(): FirebaseTransport + { + return (new FirebaseTransport('username:password', $this->createMock(HttpClientInterface::class)))->setHost('host.test'); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Firebase/composer.json b/src/Symfony/Component/Notifier/Bridge/Firebase/composer.json index 8c8f15c3fd..288babcef8 100644 --- a/src/Symfony/Component/Notifier/Bridge/Firebase/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/Firebase/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=7.2.5", "symfony/http-client": "^4.3|^5.0", - "symfony/notifier": "^5.0,<5.2" + "symfony/notifier": "~5.1.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Notifier\\Bridge\\Firebase\\": "" }, diff --git a/src/Symfony/Component/Notifier/Bridge/Firebase/phpunit.xml.dist b/src/Symfony/Component/Notifier/Bridge/Firebase/phpunit.xml.dist new file mode 100644 index 0000000000..66b1cd5652 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Firebase/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + + diff --git a/src/Symfony/Component/Notifier/Bridge/FreeMobile/FreeMobileTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/FreeMobile/FreeMobileTransportFactory.php index aa22deb1ab..aab7925d39 100644 --- a/src/Symfony/Component/Notifier/Bridge/FreeMobile/FreeMobileTransportFactory.php +++ b/src/Symfony/Component/Notifier/Bridge/FreeMobile/FreeMobileTransportFactory.php @@ -30,6 +30,11 @@ final class FreeMobileTransportFactory extends AbstractTransportFactory public function create(Dsn $dsn): TransportInterface { $scheme = $dsn->getScheme(); + + if ('freemobile' !== $scheme) { + throw new UnsupportedSchemeException($dsn, 'freemobile', $this->getSupportedSchemes()); + } + $login = $this->getUser($dsn); $password = $this->getPassword($dsn); $phone = $dsn->getOption('phone'); @@ -38,11 +43,7 @@ final class FreeMobileTransportFactory extends AbstractTransportFactory throw new IncompleteDsnException('Missing phone.', $dsn->getOriginalDsn()); } - if ('freemobile' === $scheme) { - return new FreeMobileTransport($login, $password, $phone, $this->client, $this->dispatcher); - } - - throw new UnsupportedSchemeException($dsn, 'freemobile', $this->getSupportedSchemes()); + return new FreeMobileTransport($login, $password, $phone, $this->client, $this->dispatcher); } protected function getSupportedSchemes(): array diff --git a/src/Symfony/Component/Notifier/Bridge/FreeMobile/Tests/FreeMobileTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/FreeMobile/Tests/FreeMobileTransportFactoryTest.php index 94379141da..082994b374 100644 --- a/src/Symfony/Component/Notifier/Bridge/FreeMobile/Tests/FreeMobileTransportFactoryTest.php +++ b/src/Symfony/Component/Notifier/Bridge/FreeMobile/Tests/FreeMobileTransportFactoryTest.php @@ -30,35 +30,46 @@ final class FreeMobileTransportFactoryTest extends TestCase $this->assertSame('freemobile://host.test?phone=0611223344', (string) $transport); } - public function testCreateWithNoPhoneThrowsMalformed() + public function testCreateWithNoPhoneThrowsIncompleteDsnException() { $factory = $this->createFactory(); $this->expectException(IncompleteDsnException::class); - $dsnIncomplete = 'freemobile://login:pass@default'; - $factory->create(Dsn::fromString($dsnIncomplete)); + $factory->create(Dsn::fromString('freemobile://login:pass@default')); } - public function testSupportsScheme() + public function testSupportsReturnsTrueWithSupportedScheme() { $factory = $this->createFactory(); - $dsn = 'freemobile://login:pass@default?phone=0611223344'; - $dsnUnsupported = 'foobarmobile://login:pass@default?phone=0611223344'; - - $this->assertTrue($factory->supports(Dsn::fromString($dsn))); - $this->assertFalse($factory->supports(Dsn::fromString($dsnUnsupported))); + $this->assertTrue($factory->supports(Dsn::fromString('freemobile://login:pass@default?phone=0611223344'))); } - public function testNonFreeMobileSchemeThrows() + public function testSupportsReturnsFalseWithUnsupportedScheme() + { + $factory = $this->createFactory(); + + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://login:pass@default?phone=0611223344'))); + } + + public function testUnsupportedSchemeThrowsUnsupportedSchemeException() { $factory = $this->createFactory(); $this->expectException(UnsupportedSchemeException::class); - $dsnUnsupported = 'foobarmobile://login:pass@default?phone=0611223344'; - $factory->create(Dsn::fromString($dsnUnsupported)); + $factory->create(Dsn::fromString('somethingElse://login:pass@default?phone=0611223344')); + } + + public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing() + { + $factory = $this->createFactory(); + + $this->expectException(UnsupportedSchemeException::class); + + // unsupported scheme and missing "phone" option + $factory->create(Dsn::fromString('somethingElse://login:pass@default')); } private function createFactory(): FreeMobileTransportFactory diff --git a/src/Symfony/Component/Notifier/Bridge/FreeMobile/Tests/FreeMobileTransportTest.php b/src/Symfony/Component/Notifier/Bridge/FreeMobile/Tests/FreeMobileTransportTest.php index c49a11c530..4e27181cb2 100644 --- a/src/Symfony/Component/Notifier/Bridge/FreeMobile/Tests/FreeMobileTransportTest.php +++ b/src/Symfony/Component/Notifier/Bridge/FreeMobile/Tests/FreeMobileTransportTest.php @@ -22,23 +22,24 @@ final class FreeMobileTransportTest extends TestCase { public function testToStringContainsProperties() { - $transport = $this->initTransport(); + $transport = $this->createTransport(); $this->assertSame('freemobile://host.test?phone=0611223344', (string) $transport); } public function testSupportsMessageInterface() { - $transport = $this->initTransport(); + $transport = $this->createTransport(); $this->assertTrue($transport->supports(new SmsMessage('0611223344', 'Hello!'))); - $this->assertFalse($transport->supports(new SmsMessage('0699887766', 'Hello!'))); + + $this->assertFalse($transport->supports(new SmsMessage('0699887766', 'Hello!'))); // because this phone number is not configured on the transport! $this->assertFalse($transport->supports($this->createMock(MessageInterface::class))); } public function testSendNonSmsMessageThrowsException() { - $transport = $this->initTransport(); + $transport = $this->createTransport(); $this->expectException(LogicException::class); @@ -47,14 +48,14 @@ final class FreeMobileTransportTest extends TestCase public function testSendSmsMessageButInvalidPhoneThrowsException() { - $transport = $this->initTransport(); + $transport = $this->createTransport(); $this->expectException(LogicException::class); $transport->send(new SmsMessage('0699887766', 'Hello!')); } - private function initTransport(): FreeMobileTransport + private function createTransport(): FreeMobileTransport { return (new FreeMobileTransport('login', 'pass', '0611223344', $this->createMock(HttpClientInterface::class)))->setHost('host.test'); } diff --git a/src/Symfony/Component/Notifier/Bridge/Mattermost/MattermostTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/Mattermost/MattermostTransportFactory.php index 884d470ddc..ad057c6151 100644 --- a/src/Symfony/Component/Notifier/Bridge/Mattermost/MattermostTransportFactory.php +++ b/src/Symfony/Component/Notifier/Bridge/Mattermost/MattermostTransportFactory.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Notifier\Bridge\Mattermost; +use Symfony\Component\Notifier\Exception\IncompleteDsnException; use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; use Symfony\Component\Notifier\Transport\AbstractTransportFactory; use Symfony\Component\Notifier\Transport\Dsn; @@ -26,16 +27,22 @@ final class MattermostTransportFactory extends AbstractTransportFactory public function create(Dsn $dsn): TransportInterface { $scheme = $dsn->getScheme(); + + if ('mattermost' !== $scheme) { + throw new UnsupportedSchemeException($dsn, 'mattermost', $this->getSupportedSchemes()); + } + $token = $this->getUser($dsn); $channel = $dsn->getOption('channel'); + + if (!$channel) { + throw new IncompleteDsnException('Missing channel.', $dsn->getOriginalDsn()); + } + $host = $dsn->getHost(); $port = $dsn->getPort(); - if ('mattermost' === $scheme) { - return (new MattermostTransport($token, $channel, $this->client, $this->dispatcher))->setHost($host)->setPort($port); - } - - throw new UnsupportedSchemeException($dsn, 'mattermost', $this->getSupportedSchemes()); + return (new MattermostTransport($token, $channel, $this->client, $this->dispatcher))->setHost($host)->setPort($port); } protected function getSupportedSchemes(): array diff --git a/src/Symfony/Component/Notifier/Bridge/Mattermost/Tests/MattermostTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/Mattermost/Tests/MattermostTransportFactoryTest.php new file mode 100644 index 0000000000..c65b598198 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Mattermost/Tests/MattermostTransportFactoryTest.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Mattermost\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Bridge\Mattermost\MattermostTransportFactory; +use Symfony\Component\Notifier\Exception\IncompleteDsnException; +use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; +use Symfony\Component\Notifier\Transport\Dsn; + +/** + * @author Oskar Stark + */ +final class MattermostTransportFactoryTest extends TestCase +{ + public function testCreateWithDsn() + { + $factory = $this->createFactory(); + + $accessToken = 'testAccessToken'; + $host = 'testHost'; + $channel = 'testChannel'; + + $transport = $factory->create(Dsn::fromString(sprintf('mattermost://%s@%s/?channel=%s', $accessToken, $host, $channel))); + + $this->assertSame(sprintf('mattermost://%s?channel=%s', $host, $channel), (string) $transport); + } + + public function testCreateWithMissingOptionChannelThrowsIncompleteDsnException() + { + $factory = $this->createFactory(); + + $this->expectException(IncompleteDsnException::class); + + $factory->create(Dsn::fromString('mattermost://token@host')); + } + + public function testCreateWithNoTokenThrowsIncompleteDsnException() + { + $factory = $this->createFactory(); + + $this->expectException(IncompleteDsnException::class); + $factory->create(Dsn::fromString(sprintf('mattermost://%s/?channel=%s', 'testHost', 'testChannel'))); + } + + public function testSupportsReturnsTrueWithSupportedScheme() + { + $factory = $this->createFactory(); + + $this->assertTrue($factory->supports(Dsn::fromString('mattermost://token@host/?channel=testChannel'))); + } + + public function testSupportsReturnsFalseWithUnsupportedScheme() + { + $factory = $this->createFactory(); + + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://token@host/?channel=testChannel'))); + } + + public function testUnsupportedSchemeThrowsUnsupportedSchemeException() + { + $factory = $this->createFactory(); + + $this->expectException(UnsupportedSchemeException::class); + + $factory->create(Dsn::fromString('somethingElse://token@host/?channel=testChannel')); + } + + public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing() + { + $factory = $this->createFactory(); + + $this->expectException(UnsupportedSchemeException::class); + + // unsupported scheme and missing "channel" option + $factory->create(Dsn::fromString('somethingElse://token@host')); + } + + private function createFactory(): MattermostTransportFactory + { + return new MattermostTransportFactory(); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Mattermost/Tests/MattermostTransportTest.php b/src/Symfony/Component/Notifier/Bridge/Mattermost/Tests/MattermostTransportTest.php new file mode 100644 index 0000000000..2ef829d8ff --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Mattermost/Tests/MattermostTransportTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Mattermost\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Bridge\Mattermost\MattermostTransport; +use Symfony\Component\Notifier\Exception\LogicException; +use Symfony\Component\Notifier\Message\ChatMessage; +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * @author Oskar Stark + */ +final class MattermostTransportTest extends TestCase +{ + public function testToStringContainsProperties() + { + $transport = $this->createTransport(); + + $this->assertSame('mattermost://host.test?channel=testChannel', (string) $transport); + } + + public function testSupportsChatMessage() + { + $transport = $this->createTransport(); + + $this->assertTrue($transport->supports(new ChatMessage('testChatMessage'))); + $this->assertFalse($transport->supports($this->createMock(MessageInterface::class))); + } + + public function testSendNonChatMessageThrows() + { + $transport = $this->createTransport(); + + $this->expectException(LogicException::class); + $transport->send($this->createMock(MessageInterface::class)); + } + + private function createTransport(): MattermostTransport + { + return (new MattermostTransport('testAccessToken', 'testChannel', $this->createMock(HttpClientInterface::class)))->setHost('host.test'); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Mattermost/composer.json b/src/Symfony/Component/Notifier/Bridge/Mattermost/composer.json index ced3cc8615..9bc99ef26f 100644 --- a/src/Symfony/Component/Notifier/Bridge/Mattermost/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/Mattermost/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=7.2.5", "symfony/http-client": "^4.3|^5.0", - "symfony/notifier": "^5.0,<5.2" + "symfony/notifier": "~5.1.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Notifier\\Bridge\\Mattermost\\": "" }, diff --git a/src/Symfony/Component/Notifier/Bridge/Mattermost/phpunit.xml.dist b/src/Symfony/Component/Notifier/Bridge/Mattermost/phpunit.xml.dist new file mode 100644 index 0000000000..c7f3582812 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Mattermost/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + + diff --git a/src/Symfony/Component/Notifier/Bridge/Nexmo/Tests/NexmoTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/Nexmo/Tests/NexmoTransportFactoryTest.php index ab94043055..5cc9064538 100644 --- a/src/Symfony/Component/Notifier/Bridge/Nexmo/Tests/NexmoTransportFactoryTest.php +++ b/src/Symfony/Component/Notifier/Bridge/Nexmo/Tests/NexmoTransportFactoryTest.php @@ -36,24 +36,21 @@ final class NexmoTransportFactoryTest extends TestCase $this->expectException(IncompleteDsnException::class); - $dsnIncomplete = 'nexmo://apiKey:apiSecret@default'; - $factory->create(Dsn::fromString($dsnIncomplete)); + $factory->create(Dsn::fromString('nexmo://apiKey:apiSecret@default')); } public function testSupportsReturnsTrueWithSupportedScheme() { $factory = $this->createFactory(); - $dsn = 'nexmo://apiKey:apiSecret@default?from=0611223344'; - $this->assertTrue($factory->supports(Dsn::fromString($dsn))); + $this->assertTrue($factory->supports(Dsn::fromString('nexmo://apiKey:apiSecret@default?from=0611223344'))); } public function testSupportsReturnsFalseWithUnsupportedScheme() { $factory = $this->createFactory(); - $dsnUnsupported = 'nexmoo://apiKey:apiSecret@default?from=0611223344'; - $this->assertFalse($factory->supports(Dsn::fromString($dsnUnsupported))); + $this->assertFalse($factory->supports(Dsn::fromString('nexmoo://apiKey:apiSecret@default?from=0611223344'))); } public function testUnsupportedSchemeThrowsUnsupportedSchemeException() @@ -62,8 +59,7 @@ final class NexmoTransportFactoryTest extends TestCase $this->expectException(UnsupportedSchemeException::class); - $dsnUnsupported = 'nexmoo://apiKey:apiSecret@default?from=0611223344'; - $factory->create(Dsn::fromString($dsnUnsupported)); + $factory->create(Dsn::fromString('somethingElse://apiKey:apiSecret@default?from=0611223344')); } public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing() @@ -73,7 +69,7 @@ final class NexmoTransportFactoryTest extends TestCase $this->expectException(UnsupportedSchemeException::class); // unsupported scheme and missing "from" option - $factory->create(Dsn::fromString('nexmoo://apiKey:apiSecret@default')); + $factory->create(Dsn::fromString('somethingElse://apiKey:apiSecret@default')); } private function createFactory(): NexmoTransportFactory diff --git a/src/Symfony/Component/Notifier/Bridge/OvhCloud/Tests/OvhCloudTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/OvhCloud/Tests/OvhCloudTransportFactoryTest.php index be29c21acb..dd9745fe23 100644 --- a/src/Symfony/Component/Notifier/Bridge/OvhCloud/Tests/OvhCloudTransportFactoryTest.php +++ b/src/Symfony/Component/Notifier/Bridge/OvhCloud/Tests/OvhCloudTransportFactoryTest.php @@ -36,8 +36,7 @@ final class OvhCloudTransportFactoryTest extends TestCase $this->expectException(IncompleteDsnException::class); - $dsnIncomplete = 'ovhcloud://applicationKey:applicationSecret@default?service_name=serviceName'; - $factory->create(Dsn::fromString($dsnIncomplete)); + $factory->create(Dsn::fromString('ovhcloud://applicationKey:applicationSecret@default?service_name=serviceName')); } public function testCreateWithMissingOptionServiceNameThrowsIncompleteDsnException() @@ -46,24 +45,21 @@ final class OvhCloudTransportFactoryTest extends TestCase $this->expectException(IncompleteDsnException::class); - $dsnIncomplete = 'ovhcloud://applicationKey:applicationSecret@default?consumeer_key=consumerKey'; - $factory->create(Dsn::fromString($dsnIncomplete)); + $factory->create(Dsn::fromString('ovhcloud://applicationKey:applicationSecret@default?consumeer_key=consumerKey')); } public function testSupportsReturnsTrueWithSupportedScheme() { $factory = $this->createFactory(); - $dsn = 'ovhcloud://applicationKey:applicationSecret@default?consumer_key=consumerKey&service_name=serviceName'; - $this->assertTrue($factory->supports(Dsn::fromString($dsn))); + $this->assertTrue($factory->supports(Dsn::fromString('ovhcloud://applicationKey:applicationSecret@default?consumer_key=consumerKey&service_name=serviceName'))); } public function testSupportsReturnsFalseWithUnsupportedScheme() { $factory = $this->createFactory(); - $dsnUnsupported = 'ovhclouddddd://applicationKey:applicationSecret@default?consumer_key=consumerKey&service_name=serviceName'; - $this->assertFalse($factory->supports(Dsn::fromString($dsnUnsupported))); + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://applicationKey:applicationSecret@default?consumer_key=consumerKey&service_name=serviceName'))); } public function testUnsupportedSchemeThrowsUnsupportedSchemeException() @@ -72,8 +68,7 @@ final class OvhCloudTransportFactoryTest extends TestCase $this->expectException(UnsupportedSchemeException::class); - $dsnUnsupported = 'ovhclouddddd://applicationKey:applicationSecret@default?consumer_key=consumerKey&service_name=serviceName'; - $factory->create(Dsn::fromString($dsnUnsupported)); + $factory->create(Dsn::fromString('somethingElse://applicationKey:applicationSecret@default?consumer_key=consumerKey&service_name=serviceName')); } public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing() @@ -83,7 +78,7 @@ final class OvhCloudTransportFactoryTest extends TestCase $this->expectException(UnsupportedSchemeException::class); // unsupported scheme and missing "service_name" option - $factory->create(Dsn::fromString('ovhclouddddd://applicationKey:applicationSecret@default?consumer_key=consumerKey')); + $factory->create(Dsn::fromString('somethingElse://applicationKey:applicationSecret@default?consumer_key=consumerKey')); } private function createFactory(): OvhCloudTransportFactory diff --git a/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransport.php b/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransport.php index a8a6a6fc36..38880bc5fd 100644 --- a/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransport.php +++ b/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransport.php @@ -51,7 +51,7 @@ final class RocketChatTransport extends AbstractTransport } /** - * @see https://rocket.chat/docs/administrator-guides/integrations/ + * @see https://rocket.chat/docs/administrator-guides/integrations */ protected function doSend(MessageInterface $message): void { diff --git a/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransportFactory.php index b77b4db15b..7aa31d279d 100644 --- a/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransportFactory.php +++ b/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransportFactory.php @@ -26,16 +26,17 @@ final class RocketChatTransportFactory extends AbstractTransportFactory public function create(Dsn $dsn): TransportInterface { $scheme = $dsn->getScheme(); + + if ('rocketchat' !== $scheme) { + throw new UnsupportedSchemeException($dsn, 'rocketchat', $this->getSupportedSchemes()); + } + $accessToken = $this->getUser($dsn); $channel = $dsn->getOption('channel'); $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); $port = $dsn->getPort(); - if ('rocketchat' === $scheme) { - return (new RocketChatTransport($accessToken, $channel, $this->client, $this->dispatcher))->setHost($host)->setPort($port); - } - - throw new UnsupportedSchemeException($dsn, 'rocketchat', $this->getSupportedSchemes()); + return (new RocketChatTransport($accessToken, $channel, $this->client, $this->dispatcher))->setHost($host)->setPort($port); } protected function getSupportedSchemes(): array diff --git a/src/Symfony/Component/Notifier/Bridge/RocketChat/Tests/RocketChatTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/RocketChat/Tests/RocketChatTransportFactoryTest.php new file mode 100644 index 0000000000..b6da446db3 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/RocketChat/Tests/RocketChatTransportFactoryTest.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\RocketChat\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Bridge\RocketChat\RocketChatTransportFactory; +use Symfony\Component\Notifier\Exception\IncompleteDsnException; +use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; +use Symfony\Component\Notifier\Transport\Dsn; + +/** + * @author Oskar Stark + */ +final class RocketChatTransportFactoryTest extends TestCase +{ + public function testCreateWithDsn() + { + $factory = $this->createFactory(); + + $accessToken = 'testAccessToken'; + $host = 'testHost'; + $channel = 'testChannel'; + + $transport = $factory->create(Dsn::fromString(sprintf('rocketchat://%s@%s/?channel=%s', $accessToken, $host, $channel))); + + $this->assertSame(sprintf('rocketchat://%s?channel=%s', $host, $channel), (string) $transport); + } + + public function testCreateWithNoTokenThrowsIncompleteDsnException() + { + $factory = $this->createFactory(); + + $this->expectException(IncompleteDsnException::class); + $factory->create(Dsn::fromString(sprintf('rocketchat://%s/?channel=%s', 'testHost', 'testChannel'))); + } + + public function testSupportsReturnsTrueWithSupportedScheme() + { + $factory = $this->createFactory(); + + $this->assertTrue($factory->supports(Dsn::fromString('rocketchat://token@host/?channel=testChannel'))); + } + + public function testSupportsReturnsFalseWithUnsupportedScheme() + { + $factory = $this->createFactory(); + + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://token@host/?channel=testChannel'))); + } + + public function testUnsupportedSchemeThrowsUnsupportedSchemeException() + { + $factory = $this->createFactory(); + + $this->expectException(UnsupportedSchemeException::class); + + $factory->create(Dsn::fromString('somethingElse://token@host/?channel=testChannel')); + } + + private function createFactory(): RocketChatTransportFactory + { + return new RocketChatTransportFactory(); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/RocketChat/Tests/RocketChatTransportTest.php b/src/Symfony/Component/Notifier/Bridge/RocketChat/Tests/RocketChatTransportTest.php new file mode 100644 index 0000000000..6384e5811b --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/RocketChat/Tests/RocketChatTransportTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\RocketChat\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Bridge\RocketChat\RocketChatTransport; +use Symfony\Component\Notifier\Exception\LogicException; +use Symfony\Component\Notifier\Message\ChatMessage; +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * @author Oskar Stark + */ +final class RocketChatTransportTest extends TestCase +{ + public function testToStringContainsProperties() + { + $transport = $this->createTransport(); + + $this->assertSame('rocketchat://host.test?channel=testChannel', (string) $transport); + } + + public function testSupportsChatMessage() + { + $transport = $this->createTransport(); + + $this->assertTrue($transport->supports(new ChatMessage('testChatMessage'))); + $this->assertFalse($transport->supports($this->createMock(MessageInterface::class))); + } + + public function testSendNonChatMessageThrows() + { + $transport = $this->createTransport(); + + $this->expectException(LogicException::class); + $transport->send($this->createMock(MessageInterface::class)); + } + + private function createTransport(): RocketChatTransport + { + return (new RocketChatTransport('testAccessToken', 'testChannel', $this->createMock(HttpClientInterface::class)))->setHost('host.test'); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/RocketChat/composer.json b/src/Symfony/Component/Notifier/Bridge/RocketChat/composer.json index 2ecd6b0575..cbe95a032b 100644 --- a/src/Symfony/Component/Notifier/Bridge/RocketChat/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/RocketChat/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=7.2.5", "symfony/http-client": "^4.3|^5.0", - "symfony/notifier": "^5.0,<5.2" + "symfony/notifier": "~5.1.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Notifier\\Bridge\\RocketChat\\": "" }, diff --git a/src/Symfony/Component/Notifier/Bridge/RocketChat/phpunit.xml.dist b/src/Symfony/Component/Notifier/Bridge/RocketChat/phpunit.xml.dist new file mode 100644 index 0000000000..846dd0f13e --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/RocketChat/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + + diff --git a/src/Symfony/Component/Notifier/Bridge/Sinch/Tests/SinchTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/Sinch/Tests/SinchTransportFactoryTest.php index 72e59b93a0..969ed96df8 100644 --- a/src/Symfony/Component/Notifier/Bridge/Sinch/Tests/SinchTransportFactoryTest.php +++ b/src/Symfony/Component/Notifier/Bridge/Sinch/Tests/SinchTransportFactoryTest.php @@ -36,24 +36,21 @@ final class SinchTransportFactoryTest extends TestCase $this->expectException(IncompleteDsnException::class); - $dsnIncomplete = 'sinch://accountSid:authToken@default'; - $factory->create(Dsn::fromString($dsnIncomplete)); + $factory->create(Dsn::fromString('sinch://accountSid:authToken@default')); } public function testSupportsReturnsTrueWithSupportedScheme() { $factory = $this->createFactory(); - $dsn = 'sinch://accountSid:authToken@default?from=0611223344'; - $this->assertTrue($factory->supports(Dsn::fromString($dsn))); + $this->assertTrue($factory->supports(Dsn::fromString('sinch://accountSid:authToken@default?from=0611223344'))); } public function testSupportsReturnsFalseWithUnsupportedScheme() { $factory = $this->createFactory(); - $dsnUnsupported = 'sinnnnch://accountSid:authToken@default?from=0611223344'; - $this->assertFalse($factory->supports(Dsn::fromString($dsnUnsupported))); + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://accountSid:authToken@default?from=0611223344'))); } public function testUnsupportedSchemeThrowsUnsupportedSchemeException() @@ -62,8 +59,7 @@ final class SinchTransportFactoryTest extends TestCase $this->expectException(UnsupportedSchemeException::class); - $dsnUnsupported = 'sinnnnch://accountSid:authToken@default?from=0611223344'; - $factory->create(Dsn::fromString($dsnUnsupported)); + $factory->create(Dsn::fromString('somethingElse://accountSid:authToken@default?from=0611223344')); } public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing() @@ -73,7 +69,7 @@ final class SinchTransportFactoryTest extends TestCase $this->expectException(UnsupportedSchemeException::class); // unsupported scheme and missing "from" option - $factory->create(Dsn::fromString('sinnnnch://accountSid:authToken@default')); + $factory->create(Dsn::fromString('somethingElse://accountSid:authToken@default')); } private function createFactory(): SinchTransportFactory diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/SlackTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/Slack/SlackTransportFactory.php index c3abdc9ba8..a4eed354f4 100644 --- a/src/Symfony/Component/Notifier/Bridge/Slack/SlackTransportFactory.php +++ b/src/Symfony/Component/Notifier/Bridge/Slack/SlackTransportFactory.php @@ -30,19 +30,21 @@ final class SlackTransportFactory extends AbstractTransportFactory public function create(Dsn $dsn): TransportInterface { $scheme = $dsn->getScheme(); + + if ('slack' !== $scheme) { + throw new UnsupportedSchemeException($dsn, 'slack', $this->getSupportedSchemes()); + } + $id = ltrim($dsn->getPath(), '/'); - $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); - $port = $dsn->getPort(); if (!$id) { throw new IncompleteDsnException('Missing path (maybe you haven\'t update the DSN when upgrading from 5.0).', $dsn->getOriginalDsn()); } - if ('slack' === $scheme) { - return (new SlackTransport($id, $this->client, $this->dispatcher))->setHost($host)->setPort($port); - } + $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); + $port = $dsn->getPort(); - throw new UnsupportedSchemeException($dsn, 'slack', $this->getSupportedSchemes()); + return (new SlackTransport($id, $this->client, $this->dispatcher))->setHost($host)->setPort($port); } protected function getSupportedSchemes(): array diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportFactoryTest.php index 05a1038a94..edf3f099a3 100644 --- a/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportFactoryTest.php +++ b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportFactoryTest.php @@ -13,6 +13,7 @@ namespace Symfony\Component\Notifier\Bridge\Slack\Tests; use PHPUnit\Framework\TestCase; use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; +use Symfony\Component\Notifier\Exception\IncompleteDsnException; use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; use Symfony\Component\Notifier\Transport\Dsn; @@ -20,7 +21,7 @@ final class SlackTransportFactoryTest extends TestCase { public function testCreateWithDsn() { - $factory = new SlackTransportFactory(); + $factory = $this->createFactory(); $host = 'testHost'; $path = 'testPath'; @@ -29,20 +30,50 @@ final class SlackTransportFactoryTest extends TestCase $this->assertSame(sprintf('slack://%s/%s', $host, $path), (string) $transport); } - public function testSupportsScheme() + public function testCreateWithMissingOptionIdThrowsIncompleteDsnException() { - $factory = new SlackTransportFactory(); + $factory = $this->createFactory(); + + $this->expectException(IncompleteDsnException::class); + + $factory->create(Dsn::fromString('slack://host')); + } + + public function testSupportsReturnsTrueWithSupportedScheme() + { + $factory = $this->createFactory(); $this->assertTrue($factory->supports(Dsn::fromString('slack://host/path'))); + } + + public function testSupportsReturnsFalseWithUnsupportedScheme() + { + $factory = $this->createFactory(); + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/path'))); } - public function testNonSlackSchemeThrows() + public function testUnsupportedSchemeThrowsUnsupportedSchemeException() { - $factory = new SlackTransportFactory(); + $factory = $this->createFactory(); $this->expectException(UnsupportedSchemeException::class); $factory->create(Dsn::fromString('somethingElse://host/path')); } + + public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing() + { + $factory = $this->createFactory(); + + $this->expectException(UnsupportedSchemeException::class); + + // unsupported scheme and missing "id" option + $factory->create(Dsn::fromString('somethingElse://host')); + } + + private function createFactory(): SlackTransportFactory + { + return new SlackTransportFactory(); + } } diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php index 8e690206ff..0018e5ad70 100644 --- a/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php +++ b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php @@ -28,18 +28,15 @@ final class SlackTransportTest extends TestCase { public function testToStringContainsProperties() { - $host = 'testHost'; - $path = 'testPath'; + $transport = $this->createTransport(); + $transport->setHost('host.test'); - $transport = new SlackTransport($path, $this->createMock(HttpClientInterface::class)); - $transport->setHost('testHost'); - - $this->assertSame(sprintf('slack://%s/%s', $host, $path), (string) $transport); + $this->assertSame('slack://host.test/testPath', (string) $transport); } public function testSupportsChatMessage() { - $transport = new SlackTransport('testPath', $this->createMock(HttpClientInterface::class)); + $transport = $this->createTransport(); $this->assertTrue($transport->supports(new ChatMessage('testChatMessage'))); $this->assertFalse($transport->supports($this->createMock(MessageInterface::class))); @@ -47,9 +44,9 @@ final class SlackTransportTest extends TestCase public function testSendNonChatMessageThrows() { - $this->expectException(LogicException::class); + $transport = $this->createTransport(); - $transport = new SlackTransport('testPath', $this->createMock(HttpClientInterface::class)); + $this->expectException(LogicException::class); $transport->send($this->createMock(MessageInterface::class)); } @@ -70,16 +67,13 @@ final class SlackTransportTest extends TestCase return $response; }); - $transport = new SlackTransport('testPath', $client); + $transport = $this->createTransport($client); $transport->send(new ChatMessage('testMessage')); } public function testSendWithErrorResponseThrows() { - $this->expectException(TransportException::class); - $this->expectExceptionMessage('testErrorCode'); - $response = $this->createMock(ResponseInterface::class); $response->expects($this->exactly(2)) ->method('getStatusCode') @@ -93,14 +87,16 @@ final class SlackTransportTest extends TestCase return $response; }); - $transport = new SlackTransport('testPath', $client); + $transport = $this->createTransport($client); + + $this->expectException(TransportException::class); + $this->expectExceptionMessage('testErrorCode'); $transport->send(new ChatMessage('testMessage')); } public function testSendWithOptions() { - $path = 'testPath'; $message = 'testMessage'; $response = $this->createMock(ResponseInterface::class); @@ -121,14 +117,13 @@ final class SlackTransportTest extends TestCase return $response; }); - $transport = new SlackTransport($path, $client); + $transport = $this->createTransport($client); - $transport->send(new ChatMessage('testMessage')); + $transport->send(new ChatMessage($message)); } public function testSendWithNotification() { - $host = 'testHost'; $message = 'testMessage'; $response = $this->createMock(ResponseInterface::class); @@ -156,31 +151,28 @@ final class SlackTransportTest extends TestCase return $response; }); - $transport = new SlackTransport($host, $client); + $transport = $this->createTransport($client); $transport->send($chatMessage); } public function testSendWithInvalidOptions() { - $this->expectException(LogicException::class); - $client = new MockHttpClient(function (string $method, string $url, array $options = []): ResponseInterface { return $this->createMock(ResponseInterface::class); }); - $transport = new SlackTransport('testHost', $client); + $transport = $this->createTransport($client); + + $this->expectException(LogicException::class); $transport->send(new ChatMessage('testMessage', $this->createMock(MessageOptionsInterface::class))); } public function testSendWith200ResponseButNotOk() { - $host = 'testChannel'; $message = 'testMessage'; - $this->expectException(TransportException::class); - $response = $this->createMock(ResponseInterface::class); $response->expects($this->exactly(2)) @@ -199,8 +191,15 @@ final class SlackTransportTest extends TestCase return $response; }); - $transport = new SlackTransport($host, $client); + $transport = $this->createTransport($client); - $transport->send(new ChatMessage('testMessage')); + $this->expectException(TransportException::class); + + $transport->send(new ChatMessage($message)); + } + + private function createTransport(?HttpClientInterface $client = null): SlackTransport + { + return (new SlackTransport('testPath', $client ?: $this->createMock(HttpClientInterface::class)))->setHost('host.test'); } } diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramTransportFactory.php index 719fdf0091..2a92e1c2f6 100644 --- a/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramTransportFactory.php +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramTransportFactory.php @@ -30,16 +30,17 @@ final class TelegramTransportFactory extends AbstractTransportFactory public function create(Dsn $dsn): TransportInterface { $scheme = $dsn->getScheme(); + + if ('telegram' !== $scheme) { + throw new UnsupportedSchemeException($dsn, 'telegram', $this->getSupportedSchemes()); + } + $token = $this->getToken($dsn); $channel = $dsn->getOption('channel'); $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); $port = $dsn->getPort(); - if ('telegram' === $scheme) { - return (new TelegramTransport($token, $channel, $this->client, $this->dispatcher))->setHost($host)->setPort($port); - } - - throw new UnsupportedSchemeException($dsn, 'telegram', $this->getSupportedSchemes()); + return (new TelegramTransport($token, $channel, $this->client, $this->dispatcher))->setHost($host)->setPort($port); } protected function getSupportedSchemes(): array diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportFactoryTest.php index 24a233c4ba..de8aff8786 100644 --- a/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportFactoryTest.php +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportFactoryTest.php @@ -21,7 +21,7 @@ final class TelegramTransportFactoryTest extends TestCase { public function testCreateWithDsn() { - $factory = new TelegramTransportFactory(); + $factory = $this->createFactory(); $host = 'testHost'; $channel = 'testChannel'; @@ -31,35 +31,47 @@ final class TelegramTransportFactoryTest extends TestCase $this->assertSame(sprintf('telegram://%s?channel=%s', $host, $channel), (string) $transport); } - public function testCreateWithNoPasswordThrowsMalformed() + public function testCreateWithNoPasswordThrowsIncompleteDsnException() { - $factory = new TelegramTransportFactory(); + $factory = $this->createFactory(); $this->expectException(IncompleteDsnException::class); $factory->create(Dsn::fromString(sprintf('telegram://%s@%s/?channel=%s', 'simpleToken', 'testHost', 'testChannel'))); } - public function testCreateWithNoTokenThrowsMalformed() + public function testCreateWithNoTokenThrowsIncompleteDsnException() { - $factory = new TelegramTransportFactory(); + $factory = $this->createFactory(); $this->expectException(IncompleteDsnException::class); $factory->create(Dsn::fromString(sprintf('telegram://%s/?channel=%s', 'testHost', 'testChannel'))); } - public function testSupportsScheme() + public function testSupportsReturnsTrueWithSupportedScheme() { - $factory = new TelegramTransportFactory(); + $factory = $this->createFactory(); $this->assertTrue($factory->supports(Dsn::fromString('telegram://host/?channel=testChannel'))); + } + + public function testSupportsReturnsFalseWithUnsupportedScheme() + { + $factory = $this->createFactory(); + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/?channel=testChannel'))); } - public function testNonTelegramSchemeThrows() + public function testUnsupportedSchemeThrowsUnsupportedSchemeException() { - $factory = new TelegramTransportFactory(); + $factory = $this->createFactory(); $this->expectException(UnsupportedSchemeException::class); + $factory->create(Dsn::fromString('somethingElse://user:pwd@host/?channel=testChannel')); } + + private function createFactory(): TelegramTransportFactory + { + return new TelegramTransportFactory(); + } } diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php b/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php index 72c7d4d479..c7407ed06d 100644 --- a/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php @@ -29,9 +29,9 @@ final class TelegramTransportTest extends TestCase $channel = 'testChannel'; $transport = new TelegramTransport('testToken', $channel, $this->createMock(HttpClientInterface::class)); - $transport->setHost('testHost'); + $transport->setHost('host.test'); - $this->assertSame(sprintf('telegram://%s?channel=%s', 'testHost', $channel), (string) $transport); + $this->assertSame(sprintf('telegram://%s?channel=%s', 'host.test', $channel), (string) $transport); } public function testSupportsChatMessage() diff --git a/src/Symfony/Component/Notifier/Bridge/Twilio/Tests/TwilioTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/Twilio/Tests/TwilioTransportFactoryTest.php index c465939d6d..cabc48cd4e 100644 --- a/src/Symfony/Component/Notifier/Bridge/Twilio/Tests/TwilioTransportFactoryTest.php +++ b/src/Symfony/Component/Notifier/Bridge/Twilio/Tests/TwilioTransportFactoryTest.php @@ -30,35 +30,46 @@ final class TwilioTransportFactoryTest extends TestCase $this->assertSame('twilio://host.test?from=0611223344', (string) $transport); } - public function testCreateWithNoFromThrowsMalformed() + public function testCreateWithNoFromThrowsIncompleteDsnException() { $factory = $this->createFactory(); $this->expectException(IncompleteDsnException::class); - $dsnIncomplete = 'twilio://accountSid:authToken@default'; - $factory->create(Dsn::fromString($dsnIncomplete)); + $factory->create(Dsn::fromString('twilio://accountSid:authToken@default')); } - public function testSupportsScheme() + public function testSupportsReturnsTrueWithSupportedScheme() { $factory = $this->createFactory(); - $dsn = 'twilio://accountSid:authToken@default?from=0611223344'; - $dsnUnsupported = 'twilioooo://accountSid:authToken@default?from=0611223344'; - - $this->assertTrue($factory->supports(Dsn::fromString($dsn))); - $this->assertFalse($factory->supports(Dsn::fromString($dsnUnsupported))); + $this->assertTrue($factory->supports(Dsn::fromString('twilio://accountSid:authToken@default?from=0611223344'))); } - public function testNonTwilioSchemeThrows() + public function testSupportsReturnsFalseWithUnsupportedScheme() + { + $factory = $this->createFactory(); + + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://accountSid:authToken@default?from=0611223344'))); + } + + public function testUnsupportedSchemeThrowsUnsupportedSchemeException() { $factory = $this->createFactory(); $this->expectException(UnsupportedSchemeException::class); - $dsnUnsupported = 'twilioooo://accountSid:authToken@default?from=0611223344'; - $factory->create(Dsn::fromString($dsnUnsupported)); + $factory->create(Dsn::fromString('somethingElse://accountSid:authToken@default?from=0611223344')); + } + + public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing() + { + $factory = $this->createFactory(); + + $this->expectException(UnsupportedSchemeException::class); + + // unsupported scheme and missing "from" option + $factory->create(Dsn::fromString('somethingElse://token@host')); } private function createFactory(): TwilioTransportFactory diff --git a/src/Symfony/Component/Notifier/Bridge/Twilio/TwilioTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/Twilio/TwilioTransportFactory.php index 54634820cd..a8b715db88 100644 --- a/src/Symfony/Component/Notifier/Bridge/Twilio/TwilioTransportFactory.php +++ b/src/Symfony/Component/Notifier/Bridge/Twilio/TwilioTransportFactory.php @@ -30,6 +30,11 @@ final class TwilioTransportFactory extends AbstractTransportFactory public function create(Dsn $dsn): TransportInterface { $scheme = $dsn->getScheme(); + + if ('twilio' !== $scheme) { + throw new UnsupportedSchemeException($dsn, 'twilio', $this->getSupportedSchemes()); + } + $accountSid = $this->getUser($dsn); $authToken = $this->getPassword($dsn); $from = $dsn->getOption('from'); @@ -41,11 +46,7 @@ final class TwilioTransportFactory extends AbstractTransportFactory $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); $port = $dsn->getPort(); - if ('twilio' === $scheme) { - return (new TwilioTransport($accountSid, $authToken, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port); - } - - throw new UnsupportedSchemeException($dsn, 'twilio', $this->getSupportedSchemes()); + return (new TwilioTransport($accountSid, $authToken, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port); } protected function getSupportedSchemes(): array