first commit
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
package pkgmgr
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// fakeNPMForInstall writes a fake `npm` onto PATH that packs a prebuilt tarball
|
||||
// (built from files) into --pack-destination, mimicking `npm pack`.
|
||||
func fakeNPMForInstall(t *testing.T, tarballFiles map[string]string, packName string) {
|
||||
t.Helper()
|
||||
binDir := t.TempDir()
|
||||
srcTarball := filepath.Join(binDir, "src.tgz")
|
||||
makeTarGz(t, srcTarball, tarballFiles)
|
||||
script := `#!/bin/sh
|
||||
dest=""
|
||||
prev=""
|
||||
for a in "$@"; do
|
||||
if [ "$prev" = "--pack-destination" ]; then dest="$a"; fi
|
||||
prev="$a"
|
||||
done
|
||||
cp "` + srcTarball + `" "$dest/` + packName + `"
|
||||
echo "` + packName + `"
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(binDir, "npm"), []byte(script), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
|
||||
}
|
||||
|
||||
// TestInstallExtensionEndToEnd drives Install for an extension package through
|
||||
// fetch (fake npm) → classify → distribute → lockfile.
|
||||
func TestInstallExtensionEndToEnd(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("fake npm shell script + extension install are POSIX-only")
|
||||
}
|
||||
home := t.TempDir()
|
||||
t.Setenv("PIGO_HOME", home)
|
||||
|
||||
fakeNPMForInstall(t, map[string]string{
|
||||
"package/package.json": `{"name":"pi-demo","version":"1.2.0","bin":"./cli.js"}`,
|
||||
"package/cli.js": "#!/usr/bin/env node\nconsole.log('hi')\n",
|
||||
}, "pi-demo-1.2.0.tgz")
|
||||
|
||||
lockPath := filepath.Join(home, "packages.json")
|
||||
res, err := Install("npm:pi-demo", lockPath, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Install: %v", err)
|
||||
}
|
||||
if res.Name != "pi-demo" || res.Version != "1.2.0" {
|
||||
t.Errorf("result = %+v, want pi-demo@1.2.0", res)
|
||||
}
|
||||
if len(res.Types) != 1 || res.Types[0] != TypeExtension {
|
||||
t.Errorf("types = %v, want [extension]", res.Types)
|
||||
}
|
||||
|
||||
// Launcher exists in plugins.
|
||||
if _, err := os.Stat(filepath.Join(home, "plugins", "pi-demo")); err != nil {
|
||||
t.Errorf("launcher not installed: %v", err)
|
||||
}
|
||||
|
||||
// Lockfile records the package.
|
||||
lf, err := Load(lockPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Load lockfile: %v", err)
|
||||
}
|
||||
p, ok := lf.Get("pi-demo")
|
||||
if !ok {
|
||||
t.Fatal("lockfile missing pi-demo")
|
||||
}
|
||||
if p.Source != "npm:pi-demo" || p.Version != "1.2.0" {
|
||||
t.Errorf("lockfile entry = %+v", p)
|
||||
}
|
||||
if len(p.Files) == 0 {
|
||||
t.Error("lockfile entry has no files")
|
||||
}
|
||||
}
|
||||
|
||||
// TestInstallMultiType drives Install for a package that is both extension and
|
||||
// skill, verifying both distributions happen and both types are recorded.
|
||||
func TestInstallMultiType(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("POSIX-only")
|
||||
}
|
||||
home := t.TempDir()
|
||||
skills := t.TempDir()
|
||||
t.Setenv("PIGO_HOME", home)
|
||||
t.Setenv("PIGO_SKILLS_DIR", skills)
|
||||
|
||||
fakeNPMForInstall(t, map[string]string{
|
||||
"package/package.json": `{"name":"combo","version":"1.0.0","bin":"./x.js","pi":{"types":["extension","skill"]}}`,
|
||||
"package/x.js": "#!/usr/bin/env node\n",
|
||||
"package/SKILL.md": "---\nname: combo\ndescription: d\n---\nbody",
|
||||
}, "combo-1.0.0.tgz")
|
||||
|
||||
res, err := Install("npm:combo", filepath.Join(home, "packages.json"), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Install: %v", err)
|
||||
}
|
||||
if len(res.Types) != 2 {
|
||||
t.Errorf("types = %v, want extension+skill", res.Types)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(home, "plugins", "combo")); err != nil {
|
||||
t.Errorf("extension launcher missing: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(skills, "combo", "SKILL.md")); err != nil {
|
||||
t.Errorf("skill not installed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestInstallUnrecognized verifies a non-pi package fails install with a clear
|
||||
// error and writes no lockfile entry.
|
||||
func TestInstallUnrecognized(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("POSIX-only")
|
||||
}
|
||||
home := t.TempDir()
|
||||
t.Setenv("PIGO_HOME", home)
|
||||
|
||||
fakeNPMForInstall(t, map[string]string{
|
||||
"package/package.json": `{"name":"lodash","version":"4.0.0"}`,
|
||||
}, "lodash-4.0.0.tgz")
|
||||
|
||||
lockPath := filepath.Join(home, "packages.json")
|
||||
if _, err := Install("npm:lodash", lockPath, nil); err == nil {
|
||||
t.Fatal("Install of non-pi package = nil error, want error")
|
||||
}
|
||||
if _, err := os.Stat(lockPath); !os.IsNotExist(err) {
|
||||
t.Errorf("lockfile written for failed install: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestInstallBadRef verifies an invalid reference is rejected before any fetch.
|
||||
func TestInstallBadRef(t *testing.T) {
|
||||
if _, err := Install("github:owner/repo", filepath.Join(t.TempDir(), "packages.json"), nil); err == nil {
|
||||
t.Fatal("Install with non-npm ref = nil error, want error")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user