Initial commit - Typo3 11.5.41

This commit is contained in:
Matteo Gallo
2026-07-03 17:53:31 +02:00
commit 5ca4743197
6811 changed files with 568848 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
<?php
declare(strict_types=1);
namespace GeorgRinger\News\Tests\Unit\Controller;
/**
* This file is part of the "news" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*/
use GeorgRinger\News\Controller\NewsController;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Http\ServerRequest;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Core\Bootstrap;
use TYPO3\CMS\Extbase\Service\EnvironmentService;
use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
/**
* Class NewsControllerTest
*/
class NewsControllerTest extends FunctionalTestCase
{
use ProphecyTrait;
/**
* @var NewsController
*/
protected $subject;
/**
* @var string[]
*/
protected $testExtensionsToLoad = [
'typo3conf/ext/news'
];
/**
* @var string[]
*/
protected $coreExtensionsToLoad = [
'extbase',
'fluid'
];
protected function setUp(): void
{
parent::setUp();
$this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/pages.xml');
$this->setUpFrontendRootPage(
1,
[
__DIR__ . '/../Fixtures/TypoScript/setup.typoscript'
]
);
// This part is needed for TYPO3 10 compatibility
/** @var EnvironmentService|ObjectProphecy $environmentServiceProphecy */
$environmentServiceProphecy = $this->prophesize(EnvironmentService::class);
$environmentServiceProphecy
->isEnvironmentInFrontendMode()
->willReturn(true);
$environmentServiceProphecy
->isEnvironmentInBackendMode()
->willReturn(false);
GeneralUtility::setSingletonInstance(EnvironmentService::class, $environmentServiceProphecy->reveal());
$serverRequest = new ServerRequest();
$applicationType = SystemEnvironmentBuilder::REQUESTTYPE_FE;
$serverRequest = $serverRequest->withAttribute('applicationType', $applicationType);
/** @var TypoScriptFrontendController|ObjectProphecy $typoScriptFrontendControllerProphecy */
$typoScriptFrontendControllerProphecy = $this->prophesize(TypoScriptFrontendController::class);
/** @var FrontendUserAuthentication|ObjectProphecy $frontendUserAuthenticationProphecy */
$frontendUserAuthenticationProphecy = $this->prophesize(FrontendUserAuthentication::class);
$GLOBALS['TYPO3_REQUEST'] = $serverRequest;
$GLOBALS['LANG'] = GeneralUtility::makeInstance(LanguageService::class);
$GLOBALS['TSFE'] = $typoScriptFrontendControllerProphecy->reveal();
$GLOBALS['TSFE']->fe_user = $frontendUserAuthenticationProphecy->reveal();
}
protected function tearDown(): void
{
unset(
$this->subject
);
parent::tearDown();
}
/**
* @test
*/
public function listActionWillReturnNoNews(): void
{
$extbaseBootstrap = GeneralUtility::makeInstance(Bootstrap::class);
$content = $extbaseBootstrap->run(
'',
[
'extensionName' => 'News',
'pluginName' => 'Pi1'
]
);
$this->assertStringContainsString(
'No news available.',
$content
);
}
/**
* @test
*/
public function listActionWillShowNewsOfStoragePage1(): void
{
$date = new \DateTime('now');
$connection = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable('tx_news_domain_model_news');
$connection->insert(
'tx_news_domain_model_news',
[
'uid' => 1,
'pid' => 1,
'title' => 'My first news',
'datetime' => (int)$date->format('U')
]
);
$extbaseBootstrap = GeneralUtility::makeInstance(Bootstrap::class);
$content = $extbaseBootstrap->run(
'',
[
'extensionName' => 'News',
'pluginName' => 'Pi1'
]
);
$this->assertStringContainsString(
'<span itemprop="headline">My first news</span>',
$content
);
$this->assertStringContainsString(
'<time itemprop="datePublished" datetime="' . $date->format('Y-m-d') . '">',
$content
);
}
}

View File

