\n"); write_file($dir . '/tests/TestCase.php', "install( ['duckbrain', 'src/Interfaces/CommandInterface.php', 'src/Commands/Migration.php', 'phpunit.xml', 'tests/TestCase.php'], $src, $root, $root . '/src', null, 'copy' ); ok(is_file($root . '/duckbrain'), 'binario CLI en ROOT_DIR'); ok(is_file($root . '/src/Interfaces/CommandInterface.php'), 'interfaz en ROOT_CORE'); ok(is_file($root . '/src/Commands/Migration.php'), 'comando en ROOT_CORE'); ok(is_file($root . '/phpunit.xml'), 'phpunit.xml en ROOT_DIR'); ok(is_file($root . '/tests/TestCase.php'), 'tests en ROOT_DIR'); ok(!is_dir($root . '/src/tests'), 'tests no va dentro de src'); eq(5, count($result['files'])); rrmdir($src); rrmdir($root); }); Harness::it('destino explícito sobreescribe la regla en la copia', function () { $src = tmpdir('pkg'); $root = tmpdir('proj'); write_file($src . '/src/Libs/X.php', "install( ['src/Libs/X.php'], $src, $root, $root . '/src', ['src/Libs/X.php' => 'custom/X.php'], 'copy' ); ok(is_file($root . '/custom/X.php'), 'destino explícito'); ok(!is_file($root . '/src/Libs/X.php'), 'no usa la regla por defecto'); rrmdir($src); rrmdir($root); }); Harness::it('modo enlace crea symlink y refleja cambios', function () { $src = tmpdir('pkg'); $root = tmpdir('proj'); write_file($src . '/src/Libs/X.php', "uno"); $copier = new Copier(); $result = $copier->install(['src/Libs/X.php'], $src, $root, $root . '/src', null, 'link'); $target = $root . '/src/Libs/X.php'; ok(is_link($target), 'debe ser un symlink'); eq("uno", file_get_contents($target)); write_file($src . '/src/Libs/X.php', "dos"); eq("dos", file_get_contents($target), 'el enlace refleja cambios sin recopiar'); eq(FileSync::WRITTEN, $result['actions']['src/Libs/X.php']); rrmdir($root); rrmdir($src); }); Harness::it('post-install sin hooks no ejecuta nada', function () { $console = new Console(); $executed = PostInstall::run([], $console, true, fn () => 0); eq([], $executed); }); Harness::it('post-install ejecuta con confirmación (--yes) y runner', function () { $console = new Console(); $ran = []; $executed = PostInstall::run( ['composer require --dev phpunit/phpunit'], $console, true, function (string $cmd) use (&$ran) { $ran[] = $cmd; return 0; } ); eq(['composer require --dev phpunit/phpunit'], $executed); eq(['composer require --dev phpunit/phpunit'], $ran); });