Ctrl K
ComunidadGuías…

cursor-plugin/tests/test_install.ps1

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Regression tests for the Cursor plugin installer (Windows).
$ErrorActionPreference = "Stop"

$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$pluginSrc = Split-Path -Parent $scriptDir
$repoRoot = Split-Path -Parent $pluginSrc
$canonicalPlugin = Join-Path $repoRoot "cli-anything-plugin"
$previewProtocol = Join-Path $repoRoot "docs\PREVIEW_PROTOCOL.md"

$tmpDir = Join-Path ([System.IO.Path]::GetTempPath()) ("cli-anything-cursor-test-" + [System.Guid]::NewGuid().ToString("N"))
$userHome = Join-Path $tmpDir "home"
$pluginsHome = Join-Path $tmpDir "plugins"
$installedDir = Join-Path $pluginsHome "local\cli-anything"
$staleStaging = Join-Path $pluginsHome "local\.cli-anything.tmp.stale"
$discoveryPointer = Join-Path $userHome ".cursor\cli-anything-generator.root"

function Fail([string]$Message) {
    throw "FAIL: $Message"
}

function Assert-File([string]$Path) {
    if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
        Fail "expected file: $Path"
    }
}

function Assert-SameFile([string]$Left, [string]$Right) {
    $a = Get-FileHash -LiteralPath $Left -Algorithm SHA256
    $b = Get-FileHash -LiteralPath $Right -Algorithm SHA256
    if ($a.Hash -ne $b.Hash) {
        Fail "files differ: $Left $Right"
    }
}

$oldUserProfile = $env:USERPROFILE
$oldPluginsHome = $env:CURSOR_PLUGINS_HOME

