Files
pmg/packagemanager/npm_executor_test.go
T
31f23fd065 Add support for package executors and support for PTY handling (#100)
* 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>
2026-01-09 22:03:42 +05:30

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)
})
}
}