@@ -0,0 +1,183 @@
# ==============================================
# FE-Plugin configuration for EXT:news
# ==============================================
plugin.tx_news {
mvc.callDefaultActionIfActionCantBeResolved = 1
view {
templateRootPaths {
0 = EXT:news/Resources/Private/Templates/
}
partialRootPaths {
0 = EXT:news/Resources/Private/Partials/
}
layoutRootPaths {
0 = EXT:news/Resources/Private/Layouts/
}
widget.GeorgRinger\News\ViewHelpers\Widget\PaginateViewHelper.templateRootPath = EXT:news/Resources/Private/Templates/
}
# ====================================
# Settings available inside Controller and View by accessing $this->settings or {settings.xyz}
# ====================================
settings {
cssFile =
#Displays a dummy image if the news have no media items
displayDummyIfNoMedia = 1
# Output format
format = html
# general settings
overrideFlexformSettingsIfEmpty = cropMaxCharacters,dateField,timeRestriction,timeRestrictionHigh,archiveRestriction,orderBy,orderDirection,backPid,listPid,startingpoint,recursive,list.paginate.itemsPerPage,list.paginate.templatePath
allowEmptyStringsForOverwriteDemand = 0
includeSubCategories = 0
analytics {
social {
facebookLike = 1
facebookShare = 1
twitter = 1
}
}
detailPidDetermination = flexform, categories, default
defaultDetailPid = 0
dateField = datetime
link {
typesOpeningInNewWindow = 2
hrDate = 0
hrDate {
day = j
month = n
year = Y
}
}
cropMaxCharacters = 150
orderBy = datetime
orderDirection = desc
topNewsFirst = 0
orderByAllowed = sorting,author,uid,title,teaser,author,tstamp,crdate,datetime,categories.title
facebookLocale = en_US
googlePlusLocale = en
demandClass =
# --------------
# Search
# --------------
search {
fields = teaser,title,bodytext
splitSearchWord = 0
}
# --------------
# Detail
# --------------
detail {
errorHandling = showStandaloneTemplate,EXT:news/Resources/Private/Templates/News/DetailNotFound.html,404
checkPidOfNewsRecord = 0
registerProperties = keywords,title
showPrevNext = 0
showSocialShareButtons = 1
showMetaTags = 1
# media configuration
media {
image {
lazyLoading = 0
maxWidth = 282
maxHeight =
# Get lightbox settings from fluid_styled_content
lightbox {
enabled = {$styles.content.textmedia.linkWrap.lightboxEnabled}
class = {$styles.content.textmedia.linkWrap.lightboxCssClass}
width = {$styles.content.textmedia.linkWrap.width}
height = {$styles.content.textmedia.linkWrap.height}
rel = lightbox[myImageSet]
}
}
video {
width = 282
height = 159
}
}
pageTitle = 1
pageTitle {
provider = GeorgRinger\News\Seo\NewsTitleProvider
properties = title,teaser
}
}
# --------------
# List
# --------------
list {
# media configuration
media {
image {
lazyLoading = 0
maxWidth = 100
maxHeight = 100
}
dummyImage = EXT:news/Resources/Public/Images/dummy-preview-image.png
}
# Paginate configuration.
paginate {
class = GeorgRinger\NumberedPagination\NumberedPagination
itemsPerPage = 10
insertAbove = 1
insertBelow = 1
maximumNumberOfLinks = 3
}
}
}
}
# ==============================================
# Persistence object mapping configuration
# ==============================================
config.tx_extbase.persistence.classes {
GeorgRinger\News\Domain\Model\News {
subclasses {
0 = GeorgRinger\News\Domain\Model\NewsDefault
1 = GeorgRinger\News\Domain\Model\NewsInternal
2 = GeorgRinger\News\Domain\Model\NewsExternal
}
}
GeorgRinger\News\Domain\Model\NewsDefault {
mapping {
recordType = 0
tableName = tx_news_domain_model_news
}
}
GeorgRinger\News\Domain\Model\NewsInternal {
mapping {
recordType = 1
tableName = tx_news_domain_model_news
}
}
GeorgRinger\News\Domain\Model\NewsExternal {
mapping {
recordType = 2
tableName = tx_news_domain_model_news
}
}
}

View File

