package web import ( "encoding/json" "net/http/httptest" "path/filepath" "strconv" "strings" "testing" "time" "pete/internal/config" "pete/internal/storage" ) // TestReaderCardDataAndArticleAPI exercises the reader-mode path end to end: a // classified story renders a card carrying its id + headline data attributes, // and /api/article returns the stored full text for that id. func TestReaderCardDataAndArticleAPI(t *testing.T) { storage.Close() if err := storage.Init(filepath.Join(t.TempDir(), "reader.db")); err != nil { t.Fatal(err) } t.Cleanup(func() { storage.Close() }) story := &storage.Story{ GUID: "reader-e2e", Headline: "A Distinctive Reader Headline", Lede: "The lede.", Content: "Opening paragraph of the piece.\n\nA second paragraph with more detail.", ArticleURL: "https://example.com/story", Source: "Example Wire", Channel: "tech", Classified: true, SeenAt: time.Now().Unix(), } if err := storage.InsertStory(story); err != nil { t.Fatal(err) } var id int64 if err := storage.Get().QueryRow(`SELECT id FROM stories WHERE guid = ?`, story.GUID).Scan(&id); err != nil { t.Fatal(err) } s, err := New(config.WebConfig{SiteTitle: "Pete", ListenAddr: ":0"}, nil, true, config.AdventureConfig{}, nil) if err != nil { t.Fatal(err) } // Index page renders the card with the reader data attributes. rw := httptest.NewRecorder() s.handleIndex(rw, httptest.NewRequest("GET", "/", nil)) body := rw.Body.String() if rw.Code != 200 { t.Fatalf("index status = %d", rw.Code) } for _, want := range []string{ `data-id="` + strconv.FormatInt(id, 10) + `"`, `data-headline="A Distinctive Reader Headline"`, `data-story-card`, } { if !strings.Contains(body, want) { t.Errorf("index HTML missing %q", want) } } // The article endpoint returns the stored content for that id. rw2 := httptest.NewRecorder() s.handleArticle(rw2, httptest.NewRequest("GET", "/api/article?id="+strconv.FormatInt(id, 10), nil)) if rw2.Code != 200 { t.Fatalf("article status = %d body=%s", rw2.Code, rw2.Body.String()) } var got struct { Content string `json:"content"` Lede string `json:"lede"` } if err := json.Unmarshal(rw2.Body.Bytes(), &got); err != nil { t.Fatalf("decode: %v", err) } if got.Content != story.Content { t.Errorf("content = %q, want %q", got.Content, story.Content) } // A bad id is a 400, an unknown id is a 404. for _, tc := range []struct { q string code int }{{"id=0", 400}, {"id=abc", 400}, {"id=999999", 404}} { w := httptest.NewRecorder() s.handleArticle(w, httptest.NewRequest("GET", "/api/article?"+tc.q, nil)) if w.Code != tc.code { t.Errorf("article?%s status = %d, want %d", tc.q, w.Code, tc.code) } } }