diff --git a/README.md b/README.md
index 616eb541..8b5544f0 100644
--- a/README.md
+++ b/README.md
@@ -160,9 +160,15 @@ package may be used to parse the JSON file output.
First install the example notification command with `go get gotest.tools/gotestsum/contrib/notify`.
The command will be downloaded to `$GOPATH/bin` as `notify`. Note that this
-example `notify` command only works on macOS with
+example `notify` command only works on Linux with `notify-send` and on macOS with
[terminal-notifer](https://github.com/julienXX/terminal-notifier) installed.
+On Linux, you need to have some "test-pass" and "test-fail" icons installed in your icon theme.
+Some sample icons can be found in `contrib/notify`, and can be installed with `make install`.
+
+On Windows, you can install [notify-send.exe](https://github.com/vaskovsky/notify-send)
+but it does not support custom icons so will have to use the basic "info" and "error".
+
```
gotestsum --post-run-command notify
```
diff --git a/cmd/handler.go b/cmd/handler.go
index c5159a53..0da218d5 100644
--- a/cmd/handler.go
+++ b/cmd/handler.go
@@ -161,6 +161,7 @@ func postRunHook(opts *options, execution *testjson.Execution) error {
if len(command) == 0 {
return nil
}
+ log.Debugf("exec: %s", command)
cmd := exec.Command(command[0], command[1:]...)
cmd.Stdout = opts.stdout
diff --git a/contrib/notify/.gitignore b/contrib/notify/.gitignore
new file mode 100644
index 00000000..f3b695d3
--- /dev/null
+++ b/contrib/notify/.gitignore
@@ -0,0 +1 @@
+notify
diff --git a/contrib/notify/Makefile b/contrib/notify/Makefile
new file mode 100644
index 00000000..73771c64
--- /dev/null
+++ b/contrib/notify/Makefile
@@ -0,0 +1,13 @@
+GO = go
+INSTALL = install
+
+ICONS = icons/test-pass.svg icons/test-fail.svg
+ICONDIR = $(HOME)/.icons # or /usr/share/icons
+
+build:
+ $(GO) build
+
+install: $(ICONS)
+ $(GO) install
+ $(INSTALL) -d $(ICONDIR)
+ $(INSTALL) $^ $(ICONDIR)
diff --git a/contrib/notify/icons/README.html b/contrib/notify/icons/README.html
new file mode 100644
index 00000000..4512a24e
--- /dev/null
+++ b/contrib/notify/icons/README.html
@@ -0,0 +1 @@
+Pass Fail Vectors by Vecteezy
diff --git a/contrib/notify/icons/test-fail.svg b/contrib/notify/icons/test-fail.svg
new file mode 100644
index 00000000..f6b97c74
--- /dev/null
+++ b/contrib/notify/icons/test-fail.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/contrib/notify/icons/test-pass.svg b/contrib/notify/icons/test-pass.svg
new file mode 100644
index 00000000..2e96bdaf
--- /dev/null
+++ b/contrib/notify/icons/test-pass.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/contrib/notify/notify-macos.go b/contrib/notify/notify_darwin.go
similarity index 85%
rename from contrib/notify/notify-macos.go
rename to contrib/notify/notify_darwin.go
index 3f6822ca..ad683898 100644
--- a/contrib/notify/notify-macos.go
+++ b/contrib/notify/notify_darwin.go
@@ -43,9 +43,11 @@ func main() {
"-group", "gotestsum",
"-subtitle", subtitle,
}
- log.Printf("terminal-notifier %#v", args)
- err := exec.Command("terminal-notifier", args...).Run()
- if err != nil {
+ cmd := exec.Command("terminal-notifier", args...)
+ log.Printf("%#v", cmd.Args)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
log.Fatalf("Failed to exec: %v", err)
}
}
diff --git a/contrib/notify/notify_linux.go b/contrib/notify/notify_linux.go
new file mode 100644
index 00000000..8da6c3e8
--- /dev/null
+++ b/contrib/notify/notify_linux.go
@@ -0,0 +1,57 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "strconv"
+)
+
+func main() {
+ total := envInt("TOTAL")
+ skipped := envInt("SKIPPED")
+ failed := envInt("FAILED")
+ errors := envInt("ERRORS")
+
+ icon := "test-pass"
+ title := "Passed"
+ switch {
+ case errors > 0:
+ icon = "dialog-warning"
+ title = "Errored"
+ case failed > 0:
+ icon = "test-fail"
+ title = "Failed"
+ case skipped > 0:
+ title = "Passed with skipped"
+ }
+
+ subtitle := fmt.Sprintf("%d Tests Run", total)
+ if errors > 0 {
+ subtitle += fmt.Sprintf(", %d Errored", errors)
+ }
+ if failed > 0 {
+ subtitle += fmt.Sprintf(", %d Failed", failed)
+ }
+ if skipped > 0 {
+ subtitle += fmt.Sprintf(", %d Skipped", skipped)
+ }
+
+ cmd := exec.Command("notify-send", "--icon", icon, title, subtitle)
+ log.Printf("%#v", cmd.Args)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ log.Fatalf("Failed to exec: %v", err)
+ }
+}
+
+func envInt(name string) int {
+ val := os.Getenv("TESTS_" + name)
+ n, err := strconv.Atoi(val)
+ if err != nil {
+ return 0
+ }
+ return n
+}
diff --git a/contrib/notify/notify_windows.go b/contrib/notify/notify_windows.go
new file mode 100644
index 00000000..f3d384d5
--- /dev/null
+++ b/contrib/notify/notify_windows.go
@@ -0,0 +1,57 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "strconv"
+)
+
+func main() {
+ total := envInt("TOTAL")
+ skipped := envInt("SKIPPED")
+ failed := envInt("FAILED")
+ errors := envInt("ERRORS")
+
+ icon := "info" // Info 🛈
+ title := "Passed"
+ switch {
+ case errors > 0:
+ icon = "important" // Warning âš
+ title = "Errored"
+ case failed > 0:
+ icon = "error" // Error ⮾
+ title = "Failed"
+ case skipped > 0:
+ title = "Passed with skipped"
+ }
+
+ subtitle := fmt.Sprintf("%d Tests Run", total)
+ if errors > 0 {
+ subtitle += fmt.Sprintf(", %d Errored", errors)
+ }
+ if failed > 0 {
+ subtitle += fmt.Sprintf(", %d Failed", failed)
+ }
+ if skipped > 0 {
+ subtitle += fmt.Sprintf(", %d Skipped", skipped)
+ }
+
+ cmd := exec.Command("notify-send.exe", "-i", icon, title, subtitle)
+ log.Printf("%#v", cmd.Args)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ log.Fatalf("Failed to exec: %v", err)
+ }
+}
+
+func envInt(name string) int {
+ val := os.Getenv("TESTS_" + name)
+ n, err := strconv.Atoi(val)
+ if err != nil {
+ return 0
+ }
+ return n
+}