@@ -0,0 +1,22 @@
tx_news_domain_model_news,,,,
,uid,pid,title
,1,0,News1
,2,0,News2
,3,0,News3
,4,0,News4
,5,0,News5
,6,0,News6
,7,0,News7
,8,0,News8
,9,0,News9
,10,0,News10
,11,0,News11
,12,0,News12
,13,0,News13
,14,0,News14
,15,0,News15
,16,0,News16
,17,0,News17
,18,0,News18
,19,0,News19
,20,0,News20
1 tx_news_domain_model_news,,,,
2 ,uid,pid,title
3 ,1,0,News1
4 ,2,0,News2
5 ,3,0,News3
6 ,4,0,News4
7 ,5,0,News5
8 ,6,0,News6
9 ,7,0,News7
10 ,8,0,News8
11 ,9,0,News9
12 ,10,0,News10
13 ,11,0,News11
14 ,12,0,News12
15 ,13,0,News13
16 ,14,0,News14
17 ,15,0,News15
18 ,16,0,News16
19 ,17,0,News17
20 ,18,0,News18
21 ,19,0,News19
22 ,20,0,News20

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<!--findRecordsByImportSource-->
<sys_category>
<uid>456</uid>
<pid>1</pid>
<title>findRecordByImportSource</title>
<import_source>functional_test</import_source>
<import_id>2</import_id>
<l10n_diffsource></l10n_diffsource>
<description></description>
</sys_category>
</dataset>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<tx_news_domain_model_tag>
<uid>1</uid>
<pid>1</pid>
<title>Tag 1</title>
</tx_news_domain_model_tag>
<tx_news_domain_model_tag>
<uid>2</uid>
<pid>1</pid>
<title>Tag 2</title>
</tx_news_domain_model_tag>
<tx_news_domain_model_tag>
<uid>3</uid>
<pid>1</pid>
<title>Tag 3</title>
</tx_news_domain_model_tag>
<tx_news_domain_model_tag>
<uid>4</uid>
<pid>1</pid>
<title>Tag 4</title>
</tx_news_domain_model_tag>
<tx_news_domain_model_tag>
<uid>5</uid>
<pid>1</pid>
<title>Tag 5</title>
</tx_news_domain_model_tag>
</dataset>

View File

