diff --git a/cmd/zenity/main.go b/cmd/zenity/main.go index 0eda11d..0f0a59b 100644 --- a/cmd/zenity/main.go +++ b/cmd/zenity/main.go @@ -50,6 +50,7 @@ var ( extraButton string text string icon string + windowIcon string multiple bool defaultCancel bool @@ -207,7 +208,7 @@ func setupFlags() { flag.StringVar(&cancelLabel, "cancel-label", "", "Set the `label` of the Cancel button") flag.Func("extra-button", "Add an extra `button`", setExtraButton) flag.StringVar(&text, "text", "", "Set the dialog `text`") - flag.StringVar(&icon, "window-icon", "", "Set the window `icon` (error, info, question, warning)") + flag.StringVar(&windowIcon, "window-icon", "", "Set the window `icon` (error, info, question, warning)") flag.BoolVar(&multiple, "multiple", false, "Allow multiple items to be selected") flag.BoolVar(&defaultCancel, "default-cancel", false, "Give Cancel button focus by default") @@ -277,6 +278,7 @@ func setupFlags() { extraButton = unspecified text = unspecified icon = unspecified + windowIcon = unspecified } func validateFlags() { diff --git a/color_test.go b/color_test.go index 66c7d57..3cb329e 100644 --- a/color_test.go +++ b/color_test.go @@ -26,6 +26,10 @@ func ExampleSelectColor_palette() { } func TestSelectColor_timeout(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + defer goleak.VerifyNone(t) ctx, cancel := context.WithTimeout(context.Background(), time.Second/5) defer cancel() @@ -54,6 +58,10 @@ func TestSelectColor_cancel(t *testing.T) { } func TestSelectColor_script(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + tests := []struct { name string call string diff --git a/date_test.go b/date_test.go index 0071920..c38f32d 100644 --- a/date_test.go +++ b/date_test.go @@ -15,10 +15,13 @@ import ( func ExampleCalendar() { zenity.Calendar("Select a date from below:", zenity.DefaultDate(2006, time.January, 1)) - // Output: } func TestCalendar_timeout(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + defer goleak.VerifyNone(t) ctx, cancel := context.WithTimeout(context.Background(), time.Second/5) defer cancel() @@ -47,6 +50,10 @@ func TestCalendar_cancel(t *testing.T) { } func TestCalendar_script(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + tests := []struct { name string call string diff --git a/date_unix.go b/date_unix.go index fc043ef..de403ed 100644 --- a/date_unix.go +++ b/date_unix.go @@ -14,7 +14,7 @@ func calendar(text string, opts options) (time.Time, error) { args = appendTitle(args, opts) args = appendButtons(args, opts) args = appendWidthHeight(args, opts) - args = appendIcon(args, opts) + args = appendWindowIcon(args, opts) if opts.time != nil { year, month, day := opts.time.Date() args = append(args, "--month", strconv.Itoa(int(month))) diff --git a/entry_test.go b/entry_test.go index a116258..0146678 100644 --- a/entry_test.go +++ b/entry_test.go @@ -18,6 +18,10 @@ func ExampleEntry() { } func TestEntry_timeout(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + defer goleak.VerifyNone(t) ctx, cancel := context.WithTimeout(context.Background(), time.Second/5) defer cancel() @@ -46,6 +50,10 @@ func TestEntry_cancel(t *testing.T) { } func TestEntry_script(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + tests := []struct { name string call string diff --git a/entry_unix.go b/entry_unix.go index 5fe81ce..f6bab51 100644 --- a/entry_unix.go +++ b/entry_unix.go @@ -11,7 +11,7 @@ func entry(text string, opts options) (string, error) { args = appendTitle(args, opts) args = appendButtons(args, opts) args = appendWidthHeight(args, opts) - args = appendIcon(args, opts) + args = appendWindowIcon(args, opts) if opts.entryText != "" { args = append(args, "--entry-text", opts.entryText) } diff --git a/file_test.go b/file_test.go index af3f4be..931c28e 100644 --- a/file_test.go +++ b/file_test.go @@ -79,6 +79,10 @@ var fileFuncs = []struct { } func TestSelectFile_timeout(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + for _, tt := range fileFuncs { t.Run(tt.name, func(t *testing.T) { defer goleak.VerifyNone(t) @@ -115,6 +119,9 @@ func TestSelectFile_cancel(t *testing.T) { } func TestSelectFile_script(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } t.Run("Cancel", func(t *testing.T) { zenity.Info(fmt.Sprintf("In the file selection dialog, cancel.")) str, err := zenity.SelectFile() @@ -156,6 +163,9 @@ func TestSelectFile_script(t *testing.T) { } func TestSelectFileMutiple_script(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } t.Run("Cancel", func(t *testing.T) { zenity.Info(fmt.Sprintf("In the file selection dialog, cancel.")) lst, err := zenity.SelectFileMutiple() @@ -204,6 +214,9 @@ func TestSelectFileMutiple_script(t *testing.T) { } func TestSelectFileSave_script(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } t.Run("Cancel", func(t *testing.T) { zenity.Info(fmt.Sprintf("In the file save dialog, cancel.")) str, err := zenity.SelectFileSave() diff --git a/list_test.go b/list_test.go index a3b8f2b..be1ba0f 100644 --- a/list_test.go +++ b/list_test.go @@ -44,6 +44,10 @@ func ExampleListMultipleItems() { } func TestList_timeout(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + defer goleak.VerifyNone(t) ctx, cancel := context.WithTimeout(context.Background(), time.Second/5) defer cancel() @@ -72,6 +76,10 @@ func TestList_cancel(t *testing.T) { } func TestList_script(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + items := []string{"apples", "oranges", "bananas", "strawberries"} tests := []struct { name string @@ -96,6 +104,10 @@ func TestList_script(t *testing.T) { } func TestListMultiple_script(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + items := []string{"apples", "oranges", "bananas", "strawberries"} tests := []struct { name string diff --git a/list_unix.go b/list_unix.go index 83b1661..3476bd1 100644 --- a/list_unix.go +++ b/list_unix.go @@ -9,7 +9,7 @@ func list(text string, items []string, opts options) (string, error) { args = appendTitle(args, opts) args = appendButtons(args, opts) args = appendWidthHeight(args, opts) - args = appendIcon(args, opts) + args = appendWindowIcon(args, opts) args = append(args, items...) out, err := zenutil.Run(opts.ctx, args) @@ -21,7 +21,7 @@ func listMultiple(text string, items []string, opts options) ([]string, error) { args = appendTitle(args, opts) args = appendButtons(args, opts) args = appendWidthHeight(args, opts) - args = appendIcon(args, opts) + args = appendWindowIcon(args, opts) args = append(args, items...) out, err := zenutil.Run(opts.ctx, args) diff --git a/msg_test.go b/msg_test.go index c67d2dd..e9c412b 100644 --- a/msg_test.go +++ b/msg_test.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "runtime" "testing" "time" @@ -16,35 +17,24 @@ func ExampleError() { zenity.Error("An error has occurred.", zenity.Title("Error"), zenity.ErrorIcon) - // Output: } func ExampleInfo() { zenity.Info("All updates are complete.", zenity.Title("Information"), zenity.InfoIcon) - // Output: } func ExampleWarning() { zenity.Warning("Are you sure you want to proceed?", zenity.Title("Warning"), zenity.WarningIcon) - // Output: } func ExampleQuestion() { zenity.Question("Are you sure you want to proceed?", zenity.Title("Question"), zenity.QuestionIcon) - // Output: -} - -func ExampleIcon_custom() { - zenity.Info("All updates are complete.", - zenity.Title("Information"), - zenity.Icon("testdata/icon.png")) - // Output: } var msgFuncs = []struct { @@ -58,6 +48,10 @@ var msgFuncs = []struct { } func TestMessage_timeout(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + for _, tt := range msgFuncs { t.Run(tt.name, func(t *testing.T) { defer goleak.VerifyNone(t) @@ -94,6 +88,10 @@ func TestMessage_cancel(t *testing.T) { } func TestMessage_script(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + for _, tt := range msgFuncs { t.Run(tt.name+"OK", func(t *testing.T) { err := tt.fn("Please, press OK.", zenity.OKLabel("OK")) @@ -134,12 +132,47 @@ func TestMessage_script(t *testing.T) { t.Skip("skipping:", err) } if err != tt.err { - t.Errorf("Questtion() = %v; want %v", err, tt.err) + t.Errorf("Question() = %v; want %v", err, tt.err) } }) } } +func TestMessage_icon(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + err := zenity.Question("Does this dialog have an error icon?", + zenity.OKLabel("Yes"), + zenity.CancelLabel("No"), + zenity.ErrorIcon) + if skip, err := skip(err); skip { + t.Skip("skipping:", err) + } + if err != nil { + t.Errorf("Question() = %v; want nil", err) + } +} + +func TestMessage_customIcon(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + err := zenity.Question("Does this dialog have a custom icon?", + zenity.Title(""), + zenity.OKLabel("Yes"), + zenity.CancelLabel("No"), + zenity.Icon("testdata/icon.png")) + if skip, err := skip(err); skip { + t.Skip("skipping:", err) + } + if err != nil && (runtime.GOOS == "windows" || runtime.GOOS == "darwin") { + t.Errorf("Question() = %v; want nil", err) + } +} + func TestMessage_callbacks(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) cancel() diff --git a/msg_unix.go b/msg_unix.go index a0783a9..c8817e4 100644 --- a/msg_unix.go +++ b/msg_unix.go @@ -19,7 +19,7 @@ func message(kind messageKind, text string, opts options) error { args = appendTitle(args, opts) args = appendButtons(args, opts) args = appendWidthHeight(args, opts) - args = appendIcon(args, opts) + args = appendWindowIcon(args, opts) if opts.noWrap { args = append(args, "--no-wrap") } diff --git a/msg_windows.go b/msg_windows.go index f3d44ee..dbe1788 100644 --- a/msg_windows.go +++ b/msg_windows.go @@ -37,7 +37,9 @@ func message(kind messageKind, text string, opts options) error { flags |= _MB_ICONWARNING case InfoIcon: flags |= _MB_ICONINFORMATION - case nil: + case NoIcon: + // + default: switch kind { case errorKind: flags |= _MB_ICONERROR diff --git a/notify_test.go b/notify_test.go index 3284dcb..3fee581 100644 --- a/notify_test.go +++ b/notify_test.go @@ -13,7 +13,6 @@ func ExampleNotify() { zenity.Notify("There are system updates necessary!", zenity.Title("Warning"), zenity.InfoIcon) - // Output: } func TestNotify_cancel(t *testing.T) { @@ -29,3 +28,11 @@ func TestNotify_cancel(t *testing.T) { t.Error("was not canceled:", err) } } + +func TestNotify_examples(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + ExampleNotify() +} diff --git a/progress_test.go b/progress_test.go index 690dbaa..012a8b1 100644 --- a/progress_test.go +++ b/progress_test.go @@ -39,8 +39,6 @@ func ExampleProgress() { dlg.Complete() time.Sleep(time.Second) - - // Output: } func ExampleProgress_pulsate() { @@ -66,8 +64,6 @@ func ExampleProgress_pulsate() { dlg.Complete() time.Sleep(time.Second) - - // Output: } func TestProgress_cancel(t *testing.T) { @@ -103,3 +99,12 @@ func TestProgress_cancelAfter(t *testing.T) { t.Error("was not canceled:", err) } } + +func TestProgress_examples(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + ExampleProgress() + ExampleProgress_pulsate() +} diff --git a/progress_unix.go b/progress_unix.go index c9309f0..4451002 100644 --- a/progress_unix.go +++ b/progress_unix.go @@ -9,7 +9,7 @@ func progress(opts options) (ProgressDialog, error) { args = appendTitle(args, opts) args = appendButtons(args, opts) args = appendWidthHeight(args, opts) - args = appendIcon(args, opts) + args = appendWindowIcon(args, opts) if opts.maxValue == 0 { opts.maxValue = 100 } diff --git a/pwd_test.go b/pwd_test.go index e843bcf..b6bb8ca 100644 --- a/pwd_test.go +++ b/pwd_test.go @@ -23,6 +23,10 @@ func ExamplePassword_username() { } func TestPassword_timeout(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + defer goleak.VerifyNone(t) ctx, cancel := context.WithTimeout(context.Background(), time.Second/5) defer cancel() @@ -65,6 +69,10 @@ func TestPassword_username(t *testing.T) { } func TestPassword_script(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + tests := []struct { name string call string diff --git a/util_unix.go b/util_unix.go index df98a54..a9e6271 100644 --- a/util_unix.go +++ b/util_unix.go @@ -41,11 +41,11 @@ func appendWidthHeight(args []string, opts options) []string { return args } -func appendIcon(args []string, opts options) []string { - if i, ok := opts.icon.(string); ok { +func appendWindowIcon(args []string, opts options) []string { + if i, ok := opts.windowIcon.(string); ok { args = append(args, "--window-icon", i) } - switch opts.icon { + switch opts.windowIcon { case ErrorIcon: args = append(args, "--window-icon=error") case WarningIcon: diff --git a/util_unix_test.go b/util_unix_test.go index 1586b6b..44c3a23 100644 --- a/util_unix_test.go +++ b/util_unix_test.go @@ -56,23 +56,24 @@ func Test_appendWidthHeight(t *testing.T) { } } -func Test_appendIcon(t *testing.T) { +func Test_appendWindowIcon(t *testing.T) { tests := []struct { name string opts options want []string }{ - {name: "NoIcon", opts: options{icon: NoIcon}, want: nil}, - {name: "Info", opts: options{icon: InfoIcon}, want: []string{"--window-icon=info"}}, - {name: "Error", opts: options{icon: ErrorIcon}, want: []string{"--window-icon=error"}}, - {name: "Warning", opts: options{icon: WarningIcon}, want: []string{"--window-icon=warning"}}, - {name: "Question", opts: options{icon: QuestionIcon}, want: []string{"--window-icon=question"}}, - {name: "Password", opts: options{icon: PasswordIcon}, want: nil}, + {name: "NoIcon", opts: options{windowIcon: NoIcon}, want: nil}, + {name: "Info", opts: options{windowIcon: InfoIcon}, want: []string{"--window-icon=info"}}, + {name: "Error", opts: options{windowIcon: ErrorIcon}, want: []string{"--window-icon=error"}}, + {name: "Warning", opts: options{windowIcon: WarningIcon}, want: []string{"--window-icon=warning"}}, + {name: "Question", opts: options{windowIcon: QuestionIcon}, want: []string{"--window-icon=question"}}, + {name: "Password", opts: options{windowIcon: PasswordIcon}, want: nil}, + {name: "File", opts: options{windowIcon: "png"}, want: []string{"--window-icon", "png"}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := appendIcon(nil, tt.opts); !reflect.DeepEqual(got, tt.want) { - t.Errorf("appendIcon() = %v; want %v", got, tt.want) + if got := appendWindowIcon(nil, tt.opts); !reflect.DeepEqual(got, tt.want) { + t.Errorf("appendWindowIcon() = %v; want %v", got, tt.want) } }) } diff --git a/zenity.go b/zenity.go index 221b037..98518e1 100644 --- a/zenity.go +++ b/zenity.go @@ -43,6 +43,7 @@ type options struct { extraButton *string defaultCancel bool icon any + windowIcon any // Message options noWrap bool @@ -168,6 +169,19 @@ func Icon(icon any) Option { return funcOption(func(o *options) { o.icon = icon }) } +// WindowIcon returns an Option to set the dialog icon (macOS and Unix only). +// +// WindowIcon accepts a DialogIcon, or a string path. +func WindowIcon(icon any) Option { + switch icon.(type) { + case string: + case DialogIcon: + default: + panic("interface conversion: expected string or DialogIcon") + } + return funcOption(func(o *options) { o.windowIcon = icon }) +} + // CustomIcon returns an Option to set a custom dialog icon, loaded from a file. // // Deprecated: use Icon instead. diff --git a/zenity_test.go b/zenity_test.go index 0d37714..4406205 100644 --- a/zenity_test.go +++ b/zenity_test.go @@ -23,6 +23,8 @@ func Test_applyOptions(t *testing.T) { {name: "CancelLabel", args: CancelLabel("Cancel"), want: options{cancelLabel: stringPtr("Cancel")}}, {name: "ExtraButton", args: ExtraButton("Extra"), want: options{extraButton: stringPtr("Extra")}}, {name: "DefaultCancel", args: DefaultCancel(), want: options{defaultCancel: true}}, + {name: "WindowIcon", args: WindowIcon(ErrorIcon), want: options{windowIcon: ErrorIcon}}, + {name: "WindowIcon", args: WindowIcon("error"), want: options{windowIcon: "error"}}, {name: "Icon", args: Icon(ErrorIcon), want: options{icon: ErrorIcon}}, {name: "Icon", args: Icon("error"), want: options{icon: "error"}},