[BUGFIX] Resolves extension dependencies recursively
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Tests / Unit / Service / ExtensionManagementServiceTest.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Tests\Unit\Service;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * Testcase
19 *
20 */
21 class ExtensionManagementServiceTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
22 {
23 /**
24 * @test
25 * @return void
26 */
27 public function resolveDependenciesCallsDownloadDependenciesIfDownloadKeyExistsInQueue()
28 {
29 $managementMock = $this->getAccessibleMock(
30 \TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class,
31 ['downloadDependencies', 'uninstallDependenciesToBeUpdated', 'setInExtensionRepository', 'downloadMainExtension', 'isAutomaticInstallationEnabled']
32 );
33 $managementMock->expects($this->any())->method('downloadMainExtension')->will($this->returnValue([]));
34 $managementMock->expects($this->any())->method('isAutomaticInstallationEnabled')->will($this->returnValue([false]));
35 $extensionModelMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class);
36 $extensionModelMock->_set('extensionKey', 'foobar');
37 $extensionModelMock->_set('version', '1.0.0');
38 $dependencyUtilityMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['checkDependencies']);
39 $dependencyUtilityMock->expects($this->atLeastOnce())->method('checkDependencies');
40 $managementMock->_set('dependencyUtility', $dependencyUtilityMock);
41 $downloadQueueMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\DownloadQueue::class, ['isCopyQueueEmpty', 'isQueueEmpty', 'resetExtensionQueue', 'addExtensionToInstallQueue']);
42 $downloadQueueMock->expects($this->any())->method('isCopyQueueEmpty')->willReturn(true);
43 $downloadQueueMock->expects($this->at(1))->method('isQueueEmpty')->with('download')->willReturn(false);
44 $downloadQueueMock->expects($this->at(4))->method('isQueueEmpty')->with('download')->willReturn(true);
45 $downloadQueueMock->expects($this->at(5))->method('isQueueEmpty')->with('update')->willReturn(true);
46 $downloadQueueMock->expects($this->atLeastOnce())->method('resetExtensionQueue')->will($this->returnValue([
47 'download' => [
48 'foo' => $extensionModelMock
49 ]
50 ]));
51 $managementMock->_set('downloadQueue', $downloadQueueMock);
52 $managementMock->expects($this->once())->method('downloadDependencies')->with(['foo' => $extensionModelMock])->will($this->returnValue([]));
53 $managementMock->_call('installExtension', $extensionModelMock);
54 }
55
56 /**
57 * @test
58 * @return void
59 */
60 public function resolveDependenciesCallsUpdateAndDownloadDependenciesIfUpdateKeyExistsInQueue()
61 {
62 $managementMock = $this->getAccessibleMock(
63 \TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class,
64 ['downloadDependencies', 'uninstallDependenciesToBeUpdated', 'setInExtensionRepository', 'downloadMainExtension', 'isAutomaticInstallationEnabled']
65 );
66 $managementMock->expects($this->any())->method('downloadMainExtension')->will($this->returnValue([]));
67 $managementMock->expects($this->any())->method('isAutomaticInstallationEnabled')->will($this->returnValue(true));
68 $extensionModelMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class);
69 $extensionModelMock->_set('extensionKey', 'foobar');
70 $extensionModelMock->_set('version', '1.0.0');
71 $dependencyUtilityMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['checkDependencies']);
72 $dependencyUtilityMock->expects($this->atLeastOnce())->method('checkDependencies');
73 $managementMock->_set('dependencyUtility', $dependencyUtilityMock);
74 $downloadQueueMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\DownloadQueue::class, ['isCopyQueueEmpty', 'isQueueEmpty', 'resetExtensionQueue', 'addExtensionToInstallQueue']);
75 $downloadQueueMock->expects($this->any())->method('isCopyQueueEmpty')->willReturn(true);
76 $downloadQueueMock->expects($this->at(1))->method('isQueueEmpty')->with('download')->willReturn(false);
77 $downloadQueueMock->expects($this->at(4))->method('isQueueEmpty')->with('download')->willReturn(true);
78 $downloadQueueMock->expects($this->at(5))->method('isQueueEmpty')->with('update')->willReturn(true);
79 $downloadQueueMock->expects($this->atLeastOnce())->method('resetExtensionQueue')->will($this->returnValue([
80 'update' => [
81 'foo' => $extensionModelMock
82 ]
83 ]));
84 $managementMock->_set('downloadQueue', $downloadQueueMock);
85 $managementMock->expects($this->once())->method('downloadDependencies')->with(['foo' => $extensionModelMock])->will($this->returnValue([]));
86 $managementMock->expects($this->once())->method('uninstallDependenciesToBeUpdated')->with(['foo' => $extensionModelMock])->will($this->returnValue([]));
87 $managementMock->_call('installExtension', $extensionModelMock);
88 }
89
90 /**
91 * @test
92 * @return void
93 */
94 public function downloadDependenciesCallsDownloadUtilityDownloadMethod()
95 {
96 $managementMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class, [
97 'dummy'
98 ]);
99
100 $extensionModelMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, ['getExtensionKey']);
101 $extensionModelMock->_set('extensionKey', 'foobar');
102 $extensionModelMock->_set('version', '1.0.0');
103
104 $dependencyUtilityMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class);
105 $dependencyUtilityMock->expects($this->atLeastOnce())->method('checkDependencies');
106 $installUtilityMock = $this->getMock(\TYPO3\CMS\Extensionmanager\Utility\InstallUtility::class);
107 $installUtilityMock->expects($this->any())->method('enrichExtensionWithDetails')->will($this->returnValue([]));
108 $extensionModelUtilityMock = $this->getMock(\TYPO3\CMS\Extensionmanager\Utility\ExtensionModelUtility::class);
109 $extensionModelUtilityMock->expects($this->any())->method('mapExtensionArrayToModel')->will($this->returnValue($extensionModelMock));
110 $managementMock->_set('dependencyUtility', $dependencyUtilityMock);
111 $managementMock->_set('installUtility', $installUtilityMock);
112 $managementMock->_set('extensionModelUtility', $extensionModelUtilityMock);
113
114 $downloadQueue = [
115 $extensionModelMock
116 ];
117 $downloadQueueMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\DownloadQueue::class, ['removeExtensionFromQueue', 'addExtensionToInstallQueue']);
118 $downloadUtilityMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DownloadUtility::class, ['download']);
119 $downloadUtilityMock->expects($this->once())->method('download')->with($extensionModelMock);
120 $managementMock->_set('downloadUtility', $downloadUtilityMock);
121 $managementMock->_set('downloadQueue', $downloadQueueMock);
122 $managementMock->_call('downloadDependencies', $downloadQueue);
123 }
124
125 /**
126 * @test
127 * @return void
128 */
129 public function downloadDependenciesCallsRemoveExtensionFromQueue()
130 {
131 $managementMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class, [
132 'dummy'
133 ]);
134
135 /** @var \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionModelMock */
136 $extensionModelMock = $this->getMock(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, ['getExtensionKey']);
137 $extensionModelMock->setExtensionKey('foobar');
138 $extensionModelMock->setVersion('1.0.0');
139 $downloadQueue = [
140 $extensionModelMock
141 ];
142
143 $dependencyUtilityMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class);
144 $dependencyUtilityMock->expects($this->atLeastOnce())->method('checkDependencies');
145 $installUtilityMock = $this->getMock(\TYPO3\CMS\Extensionmanager\Utility\InstallUtility::class);
146 $installUtilityMock->expects($this->any())->method('enrichExtensionWithDetails')->will($this->returnValue([]));
147 $extensionModelUtilityMock = $this->getMock(\TYPO3\CMS\Extensionmanager\Utility\ExtensionModelUtility::class);
148 $extensionModelUtilityMock->expects($this->any())->method('mapExtensionArrayToModel')->will($this->returnValue($extensionModelMock));
149 $managementMock->_set('dependencyUtility', $dependencyUtilityMock);
150 $managementMock->_set('installUtility', $installUtilityMock);
151 $managementMock->_set('extensionModelUtility', $extensionModelUtilityMock);
152
153 $downloadQueueMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\DownloadQueue::class, ['removeExtensionFromQueue', 'addExtensionToInstallQueue']);
154 $downloadUtilityMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DownloadUtility::class, ['download']);
155 $downloadQueueMock->expects($this->once())->method('removeExtensionFromQueue')->with($extensionModelMock);
156 $managementMock->_set('downloadUtility', $downloadUtilityMock);
157 $managementMock->_set('downloadQueue', $downloadQueueMock);
158 $managementMock->_call('downloadDependencies', $downloadQueue);
159 }
160
161 /**
162 * @test
163 * @return void
164 */
165 public function downloadDependenciesReturnsResolvedDependencies()
166 {
167 $managementMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class, [
168 'dummy'
169 ]);
170
171 $extensionModelMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, ['getExtensionKey']);
172 $extensionModelMock->_set('extensionKey', 'foobar');
173 $extensionModelMock->_set('version', '1.0.0');
174 $downloadQueue = [
175 $extensionModelMock
176 ];
177
178 $dependencyUtilityMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class);
179 $dependencyUtilityMock->expects($this->atLeastOnce())->method('checkDependencies');
180 $installUtilityMock = $this->getMock(\TYPO3\CMS\Extensionmanager\Utility\InstallUtility::class);
181 $installUtilityMock->expects($this->any())->method('enrichExtensionWithDetails')->will($this->returnValue([]));
182 $extensionModelUtilityMock = $this->getMock(\TYPO3\CMS\Extensionmanager\Utility\ExtensionModelUtility::class);
183 $extensionModelUtilityMock->expects($this->any())->method('mapExtensionArrayToModel')->will($this->returnValue($extensionModelMock));
184 $managementMock->_set('dependencyUtility', $dependencyUtilityMock);
185 $managementMock->_set('installUtility', $installUtilityMock);
186 $managementMock->_set('extensionModelUtility', $extensionModelUtilityMock);
187
188 $downloadQueueMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\DownloadQueue::class, ['removeExtensionFromQueue', 'addExtensionToInstallQueue']);
189 $downloadUtilityMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DownloadUtility::class, ['download']);
190 $extensionModelMock->expects($this->atLeastOnce())->method('getExtensionKey')->will($this->returnValue('foobar'));
191 $managementMock->_set('downloadUtility', $downloadUtilityMock);
192 $managementMock->_set('downloadQueue', $downloadQueueMock);
193 $resolvedDependencies = $managementMock->_call('downloadDependencies', $downloadQueue);
194 $this->assertEquals(['downloaded' => ['foobar' => $extensionModelMock]], $resolvedDependencies);
195 }
196
197 /**
198 * @test
199 * @return void
200 */
201 public function uninstallDependenciesToBeUpdatedCallsUninstall()
202 {
203 $managementMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class, [
204 'dummy'
205 ]);
206 $extensionModelMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, ['getExtensionKey']);
207 $extensionModelMock->_set('extensionKey', 'foobar');
208 $extensionModelMock->_set('version', '1.0.0');
209 $extensionModelMock->expects($this->atLeastOnce())->method('getExtensionKey')->will($this->returnValue('foobar'));
210 $downloadQueue = [
211 $extensionModelMock
212 ];
213 $installUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\InstallUtility::class, ['uninstall'], [], '', false);
214 $installUtility->expects($this->once())->method('uninstall')->with('foobar');
215 $managementMock->_set('installUtility', $installUtility);
216 $managementMock->_call('uninstallDependenciesToBeUpdated', $downloadQueue);
217 }
218
219 /**
220 * @test
221 * @return void
222 */
223 public function uninstallDependenciesToBeUpdatedReturnsResolvedDependencies()
224 {
225 $managementMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class, [
226 'dummy'
227 ]);
228 $extensionModelMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, ['getExtensionKey']);
229 $extensionModelMock->_set('extensionKey', 'foobar');
230 $extensionModelMock->_set('version', '1.0.0');
231 $extensionModelMock->expects($this->atLeastOnce())->method('getExtensionKey')->will($this->returnValue('foobar'));
232 $downloadQueue = [
233 $extensionModelMock
234 ];
235 $installUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\InstallUtility::class, ['uninstall'], [], '', false);
236 $managementMock->_set('installUtility', $installUtility);
237 $resolvedDependencies = $managementMock->_call('uninstallDependenciesToBeUpdated', $downloadQueue);
238 $this->assertEquals(['updated' => ['foobar' => $extensionModelMock]], $resolvedDependencies);
239 }
240
241 /**
242 * @test
243 * @return void
244 */
245 public function installDependenciesCallsInstall()
246 {
247 $managementMock = $this->getAccessibleMock(
248 \TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class,
249 ['emitWillInstallExtensionsSignal', 'emitHasInstalledExtensionSignal']
250 );
251 /** @var \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionMock */
252 $extensionMock = $this->getMock(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, ['dummy']);
253 $extensionMock->setExtensionKey('foobar');
254 $installQueue = [
255 'foobar' => $extensionMock,
256 ];
257 $installUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\InstallUtility::class, ['install', 'emitWillInstallExtensionsSignal'], [], '', false);
258 $installUtility->expects($this->once())->method('install')->with('foobar');
259 $managementMock->_set('installUtility', $installUtility);
260 $managementMock->_call('installDependencies', $installQueue);
261 }
262
263 /**
264 * @test
265 * @return void
266 */
267 public function installDependenciesReturnsResolvedDependencies()
268 {
269 $managementMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService::class, [
270 'emitWillInstallExtensionsSignal',
271 'emitHasInstalledExtensionSignal'
272 ]);
273 /** @var \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionMock */
274 $extensionMock = $this->getMock(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, ['dummy']);
275 $extensionMock->setExtensionKey('foobar');
276 $installQueue = [
277 'foobar' => $extensionMock,
278 ];
279 $installUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\InstallUtility::class, ['install', 'emitWillInstallExtensionsSignal'], [], '', false);
280 $installUtility->expects($this->once())->method('install')->with('foobar');
281 $managementMock->_set('installUtility', $installUtility);
282 $resolvedDependencies = $managementMock->_call('installDependencies', $installQueue);
283 $this->assertEquals([
284 'installed' => [
285 'foobar' => 'foobar'
286 ]
287 ], $resolvedDependencies);
288 }
289 }