@@ -0,0 +1,251 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<!--findRecordsByUid-->
<tx_news_domain_model_news>
<uid>1</uid>
<pid>1</pid>
<type>0</type>
<title>findRecordsByUid</title>
</tx_news_domain_model_news>
<!--findRecordsByImportSource-->
<tx_news_domain_model_news>
<uid>456</uid>
<pid>1</pid>
<type>0</type>
<title>findRecordsByImportSource</title>
<import_source>functional_test</import_source>
<import_id>2</import_id>
</tx_news_domain_model_news>
<!--findTopNewsRecords-->
<tx_news_domain_model_news>
<pid>2</pid>
<type>1</type>
<istopnews>1</istopnews>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>2</pid>
<type>1</type>
<istopnews>1</istopnews>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>2</pid>
<type>2</type>
<istopnews>1</istopnews>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>2</pid>
<type>2</type>
<istopnews>0</istopnews>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>2</pid>
<type>2</type>
<istopnews>0</istopnews>
</tx_news_domain_model_news>
<!--findRecordsByStartingpointRestriction-->
<tx_news_domain_model_news>
<pid>3</pid>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>3</pid>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>4</pid>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>4</pid>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>4</pid>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>4</pid>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>5</pid>
</tx_news_domain_model_news>
<!--findRecordsByArchiveRestriction-->
<!--22.3.2014-->
<tx_news_domain_model_news>
<pid>7</pid>
<archive>1395516100</archive>
</tx_news_domain_model_news>
<!--27.3.-->
<tx_news_domain_model_news>
<pid>7</pid>
<archive>1395948100</archive>
</tx_news_domain_model_news>
<!--1.4.2014-->
<tx_news_domain_model_news>
<pid>7</pid>
<archive>1396380100</archive>
</tx_news_domain_model_news>
<!--6.4.2014-->
<tx_news_domain_model_news>
<pid>7</pid>
<archive>1396812100</archive>
</tx_news_domain_model_news>
<!--11.4.2014-->
<tx_news_domain_model_news>
<pid>7</pid>
<archive>1397244100</archive>
</tx_news_domain_model_news>
<!--findRecordsByMonthAndYear-->
<tx_news_domain_model_news>
<pid>8</pid>
<datetime>1298156400</datetime>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>8</pid>
<datetime>1298329200</datetime>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>8</pid>
<datetime>1298934000</datetime>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>8</pid>
<datetime>1298934000</datetime>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>8</pid>
<datetime>1299711600</datetime>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>8</pid>
<datetime>1301522400</datetime>
</tx_news_domain_model_news>
<tx_news_domain_model_news>
<pid>8</pid>
<datetime>1301608800</datetime>
</tx_news_domain_model_news>
<!--findLatestLimitRecords-->
<!--SimplePrevNextViewHelperTest-->
<!--22.3.2014-->
<tx_news_domain_model_news>
<uid>101</uid>
<pid>9</pid>
<datetime>1395516730</datetime>
</tx_news_domain_model_news>
<!--25.3.2014-->
<tx_news_domain_model_news>
<uid>102</uid>
<pid>9</pid>
<datetime>1395775956</datetime>
</tx_news_domain_model_news>
<!--28.3.2014-->
<tx_news_domain_model_news>
<uid>103</uid>
<pid>9</pid>
<datetime>1396035186</datetime>
</tx_news_domain_model_news>
<!--29.3.2014-->
<tx_news_domain_model_news>
<uid>104</uid>
<pid>9</pid>
<datetime>1396121600</datetime>
</tx_news_domain_model_news>
<!--2.4.2014-->
<tx_news_domain_model_news>
<uid>105</uid>
<pid>9</pid>
<datetime>1396467221</datetime>
</tx_news_domain_model_news>
<!--4.4.2014 -->
<tx_news_domain_model_news>
<uid>106</uid>
<pid>9</pid>
<datetime>1396640035</datetime>
</tx_news_domain_model_news>
<!--Tags-->
<tx_news_domain_model_news>
<uid>130</uid>
<pid>10</pid>
<title>tag1,tag2,tag3</title>
<tags>3</tags>
</tx_news_domain_model_news>
<tx_news_domain_model_news_tag_mm>
<uid_local>130</uid_local>
<uid_foreign>1</uid_foreign>
<sorting>1</sorting>
</tx_news_domain_model_news_tag_mm>
<tx_news_domain_model_news_tag_mm>
<uid_local>130</uid_local>
<uid_foreign>2</uid_foreign>
<sorting>2</sorting>
</tx_news_domain_model_news_tag_mm>
<tx_news_domain_model_news_tag_mm>
<uid_local>130</uid_local>
<uid_foreign>3</uid_foreign>
<sorting>3</sorting>
</tx_news_domain_model_news_tag_mm>
<tx_news_domain_model_news>
<uid>131</uid>
<pid>10</pid>
<title>tag3</title>
<tags>1</tags>
</tx_news_domain_model_news>
<tx_news_domain_model_news_tag_mm>
<uid_local>131</uid_local>
<uid_foreign>3</uid_foreign>
<sorting>1</sorting>
</tx_news_domain_model_news_tag_mm>
<tx_news_domain_model_news>
<uid>132</uid>
<pid>10</pid>
<title>tag4</title>
<tags>1</tags>
</tx_news_domain_model_news>
<tx_news_domain_model_news_tag_mm>
<uid_local>132</uid_local>
<uid_foreign>4</uid_foreign>
<sorting>1</sorting>
</tx_news_domain_model_news_tag_mm>
<tx_news_domain_model_news>
<uid>133</uid>
<pid>10</pid>
<title>tag5</title>
<tags>1</tags>
</tx_news_domain_model_news>
<tx_news_domain_model_news_tag_mm>
<uid_local>133</uid_local>
<uid_foreign>5</uid_foreign>
<sorting>1</sorting>
</tx_news_domain_model_news_tag_mm>
<tx_news_domain_model_news>
<uid>134</uid>
<pid>10</pid>
<title>tag4,tag5</title>
<tags>2</tags>
</tx_news_domain_model_news>
<tx_news_domain_model_news_tag_mm>
<uid_local>134</uid_local>
<uid_foreign>4</uid_foreign>
<sorting>1</sorting>
</tx_news_domain_model_news_tag_mm>
<tx_news_domain_model_news_tag_mm>
<uid_local>134</uid_local>
<uid_foreign>5</uid_foreign>
<sorting>2</sorting>
</tx_news_domain_model_news_tag_mm>
</dataset>

View File