try {
    New-Item -ItemType Directory -Path $userHome -Force | Out-Null
    New-Item -ItemType Directory -Path $staleStaging -Force | Out-Null
    Set-Content -LiteralPath (Join-Path $staleStaging "stale.txt") -Value "left over from an interrupted install"

    $env:USERPROFILE = $userHome
    $env:CURSOR_PLUGINS_HOME = $pluginsHome
    & (Join-Path $pluginSrc "scripts\install.ps1")

    Assert-File (Join-Path $installedDir ".cursor-plugin\plugin.json")
    Assert-File (Join-Path $installedDir "PLUGIN_ROOT.txt")
    Assert-File $discoveryPointer
    Assert-File (Join-Path $installedDir "commands\cli-anything.md")
    Assert-File (Join-Path $installedDir "commands\cli-anything-refine.md")
    Assert-File (Join-Path $installedDir "commands\cli-anything-test.md")
    Assert-File (Join-Path $installedDir "commands\cli-anything-validate.md")
    Assert-File (Join-Path $installedDir "commands\cli-anything-list.md")
    Assert-File (Join-Path $installedDir "skills\cli-anything-generator\SKILL.md")
    Assert-File (Join-Path $installedDir "rules\cli-anything-generator.mdc")
    Assert-File (Join-Path $installedDir "references\HARNESS.md")
    Assert-File (Join-Path $installedDir "references\commands\cli-anything.md")
    Assert-File (Join-Path $installedDir "references\commands\refine.md")
    Assert-File (Join-Path $installedDir "references\commands\test.md")
    Assert-File (Join-Path $installedDir "references\commands\validate.md")
    Assert-File (Join-Path $installedDir "references\commands\list.md")
    Assert-File (Join-Path $installedDir "scripts\repl_skin.py")
    Assert-File (Join-Path $installedDir "scripts\preview_bundle.py")
    Assert-File (Join-Path $installedDir "scripts\skill_generator.py")
    Assert-File (Join-Path $installedDir "scripts\templates\SKILL.md.template")
    Assert-File (Join-Path $installedDir "references\docs\PREVIEW_PROTOCOL.md")

    $stamp = (Get-Content -LiteralPath (Join-Path $installedDir "PLUGIN_ROOT.txt") -Raw).Trim()
    $pointer = (Get-Content -LiteralPath $discoveryPointer -Raw).Trim()
    if (-not (Test-Path -LiteralPath (Join-Path $stamp "references\HARNESS.md"))) {
        Fail "stamped PLUGIN_ROOT missing HARNESS.md: $stamp"
    }
    if ($stamp -ne $pointer) {
        Fail "discovery pointer mismatch: $pointer != $stamp"
    }

    if (-not (Test-Path -LiteralPath $staleStaging)) {
        Fail "installer reused or removed the stale staging directory"
    }
    if (Test-Path -LiteralPath (Join-Path $installedDir "tests")) {
        Fail "installer copied tests/ into the installed plugin"
    }
    if (Test-Path -LiteralPath (Join-Path $installedDir "skills\cli-anything")) {
        Fail "old skills/cli-anything name should not be installed"
    }

    Assert-SameFile (Join-Path $canonicalPlugin "HARNESS.md") (Join-Path $installedDir "references\HARNESS.md")
    Assert-SameFile (Join-Path $canonicalPlugin "repl_skin.py") (Join-Path $installedDir "scripts\repl_skin.py")
    Assert-SameFile (Join-Path $canonicalPlugin "preview_bundle.py") (Join-Path $installedDir "scripts\preview_bundle.py")
    Assert-SameFile (Join-Path $canonicalPlugin "skill_generator.py") (Join-Path $installedDir "scripts\skill_generator.py")
    Assert-SameFile $previewProtocol (Join-Path $installedDir "references\docs\PREVIEW_PROTOCOL.md")

    foreach ($name in (Get-ChildItem (Join-Path $canonicalPlugin "commands\*.md")).Name) {
        Assert-SameFile (Join-Path $canonicalPlugin "commands\$name") (Join-Path $installedDir "references\commands\$name")
    }
    foreach ($name in (Get-ChildItem (Join-Path $canonicalPlugin "guides\*.md")).Name) {
        Assert-SameFile (Join-Path $canonicalPlugin "guides\$name") (Join-Path $installedDir "references\guides\$name")
    }
    foreach ($name in (Get-ChildItem (Join-Path $canonicalPlugin "templates\*")).Name) {
        Assert-SameFile (Join-Path $canonicalPlugin "templates\$name") (Join-Path $installedDir "scripts\templates\$name")
    }

    $py = Get-Command python -ErrorAction SilentlyContinue
    if (-not $py) { $py = Get-Command python3 -ErrorAction SilentlyContinue }
    if ($py) {
        & $py.Source -m py_compile `
            (Join-Path $installedDir "scripts\repl_skin.py") `
            (Join-Path $installedDir "scripts\preview_bundle.py") `
            (Join-Path $installedDir "scripts\skill_generator.py")
        if ($LASTEXITCODE -ne 0) {
            Fail "py_compile failed for vendored scripts"
        }
    } else {
        Fail "python/python3 not available for py_compile"
    }

    $refused = $false
    try {
        & (Join-Path $pluginSrc "scripts\install.ps1")
    } catch {
        $refused = $true
    }
    if (-not $refused) {
        Fail "installer overwrote an existing plugin without -Force"
    }

    $marker = Join-Path $installedDir ".install-marker"
    Set-Content -LiteralPath $marker -Value "first-install"
    & (Join-Path $pluginSrc "scripts\install.ps1") -Force
    if (Test-Path -LiteralPath $marker) {
        Fail "-Force upgrade did not replace the previous install"
    }
    Assert-File (Join-Path $installedDir "PLUGIN_ROOT.txt")
    Assert-File (Join-Path $installedDir "references\HARNESS.md")

    $cmdText = Get-Content -LiteralPath (Join-Path $installedDir "commands\cli-anything.md") -Raw
    if ($cmdText -notmatch "cli-anything-generator\.root") {
        Fail "installed command does not document discovery pointer"
    }
    if ($cmdText -notmatch "agent-harness/\.cli-anything-progress\.json") {
        Fail "installed command does not use agent-harness progress path"
    }

    $ruleText = Get-Content -LiteralPath (Join-Path $installedDir "rules\cli-anything-generator.mdc") -Raw
    if ($ruleText -notmatch "alwaysApply:\s*false") {
        Fail "generator rule must be alwaysApply false (avoid global context pollution)"
    }
    if ($ruleText -notmatch "agent-harness/\*\*") {
        Fail "generator rule must include agent-harness globs"
    }

    $skillText = Get-Content -LiteralPath (Join-Path $installedDir "skills\cli-anything-generator\SKILL.md") -Raw
    if ($skillText -notmatch "references/HARNESS.md") {
        Fail "installed skill does not point to vendored HARNESS.md"
    }
    if ($skillText -notmatch "cli-hub-meta-skill") {
        Fail "installed skill does not document consumer Hub path"
    }

    $manifest = Get-Content -LiteralPath (Join-Path $installedDir ".cursor-plugin\plugin.json") -Raw | ConvertFrom-Json
    if ($manifest.name -ne "cli-anything") {
        Fail "plugin manifest name mismatch"
    }

    $marketplacePath = Join-Path $repoRoot ".cursor-plugin\marketplace.json"
    Assert-File $marketplacePath
    $marketplace = Get-Content -LiteralPath $marketplacePath -Raw | ConvertFrom-Json
    $sources = @($marketplace.plugins | ForEach-Object { $_.source })
    if ($sources -notcontains "./cursor-plugin") {
        Fail "marketplace.json does not point at ./cursor-plugin"
    }

    $detachedRoot = Join-Path $tmpDir "detached"
    New-Item -ItemType Directory -Path $detachedRoot -Force | Out-Null
    Copy-Item -LiteralPath $pluginSrc -Destination (Join-Path $detachedRoot "cursor-plugin") -Recurse -Force
    $detachedFailed = $false
    try {
        $env:CURSOR_PLUGINS_HOME = Join-Path $tmpDir "detached-plugins\plugins"
        & (Join-Path $detachedRoot "cursor-plugin\scripts\install.ps1") 2>&1 | Out-Null
    } catch {
        $detachedFailed = $true
        if ($_.Exception.Message -notmatch "Cannot find canonical CLI-Anything resources") {
            Fail "detached install did not explain missing canonical resources"
        }
    }
    if (-not $detachedFailed) {
        Fail "installer accepted a detached plugin without canonical resources"
    }

    $badFailed = $false
    $badHomePath = Join-Path $tmpDir "not-plugins-dir"
    try {
        $env:CURSOR_PLUGINS_HOME = $badHomePath
        & (Join-Path $pluginSrc "scripts\install.ps1") 2>&1 | Out-Null
    } catch {
        $badFailed = $true
        if ($_.Exception.Message -notmatch "named 'plugins'") {
            Fail "installer did not reject non-plugins CURSOR_PLUGINS_HOME"
        }
    }
    if (-not $badFailed) {
        Fail "installer accepted CURSOR_PLUGINS_HOME whose basename is not plugins"
    }
    if (Test-Path -LiteralPath $badHomePath) {
        Fail "rejected CURSOR_PLUGINS_HOME should not create the target directory"
    }

    # Uninstall clears install dir + matching discovery pointer.
    $env:CURSOR_PLUGINS_HOME = $pluginsHome
    & (Join-Path $pluginSrc "scripts\uninstall.ps1")
    if (Test-Path -LiteralPath $installedDir) {
        Fail "uninstall left plugin directory behind"
    }
    if (Test-Path -LiteralPath $discoveryPointer) {
        Fail "uninstall left discovery pointer behind"
    }

    # Reinstall, then foreign pointer must be preserved across uninstall.
    & (Join-Path $pluginSrc "scripts\install.ps1")
    Assert-File (Join-Path $installedDir "references\HARNESS.md")
    $foreignRoot = Join-Path $tmpDir "some-other-plugin-root"
    Set-Content -LiteralPath $discoveryPointer -Value $foreignRoot
    & (Join-Path $pluginSrc "scripts\uninstall.ps1")
    if (Test-Path -LiteralPath $installedDir) {
        Fail "uninstall left plugin directory behind after foreign-pointer case"
    }
    if (-not (Test-Path -LiteralPath $discoveryPointer)) {
        Fail "uninstall removed a non-matching discovery pointer"
    }
    $leftPointer = (Get-Content -LiteralPath $discoveryPointer -Raw).Trim()
    if ($leftPointer -ne $foreignRoot) {
        Fail "foreign discovery pointer changed: $leftPointer"
    }

    . (Join-Path $pluginSrc "scripts\lib.ps1")
    if (-not (Test-CliAnythingInstallPath -Path "C:\Users\x\.cursor\plugins\local\cli-anything")) {
        Fail "Test-CliAnythingInstallPath should accept Windows local install path"
    }
    if (Test-CliAnythingInstallPath -Path "D:\repo\CLI-Anything\cursor-plugin") {
        Fail "Test-CliAnythingInstallPath must reject repo cursor-plugin path"
    }

    # Final reinstall for a clean installed tree at end of test.
    & (Join-Path $pluginSrc "scripts\install.ps1")
    Assert-File (Join-Path $installedDir "references\HARNESS.md")
    Assert-File $discoveryPointer
    Assert-File (Join-Path $installedDir "scripts\lib.ps1")
    Assert-File (Join-Path $installedDir "scripts\lib.sh")

    Write-Host "PASS: Cursor plugin installer vendors the complete CLI-Anything resource set."
} finally {
    if (Test-Path -LiteralPath $tmpDir) {
        Remove-Item -LiteralPath $tmpDir -Recurse -Force
    }
    if ($null -ne $oldUserProfile) {
        $env:USERPROFILE = $oldUserProfile
    } else {
        Remove-Item Env:USERPROFILE -ErrorAction SilentlyContinue
    }
    if ($null -ne $oldPluginsHome) {
        $env:CURSOR_PLUGINS_HOME = $oldPluginsHome
    } else {
        Remove-Item Env:CURSOR_PLUGINS_HOME -ErrorAction SilentlyContinue
    }
}