check / check (push) Waiting to run
Each database target on the webhook page links to /hook/ID/targets/TARGETID/download, which streams the target's archive as archive-WEBHOOK-TARGET-YYYYMMDDTHHMMSSZ.json.gz: the webhook, the target, exported_at, and archived_events, one object per row keyed by column, a body that is not valid UTF-8 in base64 with body_encoding. The export reads through one cursor inside a read-only transaction: one snapshot, no write lock. A download runs for as long as the client keeps reading, and one that fails after it has started aborts the connection. The request limit answers 504 only when the handler has not started its response, so a long download is logged as its 200. Model: opus-5-5
70 lines
1.8 KiB
Go
70 lines
1.8 KiB
Go
package server_test
|
|
|
|
import (
|
|
"compress/gzip"
|
|
"encoding/json"
|
|
"net/http"
|
|
"regexp"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"gorm.io/gorm/clause"
|
|
"sneak.berlin/go/webhooker/internal/database"
|
|
)
|
|
|
|
// TestHook_DownloadArchive follows the Download link the webhook page
|
|
// shows for a database target, and only for it, and gets the archive
|
|
// as a gzipped JSON file. Signed out, the link leads to the login page.
|
|
func TestHook_DownloadArchive(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
env := newTestEnv(t)
|
|
|
|
userID, _ := env.seedUser(t, "archivist", "somepassword")
|
|
cookies := env.authCookies(t, userID, "archivist")
|
|
wh := env.seedWebhook(t, userID)
|
|
env.seedTarget(t, wh.ID)
|
|
|
|
archive := &database.Target{
|
|
WebhookID: wh.ID,
|
|
Name: "kept",
|
|
Type: database.TargetTypeDatabase,
|
|
Active: true,
|
|
}
|
|
require.NoError(t,
|
|
env.db.DB().Omit(clause.Associations).Create(archive).Error,
|
|
)
|
|
|
|
page := env.get("/hook/"+wh.ID, cookies)
|
|
require.Equal(t, http.StatusOK, page.Code)
|
|
|
|
links := regexp.MustCompile(
|
|
`href="(/hook/[^/"]+/targets/[^/"]+/download)"`,
|
|
).FindAllStringSubmatch(page.Body.String(), -1)
|
|
require.Len(t, links, 1, "only the database target has a Download")
|
|
|
|
link := links[0][1]
|
|
assert.Equal(t,
|
|
"/hook/"+wh.ID+"/targets/"+archive.ID+"/download", link,
|
|
)
|
|
|
|
w := env.get(link, cookies)
|
|
require.Equal(t, http.StatusOK, w.Code)
|
|
assert.Equal(t, "application/gzip", w.Header().Get("Content-Type"))
|
|
|
|
zr, err := gzip.NewReader(w.Body)
|
|
require.NoError(t, err)
|
|
|
|
var got map[string]json.RawMessage
|
|
|
|
require.NoError(t, json.NewDecoder(zr).Decode(&got))
|
|
assert.JSONEq(t,
|
|
`{"id":"`+wh.ID+`","name":"routed"}`, string(got["webhook"]),
|
|
)
|
|
|
|
w = env.get(link, nil)
|
|
assert.Equal(t, http.StatusSeeOther, w.Code)
|
|
assert.Contains(t, w.Header().Get("Location"), "/pages/login")
|
|
}
|