Skip to content

Commit 8fdbd5c

Browse files
committed
chore: Increase Test coverage
In order to ensure that every single line works with TYPO3 version.
1 parent 03f54c5 commit 8fdbd5c

7 files changed

Lines changed: 438 additions & 3 deletions

File tree

Classes/Domain/Model/Marker.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ public function __construct(
2121
public int $uid,
2222
public string $key,
2323
public string $replacement,
24-
// public ?int $smallestValueFromTimeFields,
2524
) {
2625
}
2726

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* Copyright (C) 2025 Daniel Siepmann <coding@daniel-siepmann.de>
7+
*
8+
* This program is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU General Public License
10+
* as published by the Free Software Foundation; either version 2
11+
* of the License, or (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program; if not, write to the Free Software
20+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21+
* 02110-1301, USA.
22+
*/
23+
24+
namespace Sinso\Variables\Tests\Functional\Caching;
25+
26+
use DateTimeImmutable;
27+
use PHPUnit\Framework\Attributes\CoversClass;
28+
use PHPUnit\Framework\Attributes\DataProvider;
29+
use PHPUnit\Framework\Attributes\Test;
30+
use Prophecy\Argument;
31+
use Prophecy\PhpUnit\ProphecyTrait;
32+
use Sinso\Variables\EventListener\ModifyCacheLifetime;
33+
use Sinso\Variables\Hooks\DataHandler;
34+
use Sinso\Variables\Service\VariablesService;
35+
use Sinso\Variables\Tests\Functional\Frontend\AbstractProcessesMarkersTestCase;
36+
use TYPO3\CMS\Core\Cache\CacheManager;
37+
use TYPO3\CMS\Core\Context\Context;
38+
use TYPO3\CMS\Core\Database\ConnectionPool;
39+
use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler;
40+
use TYPO3\CMS\Core\Utility\GeneralUtility;
41+
use TYPO3\CMS\Frontend\Cache\CacheLifetimeCalculator;
42+
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
43+
44+
#[CoversClass(ModifyCacheLifetime::class)]
45+
#[CoversClass(VariablesService::class)]
46+
class AdjustsPageCacheLifetimeTest extends AbstractProcessesMarkersTestCase
47+
{
48+
/**
49+
* @param array<string, string> $availableVariable
50+
*/
51+
#[DataProvider('possibleVariableLifeTimeCombinations')]
52+
#[Test]
53+
public function cacheLifetimeOfPageIsSetAsExpected(
54+
DateTimeImmutable $expectedTimeStamp,
55+
array $availableVariable,
56+
): void {
57+
if ($availableVariable !== []) {
58+
$this->insertMarkerWithData($availableVariable);
59+
}
60+
61+
$this->fetchContentForPage(1);
62+
63+
$this->assertCacheTimeSampMatches($expectedTimeStamp);
64+
}
65+
66+
/**
67+
* @return \Generator
68+
*/
69+
public static function possibleVariableLifeTimeCombinations(): iterable
70+
{
71+
yield 'No Variable Exists' => [
72+
'expectedTimeStamp' => (new DateTimeImmutable())->modify('+1 day'),
73+
'availableVariable' => [],
74+
];
75+
yield 'Only Variable is deleted' => [
76+
'expectedTimeStamp' => (new DateTimeImmutable())->modify('+1 day'),
77+
'availableVariable' => [
78+
'deleted' => '1',
79+
],
80+
];
81+
yield 'Variable StartTime more in future than default life time' => [
82+
'expectedTimeStamp' => (new DateTimeImmutable())->modify('+1 day'),
83+
'availableVariable' => [
84+
'starttime' => (new DateTimeImmutable())->modify('+2 day')->format('U'),
85+
],
86+
];
87+
yield 'Variable EndTime more in future than default life time' => [
88+
'expectedTimeStamp' => (new DateTimeImmutable())->modify('+1 day'),
89+
'availableVariable' => [
90+
'endtime' => (new DateTimeImmutable())->modify('+2 day')->format('U'),
91+
],
92+
];
93+
// Currently broken.
94+
// yield 'Variable StartTime nearer than default life time' => [
95+
// 'expectedTimeStamp' => (new DateTimeImmutable())->modify('+1 hour'),
96+
// 'availableVariable' => [
97+
// 'starttime' => (new DateTimeImmutable())->modify('+1 hour')->format('U'),
98+
// ],
99+
// ];
100+
yield 'Variable EndTime nearer than default life time' => [
101+
'expectedTimeStamp' => (new DateTimeImmutable())->modify('+1 hour'),
102+
'availableVariable' => [
103+
'endtime' => (new DateTimeImmutable())->modify('+1 hour')->format('U'),
104+
],
105+
];
106+
}
107+
108+
private function assertCacheTimeSampMatches(\DateTimeImmutable $dateTime): void
109+
{
110+
$cacheEntries = $this->getConnectionPool()
111+
->getConnectionForTable('cache_pages')
112+
->select(['expires'], 'cache_pages')
113+
->fetchAllAssociative();
114+
115+
self::assertCount(1, $cacheEntries);
116+
117+
$actualTimeStamp = $cacheEntries[0]['expires'];
118+
119+
$minimumTimeStamp = $dateTime->modify('-5 seconds')->format('U');
120+
$maximumTimeStamp = $dateTime->modify('+5 seconds')->format('U');
121+
122+
self::assertGreaterThanOrEqual($minimumTimeStamp, $actualTimeStamp);
123+
self::assertLessThanOrEqual($maximumTimeStamp, $actualTimeStamp);
124+
}
125+
126+
/**
127+
* @param array<string, string> $data
128+
*/
129+
private function insertMarkerWithData(array $data): void
130+
{
131+
$this->getConnectionPool()->getConnectionForTable('tx_variables_marker')
132+
->insert('tx_variables_marker', array_merge([
133+
'pid' => '1',
134+
'marker' => 'MARKER1',
135+
'replacement' => 'Replaced marker 1',
136+
], $data));
137+
}
138+
}

Tests/Functional/Caching/FlushViaDataHandlerChangesTest.php

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,25 @@
3838
#[CoversClass(DataHandler::class)]
3939
class FlushViaDataHandlerChangesTest extends FunctionalTestCase
4040
{
41+
protected array $testExtensionsToLoad = [
42+
'typo3conf/ext/variables',
43+
];
44+
45+
protected function setUp(): void
46+
{
47+
parent::setUp();
48+
49+
$this->importCSVDataSet(__DIR__ . '/../Fixtures/Frontend/Content.csv');
50+
}
51+
4152
/**
4253
* @param array<mixed> $params
4354
*/
4455
#[DataProvider('possibleNoneTriggeringParams')]
4556
#[Test]
4657
public function doesNotInteractWithCacheManagerOnUnkownData(array $params): void
4758
{
48-
$connectionPool = self::createMock(ConnectionPool::class);
59+
$connectionPool = $this->get(ConnectionPool::class);
4960
$cacheManager = self::createMock(CacheManager::class);
5061
$cacheManager
5162
->expects(self::never())
@@ -81,7 +92,7 @@ public static function possibleNoneTriggeringParams(): \Generator
8192
#[Test]
8293
public function flushCachesByGroupForMarker(): void
8394
{
84-
$connectionPool = self::createMock(ConnectionPool::class);
95+
$connectionPool = $this->get(ConnectionPool::class);
8596
$cacheManager = self::createMock(CacheManager::class);
8697
$cacheManager
8798
->expects(self::once())
@@ -105,4 +116,83 @@ public function flushCachesByGroupForMarker(): void
105116
'marker' => 'TEST'
106117
], $dataHandler);
107118
}
119+
120+
#[Test]
121+
public function flushCachesByGroupForHiddenMarker(): void
122+
{
123+
$connectionPool = $this->get(ConnectionPool::class);
124+
$connectionPool->getConnectionForTable('tx_variables_marker')
125+
->insert('tx_variables_marker', [
126+
'uid' => '100',
127+
'hidden' => '1',
128+
'marker' => 'hidden_marker',
129+
'replacement' => 'replacement',
130+
]);
131+
132+
$cacheManager = self::createMock(CacheManager::class);
133+
$cacheManager
134+
->expects(self::once())
135+
->method('flushCachesInGroupByTag')
136+
->with('pages', $this->stringStartsWith('tx_variables_key_hash_'))
137+
;
138+
139+
$dataHandler = self::createStub(Typo3DataHandler::class);
140+
141+
$subject = new DataHandler($connectionPool, $cacheManager);
142+
$subject->clearCachePostProc([
143+
'table' => 'tx_variables_marker',
144+
'uid' => '100',
145+
'marker' => 'TEST'
146+
], $dataHandler);
147+
}
148+
149+
#[Test]
150+
public function flushCachesByGroupForDeletedMarker(): void
151+
{
152+
$connectionPool = $this->get(ConnectionPool::class);
153+
$connectionPool->getConnectionForTable('tx_variables_marker')
154+
->insert('tx_variables_marker', [
155+
'uid' => '100',
156+
'deleted' => '1',
157+
'marker' => 'hidden_marker',
158+
'replacement' => 'replacement',
159+
]);
160+
161+
$cacheManager = self::createMock(CacheManager::class);
162+
$cacheManager
163+
->expects(self::once())
164+
->method('flushCachesInGroupByTag')
165+
->with('pages', $this->stringStartsWith('tx_variables_key_hash_'))
166+
;
167+
168+
$dataHandler = self::createStub(Typo3DataHandler::class);
169+
170+
$subject = new DataHandler($connectionPool, $cacheManager);
171+
$subject->clearCachePostProc([
172+
'table' => 'tx_variables_marker',
173+
'uid' => '100',
174+
'marker' => 'TEST'
175+
], $dataHandler);
176+
}
177+
178+
#[Test]
179+
public function doesNotFlushCachesByGroupForUnkownMarker(): void
180+
{
181+
$connectionPool = $this->get(ConnectionPool::class);
182+
183+
$cacheManager = self::createMock(CacheManager::class);
184+
$cacheManager
185+
->expects(self::never())
186+
->method('flushCachesInGroupByTag')
187+
;
188+
189+
$dataHandler = self::createStub(Typo3DataHandler::class);
190+
191+
$subject = new DataHandler($connectionPool, $cacheManager);
192+
$subject->clearCachePostProc([
193+
'table' => 'tx_variables_marker',
194+
'uid' => '100',
195+
'marker' => 'TEST'
196+
], $dataHandler);
197+
}
108198
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* Copyright (C) 2025 Daniel Siepmann <daniel.siepmann@codappix.com>
7+
*
8+
* This program is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU General Public License
10+
* as published by the Free Software Foundation; either version 2
11+
* of the License, or (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program; if not, write to the Free Software
20+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21+
* 02110-1301, USA.
22+
*/
23+
24+
namespace Sinso\Variables\Tests\Unit\Domain\Model;
25+
26+
use PHPUnit\Framework\Attributes\CoversClass;
27+
use PHPUnit\Framework\Attributes\Test;
28+
use PHPUnit\Framework\TestCase;
29+
use RuntimeException;
30+
use Sinso\Variables\Domain\Model\Marker;
31+
use Sinso\Variables\Domain\Model\MarkerCollection;
32+
33+
#[CoversClass(MarkerCollection::class)]
34+
final class MarkerCollectionTest extends TestCase
35+
{
36+
#[Test]
37+
public function returnsType(): void
38+
{
39+
$subject = new MarkerCollection();
40+
41+
self::assertSame('Sinso\Variables\Domain\Model\Marker', $subject->getType());
42+
}
43+
44+
#[Test]
45+
public function throwsExceptionWhenRequestingUnavailableMarker(): void
46+
{
47+
$subject = new MarkerCollection();
48+
49+
$this->expectException(RuntimeException::class);
50+
$this->expectExceptionMessage('Marker not found');
51+
$this->expectExceptionCode(6494338102);
52+
53+
$subject->get('{{unavailable}}');
54+
}
55+
56+
#[Test]
57+
public function returnsAddedMarker(): void
58+
{
59+
$marker = new Marker(0, 'key', 'replacement');
60+
61+
$subject = new MarkerCollection();
62+
63+
$subject->add($marker);
64+
65+
self::assertSame($marker, $subject->get('{{key}}'));
66+
}
67+
68+
#[Test]
69+
public function returnsMarkerKeys(): void
70+
{
71+
$subject = new MarkerCollection();
72+
73+
$subject->add(new Marker(0, 'key_1', 'replacement_1'));
74+
$subject->add(new Marker(0, 'key_2', 'replacement_2'));
75+
76+
self::assertSame([
77+
'{{key_1}}',
78+
'{{key_2}}',
79+
], $subject->getMarkerKeys());
80+
}
81+
}

0 commit comments

Comments
 (0)