mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 22:55:48 +01:00
* test(v3): add comprehensive unit tests for pkg/application Add 11 new test files to improve test coverage of the pkg/application package from 13.6% to 17.7%. New test files: - context_test.go: Context struct operations - services_test.go: Service management and lifecycle - parameter_test.go: Parameter and CallError types - dialogs_test.go: Dialog utilities and button methods - webview_window_options_test.go: Window options and constants - application_options_test.go: ChainMiddleware and app config - keys_test.go: Keyboard accelerator parsing - single_instance_test.go: Single instance management and encryption - menuitem_internal_test.go: Menu item internal functions - menu_internal_test.go: Menu internal functions - screenmanager_internal_test.go: Screen geometry and transformations The 40% target was not fully achievable because ~50% of the codebase is platform-specific code that can only be tested on respective platforms. Tests focus on pure Go logic, utility functions, and data structures that can be tested cross-platform. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address CodeRabbit review comments - dialogs_test.go: improve ID recycling test to verify either recycled ID (id3 == id1) or new unique ID (id3 > id2) - keys_test.go: make accelerator String() tests platform-agnostic by checking suffix patterns rather than exact platform-specific strings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: normalize temp dir path for macOS compatibility in test os.TempDir() returns a trailing slash on macOS, causing path comparison to fail. Use filepath.Clean() to normalize both paths. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: remove REVIEW.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: simplify changelog entry 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
203 lines
5.2 KiB
Go
203 lines
5.2 KiB
Go
package application
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
)
|
|
|
|
// Test service implementations
|
|
type testService struct {
|
|
name string
|
|
}
|
|
|
|
func (s *testService) ServiceName() string {
|
|
return s.name
|
|
}
|
|
|
|
type testServiceWithStartup struct {
|
|
started bool
|
|
}
|
|
|
|
func (s *testServiceWithStartup) ServiceStartup(ctx context.Context, options ServiceOptions) error {
|
|
s.started = true
|
|
return nil
|
|
}
|
|
|
|
type testServiceWithShutdown struct {
|
|
shutdown bool
|
|
}
|
|
|
|
func (s *testServiceWithShutdown) ServiceShutdown() error {
|
|
s.shutdown = true
|
|
return nil
|
|
}
|
|
|
|
type testServiceNoInterface struct {
|
|
value int
|
|
}
|
|
|
|
func TestNewService(t *testing.T) {
|
|
svc := &testService{name: "test"}
|
|
service := NewService(svc)
|
|
|
|
if service.instance == nil {
|
|
t.Error("NewService should set instance")
|
|
}
|
|
if service.Instance() != svc {
|
|
t.Error("Instance() should return the original service")
|
|
}
|
|
}
|
|
|
|
func TestNewServiceWithOptions(t *testing.T) {
|
|
svc := &testService{name: "original"}
|
|
opts := ServiceOptions{
|
|
Name: "custom-name",
|
|
Route: "/api",
|
|
}
|
|
service := NewServiceWithOptions(svc, opts)
|
|
|
|
if service.Instance() != svc {
|
|
t.Error("Instance() should return the original service")
|
|
}
|
|
if service.options.Name != "custom-name" {
|
|
t.Errorf("options.Name = %q, want %q", service.options.Name, "custom-name")
|
|
}
|
|
if service.options.Route != "/api" {
|
|
t.Errorf("options.Route = %q, want %q", service.options.Route, "/api")
|
|
}
|
|
}
|
|
|
|
func TestGetServiceName_FromOptions(t *testing.T) {
|
|
svc := &testService{name: "service-name"}
|
|
opts := ServiceOptions{Name: "options-name"}
|
|
service := NewServiceWithOptions(svc, opts)
|
|
|
|
name := getServiceName(service)
|
|
if name != "options-name" {
|
|
t.Errorf("getServiceName() = %q, want %q (options takes precedence)", name, "options-name")
|
|
}
|
|
}
|
|
|
|
func TestGetServiceName_FromInterface(t *testing.T) {
|
|
svc := &testService{name: "interface-name"}
|
|
service := NewService(svc)
|
|
|
|
name := getServiceName(service)
|
|
if name != "interface-name" {
|
|
t.Errorf("getServiceName() = %q, want %q (from interface)", name, "interface-name")
|
|
}
|
|
}
|
|
|
|
func TestGetServiceName_FromType(t *testing.T) {
|
|
svc := &testServiceNoInterface{value: 42}
|
|
service := NewService(svc)
|
|
|
|
name := getServiceName(service)
|
|
// Should contain the type name
|
|
if name == "" {
|
|
t.Error("getServiceName() should return type name for services without ServiceName interface")
|
|
}
|
|
// The name should contain "testServiceNoInterface"
|
|
expected := "application.testServiceNoInterface"
|
|
if name != expected {
|
|
t.Errorf("getServiceName() = %q, want %q", name, expected)
|
|
}
|
|
}
|
|
|
|
func TestService_Instance(t *testing.T) {
|
|
svc := &testService{name: "test"}
|
|
service := NewService(svc)
|
|
|
|
instance := service.Instance()
|
|
if instance == nil {
|
|
t.Error("Instance() should not return nil")
|
|
}
|
|
|
|
// Type assertion to verify it's the correct type
|
|
if _, ok := instance.(*testService); !ok {
|
|
t.Error("Instance() should return the correct type")
|
|
}
|
|
}
|
|
|
|
func TestDefaultServiceOptions(t *testing.T) {
|
|
// Verify DefaultServiceOptions is zero-valued
|
|
if DefaultServiceOptions.Name != "" {
|
|
t.Errorf("DefaultServiceOptions.Name should be empty, got %q", DefaultServiceOptions.Name)
|
|
}
|
|
if DefaultServiceOptions.Route != "" {
|
|
t.Errorf("DefaultServiceOptions.Route should be empty, got %q", DefaultServiceOptions.Route)
|
|
}
|
|
if DefaultServiceOptions.MarshalError != nil {
|
|
t.Error("DefaultServiceOptions.MarshalError should be nil")
|
|
}
|
|
}
|
|
|
|
func TestNewService_UsesDefaultOptions(t *testing.T) {
|
|
svc := &testService{name: "test"}
|
|
service := NewService(svc)
|
|
|
|
// Service created with NewService should use DefaultServiceOptions
|
|
if service.options.Name != DefaultServiceOptions.Name {
|
|
t.Error("NewService should use DefaultServiceOptions")
|
|
}
|
|
}
|
|
|
|
func TestServiceOptions_WithMarshalError(t *testing.T) {
|
|
customMarshal := func(err error) []byte {
|
|
return []byte(`{"error": "custom"}`)
|
|
}
|
|
|
|
svc := &testService{name: "test"}
|
|
opts := ServiceOptions{
|
|
MarshalError: customMarshal,
|
|
}
|
|
service := NewServiceWithOptions(svc, opts)
|
|
|
|
if service.options.MarshalError == nil {
|
|
t.Error("MarshalError should be set")
|
|
}
|
|
|
|
result := service.options.MarshalError(nil)
|
|
expected := `{"error": "custom"}`
|
|
if string(result) != expected {
|
|
t.Errorf("MarshalError result = %q, want %q", string(result), expected)
|
|
}
|
|
}
|
|
|
|
func TestServiceStartupInterface(t *testing.T) {
|
|
svc := &testServiceWithStartup{}
|
|
service := NewService(svc)
|
|
|
|
// Verify the service implements ServiceStartup
|
|
instance := service.Instance()
|
|
if startup, ok := instance.(ServiceStartup); ok {
|
|
err := startup.ServiceStartup(context.Background(), ServiceOptions{})
|
|
if err != nil {
|
|
t.Errorf("ServiceStartup returned error: %v", err)
|
|
}
|
|
if !svc.started {
|
|
t.Error("ServiceStartup should have been called")
|
|
}
|
|
} else {
|
|
t.Error("testServiceWithStartup should implement ServiceStartup")
|
|
}
|
|
}
|
|
|
|
func TestServiceShutdownInterface(t *testing.T) {
|
|
svc := &testServiceWithShutdown{}
|
|
service := NewService(svc)
|
|
|
|
// Verify the service implements ServiceShutdown
|
|
instance := service.Instance()
|
|
if shutdown, ok := instance.(ServiceShutdown); ok {
|
|
err := shutdown.ServiceShutdown()
|
|
if err != nil {
|
|
t.Errorf("ServiceShutdown returned error: %v", err)
|
|
}
|
|
if !svc.shutdown {
|
|
t.Error("ServiceShutdown should have been called")
|
|
}
|
|
} else {
|
|
t.Error("testServiceWithShutdown should implement ServiceShutdown")
|
|
}
|
|
}
|