pluginctl/info_test.go
Felipe Martin 873bf78c22
Add custom parser for props["pluginctl"] with ignore assets support
- Add PluginCtlConfig struct with IgnoreAssets field for glob patterns
- Add ParsePluginCtlConfig function to parse manifest props["pluginctl"]
- Update updateassets command to respect ignore patterns with glob matching
- Add comprehensive logging when files are skipped due to ignore patterns
- Support patterns like *.test.js, build/, node_modules for flexible exclusion
- Add extensive tests for config parsing and path matching functionality
- Maintain backward compatibility with existing manifests
- Fix Makefile check-changes target and add logger init to tests

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-14 17:38:38 +02:00

325 lines
7.4 KiB
Go

package pluginctl
import (
"bytes"
"io"
"os"
"strings"
"testing"
"github.com/mattermost/mattermost/server/public/model"
)
func TestPrintPluginInfo(t *testing.T) {
tests := []struct {
name string
manifest *model.Manifest
expected []string
}{
{
name: "Complete plugin with all features",
manifest: &model.Manifest{
Id: "com.example.testplugin",
Name: "Test Plugin",
Version: "1.0.0",
MinServerVersion: "7.0.0",
Description: "A test plugin for unit testing",
Server: &model.ManifestServer{
Executables: map[string]string{
"linux-amd64": "server/dist/plugin-linux-amd64",
"darwin-amd64": "server/dist/plugin-darwin-amd64",
"windows-amd64": "server/dist/plugin-windows-amd64.exe",
},
},
Webapp: &model.ManifestWebapp{
BundlePath: "webapp/dist/main.js",
},
SettingsSchema: &model.PluginSettingsSchema{
Header: "Test Settings",
},
},
expected: []string{
"Plugin Information:",
"ID: com.example.testplugin",
"Name: Test Plugin",
"Version: 1.0.0",
"Min MM Version: 7.0.0",
"Description: A test plugin for unit testing",
"Code Components:",
"Server Code: Yes",
"linux-amd64",
"darwin-amd64",
"windows-amd64",
"Webapp Code: Yes",
"Bundle Path: webapp/dist/main.js",
"Settings Schema: Yes",
},
},
{
name: "Minimal plugin with no optional fields",
manifest: &model.Manifest{
Id: "com.example.minimal",
Name: "Minimal Plugin",
Version: "0.1.0",
},
expected: []string{
"Plugin Information:",
"ID: com.example.minimal",
"Name: Minimal Plugin",
"Version: 0.1.0",
"Min MM Version: Not specified",
"Code Components:",
"Server Code: No",
"Webapp Code: No",
"Settings Schema: No",
},
},
{
name: "Plugin with server code only",
manifest: &model.Manifest{
Id: "com.example.serveronly",
Name: "Server Only Plugin",
Version: "2.0.0",
MinServerVersion: "8.0.0",
Server: &model.ManifestServer{
Executables: map[string]string{
"linux-amd64": "server/plugin",
},
},
},
expected: []string{
"Plugin Information:",
"ID: com.example.serveronly",
"Name: Server Only Plugin",
"Version: 2.0.0",
"Min MM Version: 8.0.0",
"Server Code: Yes",
"linux-amd64",
"Webapp Code: No",
"Settings Schema: No",
},
},
{
name: "Plugin with webapp code only",
manifest: &model.Manifest{
Id: "com.example.webapponly",
Name: "Webapp Only Plugin",
Version: "1.5.0",
Webapp: &model.ManifestWebapp{
BundlePath: "dist/bundle.js",
},
},
expected: []string{
"Plugin Information:",
"ID: com.example.webapponly",
"Name: Webapp Only Plugin",
"Version: 1.5.0",
"Min MM Version: Not specified",
"Server Code: No",
"Webapp Code: Yes",
"Bundle Path: dist/bundle.js",
"Settings Schema: No",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Initialize logger for testing
InitLogger()
// Capture stdout
oldStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
// Run the function
err := PrintPluginInfo(tt.manifest)
if err != nil {
t.Fatalf("PrintPluginInfo returned error: %v", err)
}
// Restore stdout and get output
w.Close()
os.Stdout = oldStdout
output, _ := io.ReadAll(r)
outputStr := string(output)
// Check that all expected strings are present
for _, expected := range tt.expected {
if !strings.Contains(outputStr, expected) {
t.Errorf("Expected output to contain %q, but it didn't.\nOutput:\n%s", expected, outputStr)
}
}
})
}
}
func TestHasServerCode(t *testing.T) {
tests := []struct {
name string
manifest *model.Manifest
expected bool
}{
{
name: "Plugin with server executables",
manifest: &model.Manifest{
Server: &model.ManifestServer{
Executables: map[string]string{
"linux-amd64": "server/plugin",
},
},
},
expected: true,
},
{
name: "Plugin with empty server executables",
manifest: &model.Manifest{
Server: &model.ManifestServer{
Executables: map[string]string{},
},
},
expected: false,
},
{
name: "Plugin with nil server",
manifest: &model.Manifest{
Server: nil,
},
expected: false,
},
{
name: "Plugin with no server field",
manifest: &model.Manifest{},
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := HasServerCode(tt.manifest)
if result != tt.expected {
t.Errorf("hasServerCode() = %v, expected %v", result, tt.expected)
}
})
}
}
func TestHasWebappCode(t *testing.T) {
tests := []struct {
name string
manifest *model.Manifest
expected bool
}{
{
name: "Plugin with webapp bundle",
manifest: &model.Manifest{
Webapp: &model.ManifestWebapp{
BundlePath: "webapp/dist/main.js",
},
},
expected: true,
},
{
name: "Plugin with empty webapp bundle path",
manifest: &model.Manifest{
Webapp: &model.ManifestWebapp{
BundlePath: "",
},
},
expected: false,
},
{
name: "Plugin with nil webapp",
manifest: &model.Manifest{
Webapp: nil,
},
expected: false,
},
{
name: "Plugin with no webapp field",
manifest: &model.Manifest{},
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := HasWebappCode(tt.manifest)
if result != tt.expected {
t.Errorf("hasWebappCode() = %v, expected %v", result, tt.expected)
}
})
}
}
func TestInfoCommandWithPath_InvalidPath(t *testing.T) {
// Test with non-existent directory
err := InfoCommandWithPath("/non/existent/path")
if err == nil {
t.Error("Expected error for non-existent path, but got nil")
}
expectedErrMsg := "plugin.json not found"
if !strings.Contains(err.Error(), expectedErrMsg) {
t.Errorf("Expected error to contain %q, but got: %v", expectedErrMsg, err)
}
}
// captureOutput captures stdout during function execution
func captureOutput(fn func()) string {
oldStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
fn()
w.Close()
os.Stdout = oldStdout
var buf bytes.Buffer
io.Copy(&buf, r)
return buf.String()
}
func TestPrintPluginInfo_OutputFormat(t *testing.T) {
manifest := &model.Manifest{
Id: "test.plugin",
Name: "Test Plugin",
Version: "1.0.0",
}
output := captureOutput(func() {
PrintPluginInfo(manifest)
})
// Check for proper formatting
// Should have header separators
if !strings.Contains(output, "==================") {
t.Error("Output should contain header separators")
}
// Should have proper sections
if !strings.Contains(output, "Plugin Information:") {
t.Error("Output should contain 'Plugin Information:' header")
}
if !strings.Contains(output, "Code Components:") {
t.Error("Output should contain 'Code Components:' header")
}
// Should have proper field formatting
expectedFields := []string{
"ID: test.plugin",
"Name: Test Plugin",
"Version: 1.0.0",
}
for _, field := range expectedFields {
if !strings.Contains(output, field) {
t.Errorf("Output should contain field: %q", field)
}
}
}