cli/runtime_pkg_test.go
Snider 35400ee927 fix(runtime): Correct NewWithFactories service creation loop (#30)
Previously, the `NewWithFactories` function in `runtime_pkg.go` iterated over an empty slice, which prevented any services from being created from the provided factories. This commit fixes the loop to correctly iterate over the keys of the `factories` map, ensuring that services are properly instantiated and registered.

feat(testing): Add Good, Bad, and Ugly tests for NewWithFactories

To improve test quality and ensure the reliability of the `NewWithFactories` function, this commit replaces the existing basic test with a comprehensive test suite following the Good, Bad, Ugly methodology:

- `TestNewWithFactories_Good`: Verifies the happy path, ensuring a service is created and registered successfully.
- `TestNewWithFactories_Bad`: Checks that the function correctly returns an error when a service factory fails.
- `TestNewWithFactories_Ugly`: Confirms that the function panics when a `nil` factory is provided, as this represents an unrecoverable programmer error.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2025-11-13 21:23:56 +00:00

128 lines
2.9 KiB
Go

package core
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/wailsapp/wails/v3/pkg/application"
)
func TestNewRuntime(t *testing.T) {
testCases := []struct {
name string
app *application.App
factories map[string]ServiceFactory
expectErr bool
expectErrStr string
checkRuntime func(*testing.T, *Runtime)
}{
{
name: "Good path",
app: nil,
factories: map[string]ServiceFactory{},
expectErr: false,
checkRuntime: func(t *testing.T, rt *Runtime) {
assert.NotNil(t, rt)
assert.NotNil(t, rt.Core)
},
},
{
name: "With non-nil app",
app: &application.App{},
factories: map[string]ServiceFactory{},
expectErr: false,
checkRuntime: func(t *testing.T, rt *Runtime) {
assert.NotNil(t, rt)
assert.NotNil(t, rt.Core)
assert.NotNil(t, rt.Core.App)
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
rt, err := NewRuntime(tc.app)
if tc.expectErr {
assert.Error(t, err)
assert.Contains(t, err.Error(), tc.expectErrStr)
assert.Nil(t, rt)
} else {
assert.NoError(t, err)
if tc.checkRuntime != nil {
tc.checkRuntime(t, rt)
}
}
})
}
}
func TestNewWithFactories_Good(t *testing.T) {
factories := map[string]ServiceFactory{
"test": func() (any, error) {
return &MockService{Name: "test"}, nil
},
}
rt, err := NewWithFactories(nil, factories)
assert.NoError(t, err)
assert.NotNil(t, rt)
svc := rt.Core.Service("test")
assert.NotNil(t, svc)
mockSvc, ok := svc.(*MockService)
assert.True(t, ok)
assert.Equal(t, "test", mockSvc.Name)
}
func TestNewWithFactories_Bad(t *testing.T) {
factories := map[string]ServiceFactory{
"test": func() (any, error) {
return nil, assert.AnError
},
}
_, err := NewWithFactories(nil, factories)
assert.Error(t, err)
assert.ErrorIs(t, err, assert.AnError)
}
func TestNewWithFactories_Ugly(t *testing.T) {
factories := map[string]ServiceFactory{
"test": nil,
}
assert.Panics(t, func() {
_, _ = NewWithFactories(nil, factories)
})
}
func TestRuntime_Lifecycle_Good(t *testing.T) {
rt, err := NewRuntime(nil)
assert.NoError(t, err)
assert.NotNil(t, rt)
// ServiceName
assert.Equal(t, "Core", rt.ServiceName())
// ServiceStartup & ServiceShutdown
// These are simple wrappers around the core methods, which are tested in core_test.go.
// We call them here to ensure coverage.
rt.ServiceStartup(nil, application.ServiceOptions{})
rt.ServiceShutdown(nil)
// Test shutdown with nil core
rt.Core = nil
rt.ServiceShutdown(nil)
}
func TestNewServiceRuntime_Good(t *testing.T) {
c, err := New()
assert.NoError(t, err)
sr := NewServiceRuntime(c, "test options")
assert.NotNil(t, sr)
assert.Equal(t, c, sr.Core())
// We can't directly test sr.Config() without a registered config service,
// but we can ensure it doesn't panic. We'll test the panic case separately.
assert.Panics(t, func() {
sr.Config()
})
}