Files
Fabric/internal/plugins/plugin_test.go
Kayvan Sylvan cf55be784f refactor: add NewVendorPluginBase factory function to reduce duplication
Add centralized factory function for AI vendor plugin initialization:
- Add NewVendorPluginBase(name, configure) to internal/plugins/plugin.go
- Update 8 vendor files (anthropic, bedrock, gemini, lmstudio, ollama,
  openai, perplexity, vertexai) to use the factory function
- Add 3 test cases for the new factory function

This removes ~40 lines of duplicated boilerplate code and ensures
consistent plugin initialization across all vendors.

MAESTRO: Loop 00001 refactoring implementation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 20:12:58 -08:00

299 lines
6.8 KiB
Go

package plugins
import (
"bytes"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewVendorPluginBase(t *testing.T) {
// Test with configure function
configureCalled := false
configureFunc := func() error {
configureCalled = true
return nil
}
plugin := NewVendorPluginBase("TestVendor", configureFunc)
assert.Equal(t, "TestVendor", plugin.Name)
assert.Equal(t, "TESTVENDOR_", plugin.EnvNamePrefix)
assert.NotNil(t, plugin.ConfigureCustom)
// Test that configure function is properly stored
err := plugin.ConfigureCustom()
assert.NoError(t, err)
assert.True(t, configureCalled)
}
func TestNewVendorPluginBase_NilConfigure(t *testing.T) {
// Test with nil configure function
plugin := NewVendorPluginBase("TestVendor", nil)
assert.Equal(t, "TestVendor", plugin.Name)
assert.Equal(t, "TESTVENDOR_", plugin.EnvNamePrefix)
assert.Nil(t, plugin.ConfigureCustom)
}
func TestNewVendorPluginBase_EnvPrefixWithSpaces(t *testing.T) {
// Test that spaces are converted to underscores
plugin := NewVendorPluginBase("LM Studio", nil)
assert.Equal(t, "LM Studio", plugin.Name)
assert.Equal(t, "LM_STUDIO_", plugin.EnvNamePrefix)
}
func TestConfigurable_AddSetting(t *testing.T) {
conf := &PluginBase{
Settings: Settings{},
Name: "TestConfigurable",
EnvNamePrefix: "TEST_",
}
setting := conf.AddSetting("test_setting", true)
assert.Equal(t, "TEST_TEST_SETTING", setting.EnvVariable)
assert.True(t, setting.Required)
assert.Contains(t, conf.Settings, setting)
}
func TestConfigurable_Configure(t *testing.T) {
setting := &Setting{
EnvVariable: "TEST_SETTING",
Required: true,
}
conf := &PluginBase{
Settings: Settings{setting},
Name: "TestConfigurable",
}
_ = os.Setenv("TEST_SETTING", "test_value")
err := conf.Configure()
assert.NoError(t, err)
assert.Equal(t, "test_value", setting.Value)
}
func TestConfigurable_Setup(t *testing.T) {
setting := &Setting{
EnvVariable: "TEST_SETTING",
Required: false,
}
conf := &PluginBase{
Settings: Settings{setting},
Name: "TestConfigurable",
}
err := conf.Setup()
assert.NoError(t, err)
}
func TestSetting_IsValid(t *testing.T) {
setting := &Setting{
EnvVariable: "TEST_SETTING",
Value: "some_value",
Required: true,
}
assert.True(t, setting.IsValid())
setting.Value = ""
assert.False(t, setting.IsValid())
}
func TestSetting_Configure(t *testing.T) {
_ = os.Setenv("TEST_SETTING", "test_value")
setting := &Setting{
EnvVariable: "TEST_SETTING",
Required: true,
}
err := setting.Configure()
assert.NoError(t, err)
assert.Equal(t, "test_value", setting.Value)
}
func TestSetting_FillEnvFileContent(t *testing.T) {
buffer := &bytes.Buffer{}
setting := &Setting{
EnvVariable: "TEST_SETTING",
Value: "test_value",
}
setting.FillEnvFileContent(buffer)
expected := "TEST_SETTING=test_value\n"
assert.Equal(t, expected, buffer.String())
}
func TestSetting_Print(t *testing.T) {
setting := &Setting{
EnvVariable: "TEST_SETTING",
Value: "test_value",
}
expected := "TEST_SETTING: test_value\n"
fmtOutput := captureOutput(func() {
setting.Print()
})
assert.Equal(t, expected, fmtOutput)
}
func TestSetupQuestion_Ask(t *testing.T) {
setting := &Setting{
EnvVariable: "TEST_SETTING",
Required: true,
}
question := &SetupQuestion{
Setting: setting,
Question: "Enter test setting:",
}
input := "user_value\n"
fmtInput := captureInput(input)
defer fmtInput()
err := question.Ask("TestConfigurable")
assert.NoError(t, err)
assert.Equal(t, "user_value", setting.Value)
}
func TestSetupQuestion_Ask_Reset(t *testing.T) {
// Test that resetting a required field doesn't produce an error
setting := &Setting{
EnvVariable: "TEST_RESET_SETTING",
Value: "existing_value",
Required: true,
}
question := &SetupQuestion{
Setting: setting,
Question: "Enter test setting:",
}
input := "reset\n"
fmtInput := captureInput(input)
defer fmtInput()
err := question.Ask("TestConfigurable")
// Should NOT return an error even though the field is required
assert.NoError(t, err)
// Value should be cleared
assert.Equal(t, "", setting.Value)
}
func TestSetupQuestion_OnAnswerWithReset(t *testing.T) {
tests := []struct {
name string
setting *Setting
answer string
isReset bool
expectError bool
expectValue string
}{
{
name: "reset required field should not error",
setting: &Setting{
EnvVariable: "TEST_SETTING",
Value: "old_value",
Required: true,
},
answer: "",
isReset: true,
expectError: false,
expectValue: "",
},
{
name: "empty answer on required field should error",
setting: &Setting{
EnvVariable: "TEST_SETTING",
Value: "",
Required: true,
},
answer: "",
isReset: false,
expectError: true,
expectValue: "",
},
{
name: "valid answer on required field should not error",
setting: &Setting{
EnvVariable: "TEST_SETTING",
Value: "",
Required: true,
},
answer: "new_value",
isReset: false,
expectError: false,
expectValue: "new_value",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
question := &SetupQuestion{
Setting: tt.setting,
Question: "Test question",
}
err := question.OnAnswerWithReset(tt.answer, tt.isReset)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
assert.Equal(t, tt.expectValue, tt.setting.Value)
})
}
}
func TestSettings_IsConfigured(t *testing.T) {
settings := Settings{
{EnvVariable: "TEST_SETTING1", Value: "value1", Required: true},
{EnvVariable: "TEST_SETTING2", Value: "", Required: false},
}
assert.True(t, settings.IsConfigured())
settings[0].Value = ""
assert.False(t, settings.IsConfigured())
}
func TestSettings_Configure(t *testing.T) {
_ = os.Setenv("TEST_SETTING", "test_value")
settings := Settings{
{EnvVariable: "TEST_SETTING", Required: true},
}
err := settings.Configure()
assert.NoError(t, err)
assert.Equal(t, "test_value", settings[0].Value)
}
func TestSettings_FillEnvFileContent(t *testing.T) {
buffer := &bytes.Buffer{}
settings := Settings{
{EnvVariable: "TEST_SETTING", Value: "test_value"},
}
settings.FillEnvFileContent(buffer)
expected := "TEST_SETTING=test_value\n"
assert.Equal(t, expected, buffer.String())
}
// captureOutput captures the output of a function call
func captureOutput(f func()) string {
var buf bytes.Buffer
stdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
f()
_ = w.Close()
os.Stdout = stdout
_, _ = buf.ReadFrom(r)
return buf.String()
}
// captureInput captures the input for a function call
func captureInput(input string) func() {
r, w, _ := os.Pipe()
_, _ = w.WriteString(input)
_ = w.Close()
stdin := os.Stdin
os.Stdin = r
return func() {
os.Stdin = stdin
}
}