From 05c7672de3a8c3f7f6b2c2d83de9a17a2a4af35a Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sun, 27 Jan 2019 12:14:18 +0100 Subject: [PATCH] Improved API tests by adding fixtures --- composer.json | 1 + config/test/bootstrap_api_tests.php | 10 ++++- config/test/test_config.global.php | 6 +++ module/Common/test-db/TestHelper.php | 19 +++++++++ .../Rest/test-api/Fixtures/ApiKeyFixture.php | 36 ++++++++++++++++ .../test-api/Fixtures/ShortUrlsFixture.php | 41 +++++++++++++++++++ module/Rest/test-api/Fixtures/TagsFixture.php | 37 +++++++++++++++++ .../Rest/test-api/Fixtures/VisitsFixture.php | 35 ++++++++++++++++ .../Middleware/AuthenticationTest.php | 14 ++++++- 9 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 module/Rest/test-api/Fixtures/ApiKeyFixture.php create mode 100644 module/Rest/test-api/Fixtures/ShortUrlsFixture.php create mode 100644 module/Rest/test-api/Fixtures/TagsFixture.php create mode 100644 module/Rest/test-api/Fixtures/VisitsFixture.php diff --git a/composer.json b/composer.json index b8ce3e66..0c8af151 100644 --- a/composer.json +++ b/composer.json @@ -51,6 +51,7 @@ }, "require-dev": { "devster/ubench": "^2.0", + "doctrine/data-fixtures": "^1.3", "filp/whoops": "^2.0", "infection/infection": "^0.11.0", "phpstan/phpstan": "^0.10.0", diff --git a/config/test/bootstrap_api_tests.php b/config/test/bootstrap_api_tests.php index 6ccde6b7..c39042fa 100644 --- a/config/test/bootstrap_api_tests.php +++ b/config/test/bootstrap_api_tests.php @@ -3,6 +3,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Common; +use Doctrine\ORM\EntityManager; use Psr\Container\ContainerInterface; use function file_exists; use function touch; @@ -14,5 +15,12 @@ if (! file_exists('.env')) { /** @var ContainerInterface $container */ $container = require __DIR__ . '/../container.php'; -$container->get(TestHelper::class)->createTestDb(); +$testHelper = $container->get(TestHelper::class); +$config = $container->get('config'); + +$testHelper->createTestDb(); + +$em = $container->get(EntityManager::class); +$testHelper->seedFixtures($em, $config['data_fixtures'] ?? []); + ApiTest\ApiTestCase::setApiClient($container->get('shlink_test_api_client')); diff --git a/config/test/test_config.global.php b/config/test/test_config.global.php index 79f36791..069268b5 100644 --- a/config/test/test_config.global.php +++ b/config/test/test_config.global.php @@ -41,4 +41,10 @@ return [ ], ], + 'data_fixtures' => [ + 'paths' => [ + __DIR__ . '/../../module/Rest/test-api/Fixtures', + ], + ], + ]; diff --git a/module/Common/test-db/TestHelper.php b/module/Common/test-db/TestHelper.php index 634456fc..fc24657d 100644 --- a/module/Common/test-db/TestHelper.php +++ b/module/Common/test-db/TestHelper.php @@ -3,6 +3,9 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Common; +use Doctrine\Common\DataFixtures\Executor\ORMExecutor; +use Doctrine\Common\DataFixtures\Loader; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Process\Process; use function file_exists; use function realpath; @@ -22,4 +25,20 @@ class TestHelper $process->inheritEnvironmentVariables() ->mustRun(); } + + public function seedFixtures(EntityManagerInterface $em, array $config): void + { + $paths = $config['paths'] ?? []; + if (empty($paths)) { + return; + } + + $loader = new Loader(); + foreach ($paths as $path) { + $loader->loadFromDirectory($path); + } + + $executor = new ORMExecutor($em); + $executor->execute($loader->getFixtures(), true); + } } diff --git a/module/Rest/test-api/Fixtures/ApiKeyFixture.php b/module/Rest/test-api/Fixtures/ApiKeyFixture.php new file mode 100644 index 00000000..8990faa2 --- /dev/null +++ b/module/Rest/test-api/Fixtures/ApiKeyFixture.php @@ -0,0 +1,36 @@ +persist($this->buildApiKey('valid_api_key', true)); + $manager->persist($this->buildApiKey('disabled_api_key', false)); + $manager->persist($this->buildApiKey('expired_api_key', true, Chronos::now()->subDay())); + $manager->flush(); + } + + private function buildApiKey(string $key, bool $enabled, Chronos $expiresAt = null): ApiKey + { + $apiKey = new ApiKey($expiresAt); + $refObj = new ReflectionObject($apiKey); + $keyProp = $refObj->getProperty('key'); + $keyProp->setAccessible(true); + $keyProp->setValue($apiKey, $key); + + if (! $enabled) { + $apiKey->disable(); + } + + return $apiKey; + } +} diff --git a/module/Rest/test-api/Fixtures/ShortUrlsFixture.php b/module/Rest/test-api/Fixtures/ShortUrlsFixture.php new file mode 100644 index 00000000..438b819e --- /dev/null +++ b/module/Rest/test-api/Fixtures/ShortUrlsFixture.php @@ -0,0 +1,41 @@ +setShortCode('abc123'); + $manager->persist($abcShortUrl); + + $defShortUrl = (new ShortUrl( + 'https://shlink.io', + ShortUrlMeta::createFromParams(Chronos::now()->addDays(3)) + ))->setShortCode('def456'); + $manager->persist($defShortUrl); + + $customShortUrl = new ShortUrl( + 'https://shlink.io', + ShortUrlMeta::createFromParams(null, null, 'custom', 2) + ); + $manager->persist($customShortUrl); + + $manager->flush(); + + $this->addReference('abc123_short_url', $abcShortUrl); + $this->addReference('def456_short_url', $defShortUrl); + } +} diff --git a/module/Rest/test-api/Fixtures/TagsFixture.php b/module/Rest/test-api/Fixtures/TagsFixture.php new file mode 100644 index 00000000..c5e84648 --- /dev/null +++ b/module/Rest/test-api/Fixtures/TagsFixture.php @@ -0,0 +1,37 @@ +persist($fooTag); + $barTag = new Tag('bar'); + $manager->persist($barTag); + + /** @var ShortUrl $abcShortUrl */ + $abcShortUrl = $this->getReference('abc123_short_url'); + $abcShortUrl->setTags(new ArrayCollection([$fooTag])); + + /** @var ShortUrl $defShortUrl */ + $defShortUrl = $this->getReference('def456_short_url'); + $defShortUrl->setTags(new ArrayCollection([$fooTag, $barTag])); + + $manager->flush(); + } +} diff --git a/module/Rest/test-api/Fixtures/VisitsFixture.php b/module/Rest/test-api/Fixtures/VisitsFixture.php new file mode 100644 index 00000000..cd9cabfd --- /dev/null +++ b/module/Rest/test-api/Fixtures/VisitsFixture.php @@ -0,0 +1,35 @@ +getReference('abc123_short_url'); + $manager->persist(new Visit($abcShortUrl, new Visitor('shlink-tests-agent', '', '44.55.66.77'))); + $manager->persist(new Visit($abcShortUrl, new Visitor('shlink-tests-agent', 'https://google.com', '4.5.6.7'))); + $manager->persist(new Visit($abcShortUrl, new Visitor('shlink-tests-agent', '', '1.2.3.4'))); + + /** @var ShortUrl $defShortUrl */ + $defShortUrl = $this->getReference('def456_short_url'); + $manager->persist(new Visit($defShortUrl, new Visitor('shlink-tests-agent', '', '127.0.0.1'))); + $manager->persist(new Visit($defShortUrl, new Visitor('shlink-tests-agent', 'https://app.shlink.io', ''))); + + $manager->flush(); + } +} diff --git a/module/Rest/test-api/Middleware/AuthenticationTest.php b/module/Rest/test-api/Middleware/AuthenticationTest.php index 1e5dea06..a4692b9d 100644 --- a/module/Rest/test-api/Middleware/AuthenticationTest.php +++ b/module/Rest/test-api/Middleware/AuthenticationTest.php @@ -38,13 +38,14 @@ class AuthenticationTest extends ApiTestCase /** * @test + * @dataProvider provideInvalidApiKeys */ - public function apiKeyErrorIsReturnedWhenProvidedApiKeyIsInvalid() + public function apiKeyErrorIsReturnedWhenProvidedApiKeyIsInvalid(string $apiKey) { try { $this->callApi(self::METHOD_GET, '/short-codes', [ 'headers' => [ - ApiKeyHeaderPlugin::HEADER_NAME => 'invalid', + ApiKeyHeaderPlugin::HEADER_NAME => $apiKey, ], ]); } catch (ClientException $e) { @@ -55,4 +56,13 @@ class AuthenticationTest extends ApiTestCase $this->assertEquals('Provided API key does not exist or is invalid.', $message); } } + + public function provideInvalidApiKeys(): array + { + return [ + 'key which does not exist' => ['invalid'], + 'key which is expired' => ['expired_api_key'], + 'key which is disabled' => ['disabled_api_key'], + ]; + } }