packages()); foreach (['http', 'crypto', 'text', 'cache', 'id', 'htmx', 'commands', 'test'] as $pkg) { ok(in_array($pkg, $names, true), "paquete '{$pkg}' presente en el catálogo"); } }); Harness::it('http instala su familia y resuelve compreFace -> curlRequest', function () { $repo = $GLOBALS['g9_repo']; $proj = tmpdir('proj'); $inst = new Installer($proj, $repo, new Console(), $proj . '/src'); $result = $inst->add(['http'], ['yes' => true]); ok(is_file($proj . '/src/Libs/CurlRequest.php')); ok(is_file($proj . '/src/Libs/CompreFace.php')); $lock = Lock::load($proj); ok($lock->has('http:compreFace') && $lock->has('http:curlRequest'), 'resuelve la dependencia'); rrmdir($proj); }); Harness::it('htmx instala htmlComponent con su Sanitizer via dependencia', function () { $repo = $GLOBALS['g9_repo']; $proj = tmpdir('proj'); $inst = new Installer($proj, $repo, new Console(), $proj . '/src'); $inst->add(['htmx:htmx'], ['yes' => true]); ok(is_file($proj . '/src/Libs/HTMX.php')); ok(is_file($proj . '/src/Libs/HTMLComponent.php'), 'dependencia htmlComponent'); ok(is_file($proj . '/src/Libs/Sanitizer/SanitizerProxy.php'), 'directorio Sanitizer expandido'); rrmdir($proj); }); Harness::it('test trae commands:cli y ejecuta post-install', function () { $repo = $GLOBALS['g9_repo']; $proj = tmpdir('proj'); $inst = new Installer($proj, $repo, new Console(), $proj . '/src'); $ran = []; $result = $inst->add(['test'], ['yes' => true, 'postRunner' => function (string $c) use (&$ran) { $ran[] = $c; }]); ok(is_file($proj . '/phpunit.xml'), 'phpunit.xml en ROOT_DIR'); ok(is_file($proj . '/tests/TestCase.php'), 'directorio tests expandido'); ok(Lock::load($proj)->has('commands:cli'), 'dependencia commands:cli instalada'); eq(2, count($ran), 'se ejecutaron los dos comandos de post-install'); rrmdir($proj); }); Harness::it('no queda el Migration.php duplicado; sólo el de commands', function () { $repo = $GLOBALS['g9_repo']; ok(is_file($repo . '/packages/commands/src/Libs/Migration.php'), 'existe el de commands'); foreach (['http', 'crypto', 'text', 'cache', 'id'] as $pkg) { ok(!is_file($repo . "/packages/{$pkg}/src/Libs/Migration.php"), "extras no filtró Migration.php a {$pkg}"); } }); Harness::it('adopt registra copias idénticas y divergentes sin modificar archivos', function () { $repo = $GLOBALS['g9_repo']; $core = g7_core('0.1.0'); $proj = tmpdir('proj'); $projDiv = tmpdir('projdiv'); $aria2 = (string) file_get_contents($repo . '/packages/http/src/Libs/Aria2.php'); write_file($proj . '/src/Libs/Aria2.php', $aria2); write_file($projDiv . '/src/Libs/Aria2.php', $aria2 . "\n// edicion local\n"); $before = (string) file_get_contents($projDiv . '/src/Libs/Aria2.php'); (new AdoptCommand(new Console()))->run(['--root=' . $proj, '--toolbox=' . $repo, '--core-dir=' . $core]); $lock = Lock::load($proj); ok($lock->has('http:aria2'), 'adopta la copia idéntica'); eq('adopted', $lock->component('http:aria2')['origin']); (new AdoptCommand(new Console()))->run(['--root=' . $projDiv, '--toolbox=' . $repo, '--core-dir=' . $core]); $lockD = Lock::load($projDiv); ok($lockD->has('http:aria2'), 'adopta la copia divergente'); eq('local', $lockD->component('http:aria2')['origin'], 'la marca como edición local'); eq($before, file_get_contents($projDiv . '/src/Libs/Aria2.php'), 'no modifica el archivo'); ok(\Toolbox\Drift::isDrifted($projDiv . '/src/Libs/Aria2.php', $lockD->component('http:aria2')['files']['src/Libs/Aria2.php']), 'el drift queda detectado'); rrmdir($proj); rrmdir($projDiv); rrmdir($core); }); Harness::it('adopt registra el core existente con sus hashes', function () { $repo = $GLOBALS['g9_repo']; $core = g7_core('0.1.0'); $proj = tmpdir('proj'); // Simula un proyecto heredado con el core copiado a mano. foreach (['autoload.php', 'config.php', 'src/Libs/Router.php'] as $file) { write_file($proj . '/' . $file, (string) file_get_contents($core . '/' . $file)); } (new AdoptCommand(new Console()))->run(['--root=' . $proj, '--toolbox=' . $repo, '--core-dir=' . $core]); $lock = Lock::load($proj); ok($lock->core() !== null, 'core registrado en el lock'); ok(isset($lock->core()['files']['src/Libs/Router.php']), 'archivo del core con hash'); ok(!isset($lock->core()['files']['src/Libs/Aria2.php']), 'no adopta archivos ajenos'); rrmdir($proj); rrmdir($core); });