Files
iris-context/root/update_test.go
T
VERSE 87b91c45d7 feat: update changelog (#131)
closes #130 

- CHANGELOG.md file for people who can view changelog from github
---
`iris changelog` command:
`iris changelog [version]` (e.g. iris changelog v0.5.1)
`iris changelog -n 3` (see changelog of 3 latest releaseas)

=> `iris changelog` looks just like CHANGELOG.md, grouped headers and
all. It only stops looking that way if we personally overwrite that
release's description with something else
=> With 1-hour local cache (invalidated on updater-channel change),
`--refresh` flag to bypass, graceful fallback to stale cache on GitHub
rate-limiting

---
- New auto update config
```toml
# 0 = off (default, notify only), 1 = auto-install, 2 = always confirm first
auto-update = 1
```

- New just debug-changelog and just debug-autoupdate recipes (fully
offline, mocked HTTP servers, no real network/config touched)
2026-08-07 17:16:18 +07:00

156 lines
4.5 KiB
Go

package root
import (
"io"
"os"
"path/filepath"
"strings"
"testing"
"time"
"github.com/versenilvis/iris/internal/config"
)
func TestIsNewer(t *testing.T) {
originalConfig := config.Get()
t.Cleanup(func() {
config.Init(originalConfig)
})
tests := []struct {
current string
latest string
channel string
want bool
}{
{"v1.0.0", "v1.0.1", "stable", true},
{"v1.0.1", "v1.0.0", "stable", false},
{"v1.0.0", "v1.0.0", "stable", false},
{"v1.2.3", "v1.2.4", "stable", true},
{"v1.2.0", "v1.1.9", "stable", false},
{"dev", "v1.0.0", "stable", false}, // dev never updates
{"v1.0.0", "dev", "stable", false},
{"", "v1.0.0", "stable", false},
{"v1.0.0", "v1.1.0-nightly.8cb1f47", "stable", false}, // nightly never triggers update
{"v1.1.0-nightly.abc", "v1.2.0", "stable", true}, // but if you are on nightly, you can update to stable
{"v1.1.0-nightly.abc", "v1.1.0-nightly.def", "nightly", true}, // nightly can update to newer nightly
{"v1.1.0-nightly.abc", "v1.1.0-nightly.abc", "nightly", false}, // same nightly is not newer
}
for _, tt := range tests {
t.Run(tt.current+"_"+tt.latest+"_"+tt.channel, func(t *testing.T) {
cfg := config.DefaultConfig()
cfg.Updater.Channel = tt.channel
config.Init(cfg)
if got := IsNewer(tt.current, tt.latest); got != tt.want {
t.Errorf("IsNewer(%q, %q, %q) = %v; want %v", tt.current, tt.latest, tt.channel, got, tt.want)
}
})
}
}
func TestUpdateState(t *testing.T) {
// Use a temporary directory for the state file
tmpDir, err := os.MkdirTemp("", "iris-test-*")
if err != nil {
t.Fatal(err)
}
defer func() { _ = os.RemoveAll(tmpDir) }()
t.Setenv("HOME", tmpDir)
t.Setenv("XDG_DATA_HOME", filepath.Join(tmpDir, ".local", "share"))
state := config.LoadState()
state.Updater.SeenVersion = "v1.0.0"
state.Updater.LastCheckTime = time.Unix(123456789, 0)
err = config.SaveState(state)
if err != nil {
t.Fatalf("failed to save state: %v", err)
}
loaded := config.LoadState()
if loaded.Updater.SeenVersion != state.Updater.SeenVersion {
t.Errorf("Expected SeenVersion %q, got %q", state.Updater.SeenVersion, loaded.Updater.SeenVersion)
}
if loaded.Updater.LastCheckTime.Unix() != state.Updater.LastCheckTime.Unix() {
t.Errorf("Expected LastCheck %v, got %v", state.Updater.LastCheckTime, loaded.Updater.LastCheckTime)
}
}
func TestChangelogSummaryLines(t *testing.T) {
body := "## Changelog\n### Bug fixes\n* abc1234 fix something\n* def5678 fix another thing\n* ghi9012 a third fix\n## Update\n```bash\niris update\n```\n"
got := changelogSummaryLines(body, 2)
want := []string{"fix something", "fix another thing"}
if len(got) != len(want) {
t.Fatalf("expected %d lines, got %d: %v", len(want), len(got), got)
}
for i, line := range want {
if got[i] != line {
t.Errorf("line %d: expected %q, got %q", i, line, got[i])
}
}
}
func TestChangelogSummaryLinesEmptyBody(t *testing.T) {
if got := changelogSummaryLines("", 2); len(got) != 0 {
t.Errorf("expected no lines for an empty body, got %v", got)
}
}
func TestPrintUpdateNoticeIncludesChangelogSummary(t *testing.T) {
originalVersion := Version
Version = "v1.0.0"
t.Cleanup(func() { Version = originalVersion })
r, w, err := os.Pipe()
if err != nil {
t.Fatalf("os.Pipe: %v", err)
}
originalStdout := os.Stdout
os.Stdout = w
printUpdateNotice("v1.1.0", "## Changelog\n### Bug fixes\n* abc1234 fix something\n* def5678 fix another thing\n* ghi9012 a third fix\n")
_ = w.Close()
os.Stdout = originalStdout
out, _ := io.ReadAll(r)
got := string(out)
if !strings.Contains(got, "v1.0.0") || !strings.Contains(got, "v1.1.0") {
t.Errorf("expected the version transition in the notice, got %q", got)
}
if !strings.Contains(got, "fix something") || !strings.Contains(got, "fix another thing") {
t.Errorf("expected the first two changelog entries in the notice, got %q", got)
}
if strings.Contains(got, "a third fix") {
t.Errorf("expected the summary to cap at 2 entries, got %q", got)
}
}
func TestPrintUpdateNoticeWithoutNotes(t *testing.T) {
originalVersion := Version
Version = "v1.0.0"
t.Cleanup(func() { Version = originalVersion })
r, w, err := os.Pipe()
if err != nil {
t.Fatalf("os.Pipe: %v", err)
}
originalStdout := os.Stdout
os.Stdout = w
printUpdateNotice("v1.1.0", "")
_ = w.Close()
os.Stdout = originalStdout
out, _ := io.ReadAll(r)
got := string(out)
if !strings.Contains(got, "v1.1.0") {
t.Errorf("expected the notice to still show without changelog notes, got %q", got)
}
}