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) 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); diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesTransportFactory.php index 1f49413018..9d6863f12e 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesTransportFactory.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesTransportFactory.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Mailer\Bridge\Amazon\Transport; use AsyncAws\Core\Configuration; use AsyncAws\Ses\SesClient; use Symfony\Component\HttpClient\HttpClient; +use Symfony\Component\Mailer\Exception\LogicException; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; use Symfony\Component\Mailer\Transport\AbstractTransportFactory; use Symfony\Component\Mailer\Transport\Dsn; @@ -47,6 +48,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); } if ('ses+https' === $scheme || 'ses' === $scheme) { diff --git a/src/Symfony/Component/Notifier/Bridge/Firebase/FirebaseOptions.php b/src/Symfony/Component/Notifier/Bridge/Firebase/FirebaseOptions.php index e4a46d9007..e0e86ad23e 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 1803c41220..4c604504fb 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/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 fca9fc2680..e0807c985c 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/Mattermost/MattermostTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/Mattermost/MattermostTransportFactory.php index 8feb198b9f..52fc4bdc66 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/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 cbe3895e21..79cfd1d502 100644 --- a/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransport.php +++ b/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransport.php @@ -52,7 +52,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): SentMessage { diff --git a/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/RocketChat/RocketChatTransportFactory.php index e597045363..39fca9aa55 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/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/Telegram/TelegramTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramTransportFactory.php index da66597762..5a2ffd7785 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 16b29b5396..3d75d15fe7 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 e4349c89bb..169e0bb239 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