mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
* define contract for package executors * introduce npx executor * add npx and pnpx cmd support * fix typo * rm PackageExecutor and depend on PackageManager interface * add support for PTY to handle parent-child process interaction * refactor PTY handling in proxy flow * enforce interactiveSession interface check * close reader explicitly and clean npm version for pkg executors * rm interaction from interceptors * add docs and wait for outputRouter before exit * add support for non interactive TTY for proxy mode * add support for CI env var check for non interactive tty proxy mode * update readme to include npx, pnpx support * Update internal/flows/proxy_flow.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Sahil Bansal <bansalsahil315@gmail.com> * update ptyx lib * fix docs typo --------- Signed-off-by: Sahil Bansal <bansalsahil315@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
212 lines
7.9 KiB
Go
212 lines
7.9 KiB
Go
package packagemanager
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestNpxExecutorParseCommand(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
command string
|
|
assert func(t *testing.T, parsed *ParsedCommand, err error)
|
|
}{
|
|
{
|
|
name: "bare npx invocation",
|
|
command: "npx",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, parsed)
|
|
assert.Equal(t, 0, len(parsed.InstallTargets))
|
|
},
|
|
},
|
|
{
|
|
name: "scoped package via -p flag",
|
|
command: "npx -p @types/node",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(parsed.InstallTargets))
|
|
assert.Equal(t, "@types/node", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[0].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "scoped package with version",
|
|
command: "npx @types/node@1.2.3",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(parsed.InstallTargets))
|
|
assert.Equal(t, "@types/node", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Equal(t, "1.2.3", parsed.InstallTargets[0].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "non-package npx command",
|
|
command: "npx create-react-app my-app",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 0, len(parsed.InstallTargets))
|
|
assert.Equal(t, []string{"create-react-app", "my-app"}, parsed.Command.Args)
|
|
},
|
|
},
|
|
{
|
|
name: "single package using -p flag npx command with binary",
|
|
command: "npx -p tsx my-app",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(parsed.InstallTargets))
|
|
assert.Equal(t, "tsx", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[0].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "single package using --package flag npx command with binary",
|
|
command: "npx --package=tsx my-app",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(parsed.InstallTargets))
|
|
assert.Equal(t, "tsx", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[0].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "multiple scoped packages via flags and args",
|
|
command: "npx -p @types/node @react@2.0.0",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 2, len(parsed.InstallTargets))
|
|
assert.Equal(t, "@types/node", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[0].PackageVersion.Version)
|
|
assert.Equal(t, "@react", parsed.InstallTargets[1].PackageVersion.Package.Name)
|
|
assert.Equal(t, "2.0.0", parsed.InstallTargets[1].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "multiple packages via flags and scoped",
|
|
command: "npx @types/node -p react@2.0.0",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 2, len(parsed.InstallTargets))
|
|
assert.Equal(t, "@types/node", parsed.InstallTargets[1].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[1].PackageVersion.Version)
|
|
assert.Equal(t, "react", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Equal(t, "2.0.0", parsed.InstallTargets[0].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "multiple packages via flags and args",
|
|
command: "npx -p node -p react@2.0.0",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 2, len(parsed.InstallTargets))
|
|
assert.Equal(t, "node", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[0].PackageVersion.Version)
|
|
assert.Equal(t, "react", parsed.InstallTargets[1].PackageVersion.Package.Name)
|
|
assert.Equal(t, "2.0.0", parsed.InstallTargets[1].PackageVersion.Version)
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
exec := &npmPackageExecutor{Config: DefaultNpxPackageExecutorConfig()}
|
|
parsed, err := exec.ParseCommand(strings.Split(tc.command, " "))
|
|
tc.assert(t, parsed, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPnpxExecutorParseCommand(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
command string
|
|
assert func(t *testing.T, parsed *ParsedCommand, err error)
|
|
}{
|
|
{
|
|
name: "bare pnpx invocation",
|
|
command: "pnpx",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, parsed)
|
|
assert.Equal(t, 0, len(parsed.InstallTargets))
|
|
},
|
|
},
|
|
{
|
|
name: "scoped package via package flag",
|
|
command: "pnpx --package=@types/node",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(parsed.InstallTargets))
|
|
assert.Equal(t, "@types/node", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[0].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "scoped package with version",
|
|
command: "pnpx @types/node@1.2.3",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(parsed.InstallTargets))
|
|
assert.Equal(t, "@types/node", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Equal(t, "1.2.3", parsed.InstallTargets[0].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "single package command",
|
|
command: "pnpx tsx my-app",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(parsed.InstallTargets))
|
|
assert.Equal(t, "tsx", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[0].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "multiple scoped packages via flags and args",
|
|
command: "pnpx --package @types/node @react@2.0.0",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 2, len(parsed.InstallTargets))
|
|
assert.Equal(t, "@types/node", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[0].PackageVersion.Version)
|
|
assert.Equal(t, "@react", parsed.InstallTargets[1].PackageVersion.Package.Name)
|
|
assert.Equal(t, "2.0.0", parsed.InstallTargets[1].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "multiple packages via flags and scoped",
|
|
command: "pnpx @types/node --package react@2.0.0",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 2, len(parsed.InstallTargets))
|
|
assert.Equal(t, "@types/node", parsed.InstallTargets[1].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[1].PackageVersion.Version)
|
|
assert.Equal(t, "react", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Equal(t, "2.0.0", parsed.InstallTargets[0].PackageVersion.Version)
|
|
},
|
|
},
|
|
{
|
|
name: "multiple packages via flags and args",
|
|
command: "pnpx --package node --package react@2.0.0",
|
|
assert: func(t *testing.T, parsed *ParsedCommand, err error) {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 2, len(parsed.InstallTargets))
|
|
assert.Equal(t, "node", parsed.InstallTargets[0].PackageVersion.Package.Name)
|
|
assert.Empty(t, parsed.InstallTargets[0].PackageVersion.Version)
|
|
assert.Equal(t, "react", parsed.InstallTargets[1].PackageVersion.Package.Name)
|
|
assert.Equal(t, "2.0.0", parsed.InstallTargets[1].PackageVersion.Version)
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
exec := &npmPackageExecutor{Config: DefaultPnpxPackageExecutorConfig()}
|
|
parsed, err := exec.ParseCommand(strings.Split(tc.command, " "))
|
|
tc.assert(t, parsed, err)
|
|
})
|
|
}
|
|
}
|