Skip to content

Commit 9dc6a2a

Browse files
committed
[BUGFIX] Resolve test extension paths consistently
Testbase::linkTestExtensionsToInstance() resolves a configured test extension path with getPackageInfoWithFallback() and symlinks the extension into the test instance using the resolved extension key. Testbase::setUpPackageStates() resolves the very same value with getPackageInfo() instead, which only handles composer package names and extension keys. For a local extension that is not required by the root composer.json that lookup fails, and the code falls back to the directory basename. If the directory name differs from the extension key, the symlink and the PackageStates.php entry end up with different names, and instantiating the package fails with an InvalidPackagePathException. Use getPackageInfoWithFallback() in setUpPackageStates(), so both call sites derive the extension key the same way. Resolves: #683 Releases: main, 9, 8
1 parent 623f348 commit 9dc6a2a

3 files changed

Lines changed: 109 additions & 1 deletion

File tree

Classes/Core/Testbase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ public function setUpPackageStates(
628628

629629
// Activate test extensions that have been symlinked before
630630
foreach ($testExtensionPaths as $extensionPath) {
631-
if ($packageInfo = $this->composerPackageManager->getPackageInfo($extensionPath)) {
631+
if ($packageInfo = $this->composerPackageManager->getPackageInfoWithFallback($extensionPath)) {
632632
$extensionName = $packageInfo->getExtensionKey();
633633
} else {
634634
$extensionName = basename($extensionPath);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "typo3/testing-framework-diverging-extension-key",
3+
"description": "Test extension with a folder name differing from its extension key",
4+
"type": "typo3-cms-extension",
5+
"license": [
6+
"GPL-2.0-or-later"
7+
],
8+
"require": {
9+
"php": "*"
10+
},
11+
"extra": {
12+
"typo3/cms": {
13+
"extension-key": "diverging_extension_key",
14+
"version": "1.0.0",
15+
"Package": {
16+
"providesPackages": {}
17+
}
18+
}
19+
}
20+
}

Tests/Unit/Core/TestbaseTest.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TYPO3\TestingFramework\Tests\Unit\Core;
6+
7+
/*
8+
* This file is part of the TYPO3 CMS project.
9+
*
10+
* It is free software; you can redistribute it and/or modify it under
11+
* the terms of the GNU General Public License, either version 2
12+
* of the License, or any later version.
13+
*
14+
* For the full copyright and license information, please read the
15+
* LICENSE.txt file that was distributed with this source code.
16+
*
17+
* The TYPO3 project - inspiring people to share!
18+
*/
19+
use PHPUnit\Framework\Attributes\Test;
20+
use PHPUnit\Framework\TestCase;
21+
use TYPO3\TestingFramework\Core\Testbase;
22+
23+
final class TestbaseTest extends TestCase
24+
{
25+
private string $instancePath = '';
26+
27+
protected function tearDown(): void
28+
{
29+
if ($this->instancePath !== '' && is_dir($this->instancePath)) {
30+
$this->removeDirectory($this->instancePath);
31+
}
32+
$this->instancePath = '';
33+
parent::tearDown();
34+
}
35+
36+
/**
37+
* Testbase::linkTestExtensionsToInstance() symlinks a test extension using the
38+
* extension key determined by ComposerPackageManager::getPackageInfoWithFallback().
39+
* Testbase::setUpPackageStates() must determine the very same name, otherwise the
40+
* written PackageStates.php points to a non-existing package path.
41+
*/
42+
#[Test]
43+
public function setUpPackageStatesUsesExtensionKeyOfTestExtensionAndNotItsFolderName(): void
44+
{
45+
$extensionPath = __DIR__ . '/Fixtures/Extensions/ext_folder_name';
46+
// Folder name and extension key of the fixture extension differ on purpose.
47+
self::assertSame('ext_folder_name', basename($extensionPath));
48+
49+
$this->instancePath = $this->createTestInstance();
50+
// Symlink the extension the way linkTestExtensionsToInstance() does it.
51+
symlink($extensionPath, $this->instancePath . '/typo3conf/ext/diverging_extension_key');
52+
53+
$subject = new Testbase();
54+
$subject->setUpPackageStates($this->instancePath, [], [], [$extensionPath], []);
55+
56+
$packageStates = require $this->instancePath . '/typo3conf/PackageStates.php';
57+
58+
self::assertArrayHasKey('diverging_extension_key', $packageStates['packages']);
59+
self::assertArrayNotHasKey('ext_folder_name', $packageStates['packages']);
60+
self::assertSame(
61+
'typo3conf/ext/diverging_extension_key/',
62+
$packageStates['packages']['diverging_extension_key']['packagePath']
63+
);
64+
}
65+
66+
private function createTestInstance(): string
67+
{
68+
$instancePath = sys_get_temp_dir() . '/testbase-' . bin2hex(random_bytes(8));
69+
mkdir($instancePath . '/typo3conf/ext', 0775, true);
70+
return $instancePath;
71+
}
72+
73+
private function removeDirectory(string $path): void
74+
{
75+
foreach ((array)scandir($path) as $entry) {
76+
if ($entry === '.' || $entry === '..') {
77+
continue;
78+
}
79+
$entryPath = $path . '/' . $entry;
80+
if (is_link($entryPath) || is_file($entryPath)) {
81+
unlink($entryPath);
82+
continue;
83+
}
84+
$this->removeDirectory($entryPath);
85+
}
86+
rmdir($path);
87+
}
88+
}

0 commit comments

Comments
 (0)