mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-29 20:10:21 +00:00
319 lines
9.5 KiB
Go
319 lines
9.5 KiB
Go
package updates
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/config"
|
|
)
|
|
|
|
// mockGitHubReleases creates a test HTTP server that returns mock release data
|
|
// Handles both /releases (array) and /releases/latest (single object) endpoints
|
|
func mockGitHubReleases(releases []ReleaseInfo) *httptest.Server {
|
|
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
// Check if requesting /releases/latest
|
|
if r.URL.Path == "/repos/rcourtman/Pulse/releases/latest" {
|
|
// Return first non-prerelease as "latest"
|
|
for _, release := range releases {
|
|
if !release.Prerelease {
|
|
json.NewEncoder(w).Encode(release)
|
|
return
|
|
}
|
|
}
|
|
// No stable release found
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
// Return all releases for /releases endpoint
|
|
json.NewEncoder(w).Encode(releases)
|
|
}))
|
|
}
|
|
|
|
func TestRCUpdateNotifications(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
currentVersion string
|
|
releases []ReleaseInfo
|
|
expectedVersion string
|
|
expectUpdate bool
|
|
description string
|
|
}{
|
|
{
|
|
name: "RC user with newer RC available",
|
|
currentVersion: "4.22.0-rc.1",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.22.0-rc.3", Prerelease: true},
|
|
{TagName: "v4.22.0-rc.2", Prerelease: true},
|
|
{TagName: "v4.22.0-rc.1", Prerelease: true},
|
|
},
|
|
expectedVersion: "v4.22.0-rc.3",
|
|
expectUpdate: true,
|
|
description: "RC users should see newer RC releases",
|
|
},
|
|
{
|
|
name: "RC user with newer stable available",
|
|
currentVersion: "4.22.0-rc.3",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.22.0", Prerelease: false},
|
|
{TagName: "v4.22.0-rc.3", Prerelease: true},
|
|
{TagName: "v4.22.0-rc.2", Prerelease: true},
|
|
},
|
|
expectedVersion: "v4.22.0",
|
|
expectUpdate: true,
|
|
description: "RC users should see newer stable releases (stable > RC for same version)",
|
|
},
|
|
{
|
|
name: "RC user with both newer RC and stable (stable wins)",
|
|
currentVersion: "4.22.0-rc.1",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.23.0-rc.1", Prerelease: true},
|
|
{TagName: "v4.22.0", Prerelease: false},
|
|
{TagName: "v4.22.0-rc.2", Prerelease: true},
|
|
{TagName: "v4.22.0-rc.1", Prerelease: true},
|
|
},
|
|
expectedVersion: "v4.23.0-rc.1",
|
|
expectUpdate: true,
|
|
description: "When both RC and stable are available, return the highest version",
|
|
},
|
|
{
|
|
name: "RC user with only older releases",
|
|
currentVersion: "4.23.0-rc.1",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.22.0", Prerelease: false},
|
|
{TagName: "v4.22.0-rc.3", Prerelease: true},
|
|
},
|
|
expectedVersion: "v4.22.0",
|
|
expectUpdate: true, // Returns latest version even if not newer (Available will be false)
|
|
description: "Returns latest stable version even when user is on newer RC",
|
|
},
|
|
{
|
|
name: "RC user already on latest stable",
|
|
currentVersion: "4.22.0-rc.1",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.22.0", Prerelease: false},
|
|
{TagName: "v4.22.0-rc.1", Prerelease: true},
|
|
},
|
|
expectedVersion: "v4.22.0",
|
|
expectUpdate: true,
|
|
description: "RC user should see stable release even if RC number is same (4.22.0 > 4.22.0-rc.1)",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Setup mock GitHub API server
|
|
server := mockGitHubReleases(tt.releases)
|
|
defer server.Close()
|
|
|
|
// Set environment variable to use mock server
|
|
os.Setenv("PULSE_UPDATE_SERVER", server.URL)
|
|
defer os.Unsetenv("PULSE_UPDATE_SERVER")
|
|
|
|
// Create manager
|
|
cfg := &config.Config{UpdateChannel: "rc"}
|
|
manager := NewManager(cfg)
|
|
|
|
// Parse current version
|
|
currentVer, err := ParseVersion(tt.currentVersion)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse current version: %v", err)
|
|
}
|
|
|
|
// Check for updates
|
|
release, err := manager.getLatestReleaseForChannel(context.Background(), "rc", currentVer)
|
|
|
|
if tt.expectUpdate {
|
|
if err != nil {
|
|
t.Errorf("Expected update but got error: %v", err)
|
|
return
|
|
}
|
|
if release.TagName != tt.expectedVersion {
|
|
t.Errorf("Expected version %s but got %s. %s", tt.expectedVersion, release.TagName, tt.description)
|
|
}
|
|
} else {
|
|
if err == nil {
|
|
t.Errorf("Expected no update but got version %s. %s", release.TagName, tt.description)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestStableUpdateNotifications(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
currentVersion string
|
|
releases []ReleaseInfo
|
|
expectedVersion string
|
|
expectUpdate bool
|
|
description string
|
|
}{
|
|
{
|
|
name: "Stable user with newer stable available",
|
|
currentVersion: "4.21.0",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.22.0", Prerelease: false},
|
|
{TagName: "v4.21.0", Prerelease: false},
|
|
},
|
|
expectedVersion: "v4.22.0",
|
|
expectUpdate: true,
|
|
description: "Stable users should see newer stable releases",
|
|
},
|
|
{
|
|
name: "Stable user with only RC available",
|
|
currentVersion: "4.22.0",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.23.0-rc.1", Prerelease: true},
|
|
{TagName: "v4.22.0", Prerelease: false},
|
|
},
|
|
expectedVersion: "v4.22.0",
|
|
expectUpdate: true, // Returns latest stable version (Available will be false)
|
|
description: "Stable users get latest stable version, ignoring newer RCs",
|
|
},
|
|
{
|
|
name: "Stable user with mixed releases",
|
|
currentVersion: "4.21.0",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.23.0-rc.1", Prerelease: true},
|
|
{TagName: "v4.22.0", Prerelease: false},
|
|
{TagName: "v4.22.0-rc.3", Prerelease: true},
|
|
{TagName: "v4.21.0", Prerelease: false},
|
|
},
|
|
expectedVersion: "v4.22.0",
|
|
expectUpdate: true,
|
|
description: "Stable users should only see stable releases, ignoring RCs",
|
|
},
|
|
{
|
|
name: "Stable user already on latest",
|
|
currentVersion: "4.22.0",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.22.0", Prerelease: false},
|
|
{TagName: "v4.21.0", Prerelease: false},
|
|
},
|
|
expectedVersion: "v4.22.0",
|
|
expectUpdate: true, // Returns latest version even if already on it (Available will be false)
|
|
description: "Returns latest stable version even when already on it",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Setup mock GitHub API server
|
|
server := mockGitHubReleases(tt.releases)
|
|
defer server.Close()
|
|
|
|
// Set environment variable to use mock server
|
|
os.Setenv("PULSE_UPDATE_SERVER", server.URL)
|
|
defer os.Unsetenv("PULSE_UPDATE_SERVER")
|
|
|
|
// Create manager
|
|
cfg := &config.Config{UpdateChannel: "stable"}
|
|
manager := NewManager(cfg)
|
|
|
|
// Parse current version
|
|
currentVer, err := ParseVersion(tt.currentVersion)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse current version: %v", err)
|
|
}
|
|
|
|
// Check for updates
|
|
release, err := manager.getLatestReleaseForChannel(context.Background(), "stable", currentVer)
|
|
|
|
if tt.expectUpdate {
|
|
if err != nil {
|
|
t.Errorf("Expected update but got error: %v", err)
|
|
return
|
|
}
|
|
if release.TagName != tt.expectedVersion {
|
|
t.Errorf("Expected version %s but got %s. %s", tt.expectedVersion, release.TagName, tt.description)
|
|
}
|
|
} else {
|
|
if err == nil {
|
|
t.Errorf("Expected no update but got version %s. %s", release.TagName, tt.description)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVersionSemverOrdering(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
currentVersion string
|
|
releases []ReleaseInfo
|
|
expectedVersion string
|
|
description string
|
|
}{
|
|
{
|
|
name: "Stable release preferred over RC with same base version",
|
|
currentVersion: "4.22.0-rc.3",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.22.0", Prerelease: false},
|
|
{TagName: "v4.22.0-rc.3", Prerelease: true},
|
|
},
|
|
expectedVersion: "v4.22.0",
|
|
description: "4.22.0 should be > 4.22.0-rc.3 (stable > RC)",
|
|
},
|
|
{
|
|
name: "Higher RC number preferred",
|
|
currentVersion: "4.22.0-rc.1",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.22.0-rc.5", Prerelease: true},
|
|
{TagName: "v4.22.0-rc.3", Prerelease: true},
|
|
},
|
|
expectedVersion: "v4.22.0-rc.5",
|
|
description: "RC.5 should be > RC.3",
|
|
},
|
|
{
|
|
name: "Newer minor version preferred",
|
|
currentVersion: "4.21.0",
|
|
releases: []ReleaseInfo{
|
|
{TagName: "v4.22.0-rc.1", Prerelease: true},
|
|
{TagName: "v4.21.5", Prerelease: false},
|
|
},
|
|
expectedVersion: "v4.22.0-rc.1",
|
|
description: "For RC users, 4.22.0-rc.1 > 4.21.5 (minor version takes precedence)",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Setup mock GitHub API server
|
|
server := mockGitHubReleases(tt.releases)
|
|
defer server.Close()
|
|
|
|
// Set environment variable to use mock server
|
|
os.Setenv("PULSE_UPDATE_SERVER", server.URL)
|
|
defer os.Unsetenv("PULSE_UPDATE_SERVER")
|
|
|
|
// Create manager with RC channel (to see all releases)
|
|
cfg := &config.Config{UpdateChannel: "rc"}
|
|
manager := NewManager(cfg)
|
|
|
|
// Parse current version
|
|
currentVer, err := ParseVersion(tt.currentVersion)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse current version: %v", err)
|
|
}
|
|
|
|
// Check for updates
|
|
release, err := manager.getLatestReleaseForChannel(context.Background(), "rc", currentVer)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected update but got error: %v", err)
|
|
return
|
|
}
|
|
|
|
if release.TagName != tt.expectedVersion {
|
|
t.Errorf("Expected version %s but got %s. %s", tt.expectedVersion, release.TagName, tt.description)
|
|
}
|
|
})
|
|
}
|
|
}
|