ソースを参照

complete unit_tests for ot_core

Olivier Massot 4 年 前
コミット
f1a446fd16

+ 3 - 2
README.md

@@ -1,6 +1,7 @@
+| Extension | Status |
+| --- | --- |
+| ot_core | [![pipeline status](http://gitlab.2iopenservice.com/opentalent/ot_typo3/badges/unittests/pipeline.svg)](http://gitlab.2iopenservice.com/opentalent/ot_typo3/-/commits/unittests) [![coverage report](http://gitlab.2iopenservice.com/opentalent/ot_typo3/badges/unittests/coverage.svg)](http://gitlab.2iopenservice.com/opentalent/ot_typo3/-/commits/unittests) |
 
-[![pipeline status](http://gitlab.2iopenservice.com/opentalent/ot_typo3/badges/unittests/pipeline.svg)](http://gitlab.2iopenservice.com/opentalent/ot_typo3/-/commits/unittests)
-[![coverage report](http://gitlab.2iopenservice.com/opentalent/ot_typo3/badges/unittests/coverage.svg)](http://gitlab.2iopenservice.com/opentalent/ot_typo3/-/commits/unittests)
 
 ## Opentalent extensions for Typo3
 

+ 9 - 22
ot_admin/Classes/Controller/SiteController.php

@@ -177,7 +177,7 @@ class SiteController extends ActionController
         $site = new SiteInfos(
             $rootUid,
             $website['organization_name'],
-            $this->otWebsiteRepository->getWebsiteDomain($website['uid']),
+            $this->otWebsiteRepository->resolveWebsiteDomain($website),
             $website['template'],
             $website['template_preferences'],
             $website['matomo_id'],
@@ -678,7 +678,7 @@ class SiteController extends ActionController
 
             // ## Update the config.yaml file
             if ($deep) {
-                $organizationDomain = $this->otWebsiteRepository->getWebsiteDomain($rootUid);
+                $organizationDomain = $this->otWebsiteRepository->resolveWebsiteDomain($website);
                 $this->writeConfigFile($organizationId, $rootUid, $organizationDomain, true);
             }
 
@@ -778,10 +778,10 @@ class SiteController extends ActionController
             if ($redirectTo == $organizationId) {
                 throw new \InvalidArgumentException('redirectTo value has to be different from the organizationId');
             }
-            $originUrl = $this->otWebsiteRepository->getWebsiteDomain($websiteUid);
+            $originDomain = $this->otWebsiteRepository->resolveWebsiteDomain($website);
 
             $targetOrganizationWebsite = $this->otWebsiteRepository->getWebsiteByOrganizationId($redirectTo);
-            $targetUrl = $this->otWebsiteRepository->getWebsiteDomain($targetOrganizationWebsite['uid']);
+            $targetDomain = $this->otWebsiteRepository->resolveWebsiteDomain($targetOrganizationWebsite);
         }
 
         // start transactions
@@ -929,7 +929,7 @@ class SiteController extends ActionController
 
             // Add the redirection
             if ($redirectTo) {
-                $this->addRedirection($originUrl, $targetUrl);
+                $this->addRedirection($originDomain, $targetDomain);
             }
 
             // Try to commit the result
@@ -1336,6 +1336,7 @@ class SiteController extends ActionController
      * @return int
      * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
      * @throws NoSuchWebsiteException
+     * @throws \Opentalent\OtCore\Exception\InvalidWebsiteConfigurationException
      */
     public function setSiteCustomDomainAction(int $organizationId, string $newDomain, bool $redirect = true): int
     {
@@ -1355,9 +1356,9 @@ class SiteController extends ActionController
             ->where($queryBuilder->expr()->eq('uid', $websiteUid))
             ->execute();
 
-        $originUrl = $this->otWebsiteRepository->getWebsiteDomain($websiteUid);
+        $originDomain = $this->otWebsiteRepository->resolveWebsiteDomain($website);
 
-        if (preg_replace('/https?:\/\//', '', $originUrl) == preg_replace('/https?:\/\//', '', $newDomain) ) {
+        if (preg_replace('/https?:\/\//', '', $originDomain) == preg_replace('/https?:\/\//', '', $newDomain) ) {
             throw new \RuntimeException('The new domain should be different of the current one');
         }
 
@@ -1365,7 +1366,7 @@ class SiteController extends ActionController
 
         if ($redirect) {
             // Add the redirection
-            $this->addRedirection($originUrl, $newDomain);
+            $this->addRedirection($originDomain, $newDomain);
         }
 
         return $rootUid;
@@ -1725,20 +1726,6 @@ class SiteController extends ActionController
         }
     }
 
-    /**
-     * Update the routing index for the given website
-     *
-     * @param int $organizationId
-     * @throws NoSuchWebsiteException
-     */
-    public function updateRoutingIndexAction(int $organizationId)
-    {
-        $rootUid = $this->otWebsiteRepository->findRootUidForOrganization($organizationId);
-
-        $routingIndexer = GeneralUtility::makeInstance(ObjectManager::class)->get(Indexer::class);
-        $routingIndexer->indexRoutesForWebsite($rootUid);
-    }
-
     /**
      * Retrieve the Organization object from the repository and then,
      * from the Opentalent API

+ 1 - 0
ot_core/.gitignore

@@ -4,3 +4,4 @@ Build/testing-docker/.env
 composer.lock
 /var/
 /coverage/
+/unittest-coverage.clover

+ 52 - 14
ot_core/Classes/Website/OtWebsiteRepository.php

@@ -5,6 +5,7 @@ namespace Opentalent\OtCore\Website;
 use Opentalent\OtCore\Exception\InvalidWebsiteConfigurationException;
 use Opentalent\OtCore\Exception\NoSuchWebsiteException;
 use Symfony\Component\Yaml\Yaml;
+use TYPO3\CMS\Core\Site\Entity\Site;
 
 /**
  * Repository for the ot_websites table
@@ -101,7 +102,7 @@ class OtWebsiteRepository
      * @return int
      */
     public function getWebsiteRootUid(int $websiteUid, bool $withRestrictions = true): int {
-        $queryBuilder = $this->connectionPool->getQueryBuilderForTable('ot_websites');
+        $queryBuilder = $this->connectionPool->getQueryBuilderForTable('pages');
         if (!$withRestrictions) {
             $queryBuilder->getRestrictions()->removeAll();
         }
@@ -146,15 +147,12 @@ class OtWebsiteRepository
     /**
      * Retrieves the current full domain of the given website.
      *
-     * @param int $websiteUid
+     * @param array $website
      * @return string
      * @throws InvalidWebsiteConfigurationException
-     * @throws NoSuchWebsiteException
      */
-    public function getWebsiteDomain(int $websiteUid): string
+    public function resolveWebsiteDomain(array $website): string
     {
-        $website = $this->getWebsiteByUid($websiteUid);
-
         if ($website['custom_domain']) {
             return $website['custom_domain'];
         } else if ($website['subdomain']) {
@@ -166,14 +164,13 @@ class OtWebsiteRepository
     /**
      * Get the website current base uri
      *
-     * @param int $websiteUid
+     * @param array $website
      * @return string
      * @throws InvalidWebsiteConfigurationException
-     * @throws NoSuchWebsiteException
      */
-    public function getWebsiteBaseUri(int $websiteUid): string
+    public function resolveWebsiteBaseUri(array $website): string
     {
-        return 'https://' . $this->getWebsiteDomain($websiteUid);
+        return 'https://' . $this->resolveWebsiteDomain($website);
     }
 
     /**
@@ -182,12 +179,53 @@ class OtWebsiteRepository
      *
      * @param int $rootUid
      * @param string $domain
-     * @return array
+     * @return Site
+     * @throws InvalidWebsiteConfigurationException
+     * @throws NoSuchWebsiteException
      */
-    public function generateWebsiteConfiguration(int $rootUid, string $domain): array {
-        return [
+    public function generateWebsiteConfiguration(int $rootUid, string $domain): Site
+    {
+        $website = $this->getWebsiteByPageUid($rootUid);
 
-        ];
+        return new Site(
+            $website['uid'],
+            $rootUid,
+            [
+                'base' => $this->resolveWebsiteBaseUri($website),
+                'baseVariants' => [0 => [
+                                'base' => $website['subdomain'] . '/',
+                                'condition' => 'applicationContext == "Development"',
+                                        ],
+                                ],
+                'errorHandling' => [0 => ['errorCode' => '404',
+                                            'errorHandler' => 'PHP',
+                                            'errorPhpClassFQCN' => 'Opentalent\\OtTemplating\\Page\\ErrorHandler',
+                                         ],
+                                    1 => ['errorCode' => '403',
+                                            'errorHandler' => 'PHP',
+                                            'errorPhpClassFQCN' => 'Opentalent\\OtTemplating\\Page\\ErrorHandler',
+                                         ],
+                                    ],
+                'flux_content_types' => '',
+                'flux_page_templates' => '',
+                'languages' => [0 => [
+                                        'title' => 'Fr',
+                                        'enabled' => true,
+                                        'base' => '/',
+                                        'typo3Language' => 'fr',
+                                        'locale' => 'fr_FR',
+                                        'iso-639-1' => 'fr',
+                                        'navigationTitle' => 'Fr',
+                                        'hreflang' => 'fr-FR',
+                                        'direction' => 'ltr',
+                                        'flag' => 'fr',
+                                        'languageId' => '0',
+                                     ],
+                              ],
+                'rootPageId' => $rootUid,
+                'routes' => [],
+            ]
+        );
     }
 
     /**

ファイルの差分が大きいため隠しています
+ 1 - 1
ot_core/Tests/Unit/Fixtures/PageFixtures.php


+ 68 - 0
ot_core/Tests/Unit/Fixtures/WebsiteFixtures.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace Opentalent\OtCore\Tests\Unit\Fixtures;
+
+class WebsiteFixtures
+{
+    private array $websites = [
+        [ 'uid' => 1, 'organization_id' => 1, 'subdomain' => 'em1', 'custom_domain' => '', 'locale' => 'fr_FR', 'matomo_site_id' => null, 'template' => 'Classic', 'template_preferences' => '{"themeColor":"light-blue","displayCarousel":"1"}', 'organization_name' => 'Ecole de musique 1', 'deleted' => 0  ],
+        [ 'uid' => 2, 'organization_id' => 2, 'subdomain' => 'em2', 'custom_domain' => 'musique2.net', 'locale' => 'fr_FR', 'matomo_site_id' => null, 'template' => 'Classic', 'template_preferences' => '{"themeColor":"light-blue","displayCarousel":"1"}', 'organization_name' => 'Ecole de musique 2', 'deleted' => 0  ],
+        [ 'uid' => 3, 'organization_id' => 3, 'subdomain' => '', 'custom_domain' => '', 'locale' => 'fr_FR', 'matomo_site_id' => null, 'template' => 'Classic', 'template_preferences' => '{"themeColor":"light-blue","displayCarousel":"1"}', 'organization_name' => 'Ecole de musique 3', 'deleted' => 1  ],
+    ];
+
+    /**
+     * Returns a typical full stack of typo3 ot_websites
+     * as it could be returned by:
+     *
+     *    $queryBuilder->getRestrictions()->removeAll();
+     *    $queryBuilder->select('*')
+     *                 ->from('ot_websites')
+     *                 ->execute()
+     *                 ->fetchAll();
+     *
+     * @return array[]
+     */
+    public function getAll(): array
+    {
+        return $this->websites;
+    }
+
+    /**
+     * Returns a typical full stack of typo3 ot_websites
+     * as it could be returned by:
+     *
+     *    $queryBuilder->select('*')
+     *                 ->from('ot_websites')
+     *                 ->execute()
+     *                 ->fetchAll();
+     *
+     * @return array[]
+     */
+    public function getNonDeleted(): array
+    {
+        return array_filter($this->websites, function($p) { return $p['deleted'] == 0; });
+    }
+
+    /**
+     * Returns a typo3 page
+     * as it could be returned by:
+     *
+     *    $queryBuilder->select('*')
+     *                 ->from('ot_websites')
+     *                 ->where($queryBuilder->expr()->eq('uid', $websiteUid))
+     *                 ->execute()
+     *                 ->fetch();
+     *
+     * @param $websiteUid
+     * @return array|null
+     */
+    public function getByUid($websiteUid): ?array
+    {
+        foreach ($this->websites as $website) {
+            if ($website['uid'] == $websiteUid) {
+                return $website;
+            }
+        }
+        return null;
+    }
+}

+ 10 - 8
ot_core/Tests/Unit/QueryBuilderProphet.php

@@ -4,11 +4,7 @@ namespace Opentalent\OtCore\Tests\Unit;
 
 use Doctrine\DBAL\Driver\Statement;
 use Prophecy\Argument;
-use Prophecy\Doubler\Doubler;
-use Prophecy\Prophecy\ObjectProphecy;
-use Prophecy\Prophecy\RevealerInterface;
 use Prophecy\Prophet;
-use Prophecy\Util\StringUtil;
 use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
 use TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionContainerInterface;
@@ -63,16 +59,22 @@ class QueryBuilderProphet extends Prophet
         $queryRestrictions->removeAll()->willReturn($queryRestrictions);
 
         // Mock expression builder
-        $expressionBuilder->eq(Argument::type('string'), Argument::any())->willReturn("");
+        $expressionBuilder->eq(Argument::any(), Argument::any())->willReturn("");
         $queryBuilder->expr()->willReturn($expressionBuilder);
 
         // Mock Querybuilder
-        $queryBuilder->select(Argument::type('string'))->willReturn($queryBuilder);
-        $queryBuilder->from(Argument::type('string'))->willReturn($queryBuilder);
+        $queryBuilder->select(Argument::cetera())->willReturn($queryBuilder);
+        $queryBuilder->from(Argument::cetera())->willReturn($queryBuilder);
+        $queryBuilder->innerJoin(Argument::cetera())->willReturn($queryBuilder);
         $queryBuilder->where(Argument::any())->willReturn($queryBuilder);
+        $queryBuilder->andWhere(Argument::any())->willReturn($queryBuilder);
 
-        // Mock Statement and execution
+        // Mock Statements
         $statement->fetchAll()->willReturn(...$this->willReturn);
+        $statement->fetch()->willReturn($this->willReturn[0]);
+        $statement->fetchColumn(0)->willReturn($this->willReturn[0]);
+
+        // Mock execution
         $queryBuilder->execute()->willReturn($statement);
 
         return $queryBuilder;

+ 1 - 1
ot_core/Tests/Unit/Page/OtPageRepositoryTest.php → ot_core/Tests/Unit/Website/OtPageRepositoryTest.php

@@ -1,6 +1,6 @@
 <?php
 
-namespace Opentalent\OtCore\Tests\Unit\Page;
+namespace Opentalent\OtCore\Tests\Unit\Website;
 
 use Opentalent\OtCore\Website\OtPageRepository;
 use Nimut\TestingFramework\TestCase\UnitTestCase;

+ 234 - 0
ot_core/Tests/Unit/Website/OtWebsiteRepositoryTest.php

@@ -0,0 +1,234 @@
+<?php
+
+
+namespace Opentalent\OtCore\Tests\Unit\Website;
+
+
+use Nimut\TestingFramework\TestCase\UnitTestCase;
+use Opentalent\OtCore\Exception\InvalidWebsiteConfigurationException;
+use Opentalent\OtCore\Exception\NoSuchWebsiteException;
+use Opentalent\OtCore\Tests\Unit\Fixtures\PageFixtures;
+use Opentalent\OtCore\Tests\Unit\Fixtures\WebsiteFixtures;
+use Opentalent\OtCore\Tests\Unit\QueryBuilderProphet;
+use Opentalent\OtCore\Website\OtPageRepository;
+use Opentalent\OtCore\Website\OtWebsiteRepository;
+
+class OtWebsiteRepositoryTest extends UnitTestCase
+{
+    protected $connectionPool;
+    protected $pageFixtures;
+    protected $websiteFixtures;
+    protected $otWebsiteRepository;
+
+    public function setUp() {
+        // Prophecies to be injected in the under test OtPageRepository
+        $this->connectionPool = $this->prophesize(\TYPO3\CMS\Core\Database\ConnectionPool::class);
+
+        // Fixtures
+        $this->pageFixtures = new PageFixtures();
+        $this->websiteFixtures = new WebsiteFixtures();
+
+        // The under test OtWebsiteRepository
+        $this->otWebsiteRepository = new OtWebsiteRepository();
+    }
+
+    /**
+     * Inject the prophecies instantiated at setUp into the OtPageRepository under test object
+     */
+    protected function injectProphecies() {
+        $this->otWebsiteRepository->injectConnectionPool($this->connectionPool->reveal());
+    }
+
+    /**
+     * Calling getWebsiteByUid() on a website should return the corresponding website,
+     *
+     * @test
+     */
+    public function getWebsiteByUid()
+    {
+        $website_uid = 1;
+        $expected = $this->websiteFixtures->getByUid($website_uid);
+
+        $prophet = new QueryBuilderProphet($expected);
+        $queryBuilder = $prophet->prophesize();
+        $this->connectionPool->getQueryBuilderForTable('ot_websites')->willReturn($queryBuilder);
+        $this->injectProphecies();
+
+        $actual = $this->otWebsiteRepository->getWebsiteByUid($website_uid);
+        $this->assertEquals($expected, $actual);
+    }
+
+    /**
+     * Calling getWebsiteByUid() on a deleted website should throw a NoSuchWebsiteException
+     *
+     * @test
+     */
+    public function getDeletedWebsiteByUid()
+    {
+        $prophet = new QueryBuilderProphet([]);
+        $queryBuilder = $prophet->prophesize();
+        $this->connectionPool->getQueryBuilderForTable('ot_websites')->willReturn($queryBuilder);
+        $this->injectProphecies();
+
+        $this->expectException(NoSuchWebsiteException::class);
+        $this->otWebsiteRepository->getWebsiteByUid(-1);
+    }
+
+    /**
+     * Calling getWebsiteByOrganizationId() on a website should return the corresponding website,
+     *
+     * @test
+     */
+    public function getWebsiteByOrganizationId()
+    {
+        $expected = $this->websiteFixtures->getByUid(1);
+
+        $prophet = new QueryBuilderProphet($expected);
+        $queryBuilder = $prophet->prophesize();
+        $this->connectionPool->getQueryBuilderForTable('ot_websites')->willReturn($queryBuilder);
+        $this->injectProphecies();
+
+        $actual = $this->otWebsiteRepository->getWebsiteByOrganizationId(1);
+        $this->assertEquals($expected, $actual);
+    }
+
+    /**
+     * Calling getWebsiteByOrganizationId() on a deleted website should throw a NoSuchWebsiteException
+     *
+     * @test
+     */
+    public function getDeletedWebsiteByOrganizationId()
+    {
+        $prophet = new QueryBuilderProphet([]);
+        $queryBuilder = $prophet->prophesize();
+        $this->connectionPool->getQueryBuilderForTable('ot_websites')->willReturn($queryBuilder);
+        $this->injectProphecies();
+
+        $this->expectException(NoSuchWebsiteException::class);
+        $this->otWebsiteRepository->getWebsiteByUid(-1);
+    }
+
+    /**
+     * Calling getWebsiteRootUid() on a website should return the corresponding root page uid
+     *
+     * @test
+     */
+    public function getWebsiteRootUid() {
+        $expected = 1;
+
+        $prophet = new QueryBuilderProphet($expected);
+        $queryBuilder = $prophet->prophesize();
+        $this->connectionPool->getQueryBuilderForTable('pages')->willReturn($queryBuilder);
+        $this->injectProphecies();
+
+        $actual = $this->otWebsiteRepository->getWebsiteRootUid(1);
+        $this->assertEquals($expected, $actual);
+    }
+
+    /**
+     * Calling findRootUidForOrganization() on a website should return the corresponding root page uid
+     *
+     * @test
+     */
+    public function findRootUidForOrganization() {
+        $expected = 1;
+
+        $prophet = new QueryBuilderProphet($expected);
+        $queryBuilder = $prophet->prophesize();
+        $this->connectionPool->getQueryBuilderForTable('pages')->willReturn($queryBuilder);
+        $this->injectProphecies();
+
+        $actual = $this->otWebsiteRepository->findRootUidForOrganization(1);
+        $this->assertEquals($expected, $actual);
+    }
+
+    /**
+     * Calling findRootUidForOrganization() on a website should return the corresponding root page uid
+     *
+     * @test
+     */
+    public function findRootUidForInvalidOrganization() {
+        $expected = [];
+
+        $prophet = new QueryBuilderProphet($expected);
+        $queryBuilder = $prophet->prophesize();
+        $this->connectionPool->getQueryBuilderForTable('pages')->willReturn($queryBuilder);
+        $this->injectProphecies();
+
+        $this->expectException(NoSuchWebsiteException::class);
+        $this->otWebsiteRepository->findRootUidForOrganization(-1);
+    }
+
+    /**
+     * Calling resolveWebsiteDomain() on a website without custom_domain set
+     * should return a domain of the form <subdomain>.opentalent.fr
+     *
+     * @test
+     */
+    public function resolveWebsiteDomainWithoutCustom() {
+        $expected = 'em1.opentalent.fr';
+
+        $website = $this->websiteFixtures->getByUid(1);
+
+        $actual = $this->otWebsiteRepository->resolveWebsiteDomain($website);
+        $this->assertEquals($expected, $actual);
+    }
+
+    /**
+     * Calling resolveWebsiteDomain() on a website with a custom_domain set
+     * should return this custom domain
+     *
+     * @test
+     */
+    public function resolveWebsiteDomainWithCustom() {
+        $expected = 'musique2.net';
+
+        $website = $this->websiteFixtures->getByUid(2);
+
+        $actual = $this->otWebsiteRepository->resolveWebsiteDomain($website);
+        $this->assertEquals($expected, $actual);
+    }
+
+    /**
+     * Calling resolveWebsiteDomain() on a website without any subdomain or custom_domain set
+     * should throw an InvalidWebsiteConfigurationException
+     *
+     * @test
+     */
+    public function resolveWebsiteDomainWithoutDomain() {
+        $website = $this->websiteFixtures->getByUid(3);
+
+        $this->expectException(InvalidWebsiteConfigurationException::class);
+        $this->otWebsiteRepository->resolveWebsiteDomain($website);
+    }
+
+    /**
+     * Calling resolveWebsiteDomain() on a website should have the same result as resolveWebsiteDomain(),
+     * but with the 'https://' prefix.
+     *
+     * @test
+     */
+    public function resolveWebsiteBaseUri() {
+        $expected = 'https://em1.opentalent.fr';
+
+        $website = $this->websiteFixtures->getByUid(1);
+
+        $actual = $this->otWebsiteRepository->resolveWebsiteBaseUri($website);
+        $this->assertEquals($expected, $actual);
+    }
+
+
+    /**
+     * Calling generateWebsiteConfiguration() should return the full configuration array
+     * as it would be found in the typo3 website config.yaml
+     *
+     * @param int $rootUid
+     * @param string $domain
+     * @return array
+     */
+    public function generateWebsiteConfiguration(int $rootUid, string $domain): array {
+        return [
+
+        ];
+    }
+}

+ 1 - 1
ot_stats/Classes/Domain/Repository/MatomoWebsiteRepository.php

@@ -166,7 +166,7 @@ class MatomoWebsiteRepository
         if ($isDev) {
             $uri = rtrim($_SERVER['HTTP_HOST'], '/') . '/' . $website['subdomain'];
         } else {
-            $uri = $otWebsiteRepository->getWebsiteDomain($website['uid']);
+            $uri = $otWebsiteRepository->resolveWebsiteDomain($website);
         }
 
         if (!preg_match(self::DOMAIN_VALIDATION, $uri)) {

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません