diff --git a/README.md b/README.md index 006e5d1..2b2f6bc 100644 --- a/README.md +++ b/README.md @@ -1899,6 +1899,10 @@ retries) is individually logged for full observability. | `error` | string | Error message (on failure) | | `duration` | integer | Request duration in milliseconds | +A `database` or `log` target sends no HTTP request, so in the event log and +on the event's page its attempts show no status: a successful one reads +"archived" or "written to the log". + **Relations:** Belongs to Delivery. #### EventTotals, TargetTotals and EntrypointTotals diff --git a/internal/handlers/delivery_attempts_test.go b/internal/handlers/delivery_attempts_test.go new file mode 100644 index 0000000..5b517c3 --- /dev/null +++ b/internal/handlers/delivery_attempts_test.go @@ -0,0 +1,89 @@ +package handlers_test + +import ( + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gorm.io/gorm/clause" + "sneak.berlin/go/webhooker/internal/database" +) + +// TestDeliveryAttempts_ReadInTheTargetTypesOwnTerms proves, on the +// event's page and in the event log, that an http or slack attempt +// shows its status as before, while a database or log attempt, which +// sends no HTTP request, says what it did and shows no status. +func TestDeliveryAttempts_ReadInTheTargetTypesOwnTerms(t *testing.T) { + t.Parallel() + + cases := []struct { + targetType database.TargetType + success bool + statusCode int + errText string + outcome string + status string // "" when the attempt must show no status + }{ + { + database.TargetTypeHTTP, false, 0, "", + "failure", "Status: — (no response)", + }, + { + database.TargetTypeSlack, true, http.StatusOK, "", + "success", "Status: 200", + }, + {database.TargetTypeDatabase, true, 0, "", "archived", ""}, + { + database.TargetTypeDatabase, false, 0, + "opening archive database: disk full", "failure", "", + }, + {database.TargetTypeLog, true, 0, "", "written to the log", ""}, + } + + for _, tc := range cases { + t.Run(string(tc.targetType), func(t *testing.T) { + t.Parallel() + + f := newRecentEventsFixture(t) + target := seedTarget(t, f.db, f.webhook.ID, tc.targetType) + event := f.event(t, contentTypeJSON, "{}", time.Now()) + dlv := f.delivery( + t, event, target.ID, database.DeliveryStatusDelivered, + ) + + require.NoError(t, f.webhookDB.Omit(clause.Associations).Create( + &database.DeliveryResult{ + DeliveryID: dlv.ID, + AttemptNum: 1, + Success: tc.success, + StatusCode: tc.statusCode, + Error: tc.errText, + }, + ).Error) + + w := serveEventPage(t, f.h, f.sess, f.webhook.ID, event.ID) + require.Equal(t, http.StatusOK, w.Code) + + pages := []string{ + w.Body.String(), + renderSourceLogsPage(t, f.h, f.sess, f.webhook.ID), + } + + for _, page := range pages { + assert.Contains(t, page, ">"+tc.outcome+"") + + if tc.errText != "" { + assert.Contains(t, page, "Error: "+tc.errText) + } + + if tc.status == "" { + assert.NotContains(t, page, "Status:") + } else { + assert.Contains(t, page, tc.status) + } + } + }) + } +} diff --git a/templates/delivery_attempts.html b/templates/delivery_attempts.html index 96d77a2..59d3b72 100644 --- a/templates/delivery_attempts.html +++ b/templates/delivery_attempts.html @@ -5,11 +5,15 @@
{{.AttemptsOmitted}} attempt{{if ne .AttemptsOmitted 1}}s{{end}} omitted between the first and last shown.
{{end}} {{range .Results}} +{{/* Inside this loop, dot is one attempt and $ the whole delivery. */}}