mirror of
https://github.com/lukaszraczylo/claude-mnemonic.git
synced 2026-06-05 23:03:55 +00:00
193 lines
5.0 KiB
Go
193 lines
5.0 KiB
Go
// Package hooks provides hook utilities for claude-mnemonic.
|
|
package hooks
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestGetWorkerPort(t *testing.T) {
|
|
// Test default port
|
|
port := GetWorkerPort()
|
|
assert.Equal(t, DefaultWorkerPort, port)
|
|
|
|
// Test with environment variable
|
|
t.Setenv("CLAUDE_MNEMONIC_WORKER_PORT", "12345")
|
|
port = GetWorkerPort()
|
|
assert.Equal(t, 12345, port)
|
|
|
|
// Test with invalid environment variable (should return default)
|
|
t.Setenv("CLAUDE_MNEMONIC_WORKER_PORT", "invalid")
|
|
port = GetWorkerPort()
|
|
assert.Equal(t, DefaultWorkerPort, port)
|
|
}
|
|
|
|
func TestIsWorkerRunning(t *testing.T) {
|
|
// Create a test server that responds to health checks
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path == "/api/health" {
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(map[string]string{"status": "ready"})
|
|
} else {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Extract port from test server URL
|
|
// Note: In real tests we'd use the actual port, but test server uses random port
|
|
// So we test with a non-existent port
|
|
assert.False(t, IsWorkerRunning(99999)) // Non-existent port
|
|
}
|
|
|
|
func TestIsPortInUse(t *testing.T) {
|
|
// Create a test server to occupy a port
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Non-existent port should not be in use
|
|
assert.False(t, IsPortInUse(99999))
|
|
}
|
|
|
|
func TestGetWorkerVersion(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
serverResponse func(w http.ResponseWriter, r *http.Request)
|
|
expectedResult string
|
|
}{
|
|
{
|
|
name: "returns version from server",
|
|
serverResponse: func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path == "/api/version" {
|
|
json.NewEncoder(w).Encode(map[string]string{"version": "1.2.3"})
|
|
}
|
|
},
|
|
expectedResult: "1.2.3",
|
|
},
|
|
{
|
|
name: "returns empty on 404",
|
|
serverResponse: func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
},
|
|
expectedResult: "",
|
|
},
|
|
{
|
|
name: "returns empty on invalid JSON",
|
|
serverResponse: func(w http.ResponseWriter, r *http.Request) {
|
|
w.Write([]byte("not json"))
|
|
},
|
|
expectedResult: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(tt.serverResponse))
|
|
defer server.Close()
|
|
|
|
// We can't easily test with the actual function since it uses a hardcoded localhost
|
|
// But we can verify the logic works with the test server
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestProjectIDWithName(t *testing.T) {
|
|
tests := []struct {
|
|
cwd string
|
|
expected string
|
|
}{
|
|
{
|
|
cwd: "/Users/test/projects/my-project",
|
|
expected: "my-project_", // Will have hash suffix
|
|
},
|
|
{
|
|
cwd: "/tmp",
|
|
expected: "tmp_",
|
|
},
|
|
{
|
|
cwd: "/",
|
|
expected: "", // Empty dirname
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.cwd, func(t *testing.T) {
|
|
result := ProjectIDWithName(tt.cwd)
|
|
if tt.expected != "" {
|
|
assert.Contains(t, result, tt.expected[:len(tt.expected)-1]) // Check prefix before underscore
|
|
assert.Contains(t, result, "_") // Should have underscore separator
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVersionMatching(t *testing.T) {
|
|
// Test that version matching logic works correctly
|
|
tests := []struct {
|
|
name string
|
|
runningVersion string
|
|
hookVersion string
|
|
shouldRestart bool
|
|
}{
|
|
{
|
|
name: "matching versions",
|
|
runningVersion: "1.0.0",
|
|
hookVersion: "1.0.0",
|
|
shouldRestart: false,
|
|
},
|
|
{
|
|
name: "mismatched versions",
|
|
runningVersion: "1.0.0",
|
|
hookVersion: "2.0.0",
|
|
shouldRestart: true,
|
|
},
|
|
{
|
|
name: "dirty vs clean",
|
|
runningVersion: "1.0.0",
|
|
hookVersion: "1.0.0-dirty",
|
|
shouldRestart: true,
|
|
},
|
|
{
|
|
name: "empty running version",
|
|
runningVersion: "",
|
|
hookVersion: "1.0.0",
|
|
shouldRestart: false, // Can't determine, don't restart
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Simulate the version check logic
|
|
shouldRestart := false
|
|
if tt.runningVersion != "" && tt.runningVersion != tt.hookVersion {
|
|
shouldRestart = true
|
|
}
|
|
assert.Equal(t, tt.shouldRestart, shouldRestart)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestKillProcessOnPort_NoProcess(t *testing.T) {
|
|
// Test killing a process on a port that has no process
|
|
// Should not error, just return nil
|
|
err := KillProcessOnPort(99999) // Port unlikely to be in use
|
|
// lsof will return empty/error, which is fine
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestFindWorkerBinary(t *testing.T) {
|
|
// Test that findWorkerBinary returns empty string when binary not found
|
|
// This is hard to test without mocking the filesystem
|
|
// But we can verify it doesn't panic
|
|
result := findWorkerBinary()
|
|
// Result depends on whether worker is installed, so we just check it doesn't panic
|
|
t.Logf("findWorkerBinary returned: %s", result)
|
|
}
|