mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +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>
223 lines
5.1 KiB
Go
223 lines
5.1 KiB
Go
package application
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestGetDialogID(t *testing.T) {
|
|
// Get first dialog ID
|
|
id1 := getDialogID()
|
|
|
|
// Get second dialog ID - should be different
|
|
id2 := getDialogID()
|
|
if id1 == id2 {
|
|
t.Error("getDialogID should return unique IDs")
|
|
}
|
|
|
|
// Free first ID
|
|
freeDialogID(id1)
|
|
|
|
// Get another ID - should recycle the freed id1 or be unique from id2
|
|
id3 := getDialogID()
|
|
if id3 == id2 {
|
|
t.Error("getDialogID should not return the same ID as an active dialog")
|
|
}
|
|
// Verify recycling behavior: id3 should either be id1 (recycled) or a new unique ID
|
|
if id3 != id1 && id3 <= id2 {
|
|
t.Errorf("getDialogID returned unexpected ID: got %d, expected recycled %d or new > %d", id3, id1, id2)
|
|
}
|
|
|
|
// Cleanup
|
|
freeDialogID(id2)
|
|
freeDialogID(id3)
|
|
}
|
|
|
|
func TestFreeDialogID(t *testing.T) {
|
|
id := getDialogID()
|
|
freeDialogID(id)
|
|
|
|
// Should be able to get the same ID again after freeing
|
|
newID := getDialogID()
|
|
freeDialogID(newID)
|
|
// Just verify it doesn't panic
|
|
}
|
|
|
|
func TestButton_OnClick(t *testing.T) {
|
|
button := &Button{Label: "Test"}
|
|
called := false
|
|
|
|
result := button.OnClick(func() {
|
|
called = true
|
|
})
|
|
|
|
// Should return the same button for chaining
|
|
if result != button {
|
|
t.Error("OnClick should return the same button")
|
|
}
|
|
|
|
// Callback should be set
|
|
if button.Callback == nil {
|
|
t.Error("Callback should be set")
|
|
}
|
|
|
|
// Call the callback
|
|
button.Callback()
|
|
if !called {
|
|
t.Error("Callback should have been called")
|
|
}
|
|
}
|
|
|
|
func TestButton_SetAsDefault(t *testing.T) {
|
|
button := &Button{Label: "Test"}
|
|
|
|
result := button.SetAsDefault()
|
|
|
|
// Should return the same button for chaining
|
|
if result != button {
|
|
t.Error("SetAsDefault should return the same button")
|
|
}
|
|
|
|
if !button.IsDefault {
|
|
t.Error("IsDefault should be true")
|
|
}
|
|
}
|
|
|
|
func TestButton_SetAsCancel(t *testing.T) {
|
|
button := &Button{Label: "Test"}
|
|
|
|
result := button.SetAsCancel()
|
|
|
|
// Should return the same button for chaining
|
|
if result != button {
|
|
t.Error("SetAsCancel should return the same button")
|
|
}
|
|
|
|
if !button.IsCancel {
|
|
t.Error("IsCancel should be true")
|
|
}
|
|
}
|
|
|
|
func TestButton_Chaining(t *testing.T) {
|
|
button := &Button{Label: "OK"}
|
|
|
|
button.SetAsDefault().SetAsCancel().OnClick(func() {})
|
|
|
|
if !button.IsDefault {
|
|
t.Error("IsDefault should be true after chaining")
|
|
}
|
|
if !button.IsCancel {
|
|
t.Error("IsCancel should be true after chaining")
|
|
}
|
|
if button.Callback == nil {
|
|
t.Error("Callback should be set after chaining")
|
|
}
|
|
}
|
|
|
|
func TestDialogType_Constants(t *testing.T) {
|
|
// Verify dialog type constants are distinct
|
|
types := []DialogType{InfoDialogType, QuestionDialogType, WarningDialogType, ErrorDialogType}
|
|
seen := make(map[DialogType]bool)
|
|
|
|
for _, dt := range types {
|
|
if seen[dt] {
|
|
t.Errorf("DialogType %d is duplicated", dt)
|
|
}
|
|
seen[dt] = true
|
|
}
|
|
}
|
|
|
|
func TestMessageDialogOptions_Fields(t *testing.T) {
|
|
opts := MessageDialogOptions{
|
|
DialogType: InfoDialogType,
|
|
Title: "Test Title",
|
|
Message: "Test Message",
|
|
Buttons: []*Button{{Label: "OK"}},
|
|
Icon: []byte{1, 2, 3},
|
|
}
|
|
|
|
if opts.DialogType != InfoDialogType {
|
|
t.Error("DialogType not set correctly")
|
|
}
|
|
if opts.Title != "Test Title" {
|
|
t.Error("Title not set correctly")
|
|
}
|
|
if opts.Message != "Test Message" {
|
|
t.Error("Message not set correctly")
|
|
}
|
|
if len(opts.Buttons) != 1 {
|
|
t.Error("Buttons not set correctly")
|
|
}
|
|
if len(opts.Icon) != 3 {
|
|
t.Error("Icon not set correctly")
|
|
}
|
|
}
|
|
|
|
func TestFileFilter_Fields(t *testing.T) {
|
|
filter := FileFilter{
|
|
DisplayName: "Image Files (*.jpg, *.png)",
|
|
Pattern: "*.jpg;*.png",
|
|
}
|
|
|
|
if filter.DisplayName != "Image Files (*.jpg, *.png)" {
|
|
t.Error("DisplayName not set correctly")
|
|
}
|
|
if filter.Pattern != "*.jpg;*.png" {
|
|
t.Error("Pattern not set correctly")
|
|
}
|
|
}
|
|
|
|
func TestOpenFileDialogOptions_Fields(t *testing.T) {
|
|
opts := OpenFileDialogOptions{
|
|
CanChooseDirectories: true,
|
|
CanChooseFiles: true,
|
|
CanCreateDirectories: true,
|
|
ShowHiddenFiles: true,
|
|
ResolvesAliases: true,
|
|
AllowsMultipleSelection: true,
|
|
Title: "Open",
|
|
Message: "Select a file",
|
|
ButtonText: "Choose",
|
|
Directory: "/home",
|
|
Filters: []FileFilter{
|
|
{DisplayName: "All Files", Pattern: "*"},
|
|
},
|
|
}
|
|
|
|
if !opts.CanChooseDirectories {
|
|
t.Error("CanChooseDirectories not set correctly")
|
|
}
|
|
if !opts.CanChooseFiles {
|
|
t.Error("CanChooseFiles not set correctly")
|
|
}
|
|
if opts.Title != "Open" {
|
|
t.Error("Title not set correctly")
|
|
}
|
|
if len(opts.Filters) != 1 {
|
|
t.Error("Filters not set correctly")
|
|
}
|
|
}
|
|
|
|
func TestSaveFileDialogOptions_Fields(t *testing.T) {
|
|
opts := SaveFileDialogOptions{
|
|
CanCreateDirectories: true,
|
|
ShowHiddenFiles: true,
|
|
Title: "Save",
|
|
Message: "Save as",
|
|
Directory: "/home",
|
|
Filename: "file.txt",
|
|
ButtonText: "Save",
|
|
Filters: []FileFilter{
|
|
{DisplayName: "Text Files", Pattern: "*.txt"},
|
|
},
|
|
}
|
|
|
|
if !opts.CanCreateDirectories {
|
|
t.Error("CanCreateDirectories not set correctly")
|
|
}
|
|
if opts.Title != "Save" {
|
|
t.Error("Title not set correctly")
|
|
}
|
|
if opts.Filename != "file.txt" {
|
|
t.Error("Filename not set correctly")
|
|
}
|
|
}
|