Refactoring complete: v0.4.0 architectural milestone (#1)
## Summary Completed Phase 5 refactoring and reached the target architecture. **Architectural milestone achieved:** - Service layer owns all state and is the sole writer - UI is a thin Fyne view, all widget updates marshaled via `fyne.Do` - Core engines are stateless and injectable - Domain types are pure (no `yaml:"-"` fields) - Full module builds and `go vet ./...` clean ## Changes - Bump version: 0.3.6 → 0.4.0 - Update CHANGELOG with Phase 5 summary - Add ROADMAP "Refactoring Follow-Ups" section ## Known follow-up work 1. **Linux test build broken** — `runner_test.go` needs `//go:build windows` tag 2. **File-size limits exceeded** — `operations.go` (486 lines), `jobs_view.go` (415 lines) See ROADMAP.md for details. --------- Co-authored-by: mixeme <mix.public@ya.ru> Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gitea.mixdep.ru/mix/gosentry/src/domain"
|
||||
"gitea.mixdep.ru/mix/gosentry/src/storage"
|
||||
)
|
||||
|
||||
func newTestService(jobs []domain.Job) *Service {
|
||||
return NewService(&storage.Store{}, jobs)
|
||||
}
|
||||
|
||||
func TestNewServiceBuildsRuntimePerJob(t *testing.T) {
|
||||
jobs := []domain.Job{
|
||||
{ID: 1, Name: "Enabled", Enabled: true},
|
||||
{ID: 2, Name: "Disabled", Enabled: false},
|
||||
}
|
||||
svc := newTestService(jobs)
|
||||
|
||||
if got := svc.Runtime(1); got == nil {
|
||||
t.Fatal("expected runtime for enabled job 1")
|
||||
} else if got.LastState != "Ready" {
|
||||
t.Errorf("enabled job runtime state = %q, want %q", got.LastState, "Ready")
|
||||
}
|
||||
if got := svc.Runtime(2); got == nil {
|
||||
t.Fatal("expected runtime for disabled job 2")
|
||||
} else if got.LastState != "Paused" {
|
||||
t.Errorf("disabled job runtime state = %q, want %q", got.LastState, "Paused")
|
||||
}
|
||||
if got := svc.Runtime(99); got != nil {
|
||||
t.Errorf("expected nil runtime for unknown job, got %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJobsReturnsCopy(t *testing.T) {
|
||||
jobs := []domain.Job{{ID: 1, Name: "Original"}}
|
||||
svc := newTestService(jobs)
|
||||
|
||||
snapshot := svc.Jobs()
|
||||
if len(snapshot) != 1 {
|
||||
t.Fatalf("Jobs() len = %d, want 1", len(snapshot))
|
||||
}
|
||||
// Mutating the returned slice must not affect Service-owned state.
|
||||
snapshot[0].Name = "Mutated"
|
||||
if again := svc.Jobs(); again[0].Name != "Original" {
|
||||
t.Errorf("Service state leaked through Jobs(): name = %q, want %q", again[0].Name, "Original")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreReturnsWiredStore(t *testing.T) {
|
||||
store := &storage.Store{}
|
||||
svc := NewService(store, nil)
|
||||
if svc.Store() != store {
|
||||
t.Error("Store() did not return the wired store")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user