@@ -0,0 +1,206 @@
<?php
namespace GeorgRinger\News\Tests\Functional\Pagination;
/**
* This file is part of the "news" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*/
use GeorgRinger\News\Domain\Model\Dto\NewsDemand;
use GeorgRinger\News\Domain\Repository\NewsRepository;
use GeorgRinger\News\Pagination\QueryResultPaginator;
use TYPO3\CMS\Core\Information\Typo3Version;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
class QueryResultPaginatorTest extends FunctionalTestCase
{
/**
* @var NewsRepository
*/
protected $newsRepository;
protected $testExtensionsToLoad = ['typo3conf/ext/news'];
protected function setUp(): void
{
parent::setUp();
$this->importCSVDataSet(__DIR__ . '/../Fixtures/news_pagination.csv');
$versionInformation = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(Typo3Version::class);
if ($versionInformation->getMajorVersion() === 11) {
$this->newsRepository = $this->getContainer()->get(NewsRepository::class);
} else {
$this->newsRepository = GeneralUtility::makeInstance(ObjectManager::class)->get(NewsRepository::class);
}
}
/**
* A short integration test to check that the fixtures are as expected
*
* @test
*/
public function integration(): void
{
$queryResult = $this->newsRepository->findAll();
self::assertCount(20, $queryResult);
}
/**
* @test
*/
public function checkPaginatorWithDefaultConfiguration(): void
{
$paginator = new QueryResultPaginator($this->newsRepository->findAll());
self::assertSame(2, $paginator->getNumberOfPages());
self::assertSame(0, $paginator->getKeyOfFirstPaginatedItem());
self::assertSame(9, $paginator->getKeyOfLastPaginatedItem());
self::assertCount(10, $paginator->getPaginatedItems());
}
/**
* @test
*/
public function paginatorRespectsItemsPerPageConfiguration(): void
{
$paginator = new QueryResultPaginator(
$this->newsRepository->findAll(),
1,
3
);
self::assertSame(7, $paginator->getNumberOfPages());
self::assertSame(0, $paginator->getKeyOfFirstPaginatedItem());
self::assertSame(2, $paginator->getKeyOfLastPaginatedItem());
self::assertCount(3, $paginator->getPaginatedItems());
}
/**
* @test
*/
public function paginatorRespectsItemsPerPageConfigurationAndCurrentPage(): void
{
$paginator = new QueryResultPaginator(
$this->newsRepository->findAll(),
3,
3
);
self::assertSame(7, $paginator->getNumberOfPages());
self::assertSame(6, $paginator->getKeyOfFirstPaginatedItem());
self::assertSame(8, $paginator->getKeyOfLastPaginatedItem());
self::assertCount(3, $paginator->getPaginatedItems());
}
/**
* @test
*/
public function paginatorProperlyCalculatesLastPage(): void
{
$paginator = new QueryResultPaginator(
$this->newsRepository->findAll(),
7,
3
);
self::assertSame(7, $paginator->getNumberOfPages());
self::assertSame(18, $paginator->getKeyOfFirstPaginatedItem());
self::assertSame(19, $paginator->getKeyOfLastPaginatedItem());
self::assertCount(2, $paginator->getPaginatedItems());
}
/**
* @test
*/
public function withCurrentPageNumberThrowsInvalidArgumentExceptionIfCurrentPageIsLowerThanOne(): void
{
$this->expectExceptionCode(1573047338);
$paginator = new QueryResultPaginator(
$this->newsRepository->findAll(),
1,
3
);
$paginator->withCurrentPageNumber(0);
}
/**
* @test
*/
public function paginatorSetsCurrentPageToLastPageIfCurrentPageExceedsMaximum(): void
{
$paginator = new QueryResultPaginator(
$this->newsRepository->findAll(),
3,
10
);
self::assertEquals(2, $paginator->getCurrentPageNumber());
self::assertEquals(2, $paginator->getNumberOfPages());
self::assertCount(10, $paginator->getPaginatedItems()); // true?
}
/**
* @test
*/
public function paginatorProperlyCalculatesOnlyOnePage(): void
{
$paginator = new QueryResultPaginator(
$this->newsRepository->findAll(),
1,
50
);
self::assertSame(1, $paginator->getNumberOfPages());
self::assertSame(0, $paginator->getKeyOfFirstPaginatedItem());
self::assertSame(19, $paginator->getKeyOfLastPaginatedItem());
self::assertCount(20, $paginator->getPaginatedItems());
}
/**
* @test
* @dataProvider paginatorProperlyCalculatesWithLimitAndOffsetDataProvider
*/
public function paginatorProperlyCalculatesWithLimitAndOffset(array $given, array $expected): void
{
$demand = new NewsDemand();
$demand->setOrder('uid asc');
$demand->setOrderByAllowed('uid');
$demand->setLimit($given['limit']);
$demand->setOffset($given['offset']);
$paginator = new QueryResultPaginator(
$this->newsRepository->findDemanded($demand),
$given['currentPage'],
3,
$given['limit'],
$given['offset']
);
self::assertSame($expected['firstItemTitle'], $paginator->getPaginatedItems()[0]->getTitle());
self::assertCount($expected['itemCount'], $paginator->getPaginatedItems());
self::assertSame($expected['numberOfPages'], $paginator->getNumberOfPages());
}
public function paginatorProperlyCalculatesWithLimitAndOffsetDataProvider(): array
{
return [
'with offset' => [
['currentPage' => 3, 'limit' => 0, 'offset' => 3],
['itemCount' => 3, 'firstItemTitle' => 'News10', 'numberOfPages' => 6],
],
'with limit' => [
['currentPage' => 2, 'limit' => 4, 'offset' => 0],
['itemCount' => 1, 'firstItemTitle' => 'News4', 'numberOfPages' => 2],
],
'with limit and offset' => [
['currentPage' => 2, 'limit' => 12, 'offset' => 5],
['itemCount' => 3, 'firstItemTitle' => 'News9', 'numberOfPages' => 4],
],
];
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace GeorgRinger\News\Tests\Functional\Repository;
/**
* This file is part of the "news" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*/
use GeorgRinger\News\Domain\Repository\CategoryRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
/**
* Functional test for the DataHandler
*/
class CategoryRepositoryTest extends FunctionalTestCase
{
/** @var \GeorgRinger\News\Domain\Repository\CategoryRepository */
protected $categoryRepository;
protected $testExtensionsToLoad = ['typo3conf/ext/news'];
public function setUp(): void
{
parent::setUp();
$versionInformation = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Information\Typo3Version::class);
if ($versionInformation->getMajorVersion() === 11) {
$this->categoryRepository = $this->getContainer()->get(CategoryRepository::class);
} else {
$this->categoryRepository = GeneralUtility::makeInstance(ObjectManager::class)->get(CategoryRepository::class);
}
$this->importDataSet(__DIR__ . '/../Fixtures/sys_category.xml');
}
/**
* Test if by import source is done
*
* @test
*
* @return void
*/
public function findRecordByImportSource(): void
{
$category = $this->categoryRepository->findOneByImportSourceAndImportId('functional_test', '2');
$this->assertEquals($category->getTitle(), 'findRecordByImportSource');
}
}

View File

@@ -0,0 +1,288 @@
<?php
namespace GeorgRinger\News\Tests\Functional\Repository;
use GeorgRinger\News\Domain\Model\Dto\NewsDemand;
use GeorgRinger\News\Domain\Repository\NewsRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
/**
* This file is part of the "news" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*/
/**
* Functional test for the \GeorgRinger\News\Domain\Repository\NewsRepository
*/
class NewsRepositoryTest extends FunctionalTestCase
{
/** @var \GeorgRinger\News\Domain\Repository\NewsRepository */
protected $newsRepository;
protected $testExtensionsToLoad = ['typo3conf/ext/news'];
protected $coreExtensionsToLoad = ['fluid'];
public function setUp(): void
{
parent::setUp();
$versionInformation = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Information\Typo3Version::class);
if ($versionInformation->getMajorVersion() === 11) {
$this->newsRepository = $this->getContainer()->get(NewsRepository::class);
} else {
$this->newsRepository = GeneralUtility::makeInstance(ObjectManager::class)->get(NewsRepository::class);
}
$this->importDataSet(__DIR__ . '/../Fixtures/tags.xml');
$this->importDataSet(__DIR__ . '/../Fixtures/tx_news_domain_model_news.xml');
}
/**
* Test if startingpoint is working
*
* @test
*
* @return void
*/
public function findRecordsByUid(): void
{
$news = $this->newsRepository->findByUid(1);
$this->assertEquals($news->getTitle(), 'findRecordsByUid');
}
/**
* Test if by import source is done
*
* @test
*
* @return void
*/
public function findRecordsByImportSource(): void
{
$news = $this->newsRepository->findOneByImportSourceAndImportId('functional_test', '2');
$this->assertEquals($news->getTitle(), 'findRecordsByImportSource');
}
/**
* Test if top news constraint works
*
* @test
*
* @return void
*/
public function findTopNewsRecords(): void
{
$demand = new NewsDemand();
$demand->setStoragePage(2);
// no matter about top news
$demand->setTopNewsRestriction(0);
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 5);
// Only Top news
$demand->setTopNewsRestriction(1);
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 3);
// Only non Top news
$demand->setTopNewsRestriction(2);
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 2);
}
/**
* Test if startingpoint is working
*
* @test
*
* @return void
*/
public function findRecordsByStartingpointRestriction(): void
{
$demand = new NewsDemand();
// simple starting point
$demand->setStoragePage(3);
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 2);
// multiple starting points
$demand->setStoragePage('4,5');
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 5);
// multiple starting points, including invalid values and commas
$demand->setStoragePage('5 , x ,3');
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 3);
}
/**
* Test if record are found by archived/non archived flag
*
* @test
*
* @return void
*/
public function findRecordsByArchiveRestriction(): void
{
$GLOBALS['SIM_EXEC_TIME'] = 1396812099;
$demand = new NewsDemand();
$demand->setStoragePage(7);
// Archived means: archive date must be lower than current time AND != 0
$demand->setArchiveRestriction('archived');
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 3);
// Active means: archive date must be in future or no archive date
$demand->setArchiveRestriction('active');
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 2);
// no value means: give all
$demand->setArchiveRestriction('');
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 5);
}
/**
* Test if record by month/year constraint works
*
* @test
*
* @return void
*/
public function findRecordsByMonthAndYear(): void
{
$this->markTestSkipped('Does not work in travis');
$demand = new NewsDemand();
$demand->setStoragePage(8);
$demand->setDateField('datetime');
$demand->setMonth('4');
$demand->setYear('2011');
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 1);
}
/**
* Test if latest limit constraint works
*
* @test
*
* @return void
*/
public function findLatestLimitRecords(): void
{
$demand = new NewsDemand();
$demand->setStoragePage(9);
$GLOBALS['SIM_EXEC_TIME'] = strtotime('2014-04-03');
// get all news maximum 6 days old
$demand->setTimeRestriction((6 * 86400));
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 4);
// no restriction should get you all
$demand->setTimeRestriction(0);
$this->assertEquals((int)$this->newsRepository->findDemanded($demand)->count(), 6);
}
/**
* Test if by import source is done
*
* @test
*
* @return void
*/
public function findRecordsByTags(): void
{
$demand = new NewsDemand();
$demand->setStoragePage(10);
$demand->setOrder('uid');
$demand->setOrderByAllowed('uid');
// given is 1 tag
$demand->setTags('3');
$news = $this->newsRepository->findDemanded($demand);
$this->assertEquals('130,131', $this->getIdListOfNews($news));
// given are 2 tags
$demand->setTags('1,5');
$news = $this->newsRepository->findDemanded($demand);
$this->assertEquals('130,133,134', $this->getIdListOfNews($news));
// given are 3 real tags & 1 not existing
$demand->setTags('5,3,1,10');
$news = $this->newsRepository->findDemanded($demand);
$this->assertEquals('130,131,133,134', $this->getIdListOfNews($news));
}
/**
* @test
*
* @return void
*/
public function findRecordsForDateMenu(): void
{
$demand = new NewsDemand();
$demand->setStoragePage('9');
$demand->setDateField('datetime');
$expected = [
'single' => [
'2014' => [
'03' => 4,
'04' => 2
]
],
'total' => [
'2014' => 6
]
];
$dateMenuData = $this->newsRepository->countByDate($demand);
$this->assertEquals($expected, $dateMenuData);
}
/**
* Test if records are found by type
*
* @test
*
* @return void
*/
public function findRecordsByType(): void
{
$demand = new NewsDemand();
$demand->setStoragePage('1,2');
// given is 1 tag
$demand->setTypes(['1']);
$count = $this->newsRepository->findDemanded($demand)->count();
$this->assertEquals(2, $count);
// given are 2 tags
$demand->setTypes(['1', 2]);
$count = $this->newsRepository->findDemanded($demand)->count();
$this->assertEquals(5, $count);
}
/**
* @param \TYPO3\CMS\Extbase\Persistence\QueryResultInterface $newsList
* @return string
*/
protected function getIdListOfNews(QueryResultInterface $newsList)
{
$idList = [];
foreach ($newsList as $news) {
$idList[] = $news->getUid();
}
return implode(',', $idList);
}
public function tearDown(): void
{
unset($this->newsRepository);
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace GeorgRinger\News\Tests\Functional\ViewHelpers\Iterator;
/**
* This file is part of the "news" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*/
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
/**
* Test for ChunkViewHelper
*/
class ChunkViewHelperTest extends FunctionalTestCase
{
protected $testExtensionsToLoad = ['typo3conf/ext/news'];
protected $coreExtensionsToLoad = ['extbase', 'fluid'];
/**
* @test
*
* @return void
*/
public function chunkIsProperlyCreated(): void
{
$standaloneView = GeneralUtility::makeInstance(StandaloneView::class);
$standaloneView->setTemplateSource(
'{namespace n=GeorgRinger\News\ViewHelpers}' . LF .
'<f:for each="{news -> n:iterator.chunk(count: 3)}" as="col" iteration="cycle">' .
'<div class="row"><f:for each="{col}" as="item"><div class="col">{item.title}</div></f:for></div>' .
'</f:for>'
);
$standaloneView->assign('news', [
['title' => 'el1'],
['title' => 'el2'],
['title' => 'el3'],
['title' => 'el4'],
]);
$expected = '<div class="row">' .
'<div class="col">el1</div>' .
'<div class="col">el2</div>' .
'<div class="col">el3</div>' .
'</div>' .
'<div class="row">' .
'<div class="col">el4</div>' .
'</div>';
$this->assertEquals(trim($expected), trim($standaloneView->render()));
}
}

View File

@@ -0,0 +1,124 @@
<?php
namespace GeorgRinger\News\Tests\Functional\ViewHelpers;
/**
* This file is part of the "news" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*/
use DateTime;
use GeorgRinger\News\Domain\Model\News;
use GeorgRinger\News\ViewHelpers\SimplePrevNextViewHelper;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
/**
* Class SimplePrevNextViewHelperTest
*
*/
class SimplePrevNextViewHelperTest extends FunctionalTestCase
{
/** @var \GeorgRinger\News\ViewHelpers\SimplePrevNextViewHelper|\PHPUnit\Framework\MockObject\MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface */
protected $mockedViewHelper;
/** @var News */
protected $news;
protected $testExtensionsToLoad = ['typo3conf/ext/news'];
protected $coreExtensionsToLoad = ['extbase', 'fluid'];
public function setUp(): void
{
parent::setUp();
$this->mockedViewHelper = $this->getAccessibleMock(SimplePrevNextViewHelper::class, ['dummy'], [], '', true, true, false);
$this->news = new News();
$this->news->_setProperty('uid', 123);
$this->news->setPid(9);
$this->importDataSet(__DIR__ . '/../Fixtures/tx_news_domain_model_news.xml');
}
/**
* @test
*
* @return void
*/
public function allNeighboursCanBeFound(): void
{
$this->setDate(1396035186);
$actual = $this->mockedViewHelper->_call('getNeighbours', $this->news, '', 'datetime');
$exp = [
'prev' => $this->getRow(102),
'next' => $this->getRow(104)
];
$this->assertEquals($exp, $actual);
}
/**
* @test
*
* @return void
*/
public function nextNeighbourCanBeFound(): void
{
$this->setDate(1395516730);
$actual = $this->mockedViewHelper->_call('getNeighbours', $this->news, '', 'datetime');
$exp = [
'next' => $this->getRow(102)
];
$this->assertEquals($exp, $actual);
}
/**
* @test
*
* @return void
*/
public function previousNeighbourCanBeFound(): void
{
$this->setDate(1396640035);
$actual = $this->mockedViewHelper->_call('getNeighbours', $this->news, '', 'datetime');
$exp = [
'prev' => $this->getRow(105)
];
$this->assertEquals($exp, $actual);
}
/**
* @param int $timestamp
*
* @return void
*/
protected function setDate($timestamp): void
{
$date = new DateTime();
$date->setTimestamp($timestamp);
$this->news->_setProperty('datetime', $date);
}
/**
* @param int $id
*/
protected function getRow(int $id)
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_news_domain_model_news');
return $queryBuilder
->select('*')
->from('tx_news_domain_model_news')
->where(
$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT))
)
->setMaxResults(1)
->execute()->fetch();
}
}