Skip to content

Commit 5cff104

Browse files
committed
test: added more web tests
1 parent 982f5ab commit 5cff104

38 files changed

+888
-39
lines changed

phpmyfaq/src/phpMyFAQ/Administration/Session.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public function getLast30DaysVisits(int $endDate): array
122122
{
123123
$stats = [];
124124
$completeData = [];
125-
$startDate = strtotime(datetime: '-1 month');
125+
$startDate = strtotime('-1 month', $endDate);
126126

127127
$visits = $this->sessionRepository->getSessionTimestamps($startDate, $endDate);
128128

phpmyfaq/src/phpMyFAQ/Controller/Api/GroupController.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use phpMyFAQ\Permission\MediumPermission;
2424
use Symfony\Component\HttpFoundation\JsonResponse;
2525
use Symfony\Component\HttpFoundation\Request;
26+
use Symfony\Component\Routing\Attribute\Route;
2627

2728
final class GroupController extends AbstractApiController
2829
{

phpmyfaq/src/phpMyFAQ/Controller/Frontend/Api/CaptchaController.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@
1919

2020
namespace phpMyFAQ\Controller\Frontend\Api;
2121

22-
use phpMyFAQ\Captcha\Captcha;
22+
use phpMyFAQ\Captcha\BuiltinCaptcha;
23+
use phpMyFAQ\Captcha\CaptchaInterface;
2324
use phpMyFAQ\Controller\AbstractController;
2425
use Symfony\Component\HttpFoundation\Response;
2526
use Symfony\Component\Routing\Attribute\Route;
2627

2728
final class CaptchaController extends AbstractController
2829
{
2930
public function __construct(
30-
private readonly Captcha $captcha,
31+
private readonly CaptchaInterface $captcha,
3132
) {
3233
parent::__construct();
3334
}
@@ -38,6 +39,10 @@ public function __construct(
3839
#[Route(path: 'captcha', name: 'api.private.captcha', methods: ['GET'])]
3940
public function renderImage(): Response
4041
{
42+
if (!$this->captcha instanceof BuiltinCaptcha) {
43+
return new Response('', Response::HTTP_NOT_FOUND);
44+
}
45+
4146
$response = new Response();
4247
$response->setStatusCode(Response::HTTP_OK);
4348
$response->headers->set('Content-Type', 'image/jpeg');

phpmyfaq/src/phpMyFAQ/Controller/Frontend/CategoryController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ private function getSubCategoryContent(Category $category, int $selectedCategory
226226

227227
$currentGroups = $this->currentUser->perm->getUserGroups($this->currentUser->getUserId());
228228
$subCategory = new Category($this->configuration, $currentGroups, true);
229-
$subCategory->setUser($this->currentUser);
229+
$subCategory->setUser($this->currentUser->getUserId());
230230
$subCategory->transform($selectedCategoryId);
231231
$this->categoryHelper->setConfiguration($this->configuration)->setCategory($subCategory);
232232

phpmyfaq/src/phpMyFAQ/Controller/Frontend/NewsController.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
namespace phpMyFAQ\Controller\Frontend;
2222

23-
use phpMyFAQ\Captcha\Captcha;
23+
use phpMyFAQ\Captcha\CaptchaInterface;
2424
use phpMyFAQ\Captcha\Helper\CaptchaHelper;
2525
use phpMyFAQ\Comments;
2626
use phpMyFAQ\Core\Exception;
@@ -29,7 +29,7 @@
2929
use phpMyFAQ\Filter;
3030
use phpMyFAQ\Mail;
3131
use phpMyFAQ\News\NewsService;
32-
use phpMyFAQ\Services\Gravatar;
32+
use phpMyFAQ\Service\Gravatar;
3333
use phpMyFAQ\Session\Token;
3434
use phpMyFAQ\Strings;
3535
use phpMyFAQ\Translation;
@@ -43,7 +43,7 @@ final class NewsController extends AbstractFrontController
4343
{
4444
public function __construct(
4545
private readonly UserSession $faqSession,
46-
private readonly Captcha $captcha,
46+
private readonly CaptchaInterface $captcha,
4747
private readonly Date $date,
4848
private readonly Mail $mail,
4949
private readonly Gravatar $gravatar,
@@ -82,6 +82,15 @@ public function index(Request $request): Response
8282
$newsService = new NewsService($this->configuration, $this->currentUser);
8383
$news = $newsService->getProcessedNews($newsId);
8484

85+
if ($news === []) {
86+
$response = $this->render('404.twig', [
87+
...$this->getHeader($request),
88+
]);
89+
$response->setStatusCode(Response::HTTP_NOT_FOUND);
90+
91+
return $response;
92+
}
93+
8594
$captchaHelper = CaptchaHelper::getInstance($this->configuration);
8695

8796
$comment = new Comments($this->configuration);

phpmyfaq/src/phpMyFAQ/News/NewsService.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public function __construct(
5757
public function getProcessedNews(int $newsId): array
5858
{
5959
$news = $this->news->get($newsId);
60+
if ($news === []) {
61+
return [];
62+
}
6063

6164
// Process content with glossary
6265
$news['processedContent'] = $this->processContent($news['content'] ?? '');

phpmyfaq/src/phpMyFAQ/Visits.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public function logViews(int $faqId): void
6767
public function add(int $faqId): bool
6868
{
6969
$language = $this->configuration->getLanguage()->getLanguage();
70-
$timestamp = Request::createFromGlobals()->server->get(key: 'REQUEST_TIME');
70+
$timestamp = $this->getRequestTimestamp();
7171

7272
// If a row already exists for this (id, lang), update it instead of inserting to avoid unique constraint errors
7373
if ($this->visitsRepository->exists($faqId, $language)) {
@@ -86,7 +86,7 @@ public function add(int $faqId): bool
8686
private function update(int $faqId): void
8787
{
8888
$language = $this->configuration->getLanguage()->getLanguage();
89-
$timestamp = Request::createFromGlobals()->server->get(key: 'REQUEST_TIME');
89+
$timestamp = $this->getRequestTimestamp();
9090

9191
$this->visitsRepository->update($faqId, $language, $timestamp);
9292
}
@@ -106,7 +106,14 @@ public function getAllData(): array
106106
*/
107107
public function resetAll(): bool
108108
{
109-
$timestamp = Request::createFromGlobals()->server->get(key: 'REQUEST_TIME');
109+
$timestamp = $this->getRequestTimestamp();
110110
return $this->visitsRepository->resetAll($timestamp);
111111
}
112+
113+
private function getRequestTimestamp(): int
114+
{
115+
$timestamp = Request::createFromGlobals()->server->get(key: 'REQUEST_TIME');
116+
117+
return is_int($timestamp) ? $timestamp : time();
118+
}
112119
}

tests/phpMyFAQ/Command/UpdateCommandTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use DateTime;
66
use phpMyFAQ\Configuration;
7+
use phpMyFAQ\Database\Sqlite3;
78
use phpMyFAQ\System;
89
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
910
use PHPUnit\Framework\TestCase;
@@ -27,6 +28,10 @@ protected function setUp(): void
2728
{
2829
parent::setUp();
2930

31+
$dbHandle = new Sqlite3();
32+
$dbHandle->connect(PMF_TEST_DIR . '/test.db', '', '');
33+
new Configuration($dbHandle);
34+
3035
$this->command = new UpdateCommand();
3136
$this->commandTester = new CommandTester($this->command);
3237
}

tests/phpMyFAQ/Comment/CommentsRepositoryTest.php

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,35 @@
1212
use phpMyFAQ\Language;
1313
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
1414
use PHPUnit\Framework\TestCase;
15+
use ReflectionClass;
1516
use Symfony\Component\HttpFoundation\Session\Session;
1617

1718
#[AllowMockObjectsWithoutExpectations]
1819
class CommentsRepositoryTest extends TestCase
1920
{
2021
private Configuration $configuration;
2122
private CommentsRepository $repository;
23+
private string $databasePath;
24+
private Sqlite3 $dbHandle;
25+
private ?Configuration $previousConfiguration = null;
2226

2327
protected function setUp(): void
2428
{
2529
parent::setUp();
2630

27-
$dbHandle = new Sqlite3();
28-
$dbHandle->connect(PMF_TEST_DIR . '/test.db', '', '');
29-
$this->configuration = new Configuration($dbHandle);
31+
$configurationReflection = new ReflectionClass(Configuration::class);
32+
$configurationProperty = $configurationReflection->getProperty('configuration');
33+
$this->previousConfiguration = $configurationProperty->getValue();
34+
35+
$databasePath = tempnam(sys_get_temp_dir(), 'pmf-comments-repository-');
36+
self::assertNotFalse($databasePath);
37+
self::assertTrue(copy(PMF_TEST_DIR . '/test.db', $databasePath));
38+
$this->databasePath = $databasePath;
39+
40+
$this->dbHandle = new Sqlite3();
41+
$this->dbHandle->connect($this->databasePath, '', '');
42+
$this->configuration = new Configuration($this->dbHandle);
43+
$this->initializeDatabaseStatics($this->dbHandle);
3044
$language = new Language($this->configuration, $this->createStub(Session::class));
3145
$language->setLanguageFromConfiguration('en');
3246
$this->configuration->setLanguage($language);
@@ -36,14 +50,19 @@ protected function setUp(): void
3650

3751
protected function tearDown(): void
3852
{
53+
$configurationReflection = new ReflectionClass(Configuration::class);
54+
$configurationProperty = $configurationReflection->getProperty('configuration');
55+
$configurationProperty->setValue(null, $this->previousConfiguration);
56+
57+
if (isset($this->dbHandle)) {
58+
$this->dbHandle->close();
59+
}
60+
61+
if (isset($this->databasePath) && is_file($this->databasePath)) {
62+
unlink($this->databasePath);
63+
}
64+
3965
parent::tearDown();
40-
// Best-effort cleanup: remove comment with id_comment = 1 if exists (first insert in clean DB)
41-
$this->repository->deleteByTypeAndId(CommentType::FAQ, 1);
42-
// Remove potential category relation
43-
$category = new Category($this->configuration);
44-
$category->setLanguage('en');
45-
$relation = new Relation($this->configuration, $category);
46-
$relation->delete(1, 'en');
4766
}
4867

4968
private function makeComment(): CommentEntity
@@ -147,4 +166,17 @@ public function testIsCommentAllowed(): void
147166

148167
$this->assertTrue($this->repository->isCommentAllowed(1, 'en', CommentType::FAQ));
149168
}
169+
170+
private function initializeDatabaseStatics(Sqlite3 $dbHandle): void
171+
{
172+
$databaseReflection = new ReflectionClass(Database::class);
173+
174+
$databaseDriverProperty = $databaseReflection->getProperty('databaseDriver');
175+
$databaseDriverProperty->setValue(null, $dbHandle);
176+
177+
$dbTypeProperty = $databaseReflection->getProperty('dbType');
178+
$dbTypeProperty->setValue(null, 'sqlite3');
179+
180+
Database::setTablePrefix('');
181+
}
150182
}

tests/phpMyFAQ/Controller/Administration/Api/CommentControllerTest.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use phpMyFAQ\Comments;
88
use phpMyFAQ\Configuration;
99
use phpMyFAQ\Core\Exception;
10+
use phpMyFAQ\Database\Sqlite3;
1011
use phpMyFAQ\Strings;
1112
use phpMyFAQ\Translation;
1213
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
@@ -34,7 +35,16 @@ protected function setUp(): void
3435
->setCurrentLanguage('en')
3536
->setMultiByteLanguage();
3637

37-
$this->configuration = Configuration::getConfigurationInstance();
38+
$configuration = null;
39+
try {
40+
$configuration = Configuration::getConfigurationInstance();
41+
} catch (\TypeError) {
42+
$dbHandle = new Sqlite3();
43+
$dbHandle->connect(PMF_TEST_DIR . '/test.db', '', '');
44+
$configuration = new Configuration($dbHandle);
45+
}
46+
47+
$this->configuration = $configuration;
3848
$this->comments = $this->createStub(Comments::class);
3949
}
4050

0 commit comments

Comments
 (0)