package handlers_test import ( "context" "net/http" "net/http/httptest" "strconv" "strings" "testing" "time" "github.com/go-chi/chi" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/gorm/clause" "sneak.berlin/go/webhooker/internal/database" "sneak.berlin/go/webhooker/internal/handlers" "sneak.berlin/go/webhooker/internal/session" ) // serveEventPage runs the real event page handler as the test user // for the given webhook and event ids. func serveEventPage( t *testing.T, h *handlers.Handlers, sess *session.Session, webhookID, eventID string, ) *httptest.ResponseRecorder { t.Helper() req := httptest.NewRequestWithContext( context.Background(), http.MethodGet, "/hook/"+webhookID+"/events/"+eventID, nil, ) for _, c := range authenticatedCookies( t, sess, deleteTestUserID, deleteTestUsername, ) { req.AddCookie(c) } rctx := chi.NewRouteContext() rctx.URLParams.Add(paramSourceID, webhookID) rctx.URLParams.Add(paramEventID, eventID) req = req.WithContext( context.WithValue(req.Context(), chi.RouteCtxKey, rctx), ) w := httptest.NewRecorder() h.HandleEventDetail().ServeHTTP(w, req) return w } // TestHandleEventDetail_ShowsEventWholeWithDeliveries proves the // event's page shows its details, its whole body even past the cap // of the lists of events, pretty-printed and in the scrolling box, // and each delivery with its status and attempts. func TestHandleEventDetail_ShowsEventWholeWithDeliveries(t *testing.T) { t.Parallel() f := newRecentEventsFixture(t) target := seedTarget(t, f.db, f.webhook.ID, database.TargetTypeHTTP) const sentinel = "TAIL-SENTINEL-5b2e" body := `{"pad":"` + strings.Repeat("x", 2*bodyCap) + `","tail":"` + sentinel + `"}` event := f.event(t, contentTypeJSON, body, time.Now()) f.attempt(t, f.delivery( t, event, target.ID, database.DeliveryStatusFailed, ), http.StatusBadGateway, time.Second) w := serveEventPage(t, f.h, f.sess, f.webhook.ID, event.ID) require.Equal(t, http.StatusOK, w.Code) page := w.Body.String() assert.Contains(t, page, event.ID) assert.Contains(t, page, contentTypeJSON) assert.Contains(t, page, strconv.Itoa(len(body))+" bytes") assert.Contains(t, page, "{\n "pad": "xxx") assert.Contains(t, page, ""tail": ""+sentinel+""\n}") assert.Contains(t, page, `style="max-height: 32rem; overflow-y: auto"`) assert.NotContains(t, page, "Showing the first") assert.Contains(t, page, target.Name) assert.Contains(t, page, ">failed") assert.Contains(t, page, "Status: 502") } // TestHandleEventDetail_ResubmitLinks proves a resubmitted copy's // page links to its original's page, and the original's page says // it was resubmitted. func TestHandleEventDetail_ResubmitLinks(t *testing.T) { t.Parallel() f := newRecentEventsFixture(t) original := f.event(t, contentTypeJSON, "{}", time.Now()) cp := &database.Event{ WebhookID: f.webhook.ID, Method: http.MethodPost, Body: "{}", ContentType: contentTypeJSON, ResubmittedFromID: &original.ID, } require.NoError(t, f.webhookDB.Omit(clause.Associations).Create(cp).Error) w := serveEventPage(t, f.h, f.sess, f.webhook.ID, cp.ID) require.Equal(t, http.StatusOK, w.Code) assert.Contains( t, w.Body.String(), `href="/hook/`+f.webhook.ID+`/events/`+original.ID+`"`, ) w = serveEventPage(t, f.h, f.sess, f.webhook.ID, original.ID) require.Equal(t, http.StatusOK, w.Code) assert.Contains(t, w.Body.String(), "as 1 new event<") } // TestHandleEventDetail_UnknownEventNotFound proves the page is a // 404 for an event that does not exist and for one that belongs to // another webhook. func TestHandleEventDetail_UnknownEventNotFound(t *testing.T) { t.Parallel() var ( h *handlers.Handlers sess *session.Session db *database.Database dbMgr *database.WebhookDBManager ) app := newTestApp(t, &h, &sess, &db, &dbMgr) app.RequireStart() t.Cleanup(app.RequireStop) mine := seedWebhook(t, db) theirs := seedWebhook(t, db) seedEventWithBody(t, dbMgr, mine.ID, "{}") elsewhere := seedEventWithBody(t, dbMgr, theirs.ID, "{}") for _, id := range []string{"no-such-event", elsewhere.ID} { w := serveEventPage(t, h, sess, mine.ID, id) assert.Equal(t, http.StatusNotFound, w.Code, id) } }