package cli_test import ( "bytes" "encoding/json" "io" "net/http" "net/http/httptest" "strings" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/kopia/kopia/internal/testutil" "github.com/kopia/kopia/notification/sender" "github.com/kopia/kopia/tests/testenv" ) func TestServerNotifications(t *testing.T) { mux := http.NewServeMux() notificationsReceived := make(chan string, 100) mux.HandleFunc("/notification-webhook", func(w http.ResponseWriter, r *http.Request) { var b bytes.Buffer io.Copy(&b, r.Body) notificationsReceived <- b.String() }) server := httptest.NewServer(mux) defer server.Close() env := testenv.NewCLITest(t, testenv.RepoFormatNotImportant, testenv.NewInProcRunner(t)) dir0 := testutil.TempDirectory(t) dir1 := testutil.TempDirectory(t) dir2 := testutil.TempDirectory(t) env.RunAndExpectSuccess(t, "repo", "create", "filesystem", "--path", env.RepoDir, "--override-username=another-user", "--override-hostname=another-host") env.RunAndExpectSuccess(t, "snap", "create", dir0) env.RunAndExpectSuccess(t, "repo", "connect", "filesystem", "--path", env.RepoDir, "--override-username=test-user", "--override-hostname=test-host") env.RunAndExpectSuccess(t, "snap", "create", dir1) env.RunAndExpectSuccess(t, "snap", "create", dir2) // setup webhook notification env.RunAndExpectSuccess(t, "notification", "profile", "configure", "webhook", "--profile-name=mywebhook", "--endpoint="+server.URL+"/notification-webhook", "--method=POST", "--format=html") var sp testutil.ServerParameters jsonNotificationsReceived := make(chan string, 100) wait, kill := env.RunAndProcessStderrAsync(t, sp.ProcessOutput, func(line string) { const prefix = "NOTIFICATION: " if strings.HasPrefix(line, prefix) { t.Logf("JSON notification received: %v", line) jsonNotificationsReceived <- line[len(prefix):] } }, "server", "start", "--address=localhost:0", "--insecure", "--random-server-control-password", "--kopiaui-notifications", "--shutdown-grace-period", "100ms", ) defer func() { kill() wait() }() // trigger server snapshot env.RunAndExpectSuccess(t, "server", "snapshot", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword, dir1) select { case not := <-notificationsReceived: t.Logf("notification received: %v", not) assert.Contains(t, not, "snapshotstatus-success") case <-time.After(5 * time.Second): t.Error("notification not received in time") } select { case not := <-jsonNotificationsReceived: // make sure we received a valid sender.Message JSON dec := json.NewDecoder(strings.NewReader(not)) dec.DisallowUnknownFields() var msg sender.Message require.NoError(t, dec.Decode(&msg)) require.Contains(t, msg.Subject, "Successfully created a snapshot of") case <-time.After(5 * time.Second): t.Error("notification not received in time") } }