diff --git a/.env.test b/.env.test index 414430e7..81349c70 100644 --- a/.env.test +++ b/.env.test @@ -2,3 +2,5 @@ KERNEL_CLASS='App\Kernel' APP_SECRET='s$cretf0rt3st' SYMFONY_DEPRECATIONS_HELPER=999999 + +DATABASE_URL=mysql://root:@127.0.0.1:3306/part-db_test \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 28911e7c..94f7a95b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,11 @@ language: php +services: + - mysql + env: - SYMFONY_DEPRECATIONS_HELPER=disabled # Disable deprecation warnings + - APP_ENV=test # Test for all supported PHP versions php: @@ -11,8 +15,13 @@ php: - '7.4snapshot' - 'nightly' +before_install: + - mysql -e 'CREATE DATABASE partdb_test; + install: - composer install + - php bin/console doctrine:migrations:migrate -n + - php bin/console doctrine:fixtures:load -n script: - php bin/phpunit diff --git a/composer.json b/composer.json index 0993c383..1f094c58 100644 --- a/composer.json +++ b/composer.json @@ -51,9 +51,11 @@ "webmozart/assert": "^1.4" }, "require-dev": { + "dama/doctrine-test-bundle": "^5.0", + "doctrine/doctrine-fixtures-bundle": "^3.2", "roave/security-advisories": "dev-master", "symfony/debug-pack": "*", - "symfony/maker-bundle": "^1.0", + "symfony/maker-bundle": "^1.13", "symfony/profiler-pack": "*", "symfony/test-pack": "^1.0", "symfony/web-server-bundle": "4.3.*", diff --git a/composer.lock b/composer.lock index f1e86c2c..8dcf7c4a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3bf8b3cc9288b991bb93c494a7d571a4", + "content-hash": "1b7ba9876569ad9b9a41348701dc75f3", "packages": [ { "name": "clue/stream-filter", @@ -8017,6 +8017,189 @@ ], "time": "2019-05-27T17:52:04+00:00" }, + { + "name": "dama/doctrine-test-bundle", + "version": "v5.0.3", + "source": { + "type": "git", + "url": "https://github.com/dmaicher/doctrine-test-bundle.git", + "reference": "29882b0d1a815f4819126ef714931bb24a31cbaa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dmaicher/doctrine-test-bundle/zipball/29882b0d1a815f4819126ef714931bb24a31cbaa", + "reference": "29882b0d1a815f4819126ef714931bb24a31cbaa", + "shasum": "" + }, + "require": { + "doctrine/dbal": "~2.5", + "doctrine/doctrine-bundle": "~1.4", + "php": "^7.1", + "symfony/framework-bundle": "~2.7|~3.0|~4.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0|~7.0|~8.0", + "symfony/phpunit-bridge": "~2.8|~3.0|~4.0", + "symfony/yaml": "~2.8|~3.0|~4.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "5.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "DAMA\\DoctrineTestBundle\\": "src/DAMA/DoctrineTestBundle" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David Maicher", + "email": "mail@dmaicher.de" + } + ], + "description": "Symfony bundle to isolate doctrine database tests and improve test performance", + "keywords": [ + "Symfony 3", + "Symfony 4", + "doctrine", + "isolation", + "performance", + "symfony", + "symfony 2", + "tests" + ], + "time": "2019-03-22T10:34:17+00:00" + }, + { + "name": "doctrine/data-fixtures", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/data-fixtures.git", + "reference": "09b16943b27f3d80d63988d100ff256148c2f78b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/09b16943b27f3d80d63988d100ff256148c2f78b", + "reference": "09b16943b27f3d80d63988d100ff256148c2f78b", + "shasum": "" + }, + "require": { + "doctrine/common": "~2.2", + "php": "^7.1" + }, + "conflict": { + "doctrine/phpcr-odm": "<1.3.0" + }, + "require-dev": { + "doctrine/dbal": "^2.5.4", + "doctrine/orm": "^2.5.4", + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "For using MongoDB ODM with PHP 7", + "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", + "doctrine/orm": "For loading ORM fixtures", + "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Data Fixtures for all Doctrine Object Managers", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database" + ], + "time": "2019-07-10T18:30:35+00:00" + }, + { + "name": "doctrine/doctrine-fixtures-bundle", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", + "reference": "90e4a4f968b2dae40e290a6ee516957af043f16c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/90e4a4f968b2dae40e290a6ee516957af043f16c", + "reference": "90e4a4f968b2dae40e290a6ee516957af043f16c", + "shasum": "" + }, + "require": { + "doctrine/data-fixtures": "^1.3", + "doctrine/doctrine-bundle": "^1.6", + "doctrine/orm": "^2.6.0", + "php": "^7.1", + "symfony/doctrine-bridge": "~3.4|^4.1", + "symfony/framework-bundle": "^3.4|^4.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.4", + "symfony/phpunit-bridge": "^4.1" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\FixturesBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony DoctrineFixturesBundle", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "Fixture", + "persistence" + ], + "time": "2019-06-12T12:03:37+00:00" + }, { "name": "easycorp/easy-log-handler", "version": "v1.0.7", diff --git a/config/bundles.php b/config/bundles.php index 18638810..2db74f84 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -20,4 +20,6 @@ return [ FOS\CKEditorBundle\FOSCKEditorBundle::class => ['all' => true], Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true], + Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], + DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true], ]; diff --git a/config/packages/test/dama_doctrine_test_bundle.yaml b/config/packages/test/dama_doctrine_test_bundle.yaml new file mode 100644 index 00000000..80b00911 --- /dev/null +++ b/config/packages/test/dama_doctrine_test_bundle.yaml @@ -0,0 +1,4 @@ +dama_doctrine_test: + enable_static_connection: true + enable_static_meta_data_cache: true + enable_static_query_cache: true diff --git a/config/packages/test/security.yaml b/config/packages/test/security.yaml new file mode 100644 index 00000000..edddd4d8 --- /dev/null +++ b/config/packages/test/security.yaml @@ -0,0 +1,6 @@ +# config/packages/test/security.yaml +security: + firewalls: + # replace 'main' by the name of your own firewall + main: + http_basic: ~ \ No newline at end of file diff --git a/config/routes.yaml b/config/routes.yaml index 19c92250..a8c925b7 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -9,4 +9,4 @@ redirector: url: ".*" controller: App\Controller\RedirectController:addLocalePart # Dont match localized routes (no redirection loop, if no root with that name exists) - condition: "not (request.getPathInfo() matches '/\\\\/[a-z]{2}(_[A-Z]{2})?\\\\//')" \ No newline at end of file + condition: "not (request.getPathInfo() matches '/^\\\\/[a-z]{2}(_[A-Z]{2})?\\\\//')" \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 134c69e9..10af8b94 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -25,6 +25,10 @@ + + + + diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php new file mode 100644 index 00000000..31e3a1db --- /dev/null +++ b/src/DataFixtures/AppFixtures.php @@ -0,0 +1,18 @@ +persist($product); + + $manager->flush(); + } +} diff --git a/src/DataFixtures/GroupFixtures.php b/src/DataFixtures/GroupFixtures.php new file mode 100644 index 00000000..8c1a3065 --- /dev/null +++ b/src/DataFixtures/GroupFixtures.php @@ -0,0 +1,37 @@ +setName('admins'); + + $this->setReference(self::ADMINS, $admins); + $manager->persist($admins); + + $readonly = new Group(); + $readonly->setName('readonly'); + + $this->setReference(self::READONLY, $readonly); + $manager->persist($readonly); + + $users = new Group(); + $users->setName('users'); + + $this->setReference(self::USERS, $users); + $manager->persist($users); + + $manager->flush(); + } +} diff --git a/src/DataFixtures/UserFixtures.php b/src/DataFixtures/UserFixtures.php new file mode 100644 index 00000000..613d37dd --- /dev/null +++ b/src/DataFixtures/UserFixtures.php @@ -0,0 +1,50 @@ +em = $entityManager; + $this->encoder = $encoder; + } + + public function load(ObjectManager $manager) + { + //Reset autoincrement + $this->em->getConnection()->exec('ALTER TABLE `users` AUTO_INCREMENT = 1;'); + + $anonymous = new User(); + $anonymous->setName('anonymous'); + $anonymous->setGroup($this->getReference(GroupFixtures::READONLY)); + + $manager->persist($anonymous); + + $admin = new User(); + $admin->setName('admin'); + $admin->setPassword($this->encoder->encodePassword($admin, 'test')); + $admin->setGroup($this->getReference(GroupFixtures::ADMINS)); + $manager->persist($admin); + + $user = new User(); + $user->setName('user'); + $user->setNeedPwChange(false); + $user->setFirstName('Test')->setLastName('User'); + $user->setPassword($this->encoder->encodePassword($user, 'test')); + $user->setGroup($this->getReference(GroupFixtures::USERS)); + $manager->persist($user); + + $manager->flush(); + } +} diff --git a/src/Helpers/UTCDateTimeType.php b/src/Helpers/UTCDateTimeType.php index 7e8a5f51..51bb291c 100644 --- a/src/Helpers/UTCDateTimeType.php +++ b/src/Helpers/UTCDateTimeType.php @@ -42,12 +42,16 @@ use Doctrine\DBAL\Types\DateTimeType; */ class UTCDateTimeType extends DateTimeType { - private static $utc; + private static $utc_timezone; public function convertToDatabaseValue($value, AbstractPlatform $platform) { + if (!self::$utc_timezone) { + self::$utc_timezone = new \DateTimeZone('UTC'); + } + if ($value instanceof \DateTime) { - $value->setTimezone(self::$utc); + $value->setTimezone(self::$utc_timezone); } return parent::convertToDatabaseValue($value, $platform); @@ -55,6 +59,10 @@ class UTCDateTimeType extends DateTimeType public function convertToPHPValue($value, AbstractPlatform $platform) { + if (!self::$utc_timezone) { + self::$utc_timezone = new \DateTimeZone('UTC'); + } + if (null === $value || $value instanceof \DateTime) { return $value; } @@ -62,7 +70,7 @@ class UTCDateTimeType extends DateTimeType $converted = \DateTime::createFromFormat( $platform->getDateTimeFormatString(), $value, - self::$utc ? self::$utc : self::$utc = new \DateTimeZone('UTC') + self::$utc_timezone ); if (! $converted) { diff --git a/symfony.lock b/symfony.lock index 9f0659f8..0ea5829a 100644 --- a/symfony.lock +++ b/symfony.lock @@ -11,6 +11,18 @@ "composer/xdebug-handler": { "version": "1.3.3" }, + "dama/doctrine-test-bundle": { + "version": "4.0", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "master", + "version": "4.0", + "ref": "56eaa387b5e48ebcc7c95a893b47dfa1ad51449c" + }, + "files": [ + "./config/packages/test/dama_doctrine_test_bundle.yaml" + ] + }, "doctrine/annotations": { "version": "1.0", "recipe": { @@ -32,6 +44,9 @@ "doctrine/common": { "version": "v2.10.0" }, + "doctrine/data-fixtures": { + "version": "v1.3.2" + }, "doctrine/dbal": { "version": "v2.9.2" }, @@ -53,6 +68,18 @@ "doctrine/doctrine-cache-bundle": { "version": "1.3.5" }, + "doctrine/doctrine-fixtures-bundle": { + "version": "3.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.0", + "ref": "fc52d86631a6dfd9fdf3381d0b7e3df2069e51b3" + }, + "files": [ + "./src/DataFixtures/AppFixtures.php" + ] + }, "doctrine/doctrine-migrations-bundle": { "version": "1.2", "recipe": { diff --git a/tests/Controller/RedirectControllerTest.php b/tests/Controller/RedirectControllerTest.php new file mode 100644 index 00000000..584b4273 --- /dev/null +++ b/tests/Controller/RedirectControllerTest.php @@ -0,0 +1,151 @@ +em = self::$container->get(EntityManagerInterface::class); + $this->userRepo = $this->em->getRepository(User::class); + } + + public function urlMatchDataProvider() + { + return [ + ['/', true], + ['/part/2/info', true], + ['/part/de/2', true], + ['/part/en/', true], + ['/de/', false], + ['/de_DE/', false], + ['/en/', false], + ['/en_US/', false], + ]; + } + + /** + * Test if a certain request to an url will be redirected. + * @dataProvider urlMatchDataProvider + */ + public function testUrlMatch($url, $expect_redirect) + { + $client = static::createClient(); + $client->request('GET', $url); + $response = $client->getResponse(); + if($expect_redirect) { + $this->assertEquals(302, $response->getStatusCode()); + } + $this->assertEquals($expect_redirect, $response->isRedirect()); + } + + public function urlAddLocaleDataProvider() + { + return [ + //User locale, original target, redirect target + ['de', '/', '/de/'], + ['de', '/part/3', '/de/part/3'], + ['en', '/', '/en/'], + ['en', '/category/new', '/en/category/new'], + ['en_US', '/part/3', '/en_US/part/3'], + //Without an explicit set value, the user should be redirect to english version + [null, '/', '/en/'], + ['en_US', '/part/3', '/en_US/part/3'], + ]; + } + + /** + * Test if the user is redirected to the localized version of a page, based on his settings. + * @dataProvider urlAddLocaleDataProvider + * @depends testUrlMatch + * @param $user_locale + * @param $input_path + * @param $redirect_path + */ + public function testAddLocale($user_locale, $input_path, $redirect_path) + { + //Redirect path is absolute + $redirect_path = 'http://localhost' . $redirect_path; + + /** @var User $user */ + $user = $this->userRepo->findOneBy(['name' => 'user']); + //Set user locale + $user->setLanguage($user_locale); + $this->em->flush(); + + $client = static::createClient([], [ + 'PHP_AUTH_USER' => 'user', + 'PHP_AUTH_PW' => 'test', + ]); + + $client->followRedirects(false); + $client->request('GET', $input_path); + $this->assertEquals($redirect_path, $client->getResponse()->headers->get('Location')); + } + + /** + * Test if the user is redirected to password change page if he should do that + * @depends testAddLocale + * @testWith ["de"] + * ["en"] + */ + public function testRedirectToPasswordChange(string $locale) + { + /** @var User $user */ + $user = $this->userRepo->findOneBy(['name' => 'user']); + + //Test for german user + $user->setLanguage($locale); + $user->setNeedPwChange(true); + $this->em->flush(); + + $client = static::createClient([], [ + 'PHP_AUTH_USER' => 'user', + 'PHP_AUTH_PW' => 'test', + ]); + $client->followRedirects(false); + + $client->request('GET', '/part/3'); + $this->assertEquals("/$locale/user/settings", $client->getResponse()->headers->get('Location')); + + + } +} \ No newline at end of file