clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

feat/ui-updates
tinyrelay / internal / daemon / landing_test.go
landing_test.go 2.7K
1package daemon23import (4 "bytes"5 "context"6 "crypto/sha256"7 "encoding/base64"8 "encoding/hex"9 "encoding/json"10 "net/http"11 "net/http/httptest"12 "strings"13 "testing"14 "time"1516 "github.com/FelineStateMachine/tinyrelay/internal/event"17)1819func TestLandingSignedCreationIsSingleUseAndShowsSource(t *testing.T) {20 app, err := New(context.Background(), Config{DataDir: t.TempDir(), PublicURL: "https://tiny.example"})21 if err != nil {22 t.Fatal(err)23 }24 defer app.Close(context.Background())25 page := httptest.NewRecorder()26 app.ServeLanding(page, httptest.NewRequest(http.MethodGet, "https://tiny.example/relays", nil))27 if !strings.Contains(page.Body.String(), "Source relay") {28 t.Fatal("source field missing")29 }30 if !strings.Contains(page.Body.String(), `class="shell"`) || !strings.Contains(page.Body.String(), "width:360px") || !strings.Contains(page.Body.String(), "min-width:979px") {31 t.Fatal("landing page does not use the fixed 360/960 shell")32 }33 if !strings.Contains(page.Body.String(), `value="search"`) || !strings.Contains(page.Body.String(), `value="home"`) {34 t.Fatal("complete template catalog missing")35 }36 secret, err := event.GenerateKey()37 if err != nil {38 t.Fatal(err)39 }40 owner, err := event.PublicKey(secret)41 if err != nil {42 t.Fatal(err)43 }44 app.cfg.ProvisionOwners = []string{owner}45 body := []byte(`{"name":"owned","template":"default","owner":"` + owner + `","source":"wss://source.example"}`)46 token := landingToken(t, secret, owner, body)47 request := httptest.NewRequest(http.MethodPost, "https://tiny.example/relays", bytes.NewReader(body))48 request.Header.Set("Authorization", token)49 request.Header.Set("Content-Type", "application/json")50 response := httptest.NewRecorder()51 app.ServeLanding(response, request)52 if response.Code != http.StatusCreated {53 t.Fatalf("create status %d: %s", response.Code, response.Body.String())54 }55 replay := httptest.NewRequest(http.MethodPost, "https://tiny.example/relays", bytes.NewReader(body))56 replay.Header.Set("Authorization", token)57 replay.Header.Set("Content-Type", "application/json")58 replayResponse := httptest.NewRecorder()59 app.ServeLanding(replayResponse, replay)60 if replayResponse.Code != http.StatusUnauthorized {61 t.Fatalf("replay status %d", replayResponse.Code)62 }63}6465func landingToken(t *testing.T, secret, owner string, body []byte) string {66 t.Helper()67 sum := sha256.Sum256(body)68 e := event.Event{PubKey: owner, CreatedAt: time.Now().Unix(), Kind: 27235, Tags: [][]string{{"u", "https://tiny.example/relays"}, {"method", "POST"}, {"payload", hex.EncodeToString(sum[:])}}}69 if err := event.Sign(&e, secret); err != nil {70 t.Fatal(err)71 }72 raw, err := json.Marshal(e)73 if err != nil {74 t.Fatal(err)75 }76 return "Nostr " + base64.RawStdEncoding.EncodeToString(raw)77}