Add window icons, tests.

This commit is contained in:
Nuno Cruces 2022-05-18 14:48:09 +01:00
parent 15547b2097
commit 61a5cfeeb5
20 changed files with 160 additions and 38 deletions

View File

@ -50,6 +50,7 @@ var (
extraButton string extraButton string
text string text string
icon string icon string
windowIcon string
multiple bool multiple bool
defaultCancel bool defaultCancel bool
@ -207,7 +208,7 @@ func setupFlags() {
flag.StringVar(&cancelLabel, "cancel-label", "", "Set the `label` of the Cancel button") flag.StringVar(&cancelLabel, "cancel-label", "", "Set the `label` of the Cancel button")
flag.Func("extra-button", "Add an extra `button`", setExtraButton) flag.Func("extra-button", "Add an extra `button`", setExtraButton)
flag.StringVar(&text, "text", "", "Set the dialog `text`") 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(&multiple, "multiple", false, "Allow multiple items to be selected")
flag.BoolVar(&defaultCancel, "default-cancel", false, "Give Cancel button focus by default") flag.BoolVar(&defaultCancel, "default-cancel", false, "Give Cancel button focus by default")
@ -277,6 +278,7 @@ func setupFlags() {
extraButton = unspecified extraButton = unspecified
text = unspecified text = unspecified
icon = unspecified icon = unspecified
windowIcon = unspecified
} }
func validateFlags() { func validateFlags() {

View File

@ -26,6 +26,10 @@ func ExampleSelectColor_palette() {
} }
func TestSelectColor_timeout(t *testing.T) { func TestSelectColor_timeout(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
defer goleak.VerifyNone(t) defer goleak.VerifyNone(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Second/5) ctx, cancel := context.WithTimeout(context.Background(), time.Second/5)
defer cancel() defer cancel()
@ -54,6 +58,10 @@ func TestSelectColor_cancel(t *testing.T) {
} }
func TestSelectColor_script(t *testing.T) { func TestSelectColor_script(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
tests := []struct { tests := []struct {
name string name string
call string call string

View File

@ -15,10 +15,13 @@ import (
func ExampleCalendar() { func ExampleCalendar() {
zenity.Calendar("Select a date from below:", zenity.Calendar("Select a date from below:",
zenity.DefaultDate(2006, time.January, 1)) zenity.DefaultDate(2006, time.January, 1))
// Output:
} }
func TestCalendar_timeout(t *testing.T) { func TestCalendar_timeout(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
defer goleak.VerifyNone(t) defer goleak.VerifyNone(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Second/5) ctx, cancel := context.WithTimeout(context.Background(), time.Second/5)
defer cancel() defer cancel()
@ -47,6 +50,10 @@ func TestCalendar_cancel(t *testing.T) {
} }
func TestCalendar_script(t *testing.T) { func TestCalendar_script(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
tests := []struct { tests := []struct {
name string name string
call string call string

View File

@ -14,7 +14,7 @@ func calendar(text string, opts options) (time.Time, error) {
args = appendTitle(args, opts) args = appendTitle(args, opts)
args = appendButtons(args, opts) args = appendButtons(args, opts)
args = appendWidthHeight(args, opts) args = appendWidthHeight(args, opts)
args = appendIcon(args, opts) args = appendWindowIcon(args, opts)
if opts.time != nil { if opts.time != nil {
year, month, day := opts.time.Date() year, month, day := opts.time.Date()
args = append(args, "--month", strconv.Itoa(int(month))) args = append(args, "--month", strconv.Itoa(int(month)))

View File

@ -18,6 +18,10 @@ func ExampleEntry() {
} }
func TestEntry_timeout(t *testing.T) { func TestEntry_timeout(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
defer goleak.VerifyNone(t) defer goleak.VerifyNone(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Second/5) ctx, cancel := context.WithTimeout(context.Background(), time.Second/5)
defer cancel() defer cancel()
@ -46,6 +50,10 @@ func TestEntry_cancel(t *testing.T) {
} }
func TestEntry_script(t *testing.T) { func TestEntry_script(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
tests := []struct { tests := []struct {
name string name string
call string call string

View File

@ -11,7 +11,7 @@ func entry(text string, opts options) (string, error) {
args = appendTitle(args, opts) args = appendTitle(args, opts)
args = appendButtons(args, opts) args = appendButtons(args, opts)
args = appendWidthHeight(args, opts) args = appendWidthHeight(args, opts)
args = appendIcon(args, opts) args = appendWindowIcon(args, opts)
if opts.entryText != "" { if opts.entryText != "" {
args = append(args, "--entry-text", opts.entryText) args = append(args, "--entry-text", opts.entryText)
} }

View File

@ -79,6 +79,10 @@ var fileFuncs = []struct {
} }
func TestSelectFile_timeout(t *testing.T) { func TestSelectFile_timeout(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
for _, tt := range fileFuncs { for _, tt := range fileFuncs {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
defer goleak.VerifyNone(t) defer goleak.VerifyNone(t)
@ -115,6 +119,9 @@ func TestSelectFile_cancel(t *testing.T) {
} }
func TestSelectFile_script(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) { t.Run("Cancel", func(t *testing.T) {
zenity.Info(fmt.Sprintf("In the file selection dialog, cancel.")) zenity.Info(fmt.Sprintf("In the file selection dialog, cancel."))
str, err := zenity.SelectFile() str, err := zenity.SelectFile()
@ -156,6 +163,9 @@ func TestSelectFile_script(t *testing.T) {
} }
func TestSelectFileMutiple_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) { t.Run("Cancel", func(t *testing.T) {
zenity.Info(fmt.Sprintf("In the file selection dialog, cancel.")) zenity.Info(fmt.Sprintf("In the file selection dialog, cancel."))
lst, err := zenity.SelectFileMutiple() lst, err := zenity.SelectFileMutiple()
@ -204,6 +214,9 @@ func TestSelectFileMutiple_script(t *testing.T) {
} }
func TestSelectFileSave_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) { t.Run("Cancel", func(t *testing.T) {
zenity.Info(fmt.Sprintf("In the file save dialog, cancel.")) zenity.Info(fmt.Sprintf("In the file save dialog, cancel."))
str, err := zenity.SelectFileSave() str, err := zenity.SelectFileSave()

View File

@ -44,6 +44,10 @@ func ExampleListMultipleItems() {
} }
func TestList_timeout(t *testing.T) { func TestList_timeout(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
defer goleak.VerifyNone(t) defer goleak.VerifyNone(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Second/5) ctx, cancel := context.WithTimeout(context.Background(), time.Second/5)
defer cancel() defer cancel()
@ -72,6 +76,10 @@ func TestList_cancel(t *testing.T) {
} }
func TestList_script(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"} items := []string{"apples", "oranges", "bananas", "strawberries"}
tests := []struct { tests := []struct {
name string name string
@ -96,6 +104,10 @@ func TestList_script(t *testing.T) {
} }
func TestListMultiple_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"} items := []string{"apples", "oranges", "bananas", "strawberries"}
tests := []struct { tests := []struct {
name string name string

View File

@ -9,7 +9,7 @@ func list(text string, items []string, opts options) (string, error) {
args = appendTitle(args, opts) args = appendTitle(args, opts)
args = appendButtons(args, opts) args = appendButtons(args, opts)
args = appendWidthHeight(args, opts) args = appendWidthHeight(args, opts)
args = appendIcon(args, opts) args = appendWindowIcon(args, opts)
args = append(args, items...) args = append(args, items...)
out, err := zenutil.Run(opts.ctx, args) 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 = appendTitle(args, opts)
args = appendButtons(args, opts) args = appendButtons(args, opts)
args = appendWidthHeight(args, opts) args = appendWidthHeight(args, opts)
args = appendIcon(args, opts) args = appendWindowIcon(args, opts)
args = append(args, items...) args = append(args, items...)
out, err := zenutil.Run(opts.ctx, args) out, err := zenutil.Run(opts.ctx, args)

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"runtime"
"testing" "testing"
"time" "time"
@ -16,35 +17,24 @@ func ExampleError() {
zenity.Error("An error has occurred.", zenity.Error("An error has occurred.",
zenity.Title("Error"), zenity.Title("Error"),
zenity.ErrorIcon) zenity.ErrorIcon)
// Output:
} }
func ExampleInfo() { func ExampleInfo() {
zenity.Info("All updates are complete.", zenity.Info("All updates are complete.",
zenity.Title("Information"), zenity.Title("Information"),
zenity.InfoIcon) zenity.InfoIcon)
// Output:
} }
func ExampleWarning() { func ExampleWarning() {
zenity.Warning("Are you sure you want to proceed?", zenity.Warning("Are you sure you want to proceed?",
zenity.Title("Warning"), zenity.Title("Warning"),
zenity.WarningIcon) zenity.WarningIcon)
// Output:
} }
func ExampleQuestion() { func ExampleQuestion() {
zenity.Question("Are you sure you want to proceed?", zenity.Question("Are you sure you want to proceed?",
zenity.Title("Question"), zenity.Title("Question"),
zenity.QuestionIcon) zenity.QuestionIcon)
// Output:
}
func ExampleIcon_custom() {
zenity.Info("All updates are complete.",
zenity.Title("Information"),
zenity.Icon("testdata/icon.png"))
// Output:
} }
var msgFuncs = []struct { var msgFuncs = []struct {
@ -58,6 +48,10 @@ var msgFuncs = []struct {
} }
func TestMessage_timeout(t *testing.T) { func TestMessage_timeout(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
for _, tt := range msgFuncs { for _, tt := range msgFuncs {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
defer goleak.VerifyNone(t) defer goleak.VerifyNone(t)
@ -94,6 +88,10 @@ func TestMessage_cancel(t *testing.T) {
} }
func TestMessage_script(t *testing.T) { func TestMessage_script(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
for _, tt := range msgFuncs { for _, tt := range msgFuncs {
t.Run(tt.name+"OK", func(t *testing.T) { t.Run(tt.name+"OK", func(t *testing.T) {
err := tt.fn("Please, press OK.", zenity.OKLabel("OK")) err := tt.fn("Please, press OK.", zenity.OKLabel("OK"))
@ -134,12 +132,47 @@ func TestMessage_script(t *testing.T) {
t.Skip("skipping:", err) t.Skip("skipping:", err)
} }
if err != tt.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) { func TestMessage_callbacks(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
cancel() cancel()

View File

@ -19,7 +19,7 @@ func message(kind messageKind, text string, opts options) error {
args = appendTitle(args, opts) args = appendTitle(args, opts)
args = appendButtons(args, opts) args = appendButtons(args, opts)
args = appendWidthHeight(args, opts) args = appendWidthHeight(args, opts)
args = appendIcon(args, opts) args = appendWindowIcon(args, opts)
if opts.noWrap { if opts.noWrap {
args = append(args, "--no-wrap") args = append(args, "--no-wrap")
} }

View File

@ -37,7 +37,9 @@ func message(kind messageKind, text string, opts options) error {
flags |= _MB_ICONWARNING flags |= _MB_ICONWARNING
case InfoIcon: case InfoIcon:
flags |= _MB_ICONINFORMATION flags |= _MB_ICONINFORMATION
case nil: case NoIcon:
//
default:
switch kind { switch kind {
case errorKind: case errorKind:
flags |= _MB_ICONERROR flags |= _MB_ICONERROR

View File

@ -13,7 +13,6 @@ func ExampleNotify() {
zenity.Notify("There are system updates necessary!", zenity.Notify("There are system updates necessary!",
zenity.Title("Warning"), zenity.Title("Warning"),
zenity.InfoIcon) zenity.InfoIcon)
// Output:
} }
func TestNotify_cancel(t *testing.T) { func TestNotify_cancel(t *testing.T) {
@ -29,3 +28,11 @@ func TestNotify_cancel(t *testing.T) {
t.Error("was not canceled:", err) t.Error("was not canceled:", err)
} }
} }
func TestNotify_examples(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
ExampleNotify()
}

View File

@ -39,8 +39,6 @@ func ExampleProgress() {
dlg.Complete() dlg.Complete()
time.Sleep(time.Second) time.Sleep(time.Second)
// Output:
} }
func ExampleProgress_pulsate() { func ExampleProgress_pulsate() {
@ -66,8 +64,6 @@ func ExampleProgress_pulsate() {
dlg.Complete() dlg.Complete()
time.Sleep(time.Second) time.Sleep(time.Second)
// Output:
} }
func TestProgress_cancel(t *testing.T) { func TestProgress_cancel(t *testing.T) {
@ -103,3 +99,12 @@ func TestProgress_cancelAfter(t *testing.T) {
t.Error("was not canceled:", err) 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()
}

View File

@ -9,7 +9,7 @@ func progress(opts options) (ProgressDialog, error) {
args = appendTitle(args, opts) args = appendTitle(args, opts)
args = appendButtons(args, opts) args = appendButtons(args, opts)
args = appendWidthHeight(args, opts) args = appendWidthHeight(args, opts)
args = appendIcon(args, opts) args = appendWindowIcon(args, opts)
if opts.maxValue == 0 { if opts.maxValue == 0 {
opts.maxValue = 100 opts.maxValue = 100
} }

View File

@ -23,6 +23,10 @@ func ExamplePassword_username() {
} }
func TestPassword_timeout(t *testing.T) { func TestPassword_timeout(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
defer goleak.VerifyNone(t) defer goleak.VerifyNone(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Second/5) ctx, cancel := context.WithTimeout(context.Background(), time.Second/5)
defer cancel() defer cancel()
@ -65,6 +69,10 @@ func TestPassword_username(t *testing.T) {
} }
func TestPassword_script(t *testing.T) { func TestPassword_script(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
tests := []struct { tests := []struct {
name string name string
call string call string

View File

@ -41,11 +41,11 @@ func appendWidthHeight(args []string, opts options) []string {
return args return args
} }
func appendIcon(args []string, opts options) []string { func appendWindowIcon(args []string, opts options) []string {
if i, ok := opts.icon.(string); ok { if i, ok := opts.windowIcon.(string); ok {
args = append(args, "--window-icon", i) args = append(args, "--window-icon", i)
} }
switch opts.icon { switch opts.windowIcon {
case ErrorIcon: case ErrorIcon:
args = append(args, "--window-icon=error") args = append(args, "--window-icon=error")
case WarningIcon: case WarningIcon:

View File

@ -56,23 +56,24 @@ func Test_appendWidthHeight(t *testing.T) {
} }
} }
func Test_appendIcon(t *testing.T) { func Test_appendWindowIcon(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
opts options opts options
want []string want []string
}{ }{
{name: "NoIcon", opts: options{icon: NoIcon}, want: nil}, {name: "NoIcon", opts: options{windowIcon: NoIcon}, want: nil},
{name: "Info", opts: options{icon: InfoIcon}, want: []string{"--window-icon=info"}}, {name: "Info", opts: options{windowIcon: InfoIcon}, want: []string{"--window-icon=info"}},
{name: "Error", opts: options{icon: ErrorIcon}, want: []string{"--window-icon=error"}}, {name: "Error", opts: options{windowIcon: ErrorIcon}, want: []string{"--window-icon=error"}},
{name: "Warning", opts: options{icon: WarningIcon}, want: []string{"--window-icon=warning"}}, {name: "Warning", opts: options{windowIcon: WarningIcon}, want: []string{"--window-icon=warning"}},
{name: "Question", opts: options{icon: QuestionIcon}, want: []string{"--window-icon=question"}}, {name: "Question", opts: options{windowIcon: QuestionIcon}, want: []string{"--window-icon=question"}},
{name: "Password", opts: options{icon: PasswordIcon}, want: nil}, {name: "Password", opts: options{windowIcon: PasswordIcon}, want: nil},
{name: "File", opts: options{windowIcon: "png"}, want: []string{"--window-icon", "png"}},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := appendIcon(nil, tt.opts); !reflect.DeepEqual(got, tt.want) { if got := appendWindowIcon(nil, tt.opts); !reflect.DeepEqual(got, tt.want) {
t.Errorf("appendIcon() = %v; want %v", got, tt.want) t.Errorf("appendWindowIcon() = %v; want %v", got, tt.want)
} }
}) })
} }

View File

@ -43,6 +43,7 @@ type options struct {
extraButton *string extraButton *string
defaultCancel bool defaultCancel bool
icon any icon any
windowIcon any
// Message options // Message options
noWrap bool noWrap bool
@ -168,6 +169,19 @@ func Icon(icon any) Option {
return funcOption(func(o *options) { o.icon = icon }) 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. // CustomIcon returns an Option to set a custom dialog icon, loaded from a file.
// //
// Deprecated: use Icon instead. // Deprecated: use Icon instead.

View File

@ -23,6 +23,8 @@ func Test_applyOptions(t *testing.T) {
{name: "CancelLabel", args: CancelLabel("Cancel"), want: options{cancelLabel: stringPtr("Cancel")}}, {name: "CancelLabel", args: CancelLabel("Cancel"), want: options{cancelLabel: stringPtr("Cancel")}},
{name: "ExtraButton", args: ExtraButton("Extra"), want: options{extraButton: stringPtr("Extra")}}, {name: "ExtraButton", args: ExtraButton("Extra"), want: options{extraButton: stringPtr("Extra")}},
{name: "DefaultCancel", args: DefaultCancel(), want: options{defaultCancel: true}}, {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(ErrorIcon), want: options{icon: ErrorIcon}},
{name: "Icon", args: Icon("error"), want: options{icon: "error"}}, {name: "Icon", args: Icon("error"), want: options{icon: "error"}},