104 lines
2.5 KiB
Go
104 lines
2.5 KiB
Go
|
|
package bootstrap
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"forge.lclr.dev/AI/mcp-framework/secretstore"
|
||
|
|
)
|
||
|
|
|
||
|
|
func withLoginBitwarden(t *testing.T, fn func(secretstore.BitwardenLoginOptions) (string, error)) {
|
||
|
|
t.Helper()
|
||
|
|
previous := loginBitwarden
|
||
|
|
loginBitwarden = fn
|
||
|
|
t.Cleanup(func() { loginBitwarden = previous })
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestDefaultLoginHandlerPrintsConfirmation(t *testing.T) {
|
||
|
|
var stdout bytes.Buffer
|
||
|
|
|
||
|
|
withLoginBitwarden(t, func(opts secretstore.BitwardenLoginOptions) (string, error) {
|
||
|
|
if opts.ServiceName != "my-mcp" {
|
||
|
|
t.Fatalf("ServiceName = %q, want %q", opts.ServiceName, "my-mcp")
|
||
|
|
}
|
||
|
|
return "session-token", nil
|
||
|
|
})
|
||
|
|
|
||
|
|
handler := DefaultLoginHandler("my-mcp")
|
||
|
|
err := handler(context.Background(), Invocation{
|
||
|
|
Command: CommandLogin,
|
||
|
|
Stdout: &stdout,
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("handler returned error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
out := stdout.String()
|
||
|
|
if !strings.Contains(out, `"my-mcp"`) {
|
||
|
|
t.Fatalf("stdout = %q, want mention of binary name", out)
|
||
|
|
}
|
||
|
|
if !strings.Contains(out, "persistée") {
|
||
|
|
t.Fatalf("stdout = %q, want confirmation message", out)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestDefaultLoginHandlerPropagatesError(t *testing.T) {
|
||
|
|
var stdout bytes.Buffer
|
||
|
|
loginErr := errors.New("vault locked")
|
||
|
|
|
||
|
|
withLoginBitwarden(t, func(_ secretstore.BitwardenLoginOptions) (string, error) {
|
||
|
|
return "", loginErr
|
||
|
|
})
|
||
|
|
|
||
|
|
handler := DefaultLoginHandler("my-mcp")
|
||
|
|
err := handler(context.Background(), Invocation{
|
||
|
|
Command: CommandLogin,
|
||
|
|
Stdout: &stdout,
|
||
|
|
})
|
||
|
|
if !errors.Is(err, loginErr) {
|
||
|
|
t.Fatalf("err = %v, want %v", err, loginErr)
|
||
|
|
}
|
||
|
|
if stdout.Len() > 0 {
|
||
|
|
t.Fatalf("stdout should be empty on error, got %q", stdout.String())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRunUsesDefaultLoginHandlerWhenHookSet(t *testing.T) {
|
||
|
|
var stdout bytes.Buffer
|
||
|
|
|
||
|
|
withLoginBitwarden(t, func(_ secretstore.BitwardenLoginOptions) (string, error) {
|
||
|
|
return "tok", nil
|
||
|
|
})
|
||
|
|
|
||
|
|
err := Run(context.Background(), Options{
|
||
|
|
BinaryName: "my-mcp",
|
||
|
|
Args: []string{"login"},
|
||
|
|
Stdout: &stdout,
|
||
|
|
Hooks: Hooks{
|
||
|
|
Login: DefaultLoginHandler("my-mcp"),
|
||
|
|
},
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Run error = %v", err)
|
||
|
|
}
|
||
|
|
if !strings.Contains(stdout.String(), "persistée") {
|
||
|
|
t.Fatalf("stdout = %q, want confirmation", stdout.String())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRunLoginAutoHiddenWithoutHook(t *testing.T) {
|
||
|
|
var stdout bytes.Buffer
|
||
|
|
|
||
|
|
err := Run(context.Background(), Options{
|
||
|
|
BinaryName: "my-mcp",
|
||
|
|
Args: []string{"login"},
|
||
|
|
Stdout: &stdout,
|
||
|
|
})
|
||
|
|
if !errors.Is(err, ErrUnknownCommand) {
|
||
|
|
t.Fatalf("err = %v, want ErrUnknownCommand", err)
|
||
|
|
}
|
||
|
|
}
|