1<?php 2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project 3// 4// All Rights Reserved. See copyright.txt for details and a complete list of authors. 5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. 6// $Id$ 7 8use Tiki\Package\ComposerCli; 9use org\bovigo\vfs\vfsStream; 10 11/* 12 * @group unit 13 */ 14 15class Tiki_Package_ComposerCliTest extends TikiTestCase 16{ 17 18 const COMPOSER_JSON_DIST = '{ 19 "name": "tiki/tiki-custom", 20 "description": "Tiki Wiki CMS Groupware", 21 "license": "LGPL-2.1", 22 "homepage": "https://tiki.org", 23 "minimum-stability": "stable", 24 "require": { 25 }, 26 "config": { 27 "process-timeout": 5000, 28 "bin-dir": "bin", 29 "component-dir": "vendor/components" 30 } 31}'; 32 33 const SAMPLE_COMPOSER = '{ 34 "name": "tiki/tiki-custom", 35 "description": "Tiki Wiki CMS Groupware", 36 "license": "LGPL-2.1", 37 "homepage": "https://tiki.org", 38 "minimum-stability": "stable", 39 "config": { 40 "process-timeout": 5000, 41 "bin-dir": "bin", 42 "component-dir": "vendor/components" 43 }, 44 "require": { 45 "psr/log": "^1.0" 46 } 47}'; 48 49 const SAMPLE_COMPOSER_BIG = '{ 50 "name": "tiki/tiki-custom", 51 "description": "Tiki Wiki CMS Groupware - composer.json", 52 "license": "LGPL-2.1", 53 "homepage": "https://tiki.org", 54 "minimum-stability": "stable", 55 "require": { 56 "foo/bar": "^1.0.0", 57 "test/unit": "^1.0.0" 58 }, 59 "config": { 60 "process-timeout": 5000, 61 "bin-dir": "bin", 62 "component-dir": "vendor/components" 63 } 64}'; 65 66 protected $root; 67 protected $composerCli; 68 69 function setUp() 70 { 71 parent::setUp(); 72 73 $this->root = vfsStream::setup(__CLASS__); 74 $this->composerCli = new ComposerCli(vfsStream::url(__CLASS__)); 75 } 76 77 /** 78 * Test getComposerConfigOrDefault 79 * 80 * @param $composer 81 * @param $composerDist 82 * @param $expected 83 * 84 * @dataProvider getComposerConfigOrDefaultProvider 85 */ 86 public function testGetComposerConfigOrDefault($composer, $composerDist, $expected) 87 { 88 $structure = []; 89 if (! is_null($composer)) { 90 $structure['composer.json'] = $composer; 91 } 92 if (! is_null($composerDist)) { 93 $structure['composer.json.dist'] = $composerDist; 94 } 95 96 $stream = uniqid(true); 97 vfsStream::setup($stream, null, $structure); 98 99 $composerCli = new ComposerCli(vfsStream::url($stream)); 100 101 $this->assertEquals(json_decode($expected, true), $composerCli->getComposerConfigOrDefault()); 102 } 103 104 public function getComposerConfigOrDefaultProvider() 105 { 106 return [ 107 [self::SAMPLE_COMPOSER, self::COMPOSER_JSON_DIST, self::SAMPLE_COMPOSER], 108 [null, self::COMPOSER_JSON_DIST, self::COMPOSER_JSON_DIST], 109 [null, null, ComposerCli::FALLBACK_COMPOSER_JSON], 110 ]; 111 } 112 113 114 /** 115 * Test getListOfPackagesFromConfig 116 * 117 * @param $composerJson 118 * @param $showResult 119 * @param $expected 120 * 121 * @dataProvider getListOfPackagesFromConfigProvider 122 */ 123 function testGetListOfPackagesFromConfig($composerJson, $showResult, $expected) 124 { 125 vfsStream::create( 126 [ 127 'composer.json' => $composerJson, 128 ], 129 $this->root 130 ); 131 132 $composerCli = $this->getMockBuilder('Tiki\Package\ComposerCli') 133 ->setMethods(['checkConfigExists', 'canExecuteComposer', 'execShow']) 134 ->setConstructorArgs([vfsStream::url(__CLASS__)]) 135 ->getMock(); 136 137 $composerCli->method('checkConfigExists') 138 ->willReturn(true); 139 140 $composerCli->method('canExecuteComposer') 141 ->willReturn(true); 142 143 $composerCli->method('execShow') 144 ->willReturn($showResult); 145 146 $this->assertEquals($expected, $composerCli->getListOfPackagesFromConfig()); 147 } 148 149 public function getListOfPackagesFromConfigProvider() 150 { 151 return [ 152 [ // no package installed, no key 153 self::SAMPLE_COMPOSER_BIG, 154 [], 155 [ 156 [ 157 'name' => 'foo/bar', 158 'status' => 'missing', 159 'required' => '^1.0.0', 160 'installed' => '', 161 ], 162 [ 163 'name' => 'test/unit', 164 'status' => 'missing', 165 'required' => '^1.0.0', 166 'installed' => '', 167 ], 168 ], 169 ], 170 [ // no package installed, with key 171 self::SAMPLE_COMPOSER_BIG, 172 ['installed' => []], 173 [ 174 [ 175 'name' => 'foo/bar', 176 'status' => 'missing', 177 'required' => '^1.0.0', 178 'installed' => '', 179 ], 180 [ 181 'name' => 'test/unit', 182 'status' => 'missing', 183 'required' => '^1.0.0', 184 'installed' => '', 185 ], 186 ], 187 ], 188 [ // one package installed 189 self::SAMPLE_COMPOSER_BIG, 190 ['installed' => [['name' => 'foo/bar', 'version' => '1.2.3']]], 191 [ 192 [ 193 'name' => 'foo/bar', 194 'status' => 'installed', 195 'required' => '^1.0.0', 196 'installed' => '1.2.3', 197 ], 198 [ 199 'name' => 'test/unit', 200 'status' => 'missing', 201 'required' => '^1.0.0', 202 'installed' => '', 203 ], 204 ], 205 ], 206 [ // all packages installed 207 self::SAMPLE_COMPOSER_BIG, 208 ['installed' => [['name' => 'foo/bar', 'version' => '1.2.3'], ['name' => 'test/unit', 'version' => '1.4.5']]], 209 [ 210 [ 211 'name' => 'foo/bar', 212 'status' => 'installed', 213 'required' => '^1.0.0', 214 'installed' => '1.2.3', 215 ], 216 [ 217 'name' => 'test/unit', 218 'status' => 'installed', 219 'required' => '^1.0.0', 220 'installed' => '1.4.5', 221 ], 222 ], 223 ], 224 [ // packages installed that are not in composer.json 225 self::SAMPLE_COMPOSER_BIG, 226 ['installed' => [['name' => 'foo/bar2', 'version' => '1.2.3']]], 227 [ 228 [ 229 'name' => 'foo/bar', 230 'status' => 'missing', 231 'required' => '^1.0.0', 232 'installed' => '', 233 ], 234 [ 235 'name' => 'test/unit', 236 'status' => 'missing', 237 'required' => '^1.0.0', 238 'installed' => '', 239 ], 240 ], 241 ], 242 [ // all packages installed, case mismatch 243 self::SAMPLE_COMPOSER_BIG, 244 [ 245 'installed' => [ 246 ['name' => 'FOO/BAR', 'version' => '1.2.3'], 247 ['name' => 'TesT/UniT', 'version' => '1.4.5'], 248 ], 249 ], 250 [ 251 [ 252 'name' => 'foo/bar', 253 'status' => 'installed', 254 'required' => '^1.0.0', 255 'installed' => '1.2.3', 256 ], 257 [ 258 'name' => 'test/unit', 259 'status' => 'installed', 260 'required' => '^1.0.0', 261 'installed' => '1.4.5', 262 ], 263 ], 264 ], 265 ]; 266 } 267 268 /** 269 * Test addComposerPackageToJson 270 * @dataProvider addComposerPackageToJsonProvider 271 */ 272 function testAddComposerPackageToJson($composerJson, $package, $version, $scripts, $expected) 273 { 274 275 $result = $this->composerCli->addComposerPackageToJson( 276 $composerJson, 277 $package, 278 $version, 279 $scripts 280 ); 281 282 $this->assertEquals($expected, $result); 283 } 284 285 public function addComposerPackageToJsonProvider() 286 { 287 288 $returnDataProvider = []; 289 290 $composerJson = json_decode(self::SAMPLE_COMPOSER, true); 291 292 // simple test 293 $expected = $composerJson; 294 $expected['require']['package'] = 'version'; 295 $returnDataProvider[] = [ 296 $composerJson, 297 'package', 298 'version', 299 null, 300 $expected, 301 ]; 302 303 // empty JSON 304 $expected = ['require' => ['package' => 'version']]; 305 $returnDataProvider[] = [ 306 '', 307 'package', 308 'version', 309 null, 310 $expected, 311 ]; 312 313 // require existing package 314 $returnDataProvider[] = [ 315 $composerJson, 316 'psr/log', 317 '^1.0', 318 null, 319 $composerJson, 320 ]; 321 322 // Add all scripts 323 $expected = $composerJson; 324 $expected['require']['foo/bar'] = '^1.0'; 325 $expected['scripts'] = [ 326 'pre-install-cmd' => ['FooBarInstaller\Installer::install'], 327 'pre-update-cmd' => ['FooBarInstaller\Installer::install'], 328 'post-install-cmd' => ['FooBarInstaller\Installer::install'], 329 'post-update-cmd' => ['FooBarInstaller\Installer::install'], 330 ]; 331 $returnDataProvider[] = [ 332 $composerJson, 333 'foo/bar', 334 '^1.0', 335 [ 336 'pre-install-cmd' => ['FooBarInstaller\Installer::install'], 337 'pre-update-cmd' => ['FooBarInstaller\Installer::install'], 338 'post-install-cmd' => ['FooBarInstaller\Installer::install'], 339 'post-update-cmd' => ['FooBarInstaller\Installer::install'], 340 ], 341 $expected, 342 ]; 343 344 // Append Script 345 $source = $composerJson; 346 $source['scripts'] = [ 347 'pre-install-cmd' => ['SomeInstaller\Installer::install'], 348 ]; 349 $expected = $composerJson; 350 $expected['require']['foo/bar'] = '^1.0'; 351 $expected['scripts'] = [ 352 'pre-install-cmd' => ['SomeInstaller\Installer::install', 'FooBarInstaller\Installer::install'], 353 ]; 354 $returnDataProvider[] = [ 355 $source, 356 'foo/bar', 357 '^1.0', 358 [ 359 'pre-install-cmd' => ['FooBarInstaller\Installer::install'], 360 ], 361 $expected, 362 ]; 363 364 return $returnDataProvider; 365 } 366} 367